Nic*_*ick 10 c++ directx direct3d direct2d depth-buffer
我需要绘制一个形状列表,我正在使用Direct2D.我从文件中获取形状列表.列表已排序,文件中元素的顺序表示将绘制这些形状的顺序.所以,如果例如文件指定在相同的位置和相同大小的两个矩形,只有第二个将是可见的(因为第一将被覆盖).
鉴于我的形状列表,我按以下方式进行绘图:
list<Shape> shapes;
for (const auto& shape : shapes)
shape.draw();
Run Code Online (Sandbox Code Playgroud)
很容易看出,如果我有两个形状,我无法反转绘图操作的顺序,这意味着我必须确保shape2将始终绘制shape1,依此类推.接下来我无法使用多个线程来绘制我的形状,这在性能方面是一个巨大的劣势.
我读到Direct3D支持深度缓冲区(或z缓冲区),它为每个像素指定了它的z坐标,这样只会绘制"可见"像素(更接近观察者的on),无论顺序如何形状是绘制的.当我读取文件时,我有每个形状的深度信息.
有没有办法在Direct2D中使用深度缓冲区,或类似的技术允许我使用多个线程来绘制我的形状?
有没有办法在 Direct2D 中使用深度缓冲区,或者允许我使用多个线程来绘制形状的类似技术?
这里的答案是否定的。尽管 Direct2D 库构建在 Direct3D 之上,但它并不通过 API 向用户提供此类功能,因为您可以绘制的图元仅由二维坐标描述。确保绘制到渲染目标的最后一个图元可见,因此不会进行深度测试。另外,Direct3D 中的深度缓冲区与 CPU 端的多线程没有太大关系。
另请注意,即使您使用多个线程发出绘图命令,它们也会由 Direct3D 驱动程序序列化并按顺序执行。一些较新的图形 API(例如Direct3D 12和Vulkan)确实提供了多线程驱动程序,允许您有效地从不同线程绘制不同的内容,但它们具有更高的复杂性。
因此,如果您坚持使用 Direct2D,最终您可以选择使用单个线程按顺序绘制每个形状。
但可以做的是,您可以通过测试每个形状与所有其他形状的遮挡来消除有效遮挡的形状。因此,被遮挡的形状可以从列表中丢弃,并且根本不会渲染。这里的技巧是,由于透明区域(如文本)或形状是复杂的多边形,某些形状不会完全填充其边界矩形。这种形状不容易测试或者需要更复杂的算法。
因此,您必须迭代所有形状,如果当前形状是矩形,则仅对所有先前形状的边界 rects执行遮挡测试。
以下代码应被视为伪代码,其目的只是为了演示该想法。
#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;
Run Code Online (Sandbox Code Playgroud)
迭代所有形状。
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
遮挡测试是这样的
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);
}
Run Code Online (Sandbox Code Playgroud)
而且您不必使用单个线程迭代所有形状,您可以创建多个线程来对形状列表的不同部分执行测试。当然,从列表中删除形状时,您将需要一些锁定技术,例如互斥锁,但这是另一个主题。