Is there a way to use the depth buffer in Direct2D, or a similar
technique which allows me the use of multiple threads to draw my
shapes?
The answer here is no. Althought the Direct2D library is built on top of Direct3D, it doesn't provide the user such feature through the API, since the primitives you can draw are only described by two-dimensional coordinates. The last primitive you draw to the render target is ensured to be visible, so no depth testing is taking place. Also, the depth buffer in Direct3D doesn't have much to do with multi-threading on the CPU side.
Also note that even if you are issuing drawing commands using multiple threads they will be serialized by the Direct3D driver and performed sequentially. Some newer graphical APIs like Direct3D 12 and Vulkan does provide multithreaded drivers which allows you to effectively draw different content from different threads, but they come with higher complexity.
So eventually if you stick to Direct2D you are left with the option of drawing each shape sequentially using a single thread.
But what can be done is that you can eliminate the effectively occluded shapes by testing for occlusion each shape against all others. So the occluded shapes can be discarded from the list and never rendered at all. The trick here is that some of the shapes does not fill their bounds rect entirely, due to transparent regions (like text) or if the shape is a complex polygon. Such shapes can not be easily tested or will need more complex algorithms.
So you have to iterate thourgh all shapes and if the current shape is a rectangle only then perform occlusion testing with all previous shapes' bounds rects.
The following code should be considered pseudo-code, it is intended just to demonstrates the idea.
#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;
Iterate all 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
}
}
}
Occlusion testing is something like this
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);
}
And you don't have to iterate all shapes with a single thread, you can create multiple threads to perform tests for different parts of the shape list. Of course you will need some locking technique like mutex when deleting shapes from the list, but that is another topic.
Direct2D
itself - but typically you will assign the shape az
coord, sort by that coord and then render respectively, thereby implementing a simple Z-buffer. – GuidanceEndDraw
), so doing that from threads directly is not going to work out anyway because you are supposed to serialize the calls (or have them serialized by the implementation which is pretty much the same). – Implosive