2015-06-24 65 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