aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asset/model.c34
-rw-r--r--src/core/geometry.c73
-rw-r--r--src/core/shader_program.c29
-rw-r--r--src/memory.c4
-rw-r--r--src/render/imm.c14
-rw-r--r--src/render/llr.c119
-rw-r--r--src/render/llr_impl.h31
-rw-r--r--src/render/renderer.c5
-rw-r--r--src/scene/light.c39
-rw-r--r--src/scene/light_impl.h20
-rw-r--r--src/scene/material.c24
-rw-r--r--src/scene/material_impl.h13
-rw-r--r--src/scene/mesh.c26
-rw-r--r--src/scene/mesh_impl.h11
-rw-r--r--src/scene/object.c3
-rw-r--r--src/util/geometry.c13
16 files changed, 247 insertions, 211 deletions
diff --git a/src/asset/model.c b/src/asset/model.c
index a97d20e..b5c6b0d 100644
--- a/src/asset/model.c
+++ b/src/asset/model.c
@@ -1030,7 +1030,6 @@ static bool load_meshes(
1030 const cgltf_attribute* attrib = &prim->attributes[a]; 1030 const cgltf_attribute* attrib = &prim->attributes[a];
1031 const cgltf_accessor* accessor = attrib->data; 1031 const cgltf_accessor* accessor = attrib->data;
1032 const cgltf_buffer_view* view = accessor->buffer_view; 1032 const cgltf_buffer_view* view = accessor->buffer_view;
1033 const cgltf_size offset = accessor->offset + view->offset;
1034 const cgltf_size buffer_index = view->buffer - data->buffers; 1033 const cgltf_size buffer_index = view->buffer - data->buffers;
1035 1034
1036 assert(buffer_index < data->buffers_count); 1035 assert(buffer_index < data->buffers_count);
@@ -1120,12 +1119,20 @@ static bool load_meshes(
1120 break; 1119 break;
1121 } 1120 }
1122 1121
1123#define CONFIGURE_BUFFER(buf) \ 1122 // See comments here for accessor/view/buffer invariants:
1124 if (buf) { \ 1123 // https://github.com/KhronosGroup/glTF-Sample-Assets/issues/242
1125 buf->buffer = buffer; \ 1124 // Gfx only has Buffer and BufferView, not accessors. We must combine
1126 buf->offset_bytes = offset; \ 1125 // the glTF's accessor and view offsets correctly.
1127 buf->size_bytes = view->size; \ 1126 const cgltf_size offset = accessor->offset + view->offset;
1128 buf->stride_bytes = view->stride; \ 1127 const cgltf_size size_bytes = view->size - accessor->offset;
1128
1129#define CONFIGURE_BUFFER(buf) \
1130 if (buf) { \
1131 buf->buffer = buffer; \
1132 buf->offset_bytes = offset; \
1133 buf->size_bytes = size_bytes; \
1134 buf->stride_bytes = view->stride; \
1135 buf->count = accessor->count; \
1129 } 1136 }
1130 CONFIGURE_BUFFER(buffer_view_2d); 1137 CONFIGURE_BUFFER(buffer_view_2d);
1131 CONFIGURE_BUFFER(buffer_view_3d); 1138 CONFIGURE_BUFFER(buffer_view_3d);
@@ -1160,14 +1167,11 @@ static bool load_meshes(
1160 // either 2d or 3d positions but not both, here we can perform addition 1167 // either 2d or 3d positions but not both, here we can perform addition
1161 // to compute the total number of vertices. 1168 // to compute the total number of vertices.
1162 geometry_desc.num_verts = 1169 geometry_desc.num_verts =
1163 (geometry_desc.positions2d.size_bytes / sizeof(vec2)) + 1170 geometry_desc.positions2d.count + geometry_desc.positions3d.count;
1164 (geometry_desc.positions3d.size_bytes / sizeof(vec3)); 1171
1165 1172#define CHECK_COUNT(buffer_view, type, num_components) \
1166#define CHECK_COUNT(buffer_view, type, num_components) \ 1173 if (geometry_desc.buffer_view.buffer) { \
1167 if (geometry_desc.buffer_view.buffer) { \ 1174 assert(geometry_desc.buffer_view.count == geometry_desc.num_verts); \
1168 assert( \
1169 (geometry_desc.buffer_view.size_bytes / \
1170 (num_components * sizeof(type))) == geometry_desc.num_verts); \
1171 } 1175 }
1172 1176
1173 // Check that the number of vertices is consistent across all vertex 1177 // Check that the number of vertices is consistent across all vertex
diff --git a/src/core/geometry.c b/src/core/geometry.c
index cfc749f..488dc23 100644
--- a/src/core/geometry.c
+++ b/src/core/geometry.c
@@ -12,7 +12,7 @@
12/// 12///
13/// Note that views are allowed to have no data, in which case a buffer of the 13/// Note that views are allowed to have no data, in which case a buffer of the
14/// specified size is created. 14/// specified size is created.
15#define view_is_populated(BUFFER_VIEW) (BUFFER_VIEW.size_bytes > 0) 15#define view_is_populated(BUFFER_VIEW) (BUFFER_VIEW.count > 0)
16 16
17static GLenum primitive_type_to_gl(PrimitiveType type) { 17static GLenum primitive_type_to_gl(PrimitiveType type) {
18 switch (type) { 18 switch (type) {
@@ -34,30 +34,25 @@ void init_view_buffer(
34 BufferUsage buffer_usage) { 34 BufferUsage buffer_usage) {
35 if (!view->buffer) { 35 if (!view->buffer) {
36 view->buffer = gfx_make_buffer( 36 view->buffer = gfx_make_buffer(
37 gfxcore, 37 gfxcore, &(BufferDesc){.usage = buffer_usage,
38 &(BufferDesc){ 38 .type = buffer_type,
39 .usage = buffer_usage, 39 .data.data = view->data,
40 .type = buffer_type, 40 .data.count = view->count});
41 .data.data = view->data, 41 assert(view->buffer);
42 .data.count = view->size_bytes /
43 gfx_get_buffer_type_size_bytes(buffer_type)});
44 } 42 }
45 assert(view->size_bytes <= view->buffer->size_bytes);
46} 43}
47 44
48/// Configure the buffer in teh VAO. 45/// Configure the buffer in the VAO.
49static void configure_buffer( 46static void configure_buffer(
50 GfxCore* gfxcore, const GeometryDesc* desc, BufferView* view, 47 GfxCore* gfxcore, const GeometryDesc* desc, BufferView* view,
51 size_t num_components, size_t component_size_bytes, GLenum component_type, 48 size_t num_components, GLenum component_type, GLboolean normalized,
52 GLboolean normalized, GLuint channel) { 49 GLuint channel) {
53 assert(gfxcore); 50 assert(gfxcore);
54 assert(desc); 51 assert(desc);
55 assert(view); 52 assert(view);
56 assert(view->buffer); 53 assert(view->buffer);
57 assert( 54 assert(view->count == desc->num_verts);
58 desc->num_verts <= 55 assert((view->offset_bytes + view->size_bytes) <= view->buffer->size_bytes);
59 view->size_bytes / (num_components * component_size_bytes));
60 assert(view->size_bytes <= view->buffer->size_bytes);
61 56
62 glBindBuffer(GL_ARRAY_BUFFER, view->buffer->vbo); 57 glBindBuffer(GL_ARRAY_BUFFER, view->buffer->vbo);
63 glEnableVertexAttribArray(channel); 58 glEnableVertexAttribArray(channel);
@@ -89,8 +84,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
89 return false; 84 return false;
90 } 85 }
91 configure_buffer( 86 configure_buffer(
92 gfxcore, desc, (BufferView*)&desc->positions3d, 3, sizeof(float), 87 gfxcore, desc, (BufferView*)&desc->positions3d, 3, GL_FLOAT, GL_FALSE,
93 GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL); 88 GFX_POSITION_CHANNEL);
94 } else if (view_is_populated(desc->positions2d)) { 89 } else if (view_is_populated(desc->positions2d)) {
95 init_view_buffer( 90 init_view_buffer(
96 gfxcore, (BufferView*)&desc->positions2d, Buffer2d, desc->buffer_usage); 91 gfxcore, (BufferView*)&desc->positions2d, Buffer2d, desc->buffer_usage);
@@ -98,8 +93,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
98 return false; 93 return false;
99 } 94 }
100 configure_buffer( 95 configure_buffer(
101 gfxcore, desc, (BufferView*)&desc->positions2d, 2, sizeof(float), 96 gfxcore, desc, (BufferView*)&desc->positions2d, 2, GL_FLOAT, GL_FALSE,
102 GL_FLOAT, GL_FALSE, GFX_POSITION_CHANNEL); 97 GFX_POSITION_CHANNEL);
103 } 98 }
104 if (view_is_populated(desc->normals)) { 99 if (view_is_populated(desc->normals)) {
105 init_view_buffer( 100 init_view_buffer(
@@ -108,8 +103,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
108 return false; 103 return false;
109 } 104 }
110 configure_buffer( 105 configure_buffer(
111 gfxcore, desc, (BufferView*)&desc->normals, 3, sizeof(float), GL_FLOAT, 106 gfxcore, desc, (BufferView*)&desc->normals, 3, GL_FLOAT, GL_FALSE,
112 GL_FALSE, GFX_NORMAL_CHANNEL); 107 GFX_NORMAL_CHANNEL);
113 } 108 }
114 if (view_is_populated(desc->tangents)) { 109 if (view_is_populated(desc->tangents)) {
115 init_view_buffer( 110 init_view_buffer(
@@ -118,8 +113,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
118 return false; 113 return false;
119 } 114 }
120 configure_buffer( 115 configure_buffer(
121 gfxcore, desc, (BufferView*)&desc->tangents, 4, sizeof(float), GL_FLOAT, 116 gfxcore, desc, (BufferView*)&desc->tangents, 4, GL_FLOAT, GL_FALSE,
122 GL_FALSE, GFX_TANGENT_CHANNEL); 117 GFX_TANGENT_CHANNEL);
123 } 118 }
124 if (view_is_populated(desc->texcoords)) { 119 if (view_is_populated(desc->texcoords)) {
125 init_view_buffer( 120 init_view_buffer(
@@ -128,8 +123,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
128 return false; 123 return false;
129 } 124 }
130 configure_buffer( 125 configure_buffer(
131 gfxcore, desc, (BufferView*)&desc->texcoords, 2, sizeof(float), 126 gfxcore, desc, (BufferView*)&desc->texcoords, 2, GL_FLOAT, GL_FALSE,
132 GL_FLOAT, GL_FALSE, GFX_TEXCOORDS_CHANNEL); 127 GFX_TEXCOORDS_CHANNEL);
133 } 128 }
134 if (view_is_populated(desc->joints.u8)) { 129 if (view_is_populated(desc->joints.u8)) {
135 init_view_buffer( 130 init_view_buffer(
@@ -138,8 +133,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
138 return false; 133 return false;
139 } 134 }
140 configure_buffer( 135 configure_buffer(
141 gfxcore, desc, (BufferView*)&desc->joints.u8, 4, sizeof(uint8_t), 136 gfxcore, desc, (BufferView*)&desc->joints.u8, 4, GL_UNSIGNED_BYTE,
142 GL_UNSIGNED_BYTE, GL_FALSE, GFX_JOINTS_CHANNEL); 137 GL_FALSE, GFX_JOINTS_CHANNEL);
143 } else if (view_is_populated(desc->joints.u16)) { 138 } else if (view_is_populated(desc->joints.u16)) {
144 init_view_buffer( 139 init_view_buffer(
145 gfxcore, (BufferView*)&desc->joints.u16, BufferU16, desc->buffer_usage); 140 gfxcore, (BufferView*)&desc->joints.u16, BufferU16, desc->buffer_usage);
@@ -147,8 +142,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
147 return false; 142 return false;
148 } 143 }
149 configure_buffer( 144 configure_buffer(
150 gfxcore, desc, (BufferView*)&desc->joints.u16, 4, sizeof(uint16_t), 145 gfxcore, desc, (BufferView*)&desc->joints.u16, 4, GL_UNSIGNED_SHORT,
151 GL_UNSIGNED_SHORT, GL_FALSE, GFX_JOINTS_CHANNEL); 146 GL_FALSE, GFX_JOINTS_CHANNEL);
152 } 147 }
153 148
154 // If weights are given as unsigned integers, then they are normalized 149 // If weights are given as unsigned integers, then they are normalized
@@ -160,8 +155,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
160 return false; 155 return false;
161 } 156 }
162 configure_buffer( 157 configure_buffer(
163 gfxcore, desc, (BufferView*)&desc->weights.u8, 4, sizeof(uint8_t), 158 gfxcore, desc, (BufferView*)&desc->weights.u8, 4, GL_UNSIGNED_BYTE,
164 GL_UNSIGNED_BYTE, GL_TRUE, GFX_WEIGHTS_CHANNEL); 159 GL_TRUE, GFX_WEIGHTS_CHANNEL);
165 } else if (view_is_populated(desc->weights.u16)) { 160 } else if (view_is_populated(desc->weights.u16)) {
166 init_view_buffer( 161 init_view_buffer(
167 gfxcore, (BufferView*)&desc->weights.u16, BufferU16, 162 gfxcore, (BufferView*)&desc->weights.u16, BufferU16,
@@ -170,8 +165,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
170 return false; 165 return false;
171 } 166 }
172 configure_buffer( 167 configure_buffer(
173 gfxcore, desc, (BufferView*)&desc->weights.u16, 4, sizeof(uint16_t), 168 gfxcore, desc, (BufferView*)&desc->weights.u16, 4, GL_UNSIGNED_SHORT,
174 GL_UNSIGNED_SHORT, GL_TRUE, GFX_WEIGHTS_CHANNEL); 169 GL_TRUE, GFX_WEIGHTS_CHANNEL);
175 } else if (view_is_populated(desc->weights.floats)) { 170 } else if (view_is_populated(desc->weights.floats)) {
176 init_view_buffer( 171 init_view_buffer(
177 gfxcore, (BufferView*)&desc->weights.floats, BufferFloat, 172 gfxcore, (BufferView*)&desc->weights.floats, BufferFloat,
@@ -180,8 +175,8 @@ static bool configure_vertex_attributes(GfxCore* gfxcore, GeometryDesc* desc) {
180 return false; 175 return false;
181 } 176 }
182 configure_buffer( 177 configure_buffer(
183 gfxcore, desc, (BufferView*)&desc->weights.floats, 4, sizeof(float), 178 gfxcore, desc, (BufferView*)&desc->weights.floats, 4, GL_FLOAT,
184 GL_FLOAT, GL_FALSE, GFX_WEIGHTS_CHANNEL); 179 GL_FALSE, GFX_WEIGHTS_CHANNEL);
185 } 180 }
186 181
187 return true; 182 return true;
@@ -282,9 +277,9 @@ void gfx_update_geometry(Geometry* geometry, const GeometryDesc* desc) {
282 assert(geometry->desc.positions3d.buffer); 277 assert(geometry->desc.positions3d.buffer);
283 gfx_update_buffer( 278 gfx_update_buffer(
284 geometry->desc.positions3d.buffer, 279 geometry->desc.positions3d.buffer,
285 &(BufferDataDesc){ 280 &(BufferDataDesc){.vec3s = desc->positions3d.data,
286 .vec3s = desc->positions3d.data, 281 .count =
287 .count = desc->positions3d.size_bytes / sizeof(vec3)}); 282 desc->positions3d.size_bytes / sizeof(vec3)});
288 } 283 }
289 // TODO: more 284 // TODO: more
290 else { 285 else {
diff --git a/src/core/shader_program.c b/src/core/shader_program.c
index eeb46f8..3840019 100644
--- a/src/core/shader_program.c
+++ b/src/core/shader_program.c
@@ -209,6 +209,35 @@ static ShaderUniform* get_or_allocate_uniform(
209// The functions below save the value of a uniform in the shader program. If the 209// The functions below save the value of a uniform in the shader program. If the
210// uniform does not even exist, then there is no need to store the value. 210// uniform does not even exist, then there is no need to store the value.
211 211
212void gfx_set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) {
213 switch (uniform->type) {
214 case UniformInt:
215 gfx_set_int_uniform(prog, uniform->name.str, uniform->value.uniform_int);
216 break;
217 case UniformFloat:
218 gfx_set_float_uniform(
219 prog, uniform->name.str, uniform->value.uniform_float);
220 break;
221 case UniformMat4:
222 gfx_set_mat4_uniform(prog, uniform->name.str, &uniform->value.uniform_mat4);
223 break;
224 case UniformVec3:
225 gfx_set_vec3_uniform(prog, uniform->name.str, uniform->value.uniform_vec3);
226 break;
227 case UniformVec4:
228 gfx_set_vec4_uniform(prog, uniform->name.str, uniform->value.uniform_vec4);
229 break;
230 case UniformTexture:
231 gfx_set_texture_uniform(prog, uniform->name.str, uniform->value.texture);
232 break;
233 case UniformMat4Array:
234 gfx_set_mat4_array_uniform(
235 prog, uniform->name.str, uniform->value.array.values,
236 uniform->value.array.count);
237 break;
238 }
239}
240
212void gfx_set_int_uniform(ShaderProgram* prog, const char* name, int value) { 241void gfx_set_int_uniform(ShaderProgram* prog, const char* name, int value) {
213 assert(prog); 242 assert(prog);
214 assert(name); 243 assert(name);
diff --git a/src/memory.c b/src/memory.c
index de20f78..754f04d 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -4,7 +4,9 @@
4#include <gfx/sizes.h> 4#include <gfx/sizes.h>
5 5
6#include "animation_impl.h" 6#include "animation_impl.h"
7#include "render/llr_impl.h" 7#include "scene/light_impl.h"
8#include "scene/material_impl.h"
9#include "scene/mesh_impl.h"
8#include "scene/model_impl.h" 10#include "scene/model_impl.h"
9#include "scene/node_impl.h" 11#include "scene/node_impl.h"
10#include "scene/object_impl.h" 12#include "scene/object_impl.h"
diff --git a/src/render/imm.c b/src/render/imm.c
index 8a93488..7ab8d62 100644
--- a/src/render/imm.c
+++ b/src/render/imm.c
@@ -21,12 +21,14 @@ bool gfx_imm_make(Imm* renderer, GfxCore* gfxcore, LLR* llr) {
21 renderer->llr = llr; 21 renderer->llr = llr;
22 22
23 renderer->triangles = gfx_make_geometry( 23 renderer->triangles = gfx_make_geometry(
24 gfxcore, 24 gfxcore, &(GeometryDesc){
25 &(GeometryDesc){.type = Triangles, 25 .type = Triangles,
26 .buffer_usage = BufferDynamic, 26 .buffer_usage = BufferDynamic,
27 .num_verts = num_triangle_verts, 27 .num_verts = num_triangle_verts,
28 .positions3d = (BufferView3d){ 28 .positions3d = (BufferView3d){
29 .size_bytes = num_triangle_verts * sizeof(vec3)}}); 29 .size_bytes = num_triangle_verts * sizeof(vec3),
30 .count = num_triangle_verts}
31 });
30 if (!renderer->triangles) { 32 if (!renderer->triangles) {
31 goto cleanup; 33 goto cleanup;
32 } 34 }
diff --git a/src/render/llr.c b/src/render/llr.c
index c9c6d34..752b65b 100644
--- a/src/render/llr.c
+++ b/src/render/llr.c
@@ -1,14 +1,15 @@
1#include "llr_impl.h" 1#include "llr_impl.h"
2 2
3#include "animation_impl.h" 3#include "animation_impl.h"
4#include "memory.h" 4#include "scene/light_impl.h"
5#include "scene/material_impl.h"
6#include "scene/mesh_impl.h"
5#include "scene/node_impl.h" 7#include "scene/node_impl.h"
6 8
7#include <gfx/core.h> 9#include <gfx/core.h>
8#include <gfx/util/ibl.h> 10#include <gfx/util/ibl.h>
9 11
10#include <cassert.h> 12#include <cassert.h>
11#include <error.h>
12 13
13static const int IRRADIANCE_MAP_WIDTH = 1024; 14static const int IRRADIANCE_MAP_WIDTH = 1024;
14static const int IRRADIANCE_MAP_HEIGHT = 1024; 15static const int IRRADIANCE_MAP_HEIGHT = 1024;
@@ -17,108 +18,23 @@ static const int PREFILTERED_ENVIRONMENT_MAP_HEIGHT = 128;
17static const int BRDF_INTEGRATION_MAP_WIDTH = 512; 18static const int BRDF_INTEGRATION_MAP_WIDTH = 512;
18static const int BRDF_INTEGRATION_MAP_HEIGHT = 512; 19static const int BRDF_INTEGRATION_MAP_HEIGHT = 512;
19 20
20static void make_environment_light(
21 Light* light, const EnvironmentLightDesc* desc) {
22 assert(light);
23 assert(desc);
24 light->type = EnvironmentLightType;
25 light->environment.environment_map = desc->environment_map;
26}
27
28Light* gfx_make_light(const LightDesc* desc) {
29 assert(desc);
30
31 Light* light = mem_alloc_light();
32
33 switch (desc->type) {
34 case EnvironmentLightType:
35 make_environment_light(light, &desc->light.environment);
36 break;
37 default:
38 log_error("Unhandled light type");
39 gfx_destroy_light(&light);
40 return 0;
41 }
42
43 return light;
44}
45
46void gfx_destroy_light(Light** light) {
47 assert(light);
48 if (*light) {
49 mem_free_light(light);
50 }
51}
52
53static void material_make(Material* material, const MaterialDesc* desc) {
54 assert(material);
55 assert(desc);
56 assert(desc->num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
57 material->alpha_mode = desc->alpha_mode;
58 material->alpha_cutoff = desc->alpha_cutoff;
59 material->num_uniforms = (int8_t)desc->num_uniforms;
60 for (int i = 0; i < desc->num_uniforms; ++i) {
61 material->uniforms[i] = desc->uniforms[i];
62 }
63}
64
65Material* gfx_make_material(const MaterialDesc* desc) {
66 assert(desc);
67 Material* material = mem_alloc_material();
68 material_make(material, desc);
69 return material;
70}
71
72void gfx_destroy_material(Material** material) { mem_free_material(material); }
73
74// TODO: Move this to core/shader_program.
75static void set_uniform(ShaderProgram* prog, const ShaderUniform* uniform) {
76 switch (uniform->type) {
77 case UniformInt:
78 gfx_set_int_uniform(prog, uniform->name.str, uniform->value.uniform_int);
79 break;
80 case UniformFloat:
81 gfx_set_float_uniform(
82 prog, uniform->name.str, uniform->value.uniform_float);
83 break;
84 case UniformMat4:
85 gfx_set_mat4_uniform(prog, uniform->name.str, &uniform->value.uniform_mat4);
86 break;
87 case UniformVec3:
88 gfx_set_vec3_uniform(prog, uniform->name.str, uniform->value.uniform_vec3);
89 break;
90 case UniformVec4:
91 gfx_set_vec4_uniform(prog, uniform->name.str, uniform->value.uniform_vec4);
92 break;
93 case UniformTexture:
94 gfx_set_texture_uniform(prog, uniform->name.str, uniform->value.texture);
95 break;
96 case UniformMat4Array:
97 gfx_set_mat4_array_uniform(
98 prog, uniform->name.str, uniform->value.array.values,
99 uniform->value.array.count);
100 break;
101 }
102}
103
104/// Activate the material. 21/// Activate the material.
105/// 22///
106/// This configures the shader uniforms that are specific to the material. 23/// This configures the shader uniforms that are specific to the material.
107static void gfx_material_activate( 24static void material_activate(ShaderProgram* shader, const Material* material) {
108 ShaderProgram* shader, const Material* material) {
109 assert(material); 25 assert(material);
110 for (int i = 0; i < material->num_uniforms; ++i) { 26 for (int i = 0; i < material->num_uniforms; ++i) {
111 const ShaderUniform* uniform = &material->uniforms[i]; 27 const ShaderUniform* uniform = &material->uniforms[i];
112 set_uniform(shader, uniform); 28 gfx_set_uniform(shader, uniform);
113 } 29 }
114 if (material->alpha_mode != Opaque) { 30 if (material->alpha_mode != Opaque) {
115 set_uniform( 31 gfx_set_uniform(
116 shader, &(ShaderUniform){.name = sstring_make("AlphaMode"), 32 shader, &(ShaderUniform){.name = sstring_make("AlphaMode"),
117 .type = UniformInt, 33 .type = UniformInt,
118 .value.uniform_int = material->alpha_mode}); 34 .value.uniform_int = material->alpha_mode});
119 } 35 }
120 if (material->alpha_mode == Mask) { 36 if (material->alpha_mode == Mask) {
121 set_uniform( 37 gfx_set_uniform(
122 shader, 38 shader,
123 &(ShaderUniform){.name = sstring_make("AlphaCutoff"), 39 &(ShaderUniform){.name = sstring_make("AlphaCutoff"),
124 .type = UniformFloat, 40 .type = UniformFloat,
@@ -126,25 +42,6 @@ static void gfx_material_activate(
126 } 42 }
127} 43}
128 44
129static void mesh_make(Mesh* mesh, const MeshDesc* desc) {
130 assert(mesh);
131 assert(desc);
132 assert(desc->geometry);
133 assert(desc->material);
134 assert(desc->shader);
135 mesh->geometry = desc->geometry;
136 mesh->material = desc->material;
137 mesh->shader = desc->shader;
138}
139
140Mesh* gfx_make_mesh(const MeshDesc* desc) {
141 Mesh* mesh = mem_alloc_mesh();
142 mesh_make(mesh, desc);
143 return mesh;
144}
145
146void gfx_destroy_mesh(Mesh** mesh) { mem_free_mesh(mesh); }
147
148/// Initialize renderer state for IBL. 45/// Initialize renderer state for IBL.
149static bool init_ibl(LLR* renderer) { 46static bool init_ibl(LLR* renderer) {
150 assert(renderer); 47 assert(renderer);
@@ -334,7 +231,7 @@ static void configure_state(LLR* renderer) {
334 231
335 // Geometry may be rendered without a material. 232 // Geometry may be rendered without a material.
336 if (renderer->material) { 233 if (renderer->material) {
337 gfx_material_activate(renderer->shader, renderer->material); 234 material_activate(renderer->shader, renderer->material);
338 } 235 }
339 } 236 }
340 237
diff --git a/src/render/llr_impl.h b/src/render/llr_impl.h
index 3a5455a..9d70843 100644
--- a/src/render/llr_impl.h
+++ b/src/render/llr_impl.h
@@ -10,43 +10,12 @@
10#include <stddef.h> 10#include <stddef.h>
11#include <stdint.h> 11#include <stdint.h>
12 12
13typedef struct Geometry Geometry;
14typedef struct GfxCore GfxCore; 13typedef struct GfxCore GfxCore;
15typedef struct IBL IBL; 14typedef struct IBL IBL;
16typedef struct Material Material; 15typedef struct Material Material;
17typedef struct ShaderProgram ShaderProgram; 16typedef struct ShaderProgram ShaderProgram;
18typedef struct Texture Texture; 17typedef struct Texture Texture;
19 18
20/// An environment light.
21typedef struct EnvironmentLight {
22 const Texture* environment_map;
23 const Texture* irradiance_map; // Renderer implementation.
24 const Texture* prefiltered_environment_map; // Renderer implementation.
25 int max_reflection_lod; // Mandatory when prefiltered_environment_map is
26 // given.
27} EnvironmentLight;
28
29/// A scene light.
30typedef struct Light {
31 LightType type;
32 union {
33 EnvironmentLight environment;
34 };
35} Light;
36
37typedef struct Material {
38 AlphaMode alpha_mode;
39 float alpha_cutoff;
40 int8_t num_uniforms;
41 ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL];
42} Material;
43
44typedef struct Mesh {
45 const Geometry* geometry;
46 const Material* material;
47 ShaderProgram* shader; // TODO: Move this back to Material?
48} Mesh;
49
50/// Immediate mode renderer. 19/// Immediate mode renderer.
51/// 20///
52/// The renderer caches state changes in memory and only programs the underlying 21/// The renderer caches state changes in memory and only programs the underlying
diff --git a/src/render/renderer.c b/src/render/renderer.c
index 26b63bc..a9d9bef 100644
--- a/src/render/renderer.c
+++ b/src/render/renderer.c
@@ -3,10 +3,11 @@
3#include "animation_impl.h" 3#include "animation_impl.h"
4#include "llr_impl.h" 4#include "llr_impl.h"
5#include "memory.h" 5#include "memory.h"
6#include "scene/material_impl.h"
7#include "scene/mesh_impl.h"
6#include "scene/model_impl.h" 8#include "scene/model_impl.h"
7#include "scene/node_impl.h" 9#include "scene/node_impl.h"
8#include "scene/object_impl.h" 10#include "scene/object_impl.h"
9#include "scene/scene_impl.h"
10 11
11#include <gfx/core.h> 12#include <gfx/core.h>
12#include <gfx/render/llr.h> 13#include <gfx/render/llr.h>
@@ -236,6 +237,8 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) {
236 // potentially renders the scene multiple times as needed. For example, a 237 // potentially renders the scene multiple times as needed. For example, a
237 // depth-prepass, followed by G-buffer, followed by some post-processing, 238 // depth-prepass, followed by G-buffer, followed by some post-processing,
238 // etc. Rename this renderer to scene_renderer? 239 // etc. Rename this renderer to scene_renderer?
240 // TODO: When rendering transparent geometry, we need to turn off depth
241 // writes.
239 // Opaque. 242 // Opaque.
240 state.filter = RenderOpaqueAndAlphaMasked; 243 state.filter = RenderOpaqueAndAlphaMasked;
241 draw_recursively(&state, mat4_id(), gfx_get_scene_root(scene)); 244 draw_recursively(&state, mat4_id(), gfx_get_scene_root(scene));
diff --git a/src/scene/light.c b/src/scene/light.c
new file mode 100644
index 0000000..4233330
--- /dev/null
+++ b/src/scene/light.c
@@ -0,0 +1,39 @@
1#include "light_impl.h"
2
3#include "memory.h"
4
5#include <cassert.h>
6#include <error.h>
7
8static void make_environment_light(
9 Light* light, const EnvironmentLightDesc* desc) {
10 assert(light);
11 assert(desc);
12 light->type = EnvironmentLightType;
13 light->environment.environment_map = desc->environment_map;
14}
15
16Light* gfx_make_light(const LightDesc* desc) {
17 assert(desc);
18
19 Light* light = mem_alloc_light();
20
21 switch (desc->type) {
22 case EnvironmentLightType:
23 make_environment_light(light, &desc->light.environment);
24 break;
25 default:
26 log_error("Unhandled light type");
27 gfx_destroy_light(&light);
28 return 0;
29 }
30
31 return light;
32}
33
34void gfx_destroy_light(Light** light) {
35 assert(light);
36 if (*light) {
37 mem_free_light(light);
38 }
39}
diff --git a/src/scene/light_impl.h b/src/scene/light_impl.h
new file mode 100644
index 0000000..3191a50
--- /dev/null
+++ b/src/scene/light_impl.h
@@ -0,0 +1,20 @@
1#pragma once
2
3#include <gfx/scene.h>
4
5/// An environment light.
6typedef struct EnvironmentLight {
7 const Texture* environment_map;
8 const Texture* irradiance_map; // Renderer implementation.
9 const Texture* prefiltered_environment_map; // Renderer implementation.
10 int max_reflection_lod; // Mandatory when prefiltered_environment_map is
11 // given.
12} EnvironmentLight;
13
14/// A scene light.
15typedef struct Light {
16 LightType type;
17 union {
18 EnvironmentLight environment;
19 };
20} Light;
diff --git a/src/scene/material.c b/src/scene/material.c
new file mode 100644
index 0000000..9fe6c1b
--- /dev/null
+++ b/src/scene/material.c
@@ -0,0 +1,24 @@
1#include "material_impl.h"
2
3#include "memory.h"
4
5static void material_make(Material* material, const MaterialDesc* desc) {
6 assert(material);
7 assert(desc);
8 assert(desc->num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
9 material->alpha_mode = desc->alpha_mode;
10 material->alpha_cutoff = desc->alpha_cutoff;
11 material->num_uniforms = (int8_t)desc->num_uniforms;
12 for (int i = 0; i < desc->num_uniforms; ++i) {
13 material->uniforms[i] = desc->uniforms[i];
14 }
15}
16
17Material* gfx_make_material(const MaterialDesc* desc) {
18 assert(desc);
19 Material* material = mem_alloc_material();
20 material_make(material, desc);
21 return material;
22}
23
24void gfx_destroy_material(Material** material) { mem_free_material(material); }
diff --git a/src/scene/material_impl.h b/src/scene/material_impl.h
new file mode 100644
index 0000000..488ffc7
--- /dev/null
+++ b/src/scene/material_impl.h
@@ -0,0 +1,13 @@
1#pragma once
2
3#include <gfx/scene.h>
4#include <gfx/sizes.h>
5
6typedef struct ShaderProgram ShaderProgram;
7
8typedef struct Material {
9 AlphaMode alpha_mode;
10 float alpha_cutoff;
11 int8_t num_uniforms;
12 ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL];
13} Material;
diff --git a/src/scene/mesh.c b/src/scene/mesh.c
new file mode 100644
index 0000000..770c3fb
--- /dev/null
+++ b/src/scene/mesh.c
@@ -0,0 +1,26 @@
1#include "mesh_impl.h"
2
3#include <gfx/scene.h>
4
5#include "memory.h"
6
7#include <cassert.h>
8
9static void mesh_make(Mesh* mesh, const MeshDesc* desc) {
10 assert(mesh);
11 assert(desc);
12 assert(desc->geometry);
13 assert(desc->material);
14 assert(desc->shader);
15 mesh->geometry = desc->geometry;
16 mesh->material = desc->material;
17 mesh->shader = desc->shader;
18}
19
20Mesh* gfx_make_mesh(const MeshDesc* desc) {
21 Mesh* mesh = mem_alloc_mesh();
22 mesh_make(mesh, desc);
23 return mesh;
24}
25
26void gfx_destroy_mesh(Mesh** mesh) { mem_free_mesh(mesh); }
diff --git a/src/scene/mesh_impl.h b/src/scene/mesh_impl.h
new file mode 100644
index 0000000..c7e2211
--- /dev/null
+++ b/src/scene/mesh_impl.h
@@ -0,0 +1,11 @@
1#pragma once
2
3typedef struct Geometry Geometry;
4typedef struct Material Material;
5typedef struct ShaderProgram ShaderProgram;
6
7typedef struct Mesh {
8 const Geometry* geometry;
9 const Material* material;
10 ShaderProgram* shader; // TODO: Move this back to Material?
11} Mesh;
diff --git a/src/scene/object.c b/src/scene/object.c
index 7004ce1..ac86b39 100644
--- a/src/scene/object.c
+++ b/src/scene/object.c
@@ -3,8 +3,9 @@
3#include <gfx/core.h> 3#include <gfx/core.h>
4 4
5#include "memory.h" 5#include "memory.h"
6#include "node_impl.h"
7#include "render/llr_impl.h" 6#include "render/llr_impl.h"
7#include "scene/mesh_impl.h"
8#include "scene/node_impl.h"
8 9
9#include <assert.h> 10#include <assert.h>
10 11
diff --git a/src/util/geometry.c b/src/util/geometry.c
index afe0109..2ea0c82 100644
--- a/src/util/geometry.c
+++ b/src/util/geometry.c
@@ -17,12 +17,13 @@ static void make_quad_01_positions(vec2 positions[4]) {
17} 17}
18 18
19static GeometryDesc make_quad_desc(vec2 positions[4]) { 19static GeometryDesc make_quad_desc(vec2 positions[4]) {
20 GeometryDesc desc = (GeometryDesc){0}; 20 return (GeometryDesc){
21 desc.positions2d.data = positions; 21 .positions2d = (BufferView2d){.data = positions,
22 desc.positions2d.size_bytes = 4 * sizeof(vec2); 22 .size_bytes = 4 * sizeof(vec2),
23 desc.num_verts = 4; 23 .count = 4},
24 desc.type = TriangleStrip; 24 .num_verts = 4,
25 return desc; 25 .type = TriangleStrip
26 };
26} 27}
27 28
28Geometry* gfx_make_quad_11(GfxCore* gfxcore) { 29Geometry* gfx_make_quad_11(GfxCore* gfxcore) {