强制一个精灵对象始终在THREE.js中的天体对象前面

强制一个精灵对象始终在THREE.js中的天体对象前面

问题描述:

我目前有一个自定义着色器在天穹上画一个渐变,并希望在天蝎座前面有一个太阳/月亮(从用户角度来看) 。最简单的方法是为太阳和月亮拍摄精灵,但问题在于精灵会在天体中出现(精灵在前方和后方的中间部分)。我试图用polygonoffset来解决这个问题,但是这似乎不适用于精灵对象。强制一个精灵对象始终在THREE.js中的天体对象前面

所以我的问题是,我如何在skydome上设置太阳/月亮,而不必修改我自定义的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是这里最重要的):

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

其中skydome是网格上您已申请yourmaterial