aboutsummaryrefslogtreecommitdiff
path: root/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer')
-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
4 files changed, 269 insertions, 18 deletions
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*);