双面透明着色器看起来越野车

时间:2013-03-05 15:24:10

标签: javascript glsl three.js webgl shader

我做了一个小测试,允许您使用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上,越野车越容易被注意到。

从顶部查看球体时,您只能从外侧看到着色器。从侧面看时,似乎有点波动,从底部看,它似乎有效。

这些是不同的角度(顶部 - 底部):

top view side view bottom view

这是片段着色器的重要部分:

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);
}

那么为什么我会看到波涛汹涌的边缘以及为什么视角很重要?

2 个答案:

答案 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,您可能会得到不正确的对象放置,因为应该在背景中的对象可能会在前景中渲染。

>