强制精灵对象始终位于 THREE.js 中的天穹对象前面 [英] Force a sprite object to always be in front of skydome object in THREE.js

查看:87
本文介绍了强制精灵对象始终位于 THREE.js 中的天穹对象前面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个自定义着色器在天穹上绘制渐变,并希望在天穹前有一个太阳/月亮(从用户的角度来看).最简单的方法是为太阳和月亮设置精灵,但出现的问题是精灵卡在天穹内(精灵位于天穹前部和后部).我试图用多边形偏移来解决这个问题,但这似乎不适用于精灵对象.

I currently have a custom shader draw a gradient on a skydome and would like to have a sun/moon in front of the skydome (from users perspective). The easiest way to do this is to have sprites for the sun and moon but the problem that arises is that the sprites get lodged within the skydome (sprite is partway in front and partway in back of the skydome). I have attempted to solve this with polygonoffset, but that doesn't seem to work on sprite objects.

所以我的问题是,如何在天穹顶部设置太阳/月亮而不必修改我的自定义天穹着色器来添加带有渐变的太阳/月亮纹理(这最终可能非常困难)?

So my question is, how can I setup a sun/moon on top of skydome without having to modify my custom skydome shader to add sun/moon texture with the gradient (which could end up being very difficult)?

下面是我的天穹天空着色器的代码.

Below is the code for my sky shader for the skydome.

new THREE.ShaderMaterial({
    uniforms: {
        glow: {
            type: "t",
            value: THREE.ImageUtils.loadTexture(DEFAULT_PATH+"glow2.png")
        },
        color: {
            type: "t",
            value: THREE.ImageUtils.loadTexture(DEFAULT_PATH+"sky2.png")
        },
        lightDir: {
            type: "v3",
            value: self.lightPos
        }
    },
    vertexShader: [
        "varying vec3 vWorldPosition;",
        "varying vec3 vPosition;",
        "void main() {",
            "vec4 worldPosition = modelMatrix * vec4(position, 1.0);",
            "vWorldPosition = worldPosition.xyz;",
            "vPosition = position;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
        "}"
    ].join("\n"),
    fragmentShader: [
        "uniform sampler2D glow;",
        "uniform sampler2D color;",
        "uniform vec3 lightDir;",
        "varying vec3 vWorldPosition;",
        "varying vec3 vPosition;",
        "void main() {",
            "vec3 V = normalize(vWorldPosition.xzy);",
            "vec3 L = normalize(lightDir.xzy);",
            "float vl = dot(V, L);",
            "vec4 Kc = texture2D(color, vec2((L.y + 1.0) / 2.0, V.y));",
            "vec4 Kg = texture2D(glow,  vec2((L.y + 1.0) / 2.0, vl));",
            "gl_FragColor = vec4(Kc.rgb + Kg.rgb * Kg.a / 2.0, Kc.a);",
        "}",
    ].join("\n")
});

推荐答案

确保在任何其他对象之前绘制您的天穹并禁用 depthWrite/depthTest 标志材料(depthWrite 在这里很重要):

Make sure your skydome is drawn before any other object and disable the depthWrite / depthTest flags on the material (depthWrite being the important thing here):

yourmaterial = new THREE.ShaderMaterial({...});
yourmaterial.depthWrite = false;
yourmaterial.depthTest = false;
skydome.renderDepth = 1e20;

其中 skydome 是您应用了 yourmaterial 的网格.

where skydome is the mesh on which you have applied yourmaterial.

这篇关于强制精灵对象始终位于 THREE.js 中的天穹对象前面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆