aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/renderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/renderer.c')
-rw-r--r--src/renderer/renderer.c255
1 files changed, 53 insertions, 202 deletions
diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c
index c2a7dda..29a1813 100644
--- a/src/renderer/renderer.c
+++ b/src/renderer/renderer.c
@@ -1,10 +1,9 @@
1#include "renderer_impl.h" 1#include "renderer_impl.h"
2 2
3#include "llr/light_impl.h"
4#include "llr/mesh_impl.h"
3#include "scene/animation_impl.h" 5#include "scene/animation_impl.h"
4#include "scene/camera_impl.h" 6#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" 7#include "scene/model_impl.h"
9#include "scene/node_impl.h" 8#include "scene/node_impl.h"
10#include "scene/object_impl.h" 9#include "scene/object_impl.h"
@@ -12,41 +11,30 @@
12#include "scene/scene_memory.h" 11#include "scene/scene_memory.h"
13 12
14#include <gfx/core.h> 13#include <gfx/core.h>
15#include <gfx/util/ibl.h> 14#include <gfx/llr/llr.h>
16#include <gfx/util/shader.h> 15#include <gfx/util/shader.h>
17 16
18#include <log/log.h>
19#include <math/mat4.h> 17#include <math/mat4.h>
20#include <math/spatial3.h>
21 18
22#include <assert.h> 19#include <assert.h>
23 20
24// TODO: Move to a header like "constants.h". 21bool gfx_renderer_make(Renderer* renderer, LLR* llr, GfxCore* gfxcore) {
25static const int IRRADIANCE_MAP_WIDTH = 1024;
26static const int IRRADIANCE_MAP_HEIGHT = 1024;
27static const int PREFILTERED_ENVIRONMENT_MAP_WIDTH = 128;
28static const int PREFILTERED_ENVIRONMENT_MAP_HEIGHT = 128;
29static const int BRDF_INTEGRATION_MAP_WIDTH = 512;
30static const int BRDF_INTEGRATION_MAP_HEIGHT = 512;
31
32bool renderer_make(Renderer* renderer, GfxCore* gfxcore) {
33 assert(renderer); 22 assert(renderer);
23 assert(llr);
34 assert(gfxcore); 24 assert(gfxcore);
35 25
36 renderer->gfxcore = gfxcore; 26 renderer->gfxcore = gfxcore;
27 renderer->llr = llr;
37 28
38 return true; 29 return true;
39} 30}
40 31
41void renderer_destroy(Renderer* renderer) { 32void gfx_renderer_destroy(Renderer* renderer) {
42 if (!renderer) { 33 if (!renderer) {
43 return; 34 return;
44 } 35 }
45 assert(renderer->gfxcore); 36 assert(renderer->gfxcore);
46 GfxCore* gfxcore = renderer->gfxcore; 37 GfxCore* gfxcore = renderer->gfxcore;
47 if (renderer->ibl) {
48 gfx_destroy_ibl(gfxcore, &renderer->ibl);
49 }
50 if (renderer->shaders.debug) { 38 if (renderer->shaders.debug) {
51 gfx_destroy_shader_program(gfxcore, &renderer->shaders.debug); 39 gfx_destroy_shader_program(gfxcore, &renderer->shaders.debug);
52 } 40 }
@@ -62,24 +50,6 @@ void renderer_destroy(Renderer* renderer) {
62 } 50 }
63} 51}
64 52
65/// Initialize renderer state for IBL if not already initialized.
66static bool init_ibl(Renderer* renderer) {
67 assert(renderer);
68
69 if (!renderer->ibl && !(renderer->ibl = gfx_make_ibl(renderer->gfxcore))) {
70 return false;
71 }
72
73 if (!renderer->brdf_integration_map &&
74 !(renderer->brdf_integration_map = gfx_make_brdf_integration_map(
75 renderer->ibl, renderer->gfxcore, BRDF_INTEGRATION_MAP_WIDTH,
76 BRDF_INTEGRATION_MAP_HEIGHT))) {
77 return false;
78 }
79
80 return true;
81}
82
83static ShaderProgram* load_shader(Renderer* renderer, RenderSceneMode mode) { 53static ShaderProgram* load_shader(Renderer* renderer, RenderSceneMode mode) {
84 assert(renderer); 54 assert(renderer);
85 55
@@ -117,89 +87,17 @@ static ShaderProgram* load_shader(Renderer* renderer, RenderSceneMode mode) {
117// } 87// }
118// } 88// }
119 89
120/// Computes irradiance and prefiltered environment maps for the light if they
121/// have not been already computed.
122static bool setup_environment_light(
123 Renderer* renderer, GfxCore* gfxcore, EnvironmentLight* light) {
124 assert(renderer);
125 assert(light);
126
127 if (!init_ibl(renderer)) {
128 return false;
129 }
130
131 if (light->irradiance_map) {
132 assert(light->prefiltered_environment_map);
133 return true;
134 }
135
136 Texture* irradiance_map = 0;
137 Texture* prefiltered_environment_map = 0;
138
139 if (!(irradiance_map = gfx_make_irradiance_map(
140 renderer->ibl, gfxcore, light->environment_map,
141 IRRADIANCE_MAP_WIDTH, IRRADIANCE_MAP_HEIGHT))) {
142 goto cleanup;
143 }
144
145 int max_mip_level = 0;
146 if (!(prefiltered_environment_map = gfx_make_prefiltered_environment_map(
147 renderer->ibl, gfxcore, light->environment_map,
148 PREFILTERED_ENVIRONMENT_MAP_WIDTH,
149 PREFILTERED_ENVIRONMENT_MAP_HEIGHT, &max_mip_level))) {
150 goto cleanup;
151 }
152
153 light->irradiance_map = irradiance_map;
154 light->prefiltered_environment_map = prefiltered_environment_map;
155 light->max_reflection_lod = max_mip_level;
156
157 return true;
158
159cleanup:
160 if (irradiance_map) {
161 gfx_destroy_texture(gfxcore, &irradiance_map);
162 }
163 if (prefiltered_environment_map) {
164 gfx_destroy_texture(gfxcore, &prefiltered_environment_map);
165 }
166 return false;
167}
168
169typedef struct RenderState { 90typedef struct RenderState {
170 GfxCore* gfxcore; 91 GfxCore* gfxcore;
92 LLR* llr;
171 Renderer* renderer; 93 Renderer* renderer;
172 ShaderProgram* shader; // Null to use scene shaders. 94 ShaderProgram* shader; // Null to use scene shaders.
173 const Scene* scene; 95 const Scene* scene;
174 const Camera* camera;
175 const mat4* camera_rotation; // From camera to world space, rotation only.
176 const mat4* view_matrix;
177 const mat4* projection;
178 const float fovy;
179 const float aspect;
180 Light* environment_light;
181 const Anima* anima; 96 const Anima* anima;
182 size_t num_joints;
183 mat4 joint_matrices[GFX_MAX_NUM_JOINTS];
184} RenderState; 97} RenderState;
185 98
186/// Load joint matrices into the render state. 99static void draw_children(
187static void load_skeleton(RenderState* state, skeleton_idx skeleton_index) { 100 RenderState* state, const mat4* node_transform, const SceneNode* node);
188 assert(state);
189 assert(skeleton_index.val != 0);
190
191 const Skeleton* skeleton = mem_get_skeleton(skeleton_index);
192 assert(skeleton);
193 assert(skeleton->num_joints <= GFX_MAX_NUM_JOINTS);
194
195 state->num_joints = skeleton->num_joints;
196
197 for (size_t i = 0; i < skeleton->num_joints; ++i) {
198 const joint_idx joint_index = skeleton->joints[i];
199 const Joint* joint = &state->anima->joints[joint_index];
200 state->joint_matrices[i] = joint->joint_matrix;
201 }
202}
203 101
204/// Draw the scene recursively. 102/// Draw the scene recursively.
205static void draw_recursively( 103static void draw_recursively(
@@ -209,26 +107,27 @@ static void draw_recursively(
209 107
210 // Anima. 108 // Anima.
211 if (node->type == AnimaNode) { 109 if (node->type == AnimaNode) {
110 // Save the anima so that we can animate objects.
212 state->anima = gfx_get_node_anima(node); 111 state->anima = gfx_get_node_anima(node);
112
113 draw_children(state, &node_transform, node);
213 } 114 }
214 // Activate light. 115 // Activate light.
215 else if (node->type == LightNode) { 116 else if (node->type == LightNode) {
216 Light* light = mem_get_light(node->light); 117 Light* light = mem_get_light(node->light);
217 assert(light); 118 assert(light);
218 119 gfx_llr_push_light(state->llr, light);
219 if (light->type == EnvironmentLightType) { 120 {
220 bool result = setup_environment_light( 121 draw_children(state, &node_transform, node);
221 state->renderer, state->gfxcore, &light->environment);
222 // TODO: Handle the result in a better way.
223 assert(result);
224 state->environment_light = light;
225 } 122 }
123 gfx_llr_pop_light(state->llr);
226 } 124 }
227 // Model. 125 // Model.
228 else if (node->type == ModelNode) { 126 else if (node->type == ModelNode) {
229 const Model* model = gfx_get_node_model(node); 127 const Model* model = gfx_get_node_model(node);
230 const SceneNode* root = mem_get_node(model->root); 128 const SceneNode* root = mem_get_node(model->root);
231 draw_recursively(state, parent_transform, root); 129 draw_recursively(state, parent_transform, root);
130 draw_children(state, &node_transform, node);
232 } 131 }
233 // Render object. 132 // Render object.
234 else if (node->type == ObjectNode) { 133 else if (node->type == ObjectNode) {
@@ -237,16 +136,15 @@ static void draw_recursively(
237 136
238 // TODO: Here we would frustum-cull the object. 137 // TODO: Here we would frustum-cull the object.
239 138
240 // TODO: Avoid computing matrices like Modelview or MVP if the shader does 139 // A model/anima can have many skeletons. We need to animate the given
241 // not use them. 140 // object using its skeleton, not just any skeleton of the anima.
242 const mat4 model_matrix = node_transform;
243 const mat4 modelview = mat4_mul(*state->view_matrix, model_matrix);
244 const mat4 mvp = mat4_mul(*state->projection, modelview);
245
246 if (object->skeleton.val) { 141 if (object->skeleton.val) {
247 load_skeleton(state, object->skeleton); 142 const Skeleton* skeleton = mem_get_skeleton(object->skeleton);
143 gfx_llr_set_skeleton(state->llr, state->anima, skeleton);
248 } 144 }
249 145
146 const mat4 model_matrix = node_transform;
147
250 for (mesh_link_idx mesh_link_index = object->mesh_link; 148 for (mesh_link_idx mesh_link_index = object->mesh_link;
251 mesh_link_index.val;) { 149 mesh_link_index.val;) {
252 const MeshLink* mesh_link = mem_get_mesh_link(mesh_link_index); 150 const MeshLink* mesh_link = mem_get_mesh_link(mesh_link_index);
@@ -256,63 +154,34 @@ static void draw_recursively(
256 if (!mesh) { 154 if (!mesh) {
257 continue; 155 continue;
258 } 156 }
259 assert(mesh->geometry);
260 assert(mesh->material);
261 157
262 // TODO: Here we would frustum-cull the mesh. The AABB would have to be 158 // 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 159 // transformed by the model matrix. Rotation would make the AABB
264 // relatively large, but still, the culling would be conservative. 160 // relatively large, but still, the culling would be conservative.
265 161
266 // Apply common shader uniforms not captured by materials.
267 ShaderProgram* shader = state->shader ? state->shader : mesh->shader; 162 ShaderProgram* shader = state->shader ? state->shader : mesh->shader;
268 gfx_set_mat4_uniform(shader, "ModelMatrix", &model_matrix); 163 gfx_llr_set_shader(state->llr, shader);
269 gfx_set_mat4_uniform(shader, "Modelview", &modelview); 164 gfx_llr_set_model_matrix(state->llr, &model_matrix);
270 gfx_set_mat4_uniform(shader, "View", state->view_matrix); 165 gfx_llr_render_mesh(state->llr, mesh);
271 gfx_set_mat4_uniform(shader, "Projection", state->projection);
272 gfx_set_mat4_uniform(shader, "MVP", &mvp);
273 gfx_set_mat4_uniform(shader, "CameraRotation", state->camera_rotation);
274 gfx_set_float_uniform(shader, "Fovy", state->fovy);
275 gfx_set_float_uniform(shader, "Aspect", state->aspect);
276 if (state->camera) {
277 gfx_set_vec3_uniform(
278 shader, "CameraPosition", state->camera->spatial.p);
279 }
280 if (state->num_joints > 0) {
281 gfx_set_mat4_array_uniform(
282 shader, "JointMatrices", state->joint_matrices, state->num_joints);
283 }
284 // Apply lights.
285 if (state->environment_light) {
286 const EnvironmentLight* light = &state->environment_light->environment;
287 assert(light->environment_map);
288 assert(light->irradiance_map);
289 assert(light->prefiltered_environment_map);
290 assert(state->renderer->brdf_integration_map);
291 gfx_set_texture_uniform(
292 shader, "BRDFIntegrationMap",
293 state->renderer->brdf_integration_map);
294 gfx_set_texture_uniform(shader, "Sky", light->environment_map);
295 gfx_set_texture_uniform(shader, "IrradianceMap", light->irradiance_map);
296 gfx_set_texture_uniform(
297 shader, "PrefilteredEnvironmentMap",
298 light->prefiltered_environment_map);
299 gfx_set_float_uniform(
300 shader, "MaxReflectionLOD", light->max_reflection_lod);
301 }
302 material_activate(shader, mesh->material);
303 gfx_activate_shader_program(shader);
304 gfx_apply_uniforms(shader);
305 gfx_render_geometry(mesh->geometry);
306 } 166 }
307 167
308 // Reset state for next object. 168 if (object->skeleton.val) {
309 state->num_joints = 0; 169 gfx_llr_clear_skeleton(state->llr);
170 }
171
172 draw_children(state, &node_transform, node);
173 } else {
174 draw_children(state, &node_transform, node);
310 } 175 }
176}
311 177
178/// Draw the node's children.
179static void draw_children(
180 RenderState* state, const mat4* node_transform, const SceneNode* node) {
312 // Render children recursively. 181 // Render children recursively.
313 for (node_idx child_index = node->child; child_index.val;) { 182 for (node_idx child_index = node->child; child_index.val;) {
314 const SceneNode* child = mem_get_node(child_index); 183 const SceneNode* child = mem_get_node(child_index);
315 draw_recursively(state, node_transform, child); 184 draw_recursively(state, *node_transform, child);
316 child_index = child->next; 185 child_index = child->next;
317 } 186 }
318} 187}
@@ -324,41 +193,23 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) {
324 193
325 ShaderProgram* const shader = load_shader(renderer, params->mode); 194 ShaderProgram* const shader = load_shader(renderer, params->mode);
326 195
327 const Scene* scene = params->scene; 196 const Scene* scene = params->scene;
328 const SceneCamera* camera = params->camera; 197 const SceneCamera* camera = params->camera;
329 198 GfxCore* const gfxcore = renderer->gfxcore;
330 GfxCore* gfxcore = renderer->gfxcore;
331
332 mat4 projection, camera_rotation, view_matrix;
333 if (camera) {
334 projection = camera->camera.projection;
335 camera_rotation =
336 mat4_rotation(spatial3_transform(&camera->camera.spatial));
337 view_matrix = spatial3_inverse_transform(&camera->camera.spatial);
338 } else {
339 projection = mat4_id();
340 camera_rotation = mat4_id();
341 view_matrix = mat4_id();
342 }
343 199
344 int x, y, width, height; 200 int x, y, width, height;
345 gfx_get_viewport(gfxcore, &x, &y, &width, &height); 201 gfx_get_viewport(gfxcore, &x, &y, &width, &height);
346 const float aspect = (float)width / (float)height; 202 const R aspect = (R)width / (R)height;
347 203
348 RenderState state = { 204 RenderState state = {
349 .gfxcore = gfxcore, 205 .gfxcore = gfxcore,
350 .renderer = renderer, 206 .llr = renderer->llr,
351 .shader = shader, 207 .renderer = renderer,
352 .scene = scene, 208 .shader = shader,
353 .camera = &camera->camera, 209 .scene = scene};
354 .camera_rotation = &camera_rotation, 210
355 .view_matrix = &view_matrix, 211 gfx_llr_set_camera(renderer->llr, &camera->camera);
356 .projection = &projection, 212 gfx_llr_set_aspect(renderer->llr, aspect);
357 .environment_light = 0,
358 // Assuming a perspective matrix.
359 .fovy = atan(1.0 / (mat4_at(projection, 1, 1))) * 2,
360 .aspect = aspect};
361
362 draw_recursively(&state, mat4_id(), scene->root); 213 draw_recursively(&state, mat4_id(), scene->root);
363} 214}
364 215