aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asset/model.c5
-rw-r--r--src/core/core.c4
-rw-r--r--src/gfx.c24
-rw-r--r--src/llr/light.c2
-rw-r--r--src/llr/llr.c329
-rw-r--r--src/llr/llr_impl.h67
-rw-r--r--src/llr/material.c2
-rw-r--r--src/llr/material_impl.h5
-rw-r--r--src/llr/mesh.c2
-rw-r--r--src/renderer/imm_renderer.c192
-rw-r--r--src/renderer/imm_renderer_impl.h43
-rw-r--r--src/renderer/renderer.c46
-rw-r--r--src/renderer/renderer_impl.h6
-rw-r--r--src/scene/node.c2
-rw-r--r--src/scene/object.c2
-rw-r--r--src/scene/object_impl.h2
-rw-r--r--src/scene/scene_memory.c6
-rw-r--r--src/util/skyquad.c17
18 files changed, 406 insertions, 350 deletions
diff --git a/src/asset/model.c b/src/asset/model.c
index 402b2e1..0c57470 100644
--- a/src/asset/model.c
+++ b/src/asset/model.c
@@ -84,13 +84,12 @@
84#include "asset/texture.h" 84#include "asset/texture.h"
85#include "gfx/core.h" 85#include "gfx/core.h"
86#include "gfx/gfx.h" 86#include "gfx/gfx.h"
87#include "gfx/llr/material.h"
88#include "gfx/llr/mesh.h"
87#include "gfx/scene/animation.h" 89#include "gfx/scene/animation.h"
88#include "gfx/scene/camera.h" 90#include "gfx/scene/camera.h"
89#include "gfx/scene/material.h"
90#include "gfx/scene/mesh.h"
91#include "gfx/scene/node.h" 91#include "gfx/scene/node.h"
92#include "gfx/scene/object.h" 92#include "gfx/scene/object.h"
93#include "gfx/scene/scene.h"
94#include "gfx/sizes.h" 93#include "gfx/sizes.h"
95#include "gfx/util/shader.h" 94#include "gfx/util/shader.h"
96 95
diff --git a/src/core/core.c b/src/core/core.c
index 90038c6..e1671ea 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -420,6 +420,10 @@ void gfx_destroy_shader_program(GfxCore* gfxcore, ShaderProgram** prog) {
420 // Remove the shader program from the cache. 420 // Remove the shader program from the cache.
421 ProgramCache* cache = &gfxcore->program_cache; 421 ProgramCache* cache = &gfxcore->program_cache;
422 ShaderProgramCacheEntry* entry = find_program_cache_entry(cache, *prog); 422 ShaderProgramCacheEntry* entry = find_program_cache_entry(cache, *prog);
423 // TODO: The following assertion is too restrictive. Clients can end up
424 // re-using the same shader by virtue of the cache. The assertion assumes
425 // that no two "different" clients use the same set of shaders. This can
426 // be relaxed by reference-counting the shaders in the cache.
423 assert(entry); // Must be there, shaders can't go untracked. 427 assert(entry); // Must be there, shaders can't go untracked.
424 mempool_free(cache, &entry); 428 mempool_free(cache, &entry);
425 429
diff --git a/src/gfx.c b/src/gfx.c
index cd2ac90..4291ae7 100644
--- a/src/gfx.c
+++ b/src/gfx.c
@@ -2,20 +2,20 @@
2 2
3#include "asset/asset_cache.h" 3#include "asset/asset_cache.h"
4#include "core/core_impl.h" 4#include "core/core_impl.h"
5#include "llr/llr_impl.h"
5#include "renderer/imm_renderer_impl.h" 6#include "renderer/imm_renderer_impl.h"
6#include "renderer/renderer_impl.h" 7#include "renderer/renderer_impl.h"
7#include "scene/scene_memory.h" 8#include "scene/scene_memory.h"
8 9
9#include <log/log.h>
10
11#include <assert.h> 10#include <assert.h>
12#include <stdlib.h> 11#include <stdlib.h>
13 12
14typedef struct Gfx { 13typedef struct Gfx {
15 AssetCache asset_cache; 14 AssetCache asset_cache;
16 GfxCore gfxcore; 15 GfxCore gfxcore;
17 Renderer renderer; 16 LLR llr;
18 ImmRenderer imm_renderer; 17 ImmRenderer imm_renderer;
18 Renderer renderer;
19} Gfx; 19} Gfx;
20 20
21Gfx* gfx_init(void) { 21Gfx* gfx_init(void) {
@@ -24,16 +24,20 @@ Gfx* gfx_init(void) {
24 return 0; 24 return 0;
25 } 25 }
26 gfx_init_gfxcore(&gfx->gfxcore); 26 gfx_init_gfxcore(&gfx->gfxcore);
27 if (!renderer_make(&gfx->renderer, &gfx->gfxcore)) { 27 if (!gfx_llr_make(&gfx->llr, &gfx->gfxcore)) {
28 gfx_destroy(&gfx); 28 gfx_destroy(&gfx);
29 return 0; 29 return 0;
30 } 30 }
31 if (!imm_renderer_make(&gfx->imm_renderer, &gfx->gfxcore)) { 31 if (!gfx_imm_make(&gfx->imm_renderer, &gfx->gfxcore, &gfx->llr)) {
32 // TODO: Add error logs to the initialization failure cases here and inside 32 // TODO: Add error logs to the initialization failure cases here and inside
33 // the renderers. 33 // the renderers.
34 gfx_destroy(&gfx); 34 gfx_destroy(&gfx);
35 return 0; 35 return 0;
36 } 36 }
37 if (!gfx_renderer_make(&gfx->renderer, &gfx->llr, &gfx->gfxcore)) {
38 gfx_destroy(&gfx);
39 return 0;
40 }
37 gfx_init_asset_cache(&gfx->asset_cache); 41 gfx_init_asset_cache(&gfx->asset_cache);
38 scene_mem_init(); 42 scene_mem_init();
39 return gfx; 43 return gfx;
@@ -45,8 +49,9 @@ void gfx_destroy(Gfx** gfx) {
45 } 49 }
46 scene_mem_destroy(); 50 scene_mem_destroy();
47 gfx_destroy_asset_cache(&(*gfx)->asset_cache); 51 gfx_destroy_asset_cache(&(*gfx)->asset_cache);
48 renderer_destroy(&(*gfx)->renderer); 52 gfx_renderer_destroy(&(*gfx)->renderer);
49 imm_renderer_destroy(&(*gfx)->imm_renderer); 53 gfx_imm_destroy(&(*gfx)->imm_renderer);
54 gfx_llr_destroy(&(*gfx)->llr);
50 gfx_del_gfxcore(&(*gfx)->gfxcore); 55 gfx_del_gfxcore(&(*gfx)->gfxcore);
51 free(*gfx); 56 free(*gfx);
52 *gfx = 0; 57 *gfx = 0;
@@ -67,6 +72,11 @@ ImmRenderer* gfx_get_imm_renderer(Gfx* gfx) {
67 return &gfx->imm_renderer; 72 return &gfx->imm_renderer;
68} 73}
69 74
75LLR* gfx_get_llr(Gfx* gfx) {
76 assert(gfx);
77 return &gfx->llr;
78}
79
70AssetCache* gfx_get_asset_cache(Gfx* gfx) { 80AssetCache* gfx_get_asset_cache(Gfx* gfx) {
71 assert(gfx); 81 assert(gfx);
72 return &gfx->asset_cache; 82 return &gfx->asset_cache;
diff --git a/src/llr/light.c b/src/llr/light.c
index 168f16a..1d1c40d 100644
--- a/src/llr/light.c
+++ b/src/llr/light.c
@@ -1,4 +1,4 @@
1#include "../scene/light_impl.h" 1#include "light_impl.h"
2 2
3#include "../scene/node_impl.h" 3#include "../scene/node_impl.h"
4#include "../scene/scene_memory.h" 4#include "../scene/scene_memory.h"
diff --git a/src/llr/llr.c b/src/llr/llr.c
index 62a7c30..746f4b3 100644
--- a/src/llr/llr.c
+++ b/src/llr/llr.c
@@ -1,17 +1,14 @@
1#include "imm_renderer_impl.h"
2#include "light_impl.h" 1#include "light_impl.h"
2#include "llr_impl.h"
3#include "mesh_impl.h" 3#include "mesh_impl.h"
4 4
5#include "llr/material_impl.h"
5#include "scene/animation_impl.h" 6#include "scene/animation_impl.h"
6 7
7#include <gfx/core.h> 8#include <gfx/core.h>
8#include <gfx/util/ibl.h> 9#include <gfx/util/ibl.h>
9#include <gfx/util/shader.h>
10
11#include <math/aabb3.h>
12 10
13#include <cassert.h> 11#include <cassert.h>
14#include <string.h> // memcpy
15 12
16static const int IRRADIANCE_MAP_WIDTH = 1024; 13static const int IRRADIANCE_MAP_WIDTH = 1024;
17static const int IRRADIANCE_MAP_HEIGHT = 1024; 14static const int IRRADIANCE_MAP_HEIGHT = 1024;
@@ -21,7 +18,7 @@ static const int BRDF_INTEGRATION_MAP_WIDTH = 512;
21static const int BRDF_INTEGRATION_MAP_HEIGHT = 512; 18static const int BRDF_INTEGRATION_MAP_HEIGHT = 512;
22 19
23/// Initialize renderer state for IBL. 20/// Initialize renderer state for IBL.
24static bool init_ibl(ImmRenderer* renderer) { 21static bool init_ibl(LLR* renderer) {
25 assert(renderer); 22 assert(renderer);
26 assert(!renderer->ibl); 23 assert(!renderer->ibl);
27 assert(!renderer->brdf_integration_map); 24 assert(!renderer->brdf_integration_map);
@@ -44,8 +41,7 @@ static bool init_ibl(ImmRenderer* renderer) {
44// 41//
45/// Compute irradiance and prefiltered environment maps for the light if they 42/// Compute irradiance and prefiltered environment maps for the light if they
46/// have not been already computed. 43/// have not been already computed.
47static bool set_up_environment_light( 44static bool set_up_environment_light(LLR* renderer, EnvironmentLight* light) {
48 ImmRenderer* renderer, EnvironmentLight* light) {
49 assert(renderer); 45 assert(renderer);
50 assert(light); 46 assert(light);
51 assert(renderer->ibl); 47 assert(renderer->ibl);
@@ -92,7 +88,7 @@ cleanup:
92 return false; 88 return false;
93} 89}
94 90
95static void configure_light(ImmRenderer* renderer, Light* light) { 91static void configure_light(LLR* renderer, Light* light) {
96 assert(renderer); 92 assert(renderer);
97 assert(light); 93 assert(light);
98 94
@@ -127,20 +123,35 @@ static void configure_light(ImmRenderer* renderer, Light* light) {
127 } 123 }
128} 124}
129 125
130static void configure_state(ImmRenderer* renderer) { 126static void configure_state(LLR* renderer) {
131 assert(renderer); 127 assert(renderer);
132 128
133 // Check if anything changed first so that we don't call gfx_apply_uniforms() 129 // Check if anything changed first so that we don't call gfx_apply_uniforms()
134 // unnecessarily. 130 // unnecessarily.
135 const bool anything_changed = 131 const bool nothing_changed = (renderer->changed_flags == 0);
136 renderer->camera_changed || renderer->lights_changed || 132 if (nothing_changed) {
137 renderer->skeleton_changed || renderer->shader_changed; 133 return;
138 if (!anything_changed) { 134 }
135 // Setting a null shader is also allowed, in which case there is nothing to
136 // configure.
137 if (renderer->shader == 0) {
138 renderer->shader_changed = false;
139 return; 139 return;
140 } 140 }
141 141
142 // For convenience. 142 // For convenience.
143 ShaderProgram* const shader = renderer->shader; 143 ShaderProgram* const shader = renderer->shader;
144 const mat4* const model = &renderer->matrix_stack[renderer->stack_pointer];
145
146 // TODO: Check to see which ones the shader actually uses and avoid
147 // computing the unnecessary matrices.
148
149 if (renderer->matrix_changed || renderer->shader_changed) {
150 renderer->matrix_changed = false;
151
152 gfx_set_mat4_uniform(shader, "Model", model);
153 gfx_set_mat4_uniform(shader, "ModelMatrix", model);
154 }
144 155
145 // TODO: camera_changed is not set anywhere. Need to think how imm primitive 156 // TODO: camera_changed is not set anywhere. Need to think how imm primitive
146 // rendering and imm mesh rendering work together. We could treat imm 157 // rendering and imm mesh rendering work together. We could treat imm
@@ -150,14 +161,10 @@ static void configure_state(ImmRenderer* renderer) {
150 161
151 // Set all supported camera-related uniforms. Shaders can choose which ones 162 // Set all supported camera-related uniforms. Shaders can choose which ones
152 // to use. 163 // to use.
153 // TODO: Check to see which ones the shader actually uses and avoid 164 const mat4 modelview = mat4_mul(renderer->view, *model);
154 // computing the unnecessary matrices.
155 const mat4* const model = &renderer->matrix_stack[renderer->stack_pointer];
156 const mat4 modelview = mat4_mul(renderer->view, *model);
157 const mat4 view_proj = mat4_mul(renderer->projection, renderer->view); 165 const mat4 view_proj = mat4_mul(renderer->projection, renderer->view);
158 const mat4 mvp = mat4_mul(renderer->projection, modelview); 166 const mat4 mvp = mat4_mul(renderer->projection, modelview);
159 167
160 gfx_set_mat4_uniform(shader, "ModelMatrix", model);
161 gfx_set_mat4_uniform(shader, "Modelview", &modelview); 168 gfx_set_mat4_uniform(shader, "Modelview", &modelview);
162 gfx_set_mat4_uniform(shader, "View", &renderer->view); 169 gfx_set_mat4_uniform(shader, "View", &renderer->view);
163 gfx_set_mat4_uniform(shader, "Projection", &renderer->projection); 170 gfx_set_mat4_uniform(shader, "Projection", &renderer->projection);
@@ -195,58 +202,26 @@ static void configure_state(ImmRenderer* renderer) {
195 gfx_apply_uniforms(renderer->shader); 202 gfx_apply_uniforms(renderer->shader);
196} 203}
197 204
198bool gfx_imm_make(ImmRenderer* renderer, GfxCore* gfxcore) { 205bool gfx_llr_make(LLR* renderer, GfxCore* gfxcore) {
199 assert(renderer); 206 assert(renderer);
200 assert(gfxcore); 207 assert(gfxcore);
201 208
202 const size_t num_triangle_verts = IMM_MAX_NUM_TRIANGLES * 3;
203
204 renderer->gfxcore = gfxcore; 209 renderer->gfxcore = gfxcore;
205
206 renderer->triangles = gfx_make_geometry(
207 gfxcore,
208 &(GeometryDesc){.type = Triangles,
209 .buffer_usage = BufferDynamic,
210 .num_verts = num_triangle_verts,
211 .positions3d = (BufferView3d){
212 .size_bytes = num_triangle_verts * sizeof(vec3)}});
213 if (!renderer->triangles) {
214 goto cleanup;
215 }
216
217 renderer->imm_shader = gfx_make_immediate_mode_shader(gfxcore);
218 if (!renderer->imm_shader) {
219 goto cleanup;
220 }
221 renderer->shader = renderer->imm_shader;
222
223 if (!init_ibl(renderer)) { 210 if (!init_ibl(renderer)) {
224 goto cleanup; 211 goto cleanup;
225 } 212 }
226 213 gfx_llr_load_identity(renderer);
227 gfx_imm_load_identity(renderer);
228 gfx_imm_set_colour(renderer, vec4_make(0.0f, 0.0f, 0.0f, 1.0f));
229
230 return true; 214 return true;
231 215
232cleanup: 216cleanup:
233 gfx_imm_destroy(renderer); 217 gfx_llr_destroy(renderer);
234 return false; 218 return false;
235} 219}
236 220
237void gfx_imm_destroy(ImmRenderer* renderer) { 221void gfx_llr_destroy(LLR* renderer) {
238 assert(renderer); 222 assert(renderer);
239 assert(renderer->gfxcore); 223 assert(renderer->gfxcore);
240 224
241 if (renderer->triangles) {
242 gfx_destroy_geometry(renderer->gfxcore, &renderer->triangles);
243 // TODO: Could also destroy the geometry's buffers here.
244 }
245
246 if (renderer->imm_shader) {
247 gfx_destroy_shader_program(renderer->gfxcore, &renderer->imm_shader);
248 }
249
250 if (renderer->brdf_integration_map) { 225 if (renderer->brdf_integration_map) {
251 gfx_destroy_texture(renderer->gfxcore, &renderer->brdf_integration_map); 226 gfx_destroy_texture(renderer->gfxcore, &renderer->brdf_integration_map);
252 } 227 }
@@ -257,43 +232,9 @@ void gfx_imm_destroy(ImmRenderer* renderer) {
257 } 232 }
258} 233}
259 234
260void gfx_imm_flush(ImmRenderer* renderer) { 235void gfx_llr_set_shader(LLR* renderer, ShaderProgram* shader) {
261 assert(renderer);
262
263 if (renderer->num_triangle_verts > 0) {
264 configure_state(renderer);
265
266 gfx_update_geometry(
267 renderer->triangles,
268 &(GeometryDesc){
269 .num_verts = renderer->num_triangle_verts,
270 .positions3d = (BufferView3d){
271 .data = renderer->triangle_verts,
272 .size_bytes = renderer->num_triangle_verts * sizeof(vec3)}
273 });
274
275 gfx_apply_uniforms(renderer->shader);
276 gfx_render_geometry(renderer->triangles);
277
278 renderer->num_triangle_verts = 0;
279 }
280}
281
282void gfx_imm_set_shader(ImmRenderer* renderer, ShaderProgram* shader) {
283 assert(renderer); 236 assert(renderer);
284 assert(shader); 237 // null shader is allowed, so do not assert it.
285
286 // TODO: It would probably be best to make the imm renderer work in terms of a
287 // new LLR renderer. Otherwise we need to constantly flush stuff everywhere
288 // "just in case". This would still allow the imm to render meshes with
289 // lighting etc. We just need to create an actual Mesh out of the 'triangles'
290 // Geometry that imm currently has. The change would greatly simplify the
291 // implementation of this otherwise coupled LLR-IMM renderer.
292 // Need to decide where to put the matrix stack manipulation. Might be good
293 // to move to the LLR. (Currently, manipulating the stack causes an imm
294 // flush, but that's because we have coupled imm with stack manipulation,
295 // which the new design seems like would address.)
296 gfx_imm_flush(renderer);
297 238
298 // It's important to not set shader_changed unnecessarily, since that would 239 // It's important to not set shader_changed unnecessarily, since that would
299 // re-trigger the setting of uniforms. 240 // re-trigger the setting of uniforms.
@@ -303,36 +244,17 @@ void gfx_imm_set_shader(ImmRenderer* renderer, ShaderProgram* shader) {
303 } 244 }
304} 245}
305 246
306void gfx_imm_start(ImmRenderer* renderer) { 247void gfx_llr_push_light(LLR* renderer, Light* light) {
307 assert(renderer);
308
309 // Shader uniforms are applied lazily.
310 // TODO: In the event that gfx_activate_shader_program() activates uniforms
311 // automatically for convenience, call an overload here that doesn't do so.
312 gfx_activate_shader_program(renderer->shader);
313}
314
315void gfx_imm_end(ImmRenderer* renderer) {
316 assert(renderer);
317
318 gfx_imm_flush(renderer);
319 gfx_deactivate_shader_program(renderer->shader);
320
321 // TODO: Should we clear all of the render state here as well? At least set
322 // the 'changed' variables to false, for example.
323}
324
325void gfx_imm_push_light(ImmRenderer* renderer, Light* light) {
326 assert(renderer); 248 assert(renderer);
327 assert(light); 249 assert(light);
328 assert(renderer->num_lights >= 0); 250 assert(renderer->num_lights >= 0);
329 ASSERT(renderer->num_lights < IMM_MAX_NUM_LIGHTS); 251 ASSERT(renderer->num_lights < GFX_LLR_MAX_NUM_LIGHTS);
330 252
331 renderer->lights[renderer->num_lights++] = light; 253 renderer->lights[renderer->num_lights++] = light;
332 renderer->lights_changed = true; 254 renderer->lights_changed = true;
333} 255}
334 256
335void gfx_imm_pop_light(ImmRenderer* renderer) { 257void gfx_llr_pop_light(LLR* renderer) {
336 assert(renderer); 258 assert(renderer);
337 ASSERT(renderer->num_lights > 0); 259 ASSERT(renderer->num_lights > 0);
338 260
@@ -340,8 +262,8 @@ void gfx_imm_pop_light(ImmRenderer* renderer) {
340 renderer->lights_changed = true; 262 renderer->lights_changed = true;
341} 263}
342 264
343void gfx_imm_set_skeleton( 265void gfx_llr_set_skeleton(
344 ImmRenderer* renderer, const Anima* anima, const Skeleton* skeleton) { 266 LLR* renderer, const Anima* anima, const Skeleton* skeleton) {
345 assert(renderer); 267 assert(renderer);
346 assert(anima); 268 assert(anima);
347 assert(skeleton); 269 assert(skeleton);
@@ -356,150 +278,73 @@ void gfx_imm_set_skeleton(
356 renderer->skeleton_changed = true; 278 renderer->skeleton_changed = true;
357} 279}
358 280
359void gfx_imm_unset_skeleton(ImmRenderer* renderer) { 281void gfx_llr_unset_skeleton(LLR* renderer) {
360 assert(renderer); 282 assert(renderer);
361 283
362 renderer->num_joints = 0; 284 renderer->num_joints = 0;
363 renderer->skeleton_changed = true; 285 renderer->skeleton_changed = true;
364} 286}
365 287
366void gfx_imm_render_mesh(ImmRenderer* renderer, const Mesh* mesh) { 288void gfx_llr_set_camera(LLR* renderer, const Camera* camera) {
367 assert(renderer);
368 assert(mesh);
369 assert(mesh->geometry);
370 assert(mesh->material);
371
372 configure_state(renderer);
373 gfx_render_geometry(mesh->geometry);
374}
375
376void gfx_imm_draw_triangles(
377 ImmRenderer* renderer, const vec3 verts[], size_t num_triangles) {
378 assert(renderer); 289 assert(renderer);
379 assert(verts);
380 const size_t new_verts = num_triangles * 3;
381 assert(
382 renderer->num_triangle_verts + new_verts < (IMM_MAX_NUM_TRIANGLES * 3));
383
384 memcpy(
385 renderer->triangle_verts + renderer->num_triangle_verts, verts,
386 new_verts * sizeof(vec3));
387 290
388 renderer->num_triangle_verts += new_verts; 291 const mat4 view = spatial3_inverse_transform(&camera->spatial);
389} 292 // const mat4 view_proj = mat4_mul(camera->projection, view);
390 293 // gfx_llr_set_view_projection_matrix(renderer, &view_proj);
391void gfx_imm_draw_triangle(ImmRenderer* renderer, const vec3 verts[3]) { 294 renderer->view = view;
392 gfx_imm_draw_triangles(renderer, verts, 1); 295 renderer->projection = camera->projection;
296 renderer->camera_changed = true;
393} 297}
394 298
395void gfx_imm_draw_aabb2(ImmRenderer* renderer, aabb2 box) { 299// void gfx_llr_set_view_projection_matrix(
396 assert(renderer); 300// LLR* renderer, const mat4* view_proj) {
397 301// assert(renderer);
398 // clang-format off 302// assert(renderer->shader);
399 const vec3 verts[4] = { 303//
400 vec3_make(box.min.x, box.min.y, 0), // 3 ---- 2 304// gfx_llr_flush(renderer);
401 vec3_make(box.max.x, box.min.y, 0), // | | 305// gfx_set_mat4_uniform(renderer->shader, "ViewProjection", view_proj);
402 vec3_make(box.max.x, box.max.y, 0), // | | 306// }
403 vec3_make(box.min.x, box.max.y, 0)}; // 0 ---- 1
404 // clang-format on
405
406#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2]
407 const vec3 tris[6] = {tri(0, 1, 2), tri(0, 2, 3)};
408#undef tri
409
410 gfx_imm_draw_triangles(renderer, tris, 2);
411}
412 307
413void gfx_imm_draw_aabb3(ImmRenderer* renderer, aabb3 box) { 308void gfx_llr_render_geometry(LLR* renderer, const Geometry* geometry) {
414 assert(renderer); 309 assert(renderer);
310 assert(geometry);
415 311
416 // clang-format off 312 configure_state(renderer);
417 const vec3 vertices[8] = { 313 gfx_render_geometry(geometry);
418 vec3_make(box.min.x, box.min.y, box.max.z), // 7 ----- 6
419 vec3_make(box.max.x, box.min.y, box.max.z), // / /|
420 vec3_make(box.max.x, box.max.y, box.max.z), // 3 ----- 2 |
421 vec3_make(box.min.x, box.max.y, box.max.z), // | | |
422 vec3_make(box.min.x, box.min.y, box.min.z), // | 4 ----- 5
423 vec3_make(box.max.x, box.min.y, box.min.z), // |/ |/
424 vec3_make(box.max.x, box.max.y, box.min.z), // 0 ----- 1
425 vec3_make(box.min.x, box.max.y, box.min.z)};
426 // clang-format on
427
428 gfx_imm_draw_box3(renderer, vertices);
429}
430
431void gfx_imm_draw_box3(ImmRenderer* renderer, const vec3 vertices[8]) {
432 assert(renderer);
433 assert(vertices);
434
435 // 7 ----- 6
436 // / /|
437 // 3 ----- 2 |
438 // | | |
439 // | 4 ----- 5
440 // |/ |/
441 // 0 ----- 1
442
443#define tri(i0, i1, i2) vertices[i0], vertices[i1], vertices[i2]
444 const vec3 tris[36] = {
445 // Front.
446 tri(0, 1, 2), tri(0, 2, 3),
447 // Right.
448 tri(1, 5, 6), tri(1, 6, 2),
449 // Back.
450 tri(5, 4, 7), tri(5, 7, 6),
451 // Left.
452 tri(4, 0, 03), tri(4, 3, 7),
453 // Top.
454 tri(3, 2, 6), tri(3, 6, 7),
455 // Bottom.
456 tri(0, 4, 5), tri(0, 5, 1)};
457
458 gfx_imm_draw_triangles(renderer, tris, 12);
459} 314}
460 315
461void gfx_imm_set_colour(ImmRenderer* renderer, vec4 colour) { 316void gfx_llr_render_mesh(LLR* renderer, const Mesh* mesh) {
462 assert(renderer); 317 assert(renderer);
463 assert(renderer->shader); 318 assert(renderer->shader);
319 assert(mesh);
320 assert(mesh->geometry);
321 assert(mesh->material);
464 322
465 gfx_imm_flush(renderer); 323 gfx_material_activate(renderer->shader, mesh->material);
466 324 gfx_llr_render_geometry(renderer, mesh->geometry);
467 gfx_set_vec4_uniform(renderer->shader, "Colour", colour);
468}
469
470// Load the top of the matrix stack into the shader.
471static void update_shader_model_matrix(ImmRenderer* renderer) {
472 assert(renderer);
473
474 gfx_imm_flush(renderer);
475
476 gfx_set_mat4_uniform(
477 renderer->shader, "Model",
478 &renderer->matrix_stack[renderer->stack_pointer]);
479} 325}
480 326
481void gfx_imm_load_identity(ImmRenderer* renderer) { 327void gfx_llr_load_identity(LLR* renderer) {
482 assert(renderer); 328 assert(renderer);
483 329
484 renderer->matrix_stack[0] = mat4_id(); 330 renderer->matrix_stack[0] = mat4_id();
485 renderer->stack_pointer = 0; 331 renderer->stack_pointer = 0;
486 update_shader_model_matrix(renderer); 332 renderer->matrix_changed = true;
487} 333}
488 334
489void gfx_imm_push_matrix(ImmRenderer* renderer, const mat4* matrix) { 335void gfx_llr_push_matrix(LLR* renderer, const mat4* matrix) {
490 assert(renderer); 336 assert(renderer);
491 assert(matrix); 337 assert(matrix);
492 assert(renderer->stack_pointer >= 0); 338 assert(renderer->stack_pointer >= 0);
493 ASSERT(renderer->stack_pointer < IMM_MAX_NUM_MATRICES); 339 ASSERT(renderer->stack_pointer < GFX_LLR_MAX_NUM_MATRICES);
494 340
495 renderer->stack_pointer += 1; 341 renderer->stack_pointer += 1;
496 renderer->matrix_stack[renderer->stack_pointer] = 342 renderer->matrix_stack[renderer->stack_pointer] =
497 mat4_mul(*matrix, renderer->matrix_stack[renderer->stack_pointer - 1]); 343 mat4_mul(*matrix, renderer->matrix_stack[renderer->stack_pointer - 1]);
498 344 renderer->matrix_changed = true;
499 update_shader_model_matrix(renderer);
500} 345}
501 346
502void gfx_imm_pop_matrix(ImmRenderer* renderer) { 347void gfx_llr_pop_matrix(LLR* renderer) {
503 assert(renderer); 348 assert(renderer);
504 ASSERT(renderer->stack_pointer > 0); 349 ASSERT(renderer->stack_pointer > 0);
505 350
@@ -508,47 +353,21 @@ void gfx_imm_pop_matrix(ImmRenderer* renderer) {
508 &renderer->matrix_stack[renderer->stack_pointer], 0, 353 &renderer->matrix_stack[renderer->stack_pointer], 0,
509 sizeof(renderer->matrix_stack[0])); 354 sizeof(renderer->matrix_stack[0]));
510 renderer->stack_pointer -= 1; 355 renderer->stack_pointer -= 1;
511 356 renderer->matrix_changed = true;
512 update_shader_model_matrix(renderer);
513} 357}
514 358
515void gfx_imm_translate(ImmRenderer* renderer, vec3 offset) { 359void gfx_llr_translate(LLR* renderer, vec3 offset) {
516 assert(renderer); 360 assert(renderer);
517 361
518 const mat4 mat = mat4_translate(offset); 362 const mat4 mat = mat4_translate(offset);
519 gfx_imm_push_matrix(renderer, &mat); 363 gfx_llr_push_matrix(renderer, &mat);
520} 364}
521 365
522void gfx_imm_set_model_matrix(ImmRenderer* renderer, const mat4* model) { 366void gfx_llr_set_model_matrix(LLR* renderer, const mat4* model) {
523 assert(renderer); 367 assert(renderer);
524 assert(model); 368 assert(model);
525 369
526 gfx_imm_flush(renderer);
527
528 renderer->matrix_stack[0] = *model; 370 renderer->matrix_stack[0] = *model;
529 renderer->stack_pointer = 0; 371 renderer->stack_pointer = 0;
530 update_shader_model_matrix(renderer); 372 renderer->matrix_changed = true;
531} 373}
532
533void gfx_imm_set_camera(ImmRenderer* renderer, const Camera* camera) {
534 assert(renderer);
535 assert(renderer->shader);
536
537 gfx_imm_flush(renderer);
538
539 const mat4 view = spatial3_inverse_transform(&camera->spatial);
540 // const mat4 view_proj = mat4_mul(camera->projection, view);
541 // gfx_imm_set_view_projection_matrix(renderer, &view_proj);
542 renderer->view = view;
543 renderer->projection = camera->projection;
544 renderer->camera_changed = true;
545}
546
547// void gfx_imm_set_view_projection_matrix(
548// ImmRenderer* renderer, const mat4* view_proj) {
549// assert(renderer);
550// assert(renderer->shader);
551//
552// gfx_imm_flush(renderer);
553// gfx_set_mat4_uniform(renderer->shader, "ViewProjection", view_proj);
554// }
diff --git a/src/llr/llr_impl.h b/src/llr/llr_impl.h
index 5ccabd1..e9dc0ac 100644
--- a/src/llr/llr_impl.h
+++ b/src/llr/llr_impl.h
@@ -8,6 +8,7 @@
8 8
9#include <stdbool.h> 9#include <stdbool.h>
10#include <stddef.h> 10#include <stddef.h>
11#include <stdint.h>
11 12
12typedef struct Geometry Geometry; 13typedef struct Geometry Geometry;
13typedef struct GfxCore GfxCore; 14typedef struct GfxCore GfxCore;
@@ -33,67 +34,47 @@ typedef struct Texture Texture;
33/// Note that the shader program API has its own level of caching as well, so 34/// Note that the shader program API has its own level of caching as well, so
34/// reconfiguration at the level of the renderer does not result in the 35/// reconfiguration at the level of the renderer does not result in the
35/// worst-case set of graphics API calls. 36/// worst-case set of graphics API calls.
36/// 37typedef struct LLR {
37/// Currently, the immediate mode renderer can only draw up to a maximum number
38/// of primitives per frame. It does not adjust this number dynamically. Keeps
39/// things simple while the extra complexity is not needed.
40/// TODO: Flush the buffer when it reaches its maximum size to remove this
41/// constraint.
42typedef struct ImmRenderer {
43 GfxCore* gfxcore; 38 GfxCore* gfxcore;
44 39
45 vec3 camera_position; 40 union {
46 mat4 view; // Camera view matrix. 41 struct {
47 mat4 projection; // Camera projection matrix. 42 bool shader_changed : 1; // Whether the shader has changed.
48 bool camera_changed; // Whether the camera parameters have changed. 43 bool camera_changed : 1; // Whether the camera parameters have changed.
49 44 bool lights_changed : 1; // Whether the lights have changed.
50 // ------------------------------------------- 45 bool skeleton_changed : 1; // Whether the skeleton has changed.
51 // Immediate-mode rendering of scene elements. 46 bool matrix_changed : 1; // Whether the matrix stack has changed.
47 };
48 uint8_t changed_flags;
49 };
52 50
53 IBL* ibl; 51 IBL* ibl;
54 Texture* brdf_integration_map; 52 Texture* brdf_integration_map;
55 53
56 ShaderProgram* shader; // Active shader. Not owned. 54 ShaderProgram* shader; // Active shader. Not owned.
57 bool shader_changed; // Whether the shader has changed. 55
56 vec3 camera_position;
57 mat4 view; // Camera view matrix.
58 mat4 projection; // Camera projection matrix.
58 59
59 // Lights are not const because environment lights store lazily-computed 60 // Lights are not const because environment lights store lazily-computed
60 // irradiance maps. 61 // irradiance maps.
61 Light* lights[IMM_MAX_NUM_LIGHTS]; // Lights stack. 62 Light* lights[GFX_LLR_MAX_NUM_LIGHTS]; // Lights stack.
62 int num_lights; // Number of lights enabled at a given point in time. It 63 int num_lights; // Number of lights enabled at a given point in time. It
63 // points to one past the top of the stack. 64 // points to one past the top of the stack.
64 bool lights_changed; // Whether the lights have changed.
65 65
66 bool skeleton_changed;
67 size_t num_joints; 66 size_t num_joints;
68 mat4 joint_matrices[GFX_MAX_NUM_JOINTS]; 67 mat4 joint_matrices[GFX_MAX_NUM_JOINTS];
69 68
70 // ---------------------------------------
71 // Immediate-mode rendering of primitives.
72
73 ShaderProgram* imm_shader; // Immediate-mode shader program for primitives.
74 Geometry* triangles;
75 size_t num_triangle_verts; // Number of triangle verts this frame.
76 // TODO: wireframe rendering.
77 struct {
78 bool wireframe : 1;
79 } flags;
80 vec3 triangle_verts[IMM_MAX_NUM_TRIANGLES * 3];
81
82 // -------------
83 // Matrix stack.
84
85 // The matrix stack contains pre-multiplied matrices. 69 // The matrix stack contains pre-multiplied matrices.
86 // It is also never empty. The top of the stack is an identity matrix when the 70 // It is also never empty. The top of the stack is an identity matrix when the
87 // stack is "empty" from the user's perspective. 71 // stack is "empty" from the user's perspective.
88 mat4 matrix_stack[IMM_MAX_NUM_MATRICES]; 72 mat4 matrix_stack[GFX_LLR_MAX_NUM_MATRICES];
89 int stack_pointer; // Points to the top of the stack. 73 int stack_pointer; // Points to the top of the stack.
90} ImmRenderer; 74} LLR;
91 75
92/// Create a new immediate mode renderer. 76/// Create a new immediate mode renderer.
93bool gfx_imm_make(ImmRenderer*, GfxCore*); 77bool gfx_llr_make(LLR*, GfxCore*);
94 78
95/// Destroy the immediate mode renderer. 79/// Destroy the immediate mode renderer.
96void gfx_imm_destroy(ImmRenderer*); 80void gfx_llr_destroy(LLR*);
97
98/// Flush draw commands.
99void gfx_imm_flush(ImmRenderer*);
diff --git a/src/llr/material.c b/src/llr/material.c
index 47cb45f..4014482 100644
--- a/src/llr/material.c
+++ b/src/llr/material.c
@@ -48,7 +48,7 @@ static void set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) {
48 } 48 }
49} 49}
50 50
51void material_activate(ShaderProgram* shader, const Material* material) { 51void gfx_material_activate(ShaderProgram* shader, const Material* material) {
52 assert(material); 52 assert(material);
53 for (int i = 0; i < material->num_uniforms; ++i) { 53 for (int i = 0; i < material->num_uniforms; ++i) {
54 const ShaderUniform* uniform = &material->uniforms[i]; 54 const ShaderUniform* uniform = &material->uniforms[i];
diff --git a/src/llr/material_impl.h b/src/llr/material_impl.h
index f27bf4d..138497f 100644
--- a/src/llr/material_impl.h
+++ b/src/llr/material_impl.h
@@ -11,6 +11,5 @@ typedef struct Material {
11 11
12/// Activate the material. 12/// Activate the material.
13/// 13///
14/// This activates the material's shader and configures the shader uniforms that 14/// This configures the shader uniforms that are specific to the material.
15/// are specific to the material. 15void gfx_material_activate(ShaderProgram* shader, const Material* material);
16void material_activate(ShaderProgram* shader, const Material* material);
diff --git a/src/llr/mesh.c b/src/llr/mesh.c
index ae75d8c..3aebb04 100644
--- a/src/llr/mesh.c
+++ b/src/llr/mesh.c
@@ -1,4 +1,4 @@
1#include "../scene/mesh_impl.h" 1#include "mesh_impl.h"
2 2
3#include "../scene/scene_memory.h" 3#include "../scene/scene_memory.h"
4 4
diff --git a/src/renderer/imm_renderer.c b/src/renderer/imm_renderer.c
new file mode 100644
index 0000000..01cc5bb
--- /dev/null
+++ b/src/renderer/imm_renderer.c
@@ -0,0 +1,192 @@
1#include "imm_renderer_impl.h"
2
3#include <gfx/core.h>
4#include <gfx/llr/llr.h>
5#include <gfx/renderer/imm_renderer.h>
6#include <gfx/util/shader.h>
7
8#include <math/aabb3.h>
9
10#include <assert.h>
11#include <string.h> // memcpy
12
13bool gfx_imm_make(ImmRenderer* renderer, GfxCore* gfxcore, LLR* llr) {
14 assert(renderer);
15 assert(gfxcore);
16 assert(llr);
17
18 const size_t num_triangle_verts = GFX_IMM_MAX_NUM_TRIANGLES * 3;
19
20 renderer->gfxcore = gfxcore;
21 renderer->llr = llr;
22
23 renderer->triangles = gfx_make_geometry(
24 gfxcore,
25 &(GeometryDesc){.type = Triangles,
26 .buffer_usage = BufferDynamic,
27 .num_verts = num_triangle_verts,
28 .positions3d = (BufferView3d){
29 .size_bytes = num_triangle_verts * sizeof(vec3)}});
30 if (!renderer->triangles) {
31 goto cleanup;
32 }
33
34 renderer->shader = gfx_make_immediate_mode_shader(gfxcore);
35 if (!renderer->shader) {
36 goto cleanup;
37 }
38
39 gfx_imm_set_colour(renderer, vec4_make(0.0f, 0.0f, 0.0f, 1.0f));
40
41 return true;
42
43cleanup:
44 gfx_imm_destroy(renderer);
45 return false;
46}
47
48void gfx_imm_destroy(ImmRenderer* renderer) {
49 assert(renderer);
50 assert(renderer->gfxcore);
51
52 if (renderer->triangles) {
53 gfx_destroy_geometry(renderer->gfxcore, &renderer->triangles);
54 // TODO: Could also destroy the geometry's buffers here.
55 }
56
57 if (renderer->shader) {
58 gfx_destroy_shader_program(renderer->gfxcore, &renderer->shader);
59 }
60}
61
62void gfx_imm_flush(ImmRenderer* renderer) {
63 assert(renderer);
64
65 if (renderer->num_triangle_verts > 0) {
66 gfx_update_geometry(
67 renderer->triangles,
68 &(GeometryDesc){
69 .num_verts = renderer->num_triangle_verts,
70 .positions3d = (BufferView3d){
71 .data = renderer->triangle_verts,
72 .size_bytes = renderer->num_triangle_verts * sizeof(vec3)}
73 });
74
75 gfx_llr_render_geometry(renderer->llr, renderer->triangles);
76
77 renderer->num_triangle_verts = 0;
78 }
79}
80
81void gfx_imm_start(ImmRenderer* renderer) {
82 assert(renderer);
83
84 // Shader uniforms are applied lazily.
85 // TODO: In the event that gfx_activate_shader_program() activates uniforms
86 // automatically for convenience, call an overload here that doesn't do so.
87 // gfx_activate_shader_program(renderer->shader);
88 gfx_llr_set_shader(renderer->llr, renderer->shader);
89}
90
91void gfx_imm_end(ImmRenderer* renderer) {
92 assert(renderer);
93
94 gfx_imm_flush(renderer);
95 // gfx_deactivate_shader_program(renderer->shader);
96 gfx_llr_set_shader(renderer->llr, 0);
97}
98
99void gfx_imm_draw_triangles(
100 ImmRenderer* renderer, const vec3 verts[], size_t num_triangles) {
101 assert(renderer);
102 assert(verts);
103 const size_t new_verts = num_triangles * 3;
104 assert(
105 renderer->num_triangle_verts + new_verts <
106 (GFX_IMM_MAX_NUM_TRIANGLES * 3));
107
108 memcpy(
109 renderer->triangle_verts + renderer->num_triangle_verts, verts,
110 new_verts * sizeof(vec3));
111
112 renderer->num_triangle_verts += new_verts;
113}
114
115void gfx_imm_draw_triangle(ImmRenderer* renderer, const vec3 verts[3]) {
116 gfx_imm_draw_triangles(renderer, verts, 1);
117}
118
119void gfx_imm_draw_aabb2(ImmRenderer* renderer, aabb2 box) {
120 assert(renderer);
121
122 // clang-format off
123 const vec3 verts[4] = {
124 vec3_make(box.min.x, box.min.y, 0), // 3 ---- 2
125 vec3_make(box.max.x, box.min.y, 0), // | |
126 vec3_make(box.max.x, box.max.y, 0), // | |
127 vec3_make(box.min.x, box.max.y, 0)}; // 0 ---- 1
128 // clang-format on
129
130#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2]
131 const vec3 tris[6] = {tri(0, 1, 2), tri(0, 2, 3)};
132#undef tri
133
134 gfx_imm_draw_triangles(renderer, tris, 2);
135}
136
137void gfx_imm_draw_aabb3(ImmRenderer* renderer, aabb3 box) {
138 assert(renderer);
139
140 // clang-format off
141 const vec3 vertices[8] = {
142 vec3_make(box.min.x, box.min.y, box.max.z), // 7 ----- 6
143 vec3_make(box.max.x, box.min.y, box.max.z), // / /|
144 vec3_make(box.max.x, box.max.y, box.max.z), // 3 ----- 2 |
145 vec3_make(box.min.x, box.max.y, box.max.z), // | | |
146 vec3_make(box.min.x, box.min.y, box.min.z), // | 4 ----- 5
147 vec3_make(box.max.x, box.min.y, box.min.z), // |/ |/
148 vec3_make(box.max.x, box.max.y, box.min.z), // 0 ----- 1
149 vec3_make(box.min.x, box.max.y, box.min.z)};
150 // clang-format on
151
152 gfx_imm_draw_box3(renderer, vertices);
153}
154
155void gfx_imm_draw_box3(ImmRenderer* renderer, const vec3 vertices[8]) {
156 assert(renderer);
157 assert(vertices);
158
159 // 7 ----- 6
160 // / /|
161 // 3 ----- 2 |
162 // | | |
163 // | 4 ----- 5
164 // |/ |/
165 // 0 ----- 1
166
167#define tri(i0, i1, i2) vertices[i0], vertices[i1], vertices[i2]
168 const vec3 tris[36] = {
169 // Front.
170 tri(0, 1, 2), tri(0, 2, 3),
171 // Right.
172 tri(1, 5, 6), tri(1, 6, 2),
173 // Back.
174 tri(5, 4, 7), tri(5, 7, 6),
175 // Left.
176 tri(4, 0, 03), tri(4, 3, 7),
177 // Top.
178 tri(3, 2, 6), tri(3, 6, 7),
179 // Bottom.
180 tri(0, 4, 5), tri(0, 5, 1)};
181
182 gfx_imm_draw_triangles(renderer, tris, 12);
183}
184
185void gfx_imm_set_colour(ImmRenderer* renderer, vec4 colour) {
186 assert(renderer);
187 assert(renderer->shader);
188
189 gfx_imm_flush(renderer);
190
191 gfx_set_vec4_uniform(renderer->shader, "Colour", colour);
192}
diff --git a/src/renderer/imm_renderer_impl.h b/src/renderer/imm_renderer_impl.h
new file mode 100644
index 0000000..61b49a7
--- /dev/null
+++ b/src/renderer/imm_renderer_impl.h
@@ -0,0 +1,43 @@
1#pragma once
2
3#include <gfx/sizes.h>
4
5#include <math/vec3.h>
6
7#include <stdbool.h>
8#include <stddef.h>
9
10typedef struct Geometry Geometry;
11typedef struct GfxCore GfxCore;
12typedef struct IBL IBL;
13typedef struct LLR LLR;
14typedef struct Material Material;
15typedef struct ShaderProgram ShaderProgram;
16typedef struct Texture Texture;
17
18/// Immediate mode renderer.
19///
20/// Currently, the immediate mode renderer can only draw up to a maximum number
21/// of primitives per frame. It does not adjust this number dynamically. Keeps
22/// things simple while the extra complexity is not needed.
23/// TODO: Flush the buffer when it reaches its maximum size to remove this
24/// constraint.
25typedef struct ImmRenderer {
26 GfxCore* gfxcore;
27 LLR* llr;
28
29 ShaderProgram* shader; // Immediate-mode shader program for primitives.
30 Geometry* triangles;
31 size_t num_triangle_verts; // Number of triangle verts this frame.
32 // TODO: wireframe rendering.
33 struct {
34 bool wireframe : 1;
35 } flags;
36 vec3 triangle_verts[GFX_IMM_MAX_NUM_TRIANGLES * 3];
37} ImmRenderer;
38
39/// Create a new immediate mode renderer.
40bool gfx_imm_make(ImmRenderer*, GfxCore*, LLR*);
41
42/// Destroy the immediate mode renderer.
43void gfx_imm_destroy(ImmRenderer*);
diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c
index c2a7dda..0c1fe78 100644
--- a/src/renderer/renderer.c
+++ b/src/renderer/renderer.c
@@ -1,10 +1,10 @@
1#include "renderer_impl.h" 1#include "renderer_impl.h"
2 2
3#include "llr/light_impl.h"
4#include "llr/material_impl.h"
5#include "llr/mesh_impl.h"
3#include "scene/animation_impl.h" 6#include "scene/animation_impl.h"
4#include "scene/camera_impl.h" 7#include "scene/camera_impl.h"
5#include "scene/light_impl.h"
6#include "scene/material_impl.h"
7#include "scene/mesh_impl.h"
8#include "scene/model_impl.h" 8#include "scene/model_impl.h"
9#include "scene/node_impl.h" 9#include "scene/node_impl.h"
10#include "scene/object_impl.h" 10#include "scene/object_impl.h"
@@ -12,16 +12,18 @@
12#include "scene/scene_memory.h" 12#include "scene/scene_memory.h"
13 13
14#include <gfx/core.h> 14#include <gfx/core.h>
15#include <gfx/llr/llr.h>
15#include <gfx/util/ibl.h> 16#include <gfx/util/ibl.h>
16#include <gfx/util/shader.h> 17#include <gfx/util/shader.h>
17 18
18#include <log/log.h> 19// #include <log/log.h>
20#include "gfx/gfx.h"
21
19#include <math/mat4.h> 22#include <math/mat4.h>
20#include <math/spatial3.h> 23#include <math/spatial3.h>
21 24
22#include <assert.h> 25#include <assert.h>
23 26
24// TODO: Move to a header like "constants.h".
25static const int IRRADIANCE_MAP_WIDTH = 1024; 27static const int IRRADIANCE_MAP_WIDTH = 1024;
26static const int IRRADIANCE_MAP_HEIGHT = 1024; 28static const int IRRADIANCE_MAP_HEIGHT = 1024;
27static const int PREFILTERED_ENVIRONMENT_MAP_WIDTH = 128; 29static const int PREFILTERED_ENVIRONMENT_MAP_WIDTH = 128;
@@ -29,16 +31,18 @@ static const int PREFILTERED_ENVIRONMENT_MAP_HEIGHT = 128;
29static const int BRDF_INTEGRATION_MAP_WIDTH = 512; 31static const int BRDF_INTEGRATION_MAP_WIDTH = 512;
30static const int BRDF_INTEGRATION_MAP_HEIGHT = 512; 32static const int BRDF_INTEGRATION_MAP_HEIGHT = 512;
31 33
32bool renderer_make(Renderer* renderer, GfxCore* gfxcore) { 34bool gfx_renderer_make(Renderer* renderer, LLR* llr, GfxCore* gfxcore) {
33 assert(renderer); 35 assert(renderer);
36 assert(llr);
34 assert(gfxcore); 37 assert(gfxcore);
35 38
36 renderer->gfxcore = gfxcore; 39 renderer->gfxcore = gfxcore;
40 renderer->llr = llr;
37 41
38 return true; 42 return true;
39} 43}
40 44
41void renderer_destroy(Renderer* renderer) { 45void gfx_renderer_destroy(Renderer* renderer) {
42 if (!renderer) { 46 if (!renderer) {
43 return; 47 return;
44 } 48 }
@@ -117,9 +121,9 @@ static ShaderProgram* load_shader(Renderer* renderer, RenderSceneMode mode) {
117// } 121// }
118// } 122// }
119 123
120/// Computes irradiance and prefiltered environment maps for the light if they 124/// Compute irradiance and prefiltered environment maps for the light if they
121/// have not been already computed. 125/// have not been already computed.
122static bool setup_environment_light( 126static bool set_up_environment_light(
123 Renderer* renderer, GfxCore* gfxcore, EnvironmentLight* light) { 127 Renderer* renderer, GfxCore* gfxcore, EnvironmentLight* light) {
124 assert(renderer); 128 assert(renderer);
125 assert(light); 129 assert(light);
@@ -168,6 +172,7 @@ cleanup:
168 172
169typedef struct RenderState { 173typedef struct RenderState {
170 GfxCore* gfxcore; 174 GfxCore* gfxcore;
175 LLR* llr;
171 Renderer* renderer; 176 Renderer* renderer;
172 ShaderProgram* shader; // Null to use scene shaders. 177 ShaderProgram* shader; // Null to use scene shaders.
173 const Scene* scene; 178 const Scene* scene;
@@ -209,6 +214,7 @@ static void draw_recursively(
209 214
210 // Anima. 215 // Anima.
211 if (node->type == AnimaNode) { 216 if (node->type == AnimaNode) {
217 // Save the anima so that we can animate objects.
212 state->anima = gfx_get_node_anima(node); 218 state->anima = gfx_get_node_anima(node);
213 } 219 }
214 // Activate light. 220 // Activate light.
@@ -217,7 +223,7 @@ static void draw_recursively(
217 assert(light); 223 assert(light);
218 224
219 if (light->type == EnvironmentLightType) { 225 if (light->type == EnvironmentLightType) {
220 bool result = setup_environment_light( 226 bool result = set_up_environment_light(
221 state->renderer, state->gfxcore, &light->environment); 227 state->renderer, state->gfxcore, &light->environment);
222 // TODO: Handle the result in a better way. 228 // TODO: Handle the result in a better way.
223 assert(result); 229 assert(result);
@@ -238,11 +244,13 @@ static void draw_recursively(
238 // TODO: Here we would frustum-cull the object. 244 // TODO: Here we would frustum-cull the object.
239 245
240 // TODO: Avoid computing matrices like Modelview or MVP if the shader does 246 // TODO: Avoid computing matrices like Modelview or MVP if the shader does
241 // not use them. 247 // not use them.
242 const mat4 model_matrix = node_transform; 248 const mat4 model_matrix = node_transform;
243 const mat4 modelview = mat4_mul(*state->view_matrix, model_matrix); 249 const mat4 modelview = mat4_mul(*state->view_matrix, model_matrix);
244 const mat4 mvp = mat4_mul(*state->projection, modelview); 250 const mat4 mvp = mat4_mul(*state->projection, modelview);
245 251
252 // A model/anima can have many skeletons. We need to animate the given
253 // object using its skeleton, not just any skeleton of the anima.
246 if (object->skeleton.val) { 254 if (object->skeleton.val) {
247 load_skeleton(state, object->skeleton); 255 load_skeleton(state, object->skeleton);
248 } 256 }
@@ -260,9 +268,11 @@ static void draw_recursively(
260 assert(mesh->material); 268 assert(mesh->material);
261 269
262 // TODO: Here we would frustum-cull the mesh. The AABB would have to be 270 // TODO: Here we would frustum-cull the mesh. The AABB would have to be
263 // transformed by the model matrix. Rotation would make the AABB 271 // transformed by the model matrix. Rotation would make the AABB
264 // relatively large, but still, the culling would be conservative. 272 // relatively large, but still, the culling would be conservative.
265 273
274 // TODO: Make sure we strictly set only the uniforms that are required by
275 // mesh rendering. See the other item below.
266 // Apply common shader uniforms not captured by materials. 276 // Apply common shader uniforms not captured by materials.
267 ShaderProgram* shader = state->shader ? state->shader : mesh->shader; 277 ShaderProgram* shader = state->shader ? state->shader : mesh->shader;
268 gfx_set_mat4_uniform(shader, "ModelMatrix", &model_matrix); 278 gfx_set_mat4_uniform(shader, "ModelMatrix", &model_matrix);
@@ -270,7 +280,10 @@ static void draw_recursively(
270 gfx_set_mat4_uniform(shader, "View", state->view_matrix); 280 gfx_set_mat4_uniform(shader, "View", state->view_matrix);
271 gfx_set_mat4_uniform(shader, "Projection", state->projection); 281 gfx_set_mat4_uniform(shader, "Projection", state->projection);
272 gfx_set_mat4_uniform(shader, "MVP", &mvp); 282 gfx_set_mat4_uniform(shader, "MVP", &mvp);
283 // TODO: CameraRotation is only used by the skyquad and cubemap_filtering
284 // shaders, not mesh rendering.
273 gfx_set_mat4_uniform(shader, "CameraRotation", state->camera_rotation); 285 gfx_set_mat4_uniform(shader, "CameraRotation", state->camera_rotation);
286 // TODO: Fovy and Aspect are only used by the skyquad, not necessary here.
274 gfx_set_float_uniform(shader, "Fovy", state->fovy); 287 gfx_set_float_uniform(shader, "Fovy", state->fovy);
275 gfx_set_float_uniform(shader, "Aspect", state->aspect); 288 gfx_set_float_uniform(shader, "Aspect", state->aspect);
276 if (state->camera) { 289 if (state->camera) {
@@ -297,9 +310,9 @@ static void draw_recursively(
297 shader, "PrefilteredEnvironmentMap", 310 shader, "PrefilteredEnvironmentMap",
298 light->prefiltered_environment_map); 311 light->prefiltered_environment_map);
299 gfx_set_float_uniform( 312 gfx_set_float_uniform(
300 shader, "MaxReflectionLOD", light->max_reflection_lod); 313 shader, "MaxReflectionLOD", (float)light->max_reflection_lod);
301 } 314 }
302 material_activate(shader, mesh->material); 315 gfx_material_activate(shader, mesh->material);
303 gfx_activate_shader_program(shader); 316 gfx_activate_shader_program(shader);
304 gfx_apply_uniforms(shader); 317 gfx_apply_uniforms(shader);
305 gfx_render_geometry(mesh->geometry); 318 gfx_render_geometry(mesh->geometry);
@@ -327,7 +340,7 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) {
327 const Scene* scene = params->scene; 340 const Scene* scene = params->scene;
328 const SceneCamera* camera = params->camera; 341 const SceneCamera* camera = params->camera;
329 342
330 GfxCore* gfxcore = renderer->gfxcore; 343 GfxCore* const gfxcore = renderer->gfxcore;
331 344
332 mat4 projection, camera_rotation, view_matrix; 345 mat4 projection, camera_rotation, view_matrix;
333 if (camera) { 346 if (camera) {
@@ -347,6 +360,7 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) {
347 360
348 RenderState state = { 361 RenderState state = {
349 .gfxcore = gfxcore, 362 .gfxcore = gfxcore,
363 .llr = renderer->llr,
350 .renderer = renderer, 364 .renderer = renderer,
351 .shader = shader, 365 .shader = shader,
352 .scene = scene, 366 .scene = scene,
diff --git a/src/renderer/renderer_impl.h b/src/renderer/renderer_impl.h
index fc14dcb..6fd0c15 100644
--- a/src/renderer/renderer_impl.h
+++ b/src/renderer/renderer_impl.h
@@ -5,11 +5,13 @@
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7typedef struct IBL IBL; 7typedef struct IBL IBL;
8typedef struct LLR LLR;
8typedef struct ShaderProgram ShaderProgram; 9typedef struct ShaderProgram ShaderProgram;
9typedef struct Texture Texture; 10typedef struct Texture Texture;
10 11
11typedef struct Renderer { 12typedef struct Renderer {
12 GfxCore* gfxcore; 13 GfxCore* gfxcore;
14 LLR* llr;
13 IBL* ibl; 15 IBL* ibl;
14 Texture* brdf_integration_map; 16 Texture* brdf_integration_map;
15 struct { 17 struct {
@@ -21,7 +23,7 @@ typedef struct Renderer {
21} Renderer; 23} Renderer;
22 24
23/// Create a new renderer. 25/// Create a new renderer.
24bool renderer_make(Renderer*, GfxCore*); 26bool gfx_renderer_make(Renderer*, LLR*, GfxCore*);
25 27
26/// Destroy the renderer. 28/// Destroy the renderer.
27void renderer_destroy(Renderer*); 29void gfx_renderer_destroy(Renderer*);
diff --git a/src/scene/node.c b/src/scene/node.c
index 67ce93c..e359f73 100644
--- a/src/scene/node.c
+++ b/src/scene/node.c
@@ -2,7 +2,7 @@
2 2
3#include "animation_impl.h" 3#include "animation_impl.h"
4#include "camera_impl.h" 4#include "camera_impl.h"
5#include "light_impl.h" 5#include "llr/light_impl.h"
6#include "model_impl.h" 6#include "model_impl.h"
7#include "object_impl.h" 7#include "object_impl.h"
8#include "scene_graph.h" 8#include "scene_graph.h"
diff --git a/src/scene/object.c b/src/scene/object.c
index e8e3ee6..27ff5db 100644
--- a/src/scene/object.c
+++ b/src/scene/object.c
@@ -2,7 +2,7 @@
2 2
3#include <gfx/core.h> 3#include <gfx/core.h>
4 4
5#include "mesh_impl.h" 5#include "llr/mesh_impl.h"
6#include "node_impl.h" 6#include "node_impl.h"
7#include "scene_memory.h" 7#include "scene_memory.h"
8 8
diff --git a/src/scene/object_impl.h b/src/scene/object_impl.h
index ead93f1..e864e53 100644
--- a/src/scene/object_impl.h
+++ b/src/scene/object_impl.h
@@ -4,8 +4,6 @@
4 4
5#include "types.h" 5#include "types.h"
6 6
7#include <math/mat4.h>
8
9typedef struct MeshLink { 7typedef struct MeshLink {
10 mesh_idx mesh; 8 mesh_idx mesh;
11 mesh_link_idx next; // Next MeshLink in the list. 9 mesh_link_idx next; // Next MeshLink in the list.
diff --git a/src/scene/scene_memory.c b/src/scene/scene_memory.c
index 91880bb..3a01325 100644
--- a/src/scene/scene_memory.c
+++ b/src/scene/scene_memory.c
@@ -4,9 +4,9 @@
4 4
5#include "animation_impl.h" 5#include "animation_impl.h"
6#include "camera_impl.h" 6#include "camera_impl.h"
7#include "light_impl.h" 7#include "llr/light_impl.h"
8#include "material_impl.h" 8#include "llr/material_impl.h"
9#include "mesh_impl.h" 9#include "llr/mesh_impl.h"
10#include "model_impl.h" 10#include "model_impl.h"
11#include "node_impl.h" 11#include "node_impl.h"
12#include "object_impl.h" 12#include "object_impl.h"
diff --git a/src/util/skyquad.c b/src/util/skyquad.c
index 08fa044..094de67 100644
--- a/src/util/skyquad.c
+++ b/src/util/skyquad.c
@@ -1,18 +1,14 @@
1#include <gfx/util/skyquad.h> 1#include <gfx/util/skyquad.h>
2 2
3#include <gfx/core.h> 3#include <gfx/core.h>
4#include <gfx/gfx.h> 4#include <gfx/llr/light.h>
5#include <gfx/scene/light.h> 5#include <gfx/llr/material.h>
6#include <gfx/scene/material.h> 6#include <gfx/llr/mesh.h>
7#include <gfx/scene/mesh.h>
8#include <gfx/scene/node.h> 7#include <gfx/scene/node.h>
9#include <gfx/scene/object.h> 8#include <gfx/scene/object.h>
10#include <gfx/scene/scene.h>
11#include <gfx/util/geometry.h> 9#include <gfx/util/geometry.h>
12#include <gfx/util/shader.h> 10#include <gfx/util/shader.h>
13 11
14#include <math/vec4.h>
15
16#include <assert.h> 12#include <assert.h>
17 13
18SceneObject* gfx_make_skyquad(GfxCore* gfxcore, const Texture* texture) { 14SceneObject* gfx_make_skyquad(GfxCore* gfxcore, const Texture* texture) {
@@ -36,10 +32,9 @@ SceneObject* gfx_make_skyquad(GfxCore* gfxcore, const Texture* texture) {
36 } 32 }
37 33
38 MaterialDesc material_desc = (MaterialDesc){0}; 34 MaterialDesc material_desc = (MaterialDesc){0};
39 material_desc.uniforms[0] = (ShaderUniform){ 35 material_desc.uniforms[0] = (ShaderUniform){.type = UniformTexture,
40 .type = UniformTexture, 36 .value.texture = texture,
41 .value.texture = texture, 37 .name = sstring_make("Skyquad")};
42 .name = sstring_make("Skyquad")};
43 material_desc.num_uniforms = 1; 38 material_desc.num_uniforms = 1;
44 material = gfx_make_material(&material_desc); 39 material = gfx_make_material(&material_desc);
45 if (!material) { 40 if (!material) {