summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-02-08 07:57:14 -0800
committer3gg <3gg@shellblade.net>2024-02-08 07:57:14 -0800
commitdda4b3e598c7c955a44e3874bf2c57bd16b1c3ea (patch)
tree5594286527fd83a480421f1aac339f50a77eefca
parent32897d35fa724e46e4195927d385da4e35ac7c76 (diff)
Add AABB2 and matrix stack to immediate-mode renderer.
-rw-r--r--gfx/include/gfx/renderer.h23
-rw-r--r--gfx/include/gfx/sizes.h3
-rw-r--r--gfx/src/renderer/imm_renderer.c120
-rw-r--r--gfx/src/renderer/imm_renderer_impl.h6
4 files changed, 131 insertions, 21 deletions
diff --git a/gfx/include/gfx/renderer.h b/gfx/include/gfx/renderer.h
index 13e6c2c..c420889 100644
--- a/gfx/include/gfx/renderer.h
+++ b/gfx/include/gfx/renderer.h
@@ -1,5 +1,6 @@
1#pragma once 1#pragma once
2 2
3#include <math/aabb2.h>
3#include <math/aabb3.h> 4#include <math/aabb3.h>
4#include <math/camera.h> 5#include <math/camera.h>
5#include <math/mat4.h> 6#include <math/mat4.h>
@@ -56,13 +57,31 @@ void gfx_imm_draw_triangles(ImmRenderer*, const vec3[], size_t num_triangles);
56void gfx_imm_draw_triangle(ImmRenderer*, const vec3[3]); 57void gfx_imm_draw_triangle(ImmRenderer*, const vec3[3]);
57 58
58/// Draw a bounding box. 59/// Draw a bounding box.
59void gfx_imm_draw_aabb(ImmRenderer*, aabb3); 60void gfx_imm_draw_aabb2(ImmRenderer*, aabb2);
61
62/// Draw a bounding box.
63void gfx_imm_draw_aabb3(ImmRenderer*, aabb3);
60 64
61/// Set the camera. 65/// Set the camera.
62void gfx_imm_set_camera(ImmRenderer*, const Camera*); 66void gfx_imm_set_camera(ImmRenderer*, const Camera*);
63 67
64/// Set the model matrix. 68/// Load an identity model matrix. Clears the matrix stack.
69void gfx_imm_load_identity(ImmRenderer* renderer);
70
71/// Push the given matrix to the matrix stack.
72void gfx_imm_push_matrix(ImmRenderer* renderer, const mat4* matrix);
73
74/// Pop the top of the matrix stack.
75void gfx_imm_pop_matrix(ImmRenderer* renderer);
76
77/// Push a translation matrix to the matrix stack.
78void gfx_imm_translate(ImmRenderer* renderer, vec3 offset);
79
80/// Set the model matrix. Clears the matrix stack.
65void gfx_imm_set_model_matrix(ImmRenderer*, const mat4*); 81void gfx_imm_set_model_matrix(ImmRenderer*, const mat4*);
66 82
83/// Set the view-projection matrix.
84void gfx_imm_set_view_projection_matrix(ImmRenderer*, const mat4*);
85
67/// Set the render colour. 86/// Set the render colour.
68void gfx_imm_set_colour(ImmRenderer*, vec4 colour); 87void gfx_imm_set_colour(ImmRenderer*, vec4 colour);
diff --git a/gfx/include/gfx/sizes.h b/gfx/include/gfx/sizes.h
index 9f13e30..f2ace8a 100644
--- a/gfx/include/gfx/sizes.h
+++ b/gfx/include/gfx/sizes.h
@@ -80,6 +80,9 @@
80/// frame. 80/// frame.
81#define IMM_MAX_NUM_TRIANGLES 1024 81#define IMM_MAX_NUM_TRIANGLES 1024
82 82
83/// Maximum number of matrices in the immediate-mode renderer's matrix stack.
84#define IMM_MAX_NUM_MATRICES 32
85
83// Gfx. 86// Gfx.
84 87
85#define GFX_MAX_NUM_SCENES 4 88#define GFX_MAX_NUM_SCENES 4
diff --git a/gfx/src/renderer/imm_renderer.c b/gfx/src/renderer/imm_renderer.c
index 12b642c..492c7af 100644
--- a/gfx/src/renderer/imm_renderer.c
+++ b/gfx/src/renderer/imm_renderer.c
@@ -33,6 +33,9 @@ bool imm_renderer_make(ImmRenderer* renderer, RenderBackend* render_backend) {
33 goto cleanup; 33 goto cleanup;
34 } 34 }
35 35
36 renderer->matrix_stack[0] = mat4_id();
37 renderer->stack_pointer = 0;
38
36 gfx_imm_set_colour(renderer, vec4_make(0.0, 0.0, 0.0, 1.0)); 39 gfx_imm_set_colour(renderer, vec4_make(0.0, 0.0, 0.0, 1.0));
37 40
38 return true; 41 return true;
@@ -79,17 +82,16 @@ void imm_renderer_flush(ImmRenderer* renderer) {
79void gfx_imm_start(ImmRenderer* renderer) { 82void gfx_imm_start(ImmRenderer* renderer) {
80 assert(renderer); 83 assert(renderer);
81 84
85 // Shader uniforms are applied lazily.
86 // TODO: In the event that gfx_activate_shader_program() activates uniforms
87 // automatically for convenience, call an overload here that doesn't do so.
82 ShaderProgram* shader = renderer->shader; 88 ShaderProgram* shader = renderer->shader;
83 gfx_activate_shader_program(shader); 89 gfx_activate_shader_program(shader);
84 // TODO: Having to apply manually is annoying. Maybe just apply implicitly 90
85 // when the program is activated? 91 // TODO: Move this to the gltf_view program.
86 // Note that then we'll need to be able to just gfx_apply_uniforms() in 92 // gfx_set_blending(renderer->render_backend, true);
87 // flush(). 93 // gfx_set_depth_mask(renderer->render_backend, false);
88 // gfx_set_culling(renderer->render_backend, false); 94 // gfx_set_polygon_offset(renderer->render_backend, 0.5f, 0.5f);
89 gfx_apply_uniforms(shader);
90 gfx_set_blending(renderer->render_backend, true);
91 gfx_set_depth_mask(renderer->render_backend, false);
92 gfx_set_polygon_offset(renderer->render_backend, 0.5f, 0.5f);
93} 95}
94 96
95void gfx_imm_end(ImmRenderer* renderer) { 97void gfx_imm_end(ImmRenderer* renderer) {
@@ -97,10 +99,11 @@ void gfx_imm_end(ImmRenderer* renderer) {
97 99
98 imm_renderer_flush(renderer); 100 imm_renderer_flush(renderer);
99 101
100 gfx_set_polygon_offset(renderer->render_backend, 0.0f, 0.0f); 102 // TODO: Move this to the gltf_view program.
101 gfx_set_depth_mask(renderer->render_backend, true); 103 // gfx_set_polygon_offset(renderer->render_backend, 0.0f, 0.0f);
102 gfx_set_blending(renderer->render_backend, false); 104 // gfx_set_depth_mask(renderer->render_backend, true);
103 // gfx_set_culling(renderer->render_backend, true); 105 // gfx_set_blending(renderer->render_backend, false);
106
104 gfx_deactivate_shader_program(renderer->shader); 107 gfx_deactivate_shader_program(renderer->shader);
105} 108}
106 109
@@ -123,9 +126,28 @@ void gfx_imm_draw_triangle(ImmRenderer* renderer, const vec3 verts[3]) {
123 gfx_imm_draw_triangles(renderer, verts, 1); 126 gfx_imm_draw_triangles(renderer, verts, 1);
124} 127}
125 128
126void gfx_imm_draw_aabb(ImmRenderer* renderer, aabb3 box) { 129void gfx_imm_draw_aabb2(ImmRenderer* renderer, aabb2 box) {
130 assert(renderer);
131
132 // clang-format off
133 const vec3 verts[4] = {
134 vec3_make(box.min.x, box.min.y, 0), // 3 ---- 2
135 vec3_make(box.max.x, box.min.y, 0), // | |
136 vec3_make(box.max.x, box.max.y, 0), // | |
137 vec3_make(box.min.x, box.max.y, 0)}; // 0 ---- 1
138 // clang-format on
139
140#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2]
141 const vec3 tris[6] = {tri(0, 1, 2), tri(0, 2, 3)};
142#undef tri
143
144 gfx_imm_draw_triangles(renderer, tris, 2);
145}
146
147void gfx_imm_draw_aabb3(ImmRenderer* renderer, aabb3 box) {
127 assert(renderer); 148 assert(renderer);
128 149
150 // clang-format off
129 const vec3 verts[8] = { 151 const vec3 verts[8] = {
130 box.min, // 2 ----- 6 152 box.min, // 2 ----- 6
131 vec3_make(box.min.x, box.min.y, box.max.z), // / /| 153 vec3_make(box.min.x, box.min.y, box.max.z), // / /|
@@ -135,9 +157,9 @@ void gfx_imm_draw_aabb(ImmRenderer* renderer, aabb3 box) {
135 vec3_make(box.max.x, box.min.y, box.max.z), // |/ |/ 157 vec3_make(box.max.x, box.min.y, box.max.z), // |/ |/
136 vec3_make(box.max.x, box.max.y, box.min.z), // 1 ----- 5 158 vec3_make(box.max.x, box.max.y, box.min.z), // 1 ----- 5
137 box.max}; 159 box.max};
160 // clang-format on
138 161
139#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2] 162#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2]
140
141 // TODO: Use vertex indices in Geometry. 163 // TODO: Use vertex indices in Geometry.
142 const vec3 tris[36] = {// Front. 164 const vec3 tris[36] = {// Front.
143 tri(1, 5, 7), tri(1, 7, 3), 165 tri(1, 5, 7), tri(1, 7, 3),
@@ -151,24 +173,84 @@ void gfx_imm_draw_aabb(ImmRenderer* renderer, aabb3 box) {
151 tri(3, 7, 6), tri(3, 6, 2), 173 tri(3, 7, 6), tri(3, 6, 2),
152 // Bottom. 174 // Bottom.
153 tri(0, 4, 5), tri(0, 5, 1)}; 175 tri(0, 4, 5), tri(0, 5, 1)};
176#undef tri
154 177
155 gfx_imm_draw_triangles(renderer, tris, 12); 178 gfx_imm_draw_triangles(renderer, tris, 12);
156} 179}
157 180
181// Load the top of the matrix stack into the shader.
182static void update_shader_model_matrix(ImmRenderer* renderer) {
183 assert(renderer);
184 imm_renderer_flush(renderer);
185 gfx_set_mat4_uniform(
186 renderer->shader, "Model",
187 &renderer->matrix_stack[renderer->stack_pointer]);
188}
189
190void gfx_imm_load_identity(ImmRenderer* renderer) {
191 assert(renderer);
192 renderer->matrix_stack[0] = mat4_id();
193 renderer->stack_pointer = 0;
194 update_shader_model_matrix(renderer);
195}
196
197void gfx_imm_push_matrix(ImmRenderer* renderer, const mat4* matrix) {
198 assert(renderer);
199 assert(matrix);
200 assert(renderer->stack_pointer >= 0);
201 assert(renderer->stack_pointer < IMM_MAX_NUM_MATRICES); // TODO: hard assert.
202
203 renderer->matrix_stack[renderer->stack_pointer + 1] =
204 mat4_mul(*matrix, renderer->matrix_stack[renderer->stack_pointer]);
205 renderer->stack_pointer += 1;
206
207 update_shader_model_matrix(renderer);
208}
209
210void gfx_imm_pop_matrix(ImmRenderer* renderer) {
211 assert(renderer);
212 assert(renderer->stack_pointer > 0); // TODO: hard assert.
213
214 // For debugging, zero out the matrix stack as matrices are popped out.
215 memset(
216 &renderer->matrix_stack[renderer->stack_pointer], 0,
217 sizeof(renderer->matrix_stack[0]));
218
219 renderer->stack_pointer -= 1;
220
221 update_shader_model_matrix(renderer);
222}
223
224void gfx_imm_translate(ImmRenderer* renderer, vec3 offset) {
225 assert(renderer);
226 const mat4 mat = mat4_translate(offset);
227 gfx_imm_push_matrix(renderer, &mat);
228}
229
158void gfx_imm_set_camera(ImmRenderer* renderer, const Camera* camera) { 230void gfx_imm_set_camera(ImmRenderer* renderer, const Camera* camera) {
159 assert(renderer); 231 assert(renderer);
160 assert(renderer->shader); 232 assert(renderer->shader);
161 imm_renderer_flush(renderer); 233 imm_renderer_flush(renderer);
162 const mat4 modelview = spatial3_inverse_transform(&camera->spatial); 234 const mat4 view = spatial3_inverse_transform(&camera->spatial);
163 const mat4 mvp = mat4_mul(camera->projection, modelview); 235 const mat4 view_proj = mat4_mul(camera->projection, view);
164 gfx_set_mat4_uniform(renderer->shader, "ViewProjection", &mvp); 236 gfx_imm_set_view_projection_matrix(renderer, &view_proj);
165} 237}
166 238
167void gfx_imm_set_model_matrix(ImmRenderer* renderer, const mat4* model) { 239void gfx_imm_set_model_matrix(ImmRenderer* renderer, const mat4* model) {
168 assert(renderer); 240 assert(renderer);
169 assert(model); 241 assert(model);
170 imm_renderer_flush(renderer); 242 imm_renderer_flush(renderer);
171 gfx_set_mat4_uniform(renderer->shader, "Model", model); 243 renderer->matrix_stack[0] = mat4_id();
244 renderer->stack_pointer = 0;
245 update_shader_model_matrix(renderer);
246}
247
248void gfx_imm_set_view_projection_matrix(
249 ImmRenderer* renderer, const mat4* view_proj) {
250 assert(renderer);
251 assert(renderer->shader);
252 imm_renderer_flush(renderer);
253 gfx_set_mat4_uniform(renderer->shader, "ViewProjection", view_proj);
172} 254}
173 255
174void gfx_imm_set_colour(ImmRenderer* renderer, vec4 colour) { 256void gfx_imm_set_colour(ImmRenderer* renderer, vec4 colour) {
diff --git a/gfx/src/renderer/imm_renderer_impl.h b/gfx/src/renderer/imm_renderer_impl.h
index 6f4b818..7769855 100644
--- a/gfx/src/renderer/imm_renderer_impl.h
+++ b/gfx/src/renderer/imm_renderer_impl.h
@@ -3,6 +3,7 @@
3#include <gfx/renderer.h> 3#include <gfx/renderer.h>
4#include <gfx/sizes.h> 4#include <gfx/sizes.h>
5 5
6#include <math/mat4.h>
6#include <math/vec3.h> 7#include <math/vec3.h>
7 8
8#include <stdbool.h> 9#include <stdbool.h>
@@ -26,6 +27,11 @@ typedef struct ImmRenderer {
26 bool wireframe : 1; 27 bool wireframe : 1;
27 } flags; 28 } flags;
28 vec3 triangle_verts[IMM_MAX_NUM_TRIANGLES * 3]; 29 vec3 triangle_verts[IMM_MAX_NUM_TRIANGLES * 3];
30 // Matrix stack contains pre-multiplied matrices.
31 // It is also never empty. The top of the stack is an identity matrix when the
32 // stack is "empty" from the user's perspective.
33 mat4 matrix_stack[IMM_MAX_NUM_MATRICES];
34 int stack_pointer;
29} ImmRenderer; 35} ImmRenderer;
30 36
31/// Create a new immediate mode renderer. 37/// Create a new immediate mode renderer.