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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With