有没有一种使用Direct2D深度缓冲区或类似技术的方法,允许我使用多个线程绘制我的形状?
答案是没有。虽然Direct2D库是建立在Direct3D之上的,但它不通过API提供用户这样的功能,因为您可以绘制的基本图形仅由二维坐标描述。您绘制到渲染目标的最后一个基元保证可见,因此不进行深度测试。此外,Direct3D中的深度缓冲区与CPU方面的多线程处理关系不大。
还要注意,即使您正在使用多个线程发出绘图命令,它们也将被Direct3D驱动程序序列化并按顺序执行。一些新的图形API(如Direct3D 12和Vulkan)确实提供了多线程驱动程序,允许您有效地从不同的线程绘制不同的内容,但它们具有更高的复杂性。
如果您坚持使用Direct2D,最后只能使用单个线程逐个绘制每个形状。
但可以通过测试每个形状与其他所有形状的遮挡情况来消除实际上被遮挡的形状。因此,遮挡的形状可以从列表中丢弃,并且根本不会被渲染。这里的诀窍是,由于透明区域(如文本)或者形状是复杂的多边形,有些形状无法完全填充其边界矩形,因此不能轻松地进行测试,或者需要更复杂的算法。
因此,您必须遍历全部形状,如果当前形状是矩形,则只需对其前面所有形状的边界矩形进行遮挡测试。
以下代码应被视为伪代码,旨在演示该思想。
#define RECTANGLE 0
#define TEXT 1
#define TRIANGLE 2
typedef struct {
int type;
Rect bounds_rect;
Rect coordinates;
} Shape;
std::vector<Shape> shapes;
迭代所有形状。
for (int i=1; i<shapes.size; i++) {
if(shape[i].type != RECTANGLE) {
continue;
}
for(int j=0; j<i; j++) {
if(isOccluded(&shape[j], &shape[i])) {
}
}
}
遮挡测试就像这样。
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);
}
您不需要使用单个线程迭代所有形状,可以创建多个线程来测试形状列表的不同部分。当从列表中删除形状时,当然需要一些锁定技术,如互斥锁,但这是另一个话题。
Direct2D
本身不是很确定 - 但通常你会给形状分配一个z
坐标,按照该坐标进行排序,然后相应地进行渲染,从而实现简单的 Z 缓冲。 - rhughesEndDraw
中),所以直接从线程中执行这些操作不会奏效,因为你应该序列化这些调用(或者让实现进行序列化,这几乎是一样的)。 - Roman R.