depthWrite: false
和depthTest: false
之间是否存在显着差异?使用depthTest
提供性能优势吗?是否有任何牺牲功能选择其中一个?
我想渲染一个THREE.Points
个对象,每个点都有半透明的圆圈。我使用从THREE.Texture
元素加载的canvas
并将其传递到map
上的THREE.PointsMaterial
属性。
透明度并没有完全发挥作用,有些圆圈重叠得很好,但其他圆圈的表现就好像是坚固的。
我在了解depthWrite: false
上的depthTest: false
和THREE.PointsMaterial
后修复了它。
我有一个代码示例(嵌入在底部),显示重叠点错误,可以使用depthTest
或depthWrite
来修复它:
var points = new THREE.Points(
new THREE.Geometry(),
new THREE.PointsMaterial({
//depthTest: false,
//depthWrite: false,
map: circleTexture,
size: circleDiameter,
transparent: true
})
);
我对这一切都是新手,但是我试着阅读这个主题,并且从我所知道的(如果我错了,请纠正我)深度缓冲区用于确定哪些片段被遮挡而且不需要渲染。关闭depthWrite
或depthTest
将使对象免于此过程。他们的不同之处在于:
depthWrite: false
仍会计算深度,但无论如何都会呈现整个对象
depthTest: false
甚至不计算深度
所以听起来我会通过关闭depthTest
而不是depthWrite
而失去一些对象质量,但可能会通过完全跳过计算来提升性能?但是,我会失去什么品质?实际上是否存在性能差异?在这里,我的无知一闪而过。
// Sizes
var sceneWidth = 200;
var sceneHeight = 200;
var lineLength = 50;
var circleRadius = 32;
var circleDiameter = circleRadius * 2;
// Renderer
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(sceneWidth, sceneHeight);
document.body.appendChild(renderer.domElement);
// Scene
var scene = new THREE.Scene();
// Camera
var d = 100;
var aspect = sceneWidth / sceneHeight;
var camera = new THREE.OrthographicCamera(
-d * aspect,
d * aspect,
d,
-d,
1,
12000
);
camera.position.set(140, 140, 140);
scene.add(camera);
// Controls
var controls = new THREE.OrthographicTrackballControls(
camera,
renderer.domElement
);
controls.rotateSpeed = 0.2;
controls.addEventListener('change', function () {
renderer.render(scene, camera);
});
window.addEventListener('resize', function() {
controls.handleResize();
});
// Circle texture
var canvasEl = document.createElement('canvas');
var context = canvasEl.getContext('2d');
canvasEl.width = circleDiameter;
canvasEl.height = circleDiameter;
context.fillStyle = 'rgba(255, 255, 255, 0.5)';
context.beginPath();
context.arc(circleRadius, circleRadius, circleRadius, 0, Math.PI * 2);
context.fill();
var circleTexture = new THREE.Texture(canvasEl);
circleTexture.needsUpdate = true;
// Points
var points = new THREE.Points(
new THREE.Geometry(),
new THREE.PointsMaterial({
//depthTest: false,
//depthWrite: false,
map: circleTexture,
size: circleDiameter,
transparent: true
})
);
points.geometry.vertices.push(new THREE.Vector3(0, 0, 0));
points.geometry.vertices.push(new THREE.Vector3(0, lineLength, 0));
points.geometry.vertices.push(new THREE.Vector3(0, lineLength, lineLength));
points.geometry.vertices.push(new THREE.Vector3(0, 0, lineLength));
scene.add(points);
// Lines
var lines = new THREE.Line(
new THREE.Geometry(),
new THREE.LineBasicMaterial({
linewidth: 1.2,
color: 0xffffff,
transparent: true,
opacity: 0.25
})
);
lines.geometry.vertices.push(new THREE.Vector3(0, 0, 0));
lines.geometry.vertices.push(new THREE.Vector3(0, lineLength, 0));
lines.geometry.vertices.push(new THREE.Vector3(0, lineLength, 0));
lines.geometry.vertices.push(new THREE.Vector3(0, lineLength, lineLength));
lines.geometry.vertices.push(new THREE.Vector3(0, lineLength, lineLength));
lines.geometry.vertices.push(new THREE.Vector3(0, 0, lineLength));
lines.geometry.vertices.push(new THREE.Vector3(0, 0, lineLength));
lines.geometry.vertices.push(new THREE.Vector3(0, 0, 0));
scene.add(lines);
// Render
function render() {
window.requestAnimationFrame(render);
renderer.render(scene, camera);
controls.update();
}
render();
* { margin: 0; padding: 0; }
body { background-color: #333; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Document</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r76/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrthographicTrackballControls.js"></script>
</body>
</html>
答案 0 :(得分:21)
深度测试关闭意味着一起关闭深度测试。 (阅读/测试和写作)
深度注销意味着防止深度缓冲区被写入。
首先,什么是深度测试?假设您要在您面前直接绘制2个相同的形状,但与您的距离不同。在现实生活中,你只希望看到更接近你的形状,对吗?
如果你试图在没有深度测试的情况下做到这一点,你只会在一半的时间内获得所需的效果:如果远处的物体在较近的物体之前被绘制,没有问题,与现实生活相同;但如果在距离物体之前画出更近的物体,哦 - 哦,远处的物体应该是可见的。有问题的。
深度测试是当今GPU中内置的工具,无论绘制对象的顺序如何,都可以获得所需的绘制输出 。这通常非常有用,但它带来了一个关键的弱点:深度和混合(透明度)不能一起工作。为什么会这样?深度测试的作用是,对于绘制的每个像素,将该像素到相机的距离(深度)与存储在该像素中的深度值进行比较。如果距离小于存储的深度值,则绘制像素,否则丢弃该像素。
这解释了为什么有时会在演示中看到黑色四边形。首先绘制这些四边形时,将它们的深度值写入深度缓冲区。然后,当绘制更远的四边形时,它们的深度值大于缓冲区中的深度,因此丢弃那些像素。在其他视角中,恰好会先绘制远处的四边形,然后绘制更接近的四边形,因此不会因深度测试而丢弃像素。
希望现在很清楚,深度测试有两个方面:深度值的比较和深度值写入深度缓冲区。 DepthTest和depthWrite可以很好地控制如何存档期望的效果。
一起关闭深度测试会比深度编写更快。但是,有时您只想阻止新像素写入深度缓冲区,但仍然启用了深度测试。例如,在您的演示中,如果您要在中心绘制一个完全不透明的立方体;你仍然希望像素的深度远远超过隐藏不透明立方体的像素(深度测试方面),但也希望防止透明圆圈中的像素相互阻挡(写入方面)。您看到的常见绘图配置是在深度测试中绘制所有不透明对象,转动深度注释,然后按照从前到后的顺序绘制透明对象。