Three.js - THREE.Points上透明画布纹理贴图的depthWrite与depthTest [英] Three.js - depthWrite vs depthTest for transparent canvas texture map on THREE.Points

查看:1657
本文介绍了Three.js - THREE.Points上透明画布纹理贴图的depthWrite与depthTest的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

depthWrite:false depthTest之间是否存在显着差异:假?使用 depthTest 是否提供了性能优势?是否有任何牺牲功能选择其中一个?

Is there a significant difference between depthWrite: false and depthTest: false? Does using depthTest offer a performance advantage? Is there any sacrifice in functionality choosing one or the other?

我想渲染一个 THREE.Points 每个点都有半透明圆圈的对象。我使用从 canvas 元素加载的 THREE.Texture 并将其传递给 map <一个属性 THREE.PointsMaterial

I wanted to render a THREE.Points object with translucent circles as each point. I used a THREE.Texture loaded from a canvas element and passed it to the map property on the THREE.PointsMaterial.

透明度没有完全奏效,有些圈子重叠罚款,但其他人表现得好像是坚实的。

The transparency did not completely work, some circles overlapped fine but others behaved as if they were solid.

我在了解了 depthWrite:false depthTest:false THREE.PointsMaterial

我有一个代码示例(底部嵌入),显示重叠点错误,并且可以使用 depthTest depthWrite 来修复它:

I have a code example (embedded at bottom) that shows the overlapping points error, and can use depthTest or depthWrite to fix it:

var points = new THREE.Points(
    new THREE.Geometry(),
    new THREE.PointsMaterial({
        //depthTest: false,
        //depthWrite: false,
        map: circleTexture,
        size: circleDiameter,
        transparent: true
    })
);

我对这一切都不熟悉,但我试着阅读这个主题,并从我的内容可以告诉(纠正我,如果我错了)深度缓冲区用于确定哪些片段被遮挡而不需要渲染。关闭 depthWrite depthTest 将免除此进程中的对象。它们的区别在于:

I'm new to all this, but I tried reading up on the subject, and from what I can tell (correct me if I'm wrong) the depth buffer is used to determine what fragments are occluded and do not need rendering. Turning off either depthWrite or depthTest will exempt an object from this process. They differ in that:


  • depthWrite:false 仍然计算深度,但渲染整个对象无论

  • depthWrite: false still calculates depth, but renders the entire object regardless

depthTest:false 甚至不计算深度

所以听起来我会通过关闭 depthTest 而失去一些对象品质 depthWrite ,但可能会通过完全跳过计算来提升性能?但是,我会失去什么品质?实际上是否存在性能差异?在这里,我的无知一闪而过。

So it sounds like I would lose some object qualities by turning off depthTest instead of depthWrite, but possibly get a performance boost by skipping the calculation altogether? But, what qualities would I be losing? And is there actually a performance difference? Here my ignorance shines through.

// 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>

推荐答案

深度测试意味着一起关闭深度测试。 (阅读/测试和写作)

Depth test off means to turn off depth testing all together. (reading/testing and writing)

深度注销意味着防止写入深度缓冲区。

Depth write off means to prevent the depth buffer from being written.

首先,什么是深度测试?假设您要在您面前直接绘制2个相同的形状,但与您的距离不同。在现实生活中,你只希望看到更接近你的形状,对吗?

So first of all, what is depth test? Suppose if you are to draw 2 identical shapes directly in front of you but of different distance to you. In real life, you expect to only see the shape that is closer to you, correct?

如果你试图在没有深度测试的情况下尝试这样做,你只会在一半的时间内获得所需的效果:如果在较近的物体之前绘制了远处的物体没问题,和现实生活一样;但如果在距离物体之前画出更近的物体,哦 - 哦,远处的物体应该是可见的。有问题的。

Well if you were to try to do this without a depth test, you will only get the desired effect half the time: if the distant object is drawn before the closer object, no problem, same as real life; but if the closer object is drawn before the distance object, oh-oh, the distant object is visible when it should be not. Problematic.

深度测试是当今GPU中内置的工具,无论绘制对象的顺序如何,都可以获得所需的绘制输出 。这通常非常有用,但它带来了一个关键的弱点:深度和混合(透明度)不能一起工作。为什么会这样?深度测试的作用是,对于绘制的每个像素,将该像素到相机的距离(深度)与存储在该像素中的深度值进行比较。如果距离小于存储的深度值,则绘制像素,否则丢弃该像素。

Depth test is a tool built in today's GPUs to allow to get the desired draw output regardless of the order which the objects are drawn. This is normally very useful but it comes with a critical weakness: depth and blending(transparency) do not work together. Why is this the case? Well what depth test does is that for every pixel that is drawn, the distance(depth) of that pixel to the camera is compared to the depth value stored in that the pixel. If the distance is less that the stored depth value, the pixel is drawn, otherwise that pixel is discarded.

这解释了为什么有时会在演示中看到黑色四边形。首先绘制这些四边形时,将它们的深度值写入深度缓冲区。然后,当绘制更远的四边形时,它们的深度值大于缓冲区中的深度,因此丢弃那些像素。在其他视角中,恰好会先拍摄远处的四边形,然后是更接近的四边形,因此不会因为深度测试而丢弃像素。

This explains why you sometimes see the black quads in your demo. When those quads are drawn first, their depth values are written into the depth buffer. Then when the more distant quads are drawn, their depth value are greater than the depth in the buffer and thus those pixels are discarded. In other viewing angles it just so happens that distant quads are drawn first and then the closer quads, so no pixels are discarded due to depth testing.

希望它现在清楚了深度测试有两个方面:深度值的比较和深度值写入深度缓冲区。 DepthTest和depthWrite可以很好地控制如何存档所需的效果。

Hopefully its clear now that there are two aspects of depth testing: the comparison of depth values and the writing of depth values to the depth buffer. DepthTest and depthWrite gives you fine control over how to archive the desired effect.

一起关闭深度测试会比深度编写更快。但是,有时您只想阻止新像素写入深度缓冲区,但仍然启用了深度测试。例如,在您的演示中,如果您要在中心绘制一个完全不透明的立方体;你仍然希望像素的深度远远超过隐藏不透明立方体的像素(深度测试方面),但也希望防止透明圆圈中的像素相互阻挡(写入方面)。您看到的常见绘图配置是绘制所有不透明对象并打开深度测试,转换深度注释,然后按照从前到后的顺序绘制透明对象。

Turning off depth testing all together would be faster than just depth writing. However, sometimes you just want to prevent new pixels to write to the depth buffer but still with the depth testing enabled. For example, in your demo if you were to draw a totally opaque cube in the center; you still want pixels with further depth than the pixels representing the opaque cube to be hidden (the depth testing aspect), but also want to prevent pixels from the transparent circles from blocking each other (the writing aspect). A common draw configuration you see is to draw all the opaque object with depth testing on, turn depth write off, then draw the transparent objects in a back to front order.

这篇关于Three.js - THREE.Points上透明画布纹理贴图的depthWrite与depthTest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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