2015-06-24 60 views
4

我有一个非常简单的PNG纹理:带有透明背景的灰色圆圈。Three.js,具有透明度的自定义着色器和png纹理

PNG image with transparency

我使用它作为一个均匀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.PointCloud网格),它工作得很好:

Particles texture with transparency: OK!

但是,如果我打开相机的超过180度,我看到这一点:

Particles texture without transparency

据我所知,片段着色器没有正确考虑到PNG的Alpha值质地。

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

为什么它的一面表现正确?

回答

9

透明物体必须从后向前渲染 - 从最远到最近。这是因为深度缓冲。

但是PointCloud粒子不是根据距相机的距离排序的。这太低效了。无论相机位置如何,粒子总是以相同的顺序呈现。

您有几种解决方法。

第一个是丢弃alpha为低的片段。您可以使用一种模式,像这样:

if (textureColor.a < 0.5) discard; 

另一种选择是设置material.depthTest = falsematerial.depthWrite = false.你可能不喜欢的副作用,但是,如果你在场景中的其他对象。

three.js r.71

+0

太棒了,我试过'textureColor.a <0.3',看起来很完美。还要感谢细节,我现在更了解PointCloud的工作原理。 – taseenb

+0

呃......实际上看起来比较好用'<0.5' – taseenb