我做了一个小测试,允许您使用three.js在3D环境中试验着色器。
场景中有一个球体显示着色器。
我创建的demo shader是一个非常简单的着色器,它使用2D噪声实现。球体的很大一部分仍然是黑色的,我透明了。我希望球体的另一面也可见。所以我启用了透明度并将渲染方面设置为双面。
material = new THREE.ShaderMaterial({
'uniforms': uniforms,
'fragmentShader': $('textarea#input-fragment').val(),
'vertexShader': $('textarea#input-vertex').val()
});
material.side = THREE.DoubleSide;
material.transparent = true;
在this example上,越野车越容易被注意到。
从顶部查看球体时,您只能从外侧看到着色器。从侧面看时,似乎有点波动,从底部看,它似乎有效。
这些是不同的角度(顶部 - 底部):
这是片段着色器的重要部分:
void main() {
float r = cnoise(vNormal.yz * 2.0 + t);
float g = cnoise(vNormal.xz * -1.0 + t);
float b = cnoise(vNormal.xy * -2.0 + t);
// opacity ranges assumable from 0 - 3, which is OK
gl_FragColor = vec4(r, g, b, r + g + b);
}
那么为什么我会看到波涛汹涌的边缘以及为什么视角很重要?
答案 0 :(得分:4)
您的着色器没有任何问题。如果设置:
,您还可以看到效果gl_FragColor = vec4( 1.0, 1.0, 1.0, 0.5 );
自我透明在three.js中很棘手。
出于性能原因WebGLRenderer
,深度排序仅在对象之间(基于它们的位置),而不是在单个对象中。
无法控制对象内各个面的渲染顺序。
这就是为什么从某些视角来看,你的场景看起来比其他人更好。
一种解决方法是将几何体分解为每个面的单个网格。
另一种解决方法(你最好的选择,IMO)是用同一个位置的两个透明球体替换你的透明双面球体 - 前侧球体和后侧球体。
three.js r.56
答案 1 :(得分:0)
与我遇到的非常相似。理解这一点的原因最好在 Three.js Transparency 基础上进行解释。 没有关于您的代码或目标的更多详细信息,这里是 r128 版本的替代解决方案。只需在您的材料中再添加一行:
material.depthTest: false,
简而言之,正如@WestLangley 提到的那样,您的着色器很好,但是在渲染透明度期间,还会考虑像素彼此之间的深度 - 最终导致某些像素未渲染。这就是您的“越野车”的来源。不是真正的错误,而是默认情况下渲染场景的方式,直到被告知否则。您可能会遇到很多与您的期望不符的*问题,因此我建议您阅读我发布的链接。
*一个这样的问题:如果您的场景中还有其他对象,那么当然由于您关闭了 depthTest,您可能会得到不正确的对象放置,因为应该在背景中的对象可能会在前景中渲染。
>