Ответ 1
Есть ли способ использовать буфер глубины в Direct2D или аналогичный техника, которая позволяет мне использовать несколько потоков для рисования формы?
Ответ здесь нет. Хотя библиотека Direct2D построена поверх Direct3D, она не предоставляет пользователю такую функцию через API, поскольку примитивы, которые вы можете рисовать, описываются только двумерными координатами. Последний примитив, который вы рисуете для цели рендеринга, становится видимым, поэтому не проводится глубокое тестирование. Кроме того, буфер глубины в Direct3D не имеет большого отношения к многопоточности на стороне процессора.
Также обратите внимание, что даже если вы выдаете команды рисования с использованием нескольких потоков, они будут сериализованы драйвером Direct3D и выполняться последовательно. Некоторые новые графические API, такие как Direct3D 12 и Vulkan, предоставляют многопоточные драйверы, которые позволяют эффективно использовать различный контент из разных потоков, но они имеют более высокую сложность.
Итак, в конце концов, если вы придерживаетесь Direct2D, вы останетесь с возможностью рисования каждой фигуры последовательно с использованием одного потока.
Но что можно сделать, так это то, что вы можете исключить эффективно окклюдированные фигуры, проверяя окклюзию каждой фигуры против всех остальных. Таким образом, окклюдированные формы могут быть отброшены из списка и никогда не отображаться вообще. Трюк здесь заключается в том, что некоторые формы не заполняют свои границы полностью, из-за прозрачных областей (например, текста) или если фигура является сложным многоугольником. Такие формы не могут быть легко протестированы или потребуются более сложные алгоритмы.
Итак, вам нужно выполнить итерацию всех фигур, а если текущая форма - это прямоугольник, тогда выполните тестирование окклюзии со всеми предыдущими формами bounds 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;
Итерировать все фигуры.
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);
}
И вам не нужно перебирать все фигуры с помощью одного потока, вы можете создавать несколько потоков для выполнения тестов для разных частей списка фигур. Конечно, вам понадобится некоторая технология блокировки, такая как мьютекс при удалении фигур из списка, но это еще одна тема.