对数深度缓冲器 + 正交相机 [英] Logarithmic Depth Buffer + Orthographic Camera

查看:30
本文介绍了对数深度缓冲器 + 正交相机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

是我用错了,还是有其他问题?

var WIDTH = 250,高度 = 250,背景 = 0xcccccc;var gl1 = new THREE.WebGLRenderer({抗锯齿:真实,对数深度缓冲区:false}),gl2 = new THREE.WebGLRenderer({抗锯齿:真实,logarithmicDepthBuffer: 真}),场景 1 = 新的 THREE.Scene(),场景 2 = 新的 THREE.Scene(),s1pCam = 新的 THREE.PerspectiveCamera(28,宽度/高度,1、1000),s1oCam = new THREE.OrthographicCamera(-1 * (WIDTH/HEIGHT),1 *(宽度/高度),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));//计算正视锥体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);varprojectedLocation = modelCenter.projectOnVector(tmpCamPosition);var 距离 = tmpCamPosition.distanceTo(projectedLocation);var halfHeight = Math.tan(radFOV/2.) * 距离;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;场景1.添加(s1pCam);场景1.添加(s1oCam);场景1.添加(aLight1);场景1.添加(dLight1);scene1.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({红色'})));场景2.添加(s2pCam);场景2.添加(s2oCam);场景2.添加(aLight2);场景2.添加(dLight2);scene2.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({颜色:'绿色'})));document.getElementById("view1").appendChild(gl1.domElement);document.getElementById("view2").appendChild(gl2.domElement);gl1.setSize(WIDTH, HEIGHT);gl1.setClearColor(背景);gl2.setSize(WIDTH, HEIGHT);gl2.setClearColor(背景);gl1.render(scene1, s1pCam);gl2.render(scene2, s2pCam);函数 handleCameraChanges(e) {调试器;if (gl1 && e.target.id.indexOf("1") !== -1) {gl1.render(scene1, (e.target.id.indexOf("p") !== -1) ? s1pCam : s1oCam);}否则如果(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 {显示:内联块;}

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.min.js"></script><fieldset id="view1" class="view"><legend>标准深度缓冲</legend><label><input id="v1p" type="radio" name="cameraMode1" 勾选/>透视</label><label><input id="v1o" type="radio" name="cameraMode1"/>Orthographic</label><br></fieldset><fieldset id="view2" class="view"><legend>对数深度缓冲区</legend><label><input id="v2p" type="radio" name="cameraMode2" 勾选/>透视</label><label><input id="v2o" type="radio" name="cameraMode2"/>Orthographic</label><br></fieldset>

解决方案

此问题已在 PR 17442,设置为在 r109 中发布.

r109 于 2019 年 9 月 30 日发布.>

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

var WIDTH = 250,高度 = 250,背景 = 0xcccccc;var gl1 = new THREE.WebGLRenderer({抗锯齿:真实,对数深度缓冲区:false}),gl2 = new THREE.WebGLRenderer({抗锯齿:真实,logarithmicDepthBuffer: 真}),场景 1 = 新的 THREE.Scene(),场景 2 = 新的 THREE.Scene(),s1pCam = 新的 THREE.PerspectiveCamera(28,宽度/高度,1、1000),s1oCam = new THREE.OrthographicCamera(-1 * (WIDTH/HEIGHT),1 *(宽度/高度),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));//计算正视锥体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);varprojectedLocation = modelCenter.projectOnVector(tmpCamPosition);var 距离 = tmpCamPosition.distanceTo(projectedLocation);var halfHeight = Math.tan(radFOV/2.) * 距离;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;场景1.添加(s1pCam);场景1.添加(s1oCam);场景1.添加(aLight1);场景1.添加(dLight1);scene1.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({红色'})));场景2.添加(s2pCam);场景2.添加(s2oCam);场景2.添加(aLight2);场景2.添加(dLight2);scene2.add(new THREE.Mesh(new THREE.TorusKnotGeometry(10, 4, 100, 32), new THREE.MeshPhongMaterial({颜色:'绿色'})));document.getElementById("view1").appendChild(gl1.domElement);document.getElementById("view2").appendChild(gl2.domElement);gl1.setSize(WIDTH, HEIGHT);gl1.setClearColor(背景);gl2.setSize(WIDTH, HEIGHT);gl2.setClearColor(背景);gl1.render(scene1, s1pCam);gl2.render(scene2, s2pCam);函数 handleCameraChanges(e) {调试器;if (gl1 && e.target.id.indexOf("1") !== -1) {gl1.render(scene1, (e.target.id.indexOf("p") !== -1) ? s1pCam : s1oCam);}否则如果(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 {显示:内联块;}

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script><fieldset id="view1" class="view"><legend>标准深度缓冲</legend><label><input id="v1p" type="radio" name="cameraMode1" 勾选/>透视</label><label><input id="v1o" type="radio" name="cameraMode1"/>Orthographic</label><br></fieldset><fieldset id="view2" class="view"><legend>对数深度缓冲区</legend><label><input id="v2p" type="radio" name="cameraMode2" 勾选/>透视</label><label><input id="v2o" type="radio" name="cameraMode2"/>Orthographic</label><br></fieldset>

I'm trying to use the Logarithmic Depth Buffer with an Orthographic camera, and encountering some interesting results. I've constructed a sample here: http://jsfiddle.net/TheJim01/05up96m0/

The renderer on the left (the red knot) uses a standard linear depth buffer (1 to 1000). Selecting Perspective or Orthographic will re-render the scene with the selected camera type, and both appear to work as expected.

The renderer on the right (the green knot) uses a logarithmic depth buffer (1e-6 to 1e27). As with the left sample, selecting a camera will re-render the scene with that camera. But in this case, only the Perspective camera works as expected. When Orthographic is selected, the knot "unties". It looks almost like it's not considering the depth buffer at all.

Am I using it wrong, or is something else going on here?

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>

解决方案

This has been resolved in PR 17442, set for release in r109.

r109 was released on 30 September, 2019.

Here is the exact same example as above, using r109. Thanks to everyone involved in the fix!

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>

这篇关于对数深度缓冲器 + 正交相机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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