Depth Testing
If I try to render a cube right now Some of the fragments will be fighting to be displayed even thought they are behind other fragments. I will fix this with a simple depth test buffer.
Depth Buffer
The depth buffer is a buffer similar to the pixel buffer but its only purpose is to store the z value of the fragment that is the closest to the camera/view.
Every time that I want to draw a fragment/pixel, I check if the current fragment’s z value is closer to the view (smaller z). If it does not pass the test, the fragment is discarded. Otherwise, the fragment is painted and the depth buffer in that coordinate is updated.
struct Renderer {
// Previously...
bool ready;
uint32_t *pixels;
int width, height;
int windowWidth, windowHeight;
int pixelScale;
// New buffer
float *zBuffer;
};
Now, when I set the pixels or clear the screen I need to update the zBuffer:
void Renderer_ClearBackground(Renderer *r, uint32_t color) {
if (r == nullptr) {
return;
}
for (int i = 0; i < r->width * r->height; i++) {
r->pixels[i] = color;
r->zBuffer[i] = std::numeric_limits<float>::infinity();
}
}
void Renderer_SetPixel(Renderer *r, int x, int y, float z, uint32_t color) {
if (r == nullptr) {
return;
}
if (x < 0 || x >= r->width || y < 0 || y >= r->height)
return;
int idx = y * r->width + x;
if (z < r->zBuffer[idx]) {
r->zBuffer[idx] = z;
r->pixels[idx] = color;
}
}
Finally I can draw a Cube:
Vec3 position = Vec3{0.0f, 0.0f, 0.0f};
Vec3 rotation = Vec3{0.0f, 0.0f, 0.0f};
Vec3 scale = Vec3{1.0f, 1.0f, 1.0f};
ColorRGBA color = ColorRGBA{1.0f, 0.5f, 0.31f};
Renderer_DrawCube(&gRenderer, position, rotation, scale, color);
Right now it is difficult to identify the different faces of the cube because each of pixel has the same color.
In the next chapter I will add basic lighting to each fragment and by the end of that chapter I will be able to see the different faces of the cube.