13 :
width(
w), height(
h), z_buffer(
w *
h, 1.0f), normal_buffer(
w *
h,
Vec3(0.0f)) {}
28static float view_distance_from_ndc(
float z_ndc,
float z_near,
float z_far,
30 if (!(z_far > z_near) || z_near <= 0.0f) {
38 return (
z_ndc * (z_far - z_near) + (z_far + z_near)) * 0.5f;
44 const float denom = (z_far + z_near) -
z_ndc * (z_far - z_near);
45 if (std::abs(
denom) < 1e-12f)
return z_far;
46 return (2.0f * z_near * z_far) /
denom;
76 if (b.x < a.x || (b.x == a.x && b.y < a.y)) {
82void Rasterizer::shade_and_write(
int x,
int y,
float depth,
83 const Color &color,
const Vec3 &normal,
101 }
else if (
lights.empty()) {
110 auto apply_contrast = [&](
float v) {
111 return std::clamp((
v - 0.5f) *
contrast + 0.5f, 0.0f, 1.0f);
131 if (std::abs(
span) < 1e-12f) {
147 float src_a = a / 255.0f;
166 bool backface_culling,
170 const Color &wireframe_color,
176 if (backface_culling &&
area > 0.0f)
179 if (std::abs(
area) < 1e-12f)
203 int x_start = std::max(0,
static_cast<int>(std::floor(
min_x)));
205 int y_start = std::max(0,
static_cast<int>(std::floor(
min_y)));
232#pragma omp parallel for if((y_end - y_start) > 16) schedule(static)
236 float px =
static_cast<float>(
x) + 0.5f;
237 float py =
static_cast<float>(
y) + 0.5f;
254 if (
w0 < 0.0f ||
w1 < 0.0f ||
w2 < 0.0f)
273 static_cast<uint8_t>(std::clamp(wireframe_color.
r, 0.0f, 1.0f) * 255.0f),
274 static_cast<uint8_t>(std::clamp(wireframe_color.
g, 0.0f, 1.0f) * 255.0f),
275 static_cast<uint8_t>(std::clamp(wireframe_color.
b, 0.0f, 1.0f) * 255.0f),
276 static_cast<uint8_t>(std::clamp(wireframe_color.
a, 0.0f, 1.0f) * 255.0f));
332 int cx =
static_cast<int>(std::floor(
screen_x));
333 int cy =
static_cast<int>(std::floor(
screen_y));
334 int r =
static_cast<int>(std::ceil(
radius));
337 for (
int dy = -r;
dy <= r; ++
dy) {
340 for (
int dx = -r;
dx <= r; ++
dx) {
364 const float span = std::max(std::abs(
dx), std::abs(
dy));
365 const int steps = std::max(1,
static_cast<int>(std::ceil(
span)));
375 const float t =
static_cast<float>(
i) /
static_cast<float>(
steps);
383 const int cx =
static_cast<int>(std::lround(
sx));
384 const int cy =
static_cast<int>(std::lround(
sy));
394 const float ox =
static_cast<float>(
px -
cx);
395 const float oy =
static_cast<float>(
py -
cy);
422 const float dirs[
ns][2] = {
423 { 0.309f, 0.951f}, {-0.809f, 0.588f}, { 1.000f, -0.000f}, { 0.809f, -0.588f},
424 {-0.309f, -0.951f}, { 0.588f, 0.809f}, {-0.588f, 0.809f}, {-1.000f, -0.000f},
455 for (
int s = 0;
s <
ns; ++
s) {
499 ao = std::max(0.0f, std::min(1.0f,
ao));
Low-level math utilities for the rendering pipeline.
glm::vec2 Vec2
2-component floating-point vector (xy).
glm::vec3 Vec3
3-component floating-point vector (xyz).
Color shade_pixel(const Color &base_color, const Vec3 &normal, const Vec3 &light_direction, const Color &specular_color=Color(0, 0, 0, 0), float shininess=0.0f)
Compute the shaded color of a pixel with a single directional light.
Color shade_pixel_multi(const Color &base_color, const Vec3 &normal, const std::vector< Light > &lights, float ambient, const Color &specular_color=Color(0, 0, 0, 0), float shininess=0.0f)
Compute the shaded color with multiple light sources.
@ WORLD
World units: distance from the camera, measured along the camera's viewing direction.
The Rasterizer — the per-pixel rendering engine.
An RGBA color with floating-point components.
float g
Green channel, [0, 1].
float r
Red channel, [0, 1].
float b
Blue channel, [0, 1].
float a
Alpha (opacity) channel, [0, 1]. 1.0 = fully opaque.
Color sample_bilinear(float u, float v) const
Sample the image at texture coordinates (u, v) using bilinear interpolation.
void rasterize_line(const Vec3 &screen_v0, const Color &color0, const Vec3 &screen_v1, const Color &color1, float width, bool lit, const Vec3 &normal, const Vec3 &light_direction, Image &output)
Rasterize a line segment with a screen-space width.
float ssao_radius
SSAO sample radius in pixels (default: 16).
void clear(float clear_depth=1.0f)
Clear the depth and normal buffers.
void rasterize_point(float screen_x, float screen_y, float depth, float radius, const Color &color, const Vec3 &normal, const Vec3 &light_direction, Image &output)
Rasterize a single point (filled circle) into the output image.
float fog_end
Distance where fog is fully opaque (default: 1).
Color fog_color
The fog color (what distant objects blend into).
bool fog_enabled
Enable depth fog (default: false).
FogSpace fog_space
The space (and unit) of fog_start / fog_end (default: FogSpace::WORLD).
float z_far
Far plane distance of the current projection (default: 10000.0).
float fog_depth_from_ndc(float z_ndc) const
Convert a depth-buffer value to a distance in world units.
float fog_start
Distance where fog begins (default: 0).
bool orthographic
Whether the current projection is orthographic (default: false).
Rasterizer(int w, int h)
Construct a rasterizer for the given output size.
void apply_ssao(Image &output, float z_near, float z_far)
Apply screen-space ambient occlusion to the output image.
int height
Output image height in pixels.
Image * active_texture
Optional texture image for textured meshes.
float ssao_intensity
SSAO darkening intensity (0.0–1.0, default: 0.8).
float ambient
Ambient light level (0.0–1.0, default: 0.3).
int width
Output image width in pixels.
Color specular_color
Specular highlight color.
std::vector< Light > lights
Light sources for Blinn-Phong shading.
float shininess
Shininess exponent (Phong model).
void rasterize_triangle(const Vec3 &screen_v0, const Color &color0, const Vec3 &normal0, const Vec2 &uv0, const Vec3 &screen_v1, const Color &color1, const Vec3 &normal1, const Vec2 &uv1, const Vec3 &screen_v2, const Color &color2, const Vec3 &normal2, const Vec2 &uv2, bool backface_culling, bool smooth_shading, const Vec3 &light_direction, bool wireframe, const Color &wireframe_color, Image &output)
Rasterize a single triangle into the output image.
bool ssao_enabled
Enable SSAO (default: false).
float z_near
Near plane distance of the current projection (default: 0.1).
std::vector< float > z_buffer
Z-buffer (depth buffer), one float per pixel.
bool blend_mode
Enable alpha blending for transparent triangles (default: false).
float contrast
Contrast adjustment (1.0 = no change).
std::vector< Vec3 > normal_buffer
Normal buffer, one Vec3 per pixel.
int y
Top edge of the bitmap, in image pixels.
int x
Left edge of the bitmap, in image pixels.