Three JS中使用ShaderMaterial实现透明效果

14

我正在将两个几何形状并排绘制并使它们旋转。问题在于,第一个绘制的物体会阻挡第二个物体,这里应该使用透明度效果。这两个物体应该具有相同的透明度,无论谁先绘制。因此,混合开启而深度测试关闭。

以下是图像:

这两个几何形状都是使用THREE.ShaderMaterial作为点云绘制的:

var shaderMaterial = new THREE.ShaderMaterial({
                uniforms: uniforms,
                attributes: attributes,
                vertexShader: document.getElementById('vertexshader').textContent,
                fragmentShader: document.getElementById('fragmentshader').textContent,
                blending: THREE.NormalBlending,
                depthTest: false,
                transparent: true
            });

where

// attributes
attributes = {
                size: { type: 'f', value: null },
                alpha: { type: 'f', value: [] },
                customColor: { type: 'c', value: null }
            };

 // uniforms
uniforms = {
             color: { type: "c", value: new THREE.Color(0x00ff00) },
             texture: { type: "t", value: THREE.ImageUtils.loadTexture("../textures/sprites/circle.png") }
            };

并且

<script type="x-shader/x-vertex" id="vertexshader">
        attribute float alpha;
        attribute float size;
        attribute vec3 customColor;        
        varying float vAlpha;
        varying vec3 vColor;
        void main() {
        vAlpha = alpha;
        vColor = customColor;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_PointSize =  size * ( 120.0 / length( mvPosition.xyz ));
        gl_Position = projectionMatrix * mvPosition;
        }
    </script>
<script type="x-shader/x-fragment" id="fragmentshader">
        uniform vec3 color;
        uniform sampler2D texture;
        varying float vAlpha;
        varying vec3 vColor;
        void main() {
        gl_FragColor = vec4( vColor, vAlpha );
        gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
        }
    </script>

我应该在哪里添加 material.alphaTest = 0.5? - Eyal Shacham
2
抱歉。由于您正在使用ShaderMaterial,所以您必须自己处理:if (gl_FragColor.a < 0.5) discard; - WestLangley
谢谢,但这个更改只是丢弃了一些顶点,使物体更加透明,因为点云对象不再“拥挤”。 - Eyal Shacham
我应该将它托管在哪里?你知道一个可以上传代码的网站吗?谢谢! - Eyal Shacham
好的,我已经成功将它加载到JSFiddle上了,链接为http://jsfiddle.net/e8h7k520/5/。 - Eyal Shacham
显示剩余5条评论
1个回答

14

以下是包含2个纹理的示例代码,但也可以通过修改实现单纹理:

<script id="fragmentShaderLoader" type="x-shader/x-fragment">
        uniform float percent;

        uniform sampler2D texture1;
        uniform sampler2D texture2;

        varying vec2 vUv;

        void main() {
            gl_FragColor = texture2D( texture1, vUv);
            vec4 tex2 = texture2D( texture2, vUv );
            if(tex2.a - percent < 0.0) {
                gl_FragColor.a = 0.0;
                //or without transparent = true use
                //discard; 
            }

        }

    </script>

    <script id="vertexShaderLoader" type="x-shader/x-vertex">
        varying vec2 vUv;

        void main()
        {
            vUv = uv;

            vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
            gl_Position = projectionMatrix * mvPosition;
        }
    </script>

然后是初始化:
uniformsMove = {
                    percent: { type: "f", value: 1.0 },
                    texture1: { type: "t", value: (new THREE.TextureLoader()).load( "govr/loader-test.png" ) },
                    texture2: { type: "t", value: (new THREE.TextureLoader()).load( "govr/loader-mask2.png" ) } 
                };

            material = new THREE.ShaderMaterial( {
                uniforms: uniformsMove,
                vertexShader: document.getElementById( 'vertexShaderLoader' ).textContent,
                fragmentShader: document.getElementById( 'fragmentShaderLoader' ).textContent

            } );
material.transparent = true;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接