顶点位移着色器具有径向扭曲。我该如何解决?

时间:2013-09-10 20:22:25

标签: opengl-es three.js webgl glsl

我正在编写一个顶点置换着色器。我成功地将平面的顶点映射到具有GLSL着色器和Three.js的视频的亮度值,但GLSL着色器以径向方式映射值,这可能适合于纹理化球体,但不适用于此平面。中心向外有径向扭曲。如何修复此径向扭曲?

RuttEtraShader = {

    uniforms: {

        "tDiffuse": { type: "t", value: null },
        "opacity":  { type: "f", value: 1.0 }
    },



    vertexShader: [

    'uniform sampler2D tDiffuse;',
    'varying vec3 vColor;',
    "varying vec2 vUv;",

    'void main() {',
        'vec4 newVertexPos;',
        'vec4 dv;',
        'float df;',
        "vUv = uv;",
        'dv = texture2D( tDiffuse, vUv.xy );',
        'df = 1.33*dv.x + 1.33*dv.y + 16.33*dv.z;',
        'newVertexPos = vec4( normalize(position) * df * 10.3, 0.0 ) + vec4( position, 1.0 );', 
        'vColor = vec3( dv.x, dv.y, dv.z );',

        'gl_Position = projectionMatrix * modelViewMatrix * newVertexPos;',
    '}'

    ].join("\n"),

    fragmentShader: [

      'varying vec3 vColor;',

      'void main() {',
          'gl_FragColor = vec4( vColor.rgb, 1.0 );',
      '}'



    ].join("\n")

};



texture = new THREE.Texture( video );
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
texture.generateMipmaps = true;


videoMaterial = new THREE.ShaderMaterial( {
    uniforms: {

        "tDiffuse": { type: "t", value: texture },
    },

    vertexShader: RuttEtraShader.vertexShader,
    fragmentShader: RuttEtraShader.fragmentShader,
    depthWrite: false,
    depthTest: true,
    transparent: true,
    overdraw: false

} );
videoMaterial.renderToScreen = true;



geometry = new THREE.PlaneGeometry(720, 480, 720, 480);
geometry.overdraw = false;
geometry.dynamic = true;
mesh = new THREE.Mesh( geometry, videoMaterial );

mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;

mesh.visible = true;

scene.add( mesh );

1 个答案:

答案 0 :(得分:1)

由于您使用相对于标准化设备坐标(NDC)中的点(0,0,0)的方向向量,您的位移从屏幕中心辐射。

如果不重新定义任何矩阵,您可以使用newVertexPos = vec4( normalize(position - origin) * df * 10.3, 0.0 ) + vec4( position, 1.0 );来解决此问题,其中origin是您想要辐射的点。在NDC中,vec3 origin = vec3 (-1.0,-1.0,0.0)将从左下角辐射出所有内容。

但是,如果仅进行此更改,仍会有非常明显的径向位移。您可能会考虑的另一件事是使用非均匀缩放的位移。您可以使用* df * 10.3而不是* df * vec3 (1.0, 1.0, 10.3)。这将使Z位移 更加明显。

您可以混合使用这两种方法来找到最佳效果。我怀疑增加Z位移的比例会产生你想要的结果,但是理解为什么位移从屏幕中心辐射出来总是有帮助的。

我感觉你的飞机可能位于Z = 0,所以除非你向前/向前移动,否则Z位移总是为0。如果你向position.z添加1.0,它会将它移动到far平面,如果你从position.z中减去1.0,它会将它移动到近平面。