shaderMaterial:logarithmicDepthBuffer 的渲染顺序错误

在three.js中开启对数缓冲区,会导致shaderMaterial材质的渲染顺序问题,产生比较诡异的效果.

renderer关闭对数缓冲区的效果:

renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
    precision: 'highp',
    logarithmicDepthBuffer: false // 设置对数深度缓冲区
  })

绿色的为自定义的shaderMaterial材质,白色的是MeshBasicMaterial的材质,这是正常渲染的一个效果.

开启对数缓冲区的效果:

renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
    precision: 'highp',
    logarithmicDepthBuffer: true// 设置对数深度缓冲区
  })

就会产生不正常的渲染,具体就是绿色的材质比白色的材质更靠近相机,理论上应该是绿色会遮盖住白色的材质,然而开启对数缓冲区后,ShaderMaterial材质渲染循序会出现问题,导致优先显示了白色的MeshBasicMaterial材质

那么问题来了,既然会产生这样的问题,renderdr不开启对数缓冲区不就行了嘛。这就不得不提一下对数缓冲区的作用了,在Three.js中,Renderer的对数缓冲区(logarithmicDepthBuffer)是一项用于提高深度精度的技术。默认情况下,Three.js使用线性深度缓冲(linear depth buffer),但在某些场景中,线性深度缓冲可能导致深度精度不足,特别是在场景中包含大范围深度值时。

使用对数深度缓冲可以在远距离处提高深度精度,减少深度缓冲的精度变化。这对于渲染大型场景或有广泛深度变化的场景特别有用,因为它能够更均匀地分配深度精度,防止Z-fighting的精度问题。
那么开启对数缓冲区后,怎么解决shaderMaterial材质渲染顺序错误的问题呢?

解决的方法就是在定义ShaderMaterial时使用内部着色器块增强自定义着色器,具体如下:
 

const mat = new THREE.ShaderMaterial({
    uniforms: {
      baseColor: { value: new THREE.Vector3(0.7681511472425808, 0.9386857284565036, 0.9911020971136257) },
      targetColor: { value: new THREE.Vector3(0.011612245176281512, 0.6724431569510133, 0.1499597898006365) },
      height: { value: height || 0.15 }
    },
    side: THREE.DoubleSide,
    transparent: true,
    depthWrite: true,
    depthTest: true,
    vertexShader: [
      'varying vec3 modelPos;',
      '#include <common>', // 添加着色器快
      '#include <logdepthbuf_pars_vertex>',  // 添加的着色器快
      'void main() {',
      '   modelPos = position;',
      '	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
      ' #include <logdepthbuf_vertex>',  // 添加的着色器快
      '}'
    ].join('\n'),
    fragmentShader: [
      '#include <common>',   // 添加的着色器快
      '#include <logdepthbuf_pars_fragment>',   // 添加的着色器快
      'uniform vec3 baseColor;',
      'uniform vec3 targetColor;',
      'uniform float height;',
      'varying vec3 modelPos;',
      'void main() {',
      '  #include <logdepthbuf_fragment>',  // 添加的着色器快
      '  gl_FragColor = vec4(targetColor.xyz, 1);', // (0.0 - modelPos.z/height)*(0.0 - modelPos.z/height)
      '  if(modelPos.z/height > 0.333 && modelPos.z/height < 0.666) {gl_FragColor = vec4(baseColor.xyz, 1);}',
      '  if(modelPos.z/height > 0.666) {gl_FragColor = vec4(targetColor.xyz, 1);}',
      '}'
    ].join('\n')
  })

有四个logdepthbuffer块以及common添加到代码中的块。问题就解决了。

three社区对这个问题的讨论,可以查看原帖shaderMaterial: render-order with logarithmicDepthBuffer is wrong

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值