【问题标题】:Three.js, custom shader and png texture with transparencyThree.js,自定义着色器和具有透明度的 png 纹理
【发布时间】:2015-09-11 06:48:22
【问题描述】:

我有一个非常简单的 PNG 纹理:一个带有透明背景的灰色圆圈。

我将它用作map 的制服THREE.ShaderMaterial

var uniforms = THREE.UniformsUtils.merge( [basicShader.uniforms] );
uniforms['map'].value = THREE.ImageUtils.loadTexture( "img/particle.png" );
uniforms['size'].value = 100;
uniforms['opacity'].value = 0.5;
uniforms['psColor'].value = new THREE.Color( 0xffffff );

这是我的片段着色器(只是其中的一部分):

gl_FragColor = vec4( psColor, vOpacity );
gl_FragColor = gl_FragColor * texture2D( map,vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );
gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );

我将材质应用于一些粒子(THREE.PointCloudmesh),效果很好:

但如果我将相机旋转超过 180 度,我会看到:

我了解片段着色器未正确考虑 PNG 纹理的 Alpha 值。

在这种情况下,获得正确的颜色和不透明度(来自自定义属性)并仍然从 PNG 中获得 alpha 的最佳方法是什么?

为什么它在一侧表现正确?

【问题讨论】:

    标签: three.js png textures shader fragment-shader


    【解决方案1】:

    透明对象必须从后向前渲染——从最远到最近。这是因为深度缓冲区。

    PointCloud 粒子不会根据与相机的距离进行排序。那效率太低了。无论相机位置如何,粒子总是以相同的顺序渲染。

    您有几种解决方法。

    首先是丢弃 alpha 较低的片段。你可以使用这样的模式:

    if ( textureColor.a < 0.5 ) discard;
    

    另一个选项是设置material.depthTest = falsematerial.depthWrite = false. 但是,如果场景中有其他对象,您可能不喜欢副作用。

    three.js r.71

    【讨论】:

    • 太好了,我试过textureColor.a &lt; 0.3,看起来很完美。也感谢您提供的详细信息,我现在更了解 PointCloud 的工作原理。
    • 嗯...实际上看起来更好&lt; 0.5
    猜你喜欢
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 2012-09-19
    • 2014-02-06
    • 2020-04-14
    • 1970-01-01
    • 2016-03-06
    • 2014-12-03
    相关资源
    最近更新 更多