Direct2D深度缓冲区
Direct2D Depth Buffer
我需要绘制一个形状列表,并且我正在使用Direct2D。我从文件中得到形状列表。列表经过排序,文件中元素的顺序表示这些形状的绘制顺序。因此,例如,如果文件指定两个位于相同位置且大小相同的矩形,则只有第二个矩形可见(因为第一个矩形将被覆盖)。
根据我的形状列表,我以以下方式绘制:
list<Shape> shapes;
for (const auto& shape : shapes)
shape.draw();
很明显,如果我有两个形状,我就不能颠倒绘制操作的顺序,这意味着我必须确保shape2
总是在shape1
之后绘制,以此类推。接下来,我不能使用多个线程来绘制我的形状,这在性能方面是一个巨大的缺点。
我读到Direct3D支持深度缓冲区(或z缓冲区),它为每个像素指定其z坐标,这样无论形状的绘制顺序如何,都只会绘制"可见"像素(离查看器较近的像素)。当我读取文件时,我有每个形状的深度信息。
有没有一种方法可以在Direct2D中使用深度缓冲区,或者类似的技术可以让我使用多个线程来绘制形状?
有没有一种方法可以在Direct2D中使用深度缓冲区,或类似的方法允许我使用多个线程来绘制形状?
这里的答案是否。尽管Direct2D库是在Direct3D的基础上构建的,但它并没有通过API为用户提供这样的功能,因为你可以绘制的基元仅由二维坐标描述。确保绘制到渲染目标的最后一个基本体可见,因此不会进行深度测试。此外,Direct3D中的深度缓冲区与CPU端的多线程处理没有太大关系。
另外请注意,即使使用多个线程发出绘图命令,它们也将由Direct3D驱动程序序列化并按顺序执行。一些较新的图形API,如Direct3D12和Vulkan,确实提供了多线程驱动程序,允许您从不同的线程中有效地绘制不同的内容,但它们具有更高的复杂性。
因此,如果最终坚持使用Direct2D,则可以选择使用单个线程按顺序绘制每个形状。
但可以做的是,通过测试每个形状与所有其他形状的遮挡情况,可以消除有效遮挡的形状。因此,被遮挡的形状可以从列表中丢弃,并且永远不会渲染。这里的技巧是,由于透明区域(如文本)或形状是复杂的多边形,一些形状没有完全填充其边界rect。这样的形状不容易测试,或者需要更复杂的算法。
因此,您必须迭代所有形状,如果当前形状是矩形,则仅对所有以前形状的边界矩形执行遮挡测试。
下面的代码应该被视为伪代码,它只是用来演示这个想法。
#define RECTANGLE 0
#define TEXT 1
#define TRIANGLE 2
//etc
typedef struct {
int type; //We have a type field
Rect bounds_rect; //Bounds rect
Rect coordinates; //Coordinates, which count vary according to shape type
//Probably you have many other fields here
} Shape;
//We have all shapes in a vector
std::vector<Shape> shapes;
迭代所有形状。
for (int i=1; i<shapes.size; i++) {
if(shape[i].type != RECTANGLE) {
//We will not perform testing if the current shape is not rectangle.
continue;
}
for(int j=0; j<i; j++) {
if(isOccluded(&shape[j], &shape[i])) {
//shape[j] is totally invisible, so remove it from 'shapes' list
}
}
}
遮挡测试类似于
bool isOccluded(Shape *a, Shape *b) {
return (a.bounds_rect.left > b.coordinates.left && a.bounds_rect.right < b.coordinates.right &&
a.bounds_rect.top > b.coordinates.to && a.bounds_rect.bottom < b.coordinates.bottom);
}
您不必用一个线程迭代所有形状,您可以创建多个线程来对形状列表的不同部分执行测试。当然,在从列表中删除形状时,您需要一些锁定技术,如互斥锁,但这是另一个主题。
深度缓冲区用于丢弃将在3D空间中被其前面的东西遮挡的基元,通过不去处理无论如何都看不到的东西来节省重画时间。如果你想象一个场景,面对镜头的球前面有一根又高又细的蜡烛,整个球没有画出来,然后蜡烛画在上面,只有球的可见边。这就是为什么图纸顺序与无关
我没有听说过在D2D中使用深度缓冲区,因为它有点毫无意义;在D2D中,所有的东西都被画在一个平面上,怎么会有东西在其他东西的前面或后面?API可能支持它,但我对此表示怀疑,因为它没有抽象的意义。每个形状上的深度信息只是绘制它的顺序,本质上你已经有了
相反,你可以做的是,在维持秩序的同时,将你的形状划分并分配给你的线程,即
t1 { shape1, shape2, shape3 } = shape123
t2 { shape4, shape5, shape6 } = shape456
...
并将形状绘制到一个新对象上(但不是后缓冲区),根据您的形状类,您可能能够将结果表示为一个形状。这将给你留下许多仍然有序但已经并行计算的形状。然后,你可以通过按顺序绘制结果(即)来逐渐合成你的最终结果
t1 { shape123, shape456, shape789 }
t2 { shape101112, shape131415 }
t1 { shape123456789, shape101112131415 } = final shape
现在你有了最终的形状,你可以把它画成普通的
- 深度缓冲区未填充阴影贴图渲染通道中的数据
- 从OpenGL应用程序中提取颜色/深度缓冲区
- 为什么为什么偏离gl_fragcoord.z偏离深度缓冲区
- DirectX-启用深度缓冲区后没有任何渲染
- OpenGL - 深度缓冲区在渲染半透明立方体时剪切掉不应该剪切的面
- C++深度缓冲区Oculus Rift DK2 VR HMD
- 多采样框架渲染对象和深度缓冲区
- GlReadPixel始终从深度缓冲区0中获取
- 有没有办法访问OpenGL的深度缓冲区
- Qopenglwidget和GlreadPixels和深度缓冲区
- 深度缓冲区的绝对距离
- 弄乱了OpenGL深度缓冲区
- OpenGL:只获取模具缓冲区而不获取深度缓冲区
- 使用帧缓冲区将深度缓冲区渲染到纹理中
- 是否可以在opengl中使用深度缓冲区渲染3D纹理
- Direct2D深度缓冲区
- OpenGL ES深度缓冲区渲染(iOS模拟器与真实设备)
- 深度缓冲区未正确渲染
- 将深度呈现缓冲区复制到深度缓冲区
- 为什么我们必须在渲染过程中清除 OpenGL 中的深度缓冲区