Switch to using a viewport matrix
This commit is contained in:
parent
3e414881d9
commit
f77fa5694b
68
src/obj.c
68
src/obj.c
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define TRIANGLE_VERTICES 3
|
#define TRIANGLE_VERTICES 3
|
||||||
#define CAMERA_DISTANCE 5.0f
|
#define CAMERA_DISTANCE 5.0f
|
||||||
|
#define DEPTH_MAX 255
|
||||||
|
|
||||||
#define V2(T, ELEM_T, X0, Y0, X1, Y1) \
|
#define V2(T, ELEM_T, X0, Y0, X1, Y1) \
|
||||||
((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
|
((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
|
||||||
@ -106,14 +107,13 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
|||||||
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
V2f coordinates[TRIANGLE_VERTICES], Colour colour,
|
||||||
Image *texture, RenderType type);
|
Image *texture, RenderType type);
|
||||||
internal M4x4f lookat(V3f eye, V3f target, V3f up);
|
internal M4x4f lookat(V3f eye, V3f target, V3f up);
|
||||||
|
internal M4x4f viewport(f32 x, f32 y, u64 w, u64 h);
|
||||||
internal TriangleBBox get_triangle_bbox(const Image *img,
|
internal TriangleBBox get_triangle_bbox(const Image *img,
|
||||||
V3f vertices[TRIANGLE_VERTICES]);
|
V3f vertices[TRIANGLE_VERTICES]);
|
||||||
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
||||||
const V2i *ab, const V2i *ac,
|
const V2i *ab, const V2i *ac,
|
||||||
const V2i *ap);
|
const V2i *ap);
|
||||||
internal void get_image_coordinates(f32 norm_x, f32 norm_y, const Image *img,
|
internal V3f get_viewport_vertex(V3f vertex, const Image *img);
|
||||||
u64 *x, u64 *y);
|
|
||||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max);
|
|
||||||
|
|
||||||
V3f g_light_dir = {0.0f, 0.0f, 1.0f};
|
V3f g_light_dir = {0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
@ -293,14 +293,15 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
|
|||||||
if (type == RENDER_TYPE_WIREFRAME) {
|
if (type == RENDER_TYPE_WIREFRAME) {
|
||||||
V3f v0, v1;
|
V3f v0, v1;
|
||||||
u64 x0, y0, x1, y1;
|
u64 x0, y0, x1, y1;
|
||||||
|
V3f vp0, vp1;
|
||||||
for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
|
for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
|
||||||
v0 = vertices[i];
|
v0 = vertices[i];
|
||||||
v1 = vertices[(i + 1) % TRIANGLE_VERTICES];
|
v1 = vertices[(i + 1) % TRIANGLE_VERTICES];
|
||||||
|
|
||||||
get_image_coordinates(v0.x, v0.y, img, &x0, &y0);
|
vp0 = get_viewport_vertex(v0, img);
|
||||||
get_image_coordinates(v1.x, v1.y, img, &x1, &y1);
|
vp1 = get_viewport_vertex(v1, img);
|
||||||
|
|
||||||
draw_line(img, x0, y0, x1, y1, colour);
|
draw_line(img, (u64)vp0.x, (u64)vp0.y, (u64)vp1.x, (u64)vp1.y, colour);
|
||||||
}
|
}
|
||||||
} else if (type == RENDER_TYPE_FILLED || type == RENDER_TYPE_SHADED) {
|
} else if (type == RENDER_TYPE_FILLED || type == RENDER_TYPE_SHADED) {
|
||||||
fill_triangle(render, vertices, normals, coordinates, colour,
|
fill_triangle(render, vertices, normals, coordinates, colour,
|
||||||
@ -316,10 +317,9 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES],
|
|||||||
Depth *depth = &(render->depth);
|
Depth *depth = &(render->depth);
|
||||||
TriangleBBox bbox = get_triangle_bbox(img, vertices);
|
TriangleBBox bbox = get_triangle_bbox(img, vertices);
|
||||||
|
|
||||||
V2u v0, v1, v2;
|
V3f v0 = get_viewport_vertex(vertices[0], img);
|
||||||
get_image_coordinates(vertices[0].x, vertices[0].y, img, &(v0.x), &(v0.y));
|
V3f v1 = get_viewport_vertex(vertices[1], img);
|
||||||
get_image_coordinates(vertices[1].x, vertices[1].y, img, &(v1.x), &(v1.y));
|
V3f v2 = get_viewport_vertex(vertices[2], img);
|
||||||
get_image_coordinates(vertices[2].x, vertices[2].y, img, &(v2.x), &(v2.y));
|
|
||||||
|
|
||||||
V2i ab = V2(V2i, i64, v0.x, v0.y, v1.x, v1.y);
|
V2i ab = V2(V2i, i64, v0.x, v0.y, v1.x, v1.y);
|
||||||
V2i ac = V2(V2i, i64, v0.x, v0.y, v2.x, v2.y);
|
V2i ac = V2(V2i, i64, v0.x, v0.y, v2.x, v2.y);
|
||||||
@ -416,6 +416,22 @@ internal M4x4f lookat(V3f eye, V3f target, V3f up) {
|
|||||||
return mat4x4_mul(rotation, translation);
|
return mat4x4_mul(rotation, translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal M4x4f viewport(f32 x, f32 y, u64 w, u64 h) {
|
||||||
|
M4x4f output = mat4x4_identity;
|
||||||
|
|
||||||
|
f32 half_width = (f32)w * 0.5f;
|
||||||
|
f32 half_height = (f32)h * 0.5f;
|
||||||
|
f32 half_depth = (f32)DEPTH_MAX * 0.5f;
|
||||||
|
|
||||||
|
output.row0.x = half_width;
|
||||||
|
output.row0.w = x + half_width;
|
||||||
|
output.row1.y = half_height;
|
||||||
|
output.row1.w = y + half_height;
|
||||||
|
output.row2.z = output.row2.w = half_depth;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
internal TriangleBBox get_triangle_bbox(const Image *img,
|
internal TriangleBBox get_triangle_bbox(const Image *img,
|
||||||
V3f vertices[TRIANGLE_VERTICES]) {
|
V3f vertices[TRIANGLE_VERTICES]) {
|
||||||
f32 x0 = min(vertices[0].x, min(vertices[1].x, vertices[2].x));
|
f32 x0 = min(vertices[0].x, min(vertices[1].x, vertices[2].x));
|
||||||
@ -425,11 +441,15 @@ internal TriangleBBox get_triangle_bbox(const Image *img,
|
|||||||
f32 y0 = max(vertices[0].y, max(vertices[1].y, vertices[2].y));
|
f32 y0 = max(vertices[0].y, max(vertices[1].y, vertices[2].y));
|
||||||
f32 y1 = min(vertices[0].y, min(vertices[1].y, vertices[2].y));
|
f32 y1 = min(vertices[0].y, min(vertices[1].y, vertices[2].y));
|
||||||
|
|
||||||
TriangleBBox bbox = {0};
|
V3f minimum = get_viewport_vertex((V3f){x0, y0, 0.0f}, img);
|
||||||
get_image_coordinates(x0, y0, img, &(bbox.x0), &(bbox.y0));
|
V3f maximum = get_viewport_vertex((V3f){x1, y1, 0.0f}, img);
|
||||||
get_image_coordinates(x1, y1, img, &(bbox.x1), &(bbox.y1));
|
|
||||||
|
|
||||||
return bbox;
|
return (TriangleBBox){
|
||||||
|
.x0 = minimum.x,
|
||||||
|
.y0 = minimum.y,
|
||||||
|
.x1 = maximum.x,
|
||||||
|
.y1 = maximum.y,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
||||||
@ -449,20 +469,8 @@ internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
|
|||||||
return (V3f){v, w, u};
|
return (V3f){v, w, u};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void get_image_coordinates(f32 norm_x, f32 norm_y, const Image *img,
|
internal V3f get_viewport_vertex(V3f vertex, const Image *img) {
|
||||||
u64 *x, u64 *y) {
|
V4f vh = {.x = vertex.x, .y = 0.0f - vertex.y, .z = vertex.z, .w = 1.0f};
|
||||||
*x = ndc_to_image_coordinate(norm_x, img->width);
|
vh = mat4x4_mul_vec4(viewport(vh.x, vh.y, img->width, img->height), vh);
|
||||||
*y = ndc_to_image_coordinate(0.0f - norm_y, img->height);
|
return project_vec4(vh);
|
||||||
|
|
||||||
if (*x >= img->width) {
|
|
||||||
*x = img->width - 1;
|
|
||||||
}
|
|
||||||
if (*y >= img->height) {
|
|
||||||
*y = img->height - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max) {
|
|
||||||
f32 result = (value + 1.0f) * max * 0.5f;
|
|
||||||
return clamp((u64)result, 0, max);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user