three.js - 对数深度缓冲器 + 正交相机

标签 three.js

我正在尝试将 Logarithmic Depth Buffer 与 Orthographic 相机一起使用,并遇到了一些有趣的结果。我在这里构建了一个示例:http://jsfiddle.net/TheJim01/05up96m0/

左侧的渲染器(红结)使用标准线性深度缓冲区( 11000 )。选择 Perspective 或 Orthographic 将使用选定的相机类型重新渲染场景,并且两者都按预期工作。

右侧的渲染器(绿色结)使用对数深度缓冲区( 1e-61e27 )。与左侧示例一样,选择相机将使用该相机重新渲染场景。但在这种情况下,只有透视相机按预期工作。 When Orthographic is selected, the knot "unties".看起来几乎完全没有考虑深度缓冲区。

我用错了,还是这里发生了其他事情?

var WIDTH = 250,
  HEIGHT = 250,
  BACKGROUND = 0xcccccc;

var gl1 = new THREE.WebGLRenderer({
    antialias: true,
    logarithmicDepthBuffer: false
  }),
  gl2 = new THREE.WebGLRenderer({
    antialias: true,
    logarithmicDepthBuffer: true
  }),
  scene1 = new THREE.Scene(),
  scene2 = new THREE.Scene(),
  s1pCam = new THREE.PerspectiveCamera(
    28,
    WIDTH / HEIGHT,
    1,
    1000
  ),
  s1oCam = new THREE.OrthographicCamera(-1 * (WIDTH / HEIGHT),
    1 * (WIDTH / HEIGHT),
    1, -1,
    1,
    1000),
  aLight1 = new THREE.AmbientLight(0x333333),
  dLight1 = new THREE.DirectionalLight(0xffffff, 0.75);

s1pCam.position.set(0, 0, 100);
s1pCam.lookAt(scene1.position);
s1oCam.position.set(0, 0, 100);
s1oCam.lookAt(scene1.position);
dLight1.position.set(0, 0, 100);
dLight1.lookAt(new THREE.Vector3(0, 0, -1));

// calculate ortho frustum
var modelCenter = new THREE.Vector3(),
  tmpCamPosition = s1pCam.position.clone(),
  camTarget = new THREE.Vector3(),
  radFOV = (Math.PI / 180.) * s1pCam.fov;
modelCenter.sub(camTarget);
tmpCamPosition.sub(camTarget);
var projectedLocation = modelCenter.projectOnVector(tmpCamPosition);
var distance = tmpCamPosition.distanceTo(projectedLocation);
var halfHeight = Math.tan(radFOV / 2.) * distance;
var halfWidth = halfHeight * s1pCam.aspect;
s1oCam.left = -halfWidth;
s1oCam.right = halfWidth;
s1oCam.top = halfHeight;
s1oCam.bottom = -halfHeight;
s1oCam.zoom = s1pCam.zoom;
s1oCam.updateProjectionMatrix();

var s2pCam = s1pCam.clone(),
  s2oCam = s1oCam.clone(),
  aLight2 = aLight1.clone(),
  dLight2 = dLight1.clone();

s2pCam.near = 1e-6;
s2pCam.far = 1e27;
s2oCam.near = 1e-6;
s2oCam.far = 1e27;

scene1.add(s1pCam);
scene1.add(s1oCam);
scene1.add(aLight1);
scene1.add(dLight1);
scene1.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({
  color: 'red'
})));

scene2.add(s2pCam);
scene2.add(s2oCam);
scene2.add(aLight2);
scene2.add(dLight2);
scene2.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({
  color: 'green'
})));

document.getElementById("view1").appendChild(gl1.domElement);
document.getElementById("view2").appendChild(gl2.domElement);

gl1.setSize(WIDTH, HEIGHT);
gl1.setClearColor(BACKGROUND);

gl2.setSize(WIDTH, HEIGHT);
gl2.setClearColor(BACKGROUND);

gl1.render(scene1, s1pCam);
gl2.render(scene2, s2pCam);

function handleCameraChanges(e) {
  debugger;
  if (gl1 && e.target.id.indexOf("1") !== -1) {
    gl1.render(scene1, (e.target.id.indexOf("p") !== -1) ? s1pCam : s1oCam);
  } else if (gl2) {
    gl2.render(scene2, (e.target.id.indexOf("p") !== -1) ? s2pCam : s2oCam);
  }
}

document.getElementById("v1p").addEventListener("click", handleCameraChanges);
document.getElementById("v1o").addEventListener("click", handleCameraChanges);
document.getElementById("v2p").addEventListener("click", handleCameraChanges);
document.getElementById("v2o").addEventListener("click", handleCameraChanges);
.view {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js"></script>

<fieldset id="view1" class="view">
  <legend>Standard Depth Buffer</legend>
  <label><input id="v1p" type="radio" name="cameraMode1" checked />Perspective</label>
  <label><input id="v1o" type="radio" name="cameraMode1" />Orthographic</label><br>
</fieldset>

<fieldset id="view2" class="view">
  <legend>Logarithmic Depth Buffer</legend>
  <label><input id="v2p" type="radio" name="cameraMode2" checked />Perspective</label>
  <label><input id="v2o" type="radio" name="cameraMode2" />Orthographic</label><br></fieldset>

最佳答案

这已在 PR 17442 中得到解决, 设置为在 r109 中发布。

r109 was released on 30 September, 2019 .

这是与上面完全相同的示例,使用 r109。感谢所有参与修复的人!

var WIDTH = 250,
  HEIGHT = 250,
  BACKGROUND = 0xcccccc;

var gl1 = new THREE.WebGLRenderer({
    antialias: true,
    logarithmicDepthBuffer: false
  }),
  gl2 = new THREE.WebGLRenderer({
    antialias: true,
    logarithmicDepthBuffer: true
  }),
  scene1 = new THREE.Scene(),
  scene2 = new THREE.Scene(),
  s1pCam = new THREE.PerspectiveCamera(
    28,
    WIDTH / HEIGHT,
    1,
    1000
  ),
  s1oCam = new THREE.OrthographicCamera(-1 * (WIDTH / HEIGHT),
    1 * (WIDTH / HEIGHT),
    1, -1,
    1,
    1000),
  aLight1 = new THREE.AmbientLight(0x333333),
  dLight1 = new THREE.DirectionalLight(0xffffff, 0.75);

s1pCam.position.set(0, 0, 100);
s1pCam.lookAt(scene1.position);
s1oCam.position.set(0, 0, 100);
s1oCam.lookAt(scene1.position);
dLight1.position.set(0, 0, 100);
dLight1.lookAt(new THREE.Vector3(0, 0, -1));

// calculate ortho frustum
var modelCenter = new THREE.Vector3(),
  tmpCamPosition = s1pCam.position.clone(),
  camTarget = new THREE.Vector3(),
  radFOV = (Math.PI / 180.) * s1pCam.fov;
modelCenter.sub(camTarget);
tmpCamPosition.sub(camTarget);
var projectedLocation = modelCenter.projectOnVector(tmpCamPosition);
var distance = tmpCamPosition.distanceTo(projectedLocation);
var halfHeight = Math.tan(radFOV / 2.) * distance;
var halfWidth = halfHeight * s1pCam.aspect;
s1oCam.left = -halfWidth;
s1oCam.right = halfWidth;
s1oCam.top = halfHeight;
s1oCam.bottom = -halfHeight;
s1oCam.zoom = s1pCam.zoom;
s1oCam.updateProjectionMatrix();

var s2pCam = s1pCam.clone(),
  s2oCam = s1oCam.clone(),
  aLight2 = aLight1.clone(),
  dLight2 = dLight1.clone();

s2pCam.near = 1e-6;
s2pCam.far = 1e27;
s2oCam.near = 1e-6;
s2oCam.far = 1e27;

scene1.add(s1pCam);
scene1.add(s1oCam);
scene1.add(aLight1);
scene1.add(dLight1);
scene1.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({
  color: 'red'
})));

scene2.add(s2pCam);
scene2.add(s2oCam);
scene2.add(aLight2);
scene2.add(dLight2);
scene2.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({
  color: 'green'
})));

document.getElementById("view1").appendChild(gl1.domElement);
document.getElementById("view2").appendChild(gl2.domElement);

gl1.setSize(WIDTH, HEIGHT);
gl1.setClearColor(BACKGROUND);

gl2.setSize(WIDTH, HEIGHT);
gl2.setClearColor(BACKGROUND);

gl1.render(scene1, s1pCam);
gl2.render(scene2, s2pCam);

function handleCameraChanges(e) {
  debugger;
  if (gl1 && e.target.id.indexOf("1") !== -1) {
    gl1.render(scene1, (e.target.id.indexOf("p") !== -1) ? s1pCam : s1oCam);
  } else if (gl2) {
    gl2.render(scene2, (e.target.id.indexOf("p") !== -1) ? s2pCam : s2oCam);
  }
}

document.getElementById("v1p").addEventListener("click", handleCameraChanges);
document.getElementById("v1o").addEventListener("click", handleCameraChanges);
document.getElementById("v2p").addEventListener("click", handleCameraChanges);
document.getElementById("v2o").addEventListener("click", handleCameraChanges);
.view {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>

<fieldset id="view1" class="view">
  <legend>Standard Depth Buffer</legend>
  <label><input id="v1p" type="radio" name="cameraMode1" checked />Perspective</label>
  <label><input id="v1o" type="radio" name="cameraMode1" />Orthographic</label><br>
</fieldset>

<fieldset id="view2" class="view">
  <legend>Logarithmic Depth Buffer</legend>
  <label><input id="v2p" type="radio" name="cameraMode2" checked />Perspective</label>
  <label><input id="v2o" type="radio" name="cameraMode2" />Orthographic</label><br></fieldset>

关于three.js - 对数深度缓冲器 + 正交相机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37733259/

相关文章:

javascript - Three.js — 如何在加载器之外选择网格?

javascript - three.js 改变 Material 的纹理

javascript - 如何触发鼠标滚轮事件?

javascript - Three.js: map 和属性未定义以及在本地使用图像

javascript - Three.js - GLTF 模型位置不是从原点开始

javascript - A-frame 显示鼠标指针和函数

javascript - Three.js 中的旋转方向或惯用手

javascript - 退出pointerlockcontrols Three.js不工作

three.js - ThreeJS 中的阴影黑暗和对象不透明度

three.js - 有没有办法让一个 CSS2DObject 出现在另一个 CSS2DObject 之上?或者让它出现在场景中所有物体的顶部?