使用VertexShader更改几何体时,Shadow不会更新

时间:2016-03-08 17:16:30

标签: three.js shader

我使用自定义着色器弯曲平面。我的自定义着色器扩展了Lambert着色器,因此它支持灯光和阴影。这一切都按预期工作,但是当vertexShader改变平面的几何形状时,阴影不会更新。我是否遗漏了标记几何体在我的vertexShader中更新并且阴影需要更改的内容?

[这是问题的截图。平面弯曲有顶点阴影,但阴影没有更新] [1]      [1]:http://i.stack.imgur.com/6kfCF.png

以下是演示/代码:http://dev.cartelle.nl/curve/ 如果你拖动" bendAngle"滑块,你可以看到阴影没有更新。

我想到的一个解决办法就是得到我弯曲平面的边界框。然后使用这些点并创建一个新的网格/框并使用该对象投射阴影。但后来我不确定如何获得新曲面几何的坐标。当我在应用着色器后检查geometry.boundingBox时,它也会每次都给我原始坐标。

由于 约翰尼

1 个答案:

答案 0 :(得分:1)

如果要修改顶点着色器中的几何体位置,并且要投射阴影,则需要指定自定义深度材质,以便阴影响应修改后的位置。

在自定义深度素材的顶点着色器中,您修改顶点位置的方式与在材质的顶点着色器中修改它们的方式相同。

可以在this three.js example中看到自定义深度材质的示例(尽管在该示例中顶点着色器中没有修改顶点;它们在CPU上被修改)。

在您的情况下,您将使用如下模式为自定义深度材质创建顶点着色器:

<script type="x-shader/x-vertex" id="vertexShaderDepth">

  uniform float bendAngle;
  uniform vec2 bounds;
  uniform float bendOffset;
  uniform float bendAxisAngle;

    vec3 bendIt( vec3 ip, float ba, vec2 b, float o, float a ) {
        // your code here
        return ip;
    }

    void main() {

        vec3 p = bendIt( position, bendAngle, bounds, bendOffset, bendAxisAngle );

        vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );

        gl_Position = projectionMatrix * mvPosition;

    }

</script>

片段着色器如下:

<script type="x-shader/x-fragment" id="fragmentShaderDepth">

    vec4 pack_depth( const in float depth ) {

        const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );
        const vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );
        vec4 res = fract( depth * bit_shift );
        res -= res.xxyz * bit_mask;
        return res;

    }

    void main() {

        gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );

    }
</script>

然后在您的javascript中,指定自定义深度素材:

uniforms = {};
uniforms.bendAngle = { type: "f", value: properties.bendAngle };
uniforms.bendOffset = { type: "f", value: properties.offset };
uniforms.bendAxisAngle = { type: "f", value: properties.bendAxisAngle };
uniforms.bounds = { type: "v2", value: new THREE.Vector2( - 8, 16 ) };

var vertexShader = document.getElementById( 'vertexShaderDepth' ).textContent;
var fragmentShader = document.getElementById( 'fragmentShaderDepth' ).textContent;

myObject.customDepthMaterial = new THREE.ShaderMaterial( {
    uniforms: uniforms,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
} );

three.js r.74