Force a sprite object to always be in front of skydome object in THREE.js

偶尔善良 提交于 2019-12-24 12:33:44

问题


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

回答1:


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;

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



来源:https://stackoverflow.com/questions/16247280/force-a-sprite-object-to-always-be-in-front-of-skydome-object-in-three-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!