我使用ShaderMaterial创建具有基于属性的大小和不透明度的点云。我还需要贴图。问题在于纹理的渲染没有透明度。看起来每种纹理像素颜色都以某种方式与背景颜色(本例中为白色)混合;如何避免这种情况?
我使用svg纹理:
<div id="circle-texture" style="width: 0; height: 0; display: none">
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="16" cy="16" r="13" stroke="none" fill="white" fill-opacity="1" />
</svg>
</div>
这是我的片段着色器:
<script type="x-shader/x-fragment" id="point-cloud-fragment-shader">
...
uniform sampler2D texture;
varying vec3 vColor;
varying float vOpacity;
#include <clipping_planes_pars_fragment>
void main() {
#include <clipping_planes_fragment>
vec3 outgoingLight = vec3( 0.0 );
vec4 diffuseColor = vec4( diffuse, vOpacity );
if (enableTexture) {
vec4 mapTexel = texture2D( texture, gl_PointCoord );
diffuseColor *= mapTexelToLinear( mapTexel );
}
diffuseColor.rgb *= vColor;
outgoingLight = diffuseColor.rgb;
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
}
在以下情况下放弃修复:
if ( gl_FragColor.a < 0.001 ) discard;
但是有可能不丢弃吗? (使用自定义混合功能或其他方法)我玩过自定义混合功能,但到目前为止没有成功。
在处理部分透明的点云时有效的设置是将transparent: true
,depthTest: false
和blending mode设为必要。根据您的用例,加法或乘法混合看起来不错,并且消除了对子图形深度进行排序的需要,因为混合消除了将颜色放置在另一个“前面”的需要:
const spriteMat = new THREE.ShaderMaterial({
uniforms: {
// List of uniforms
},
vertexShader: spriteVert,
fragmentShader: spriteFrag,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
[Turn transparent: true
会尊重片段着色器中的alpha通道,因此您不再需要丢弃像素。