diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/gfx/asset.h | 99 | ||||
-rw-r--r-- | include/gfx/core.h | 505 | ||||
-rw-r--r-- | include/gfx/gfx.h | 35 | ||||
-rw-r--r-- | include/gfx/llr/light.h | 30 | ||||
-rw-r--r-- | include/gfx/llr/llr.h | 67 | ||||
-rw-r--r-- | include/gfx/llr/material.h | 25 | ||||
-rw-r--r-- | include/gfx/llr/mesh.h | 23 | ||||
-rw-r--r-- | include/gfx/renderer.h | 29 | ||||
-rw-r--r-- | include/gfx/renderer/imm_renderer.h | 55 | ||||
-rw-r--r-- | include/gfx/scene.h | 12 | ||||
-rw-r--r-- | include/gfx/scene/animation.h | 140 | ||||
-rw-r--r-- | include/gfx/scene/camera.h | 22 | ||||
-rw-r--r-- | include/gfx/scene/model.h | 12 | ||||
-rw-r--r-- | include/gfx/scene/node.h | 152 | ||||
-rw-r--r-- | include/gfx/scene/object.h | 39 | ||||
-rw-r--r-- | include/gfx/scene/scene.h | 21 | ||||
-rw-r--r-- | include/gfx/sizes.h | 101 | ||||
-rw-r--r-- | include/gfx/util/geometry.h | 13 | ||||
-rw-r--r-- | include/gfx/util/ibl.h | 25 | ||||
-rw-r--r-- | include/gfx/util/shader.h | 46 | ||||
-rw-r--r-- | include/gfx/util/skyquad.h | 22 |
21 files changed, 1473 insertions, 0 deletions
diff --git a/include/gfx/asset.h b/include/gfx/asset.h new file mode 100644 index 0000000..caf40c1 --- /dev/null +++ b/include/gfx/asset.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* Asset Management */ | ||
2 | #pragma once | ||
3 | |||
4 | #include <gfx/core.h> | ||
5 | |||
6 | #include <stddef.h> | ||
7 | |||
8 | typedef struct Gfx Gfx; | ||
9 | typedef struct Model Model; | ||
10 | typedef struct ShaderProgram ShaderProgram; | ||
11 | typedef struct Texture Texture; | ||
12 | |||
13 | /// Describes where the asset comes from. | ||
14 | typedef enum AssetOrigin { | ||
15 | AssetFromMemory, | ||
16 | AssetFromFile, | ||
17 | } AssetOrigin; | ||
18 | |||
19 | /// Describes a texture's colour space. | ||
20 | typedef enum TextureColourSpace { | ||
21 | sRGB, // The most likely default. | ||
22 | LinearColourSpace, | ||
23 | } TextureColourSpace; | ||
24 | |||
25 | /// Describes a command to load a texture. | ||
26 | typedef struct LoadTextureCmd { | ||
27 | AssetOrigin origin; | ||
28 | enum { LoadTexture, LoadCubemap } type; | ||
29 | TextureColourSpace colour_space; | ||
30 | TextureFiltering filtering; | ||
31 | TextureWrapping wrap; | ||
32 | bool mipmaps; | ||
33 | union { | ||
34 | // A single texture. | ||
35 | struct { | ||
36 | union { | ||
37 | struct { | ||
38 | mstring filepath; | ||
39 | }; | ||
40 | struct { | ||
41 | const void* data; | ||
42 | size_t size_bytes; | ||
43 | }; | ||
44 | }; | ||
45 | } texture; | ||
46 | // Cubemap texture. | ||
47 | struct { | ||
48 | union { | ||
49 | struct { | ||
50 | mstring filepath_pos_x; | ||
51 | mstring filepath_neg_x; | ||
52 | mstring filepath_pos_y; | ||
53 | mstring filepath_neg_y; | ||
54 | mstring filepath_pos_z; | ||
55 | mstring filepath_neg_z; | ||
56 | } filepaths; | ||
57 | struct { | ||
58 | const void* data_pos_x; | ||
59 | const void* data_neg_x; | ||
60 | const void* data_pos_y; | ||
61 | const void* data_neg_y; | ||
62 | const void* data_pos_z; | ||
63 | const void* data_neg_z; | ||
64 | } buffers; | ||
65 | }; | ||
66 | } cubemap; | ||
67 | } data; | ||
68 | } LoadTextureCmd; | ||
69 | |||
70 | /// Describes a command to load a model. | ||
71 | /// | ||
72 | /// |shader| is an optional shader program assigned to the loaded model objects. | ||
73 | /// If no shader is given, a Cook-Torrance shader based on the object's | ||
74 | /// characteristics (presence of normals, tangents, etc) is assigned. | ||
75 | typedef struct LoadModelCmd { | ||
76 | AssetOrigin origin; | ||
77 | union { | ||
78 | struct { | ||
79 | mstring filepath; | ||
80 | }; | ||
81 | struct { | ||
82 | const void* data; | ||
83 | size_t size_bytes; | ||
84 | }; | ||
85 | }; | ||
86 | ShaderProgram* shader; | ||
87 | } LoadModelCmd; | ||
88 | |||
89 | /// Load a model. | ||
90 | /// | ||
91 | /// For animated models, this function returns a (shallow) clone of the model | ||
92 | /// that is safe to mutate. For static models, this returns the original model | ||
93 | /// in the cache. | ||
94 | /// | ||
95 | /// Currently only supports the GLTF format. | ||
96 | Model* gfx_load_model(Gfx*, const LoadModelCmd*); | ||
97 | |||
98 | /// Load a texture. | ||
99 | const Texture* gfx_load_texture(Gfx*, const LoadTextureCmd*); | ||
diff --git a/include/gfx/core.h b/include/gfx/core.h new file mode 100644 index 0000000..0cf4465 --- /dev/null +++ b/include/gfx/core.h | |||
@@ -0,0 +1,505 @@ | |||
1 | /// Render Backend. | ||
2 | /// | ||
3 | /// The Render Backend creates and owns graphics objects and performs low-level | ||
4 | /// rendering operations. | ||
5 | #pragma once | ||
6 | |||
7 | #include "sizes.h" | ||
8 | |||
9 | #include <math/aabb3.h> | ||
10 | #include <math/fwd.h> | ||
11 | #include <math/mat4.h> | ||
12 | #include <math/vec4.h> | ||
13 | |||
14 | #include <cstring.h> | ||
15 | |||
16 | #include <stddef.h> | ||
17 | #include <stdint.h> | ||
18 | |||
19 | // Implementation objects. | ||
20 | typedef struct Buffer Buffer; | ||
21 | typedef struct FrameBuffer FrameBuffer; | ||
22 | typedef struct Geometry Geometry; | ||
23 | typedef struct GfxCore GfxCore; | ||
24 | typedef struct RenderBuffer RenderBuffer; | ||
25 | typedef struct Shader Shader; | ||
26 | typedef struct ShaderProgram ShaderProgram; | ||
27 | typedef struct Texture Texture; | ||
28 | |||
29 | /// Data type for vertex indices. | ||
30 | /// Might need U32 for bigger models. | ||
31 | typedef uint8_t VertexIndex8; | ||
32 | typedef uint16_t VertexIndex16; | ||
33 | typedef uint16_t VertexCount; | ||
34 | |||
35 | /// Geometry drawing modes. | ||
36 | typedef enum PrimitiveType { | ||
37 | Triangles, | ||
38 | TriangleFan, | ||
39 | TriangleStrip | ||
40 | } PrimitiveType; | ||
41 | |||
42 | /// Buffer usage. | ||
43 | typedef enum BufferUsage { BufferStatic, BufferDynamic } BufferUsage; | ||
44 | |||
45 | /// Buffer type. | ||
46 | typedef enum BufferType { | ||
47 | BufferUntyped, | ||
48 | Buffer2d, | ||
49 | Buffer3d, | ||
50 | Buffer4d, | ||
51 | BufferFloat, | ||
52 | BufferU8, | ||
53 | BufferU16 | ||
54 | } BufferType; | ||
55 | |||
56 | /// Buffer data descriptor. | ||
57 | typedef struct BufferDataDesc { | ||
58 | union { | ||
59 | const void* data; | ||
60 | const vec2* vec2s; | ||
61 | const vec3* vec3s; | ||
62 | const float* floats; | ||
63 | const uint8_t* u8s; | ||
64 | const uint16_t* u16s; | ||
65 | }; | ||
66 | size_t count; | ||
67 | } BufferDataDesc; | ||
68 | |||
69 | /// Buffer descriptor. | ||
70 | /// | ||
71 | /// 'count' is the number of elements in the array. For untyped buffers, this is | ||
72 | /// the size in bytes of the 'data' array. For other types, it is the number of | ||
73 | /// vec2s, vec3s, etc. in the corresponding array. | ||
74 | /// | ||
75 | /// The data pointers can also be null. In such a case, a buffer of the given | ||
76 | /// size is created with its contents uninitialized. | ||
77 | /// | ||
78 | /// TODO: Think about typed buffers (Buffer, Buffer2d, Buffer3d, BufferU8, etc). | ||
79 | /// Typed buffers don't work well with interleaved vertex attributes. Not sure | ||
80 | /// this is really worth it. | ||
81 | typedef struct BufferDesc { | ||
82 | BufferUsage usage; | ||
83 | BufferType type; | ||
84 | BufferDataDesc data; | ||
85 | } BufferDesc; | ||
86 | |||
87 | /// A buffer view for vertex data (attributes or indices). | ||
88 | /// Either 'data' or 'buffer' must be set. | ||
89 | #define MAKE_BUFFER_VIEW(NAME, TYPE) \ | ||
90 | typedef struct NAME { \ | ||
91 | const TYPE* data; \ | ||
92 | Buffer* buffer; \ | ||
93 | size_t offset_bytes; \ | ||
94 | size_t size_bytes; \ | ||
95 | size_t stride_bytes; \ | ||
96 | } NAME; | ||
97 | |||
98 | /// A buffer view for untyped data. | ||
99 | MAKE_BUFFER_VIEW(BufferView, void) | ||
100 | |||
101 | /// A buffer view for 2D vectors. | ||
102 | MAKE_BUFFER_VIEW(BufferView2d, vec2) | ||
103 | |||
104 | /// A buffer view for 3D vectors. | ||
105 | MAKE_BUFFER_VIEW(BufferView3d, vec3) | ||
106 | |||
107 | /// A buffer view for 4D vectors. | ||
108 | MAKE_BUFFER_VIEW(BufferView4d, vec4) | ||
109 | |||
110 | /// A buffer view for floats. | ||
111 | MAKE_BUFFER_VIEW(BufferViewFloat, float) | ||
112 | |||
113 | /// A buffer view for 8-bit unsigned integers. | ||
114 | MAKE_BUFFER_VIEW(BufferViewU8, uint8_t) | ||
115 | |||
116 | /// A buffer view for 16-bit unsigned integers. | ||
117 | MAKE_BUFFER_VIEW(BufferViewU16, uint16_t) | ||
118 | |||
119 | /// A buffer view for 8-bit vertex indices. | ||
120 | MAKE_BUFFER_VIEW(BufferViewIdx8, uint16_t) | ||
121 | |||
122 | /// A buffer view for 16-bit vertex indices. | ||
123 | MAKE_BUFFER_VIEW(BufferViewIdx16, uint16_t) | ||
124 | |||
125 | /// Describes a piece of geometry. | ||
126 | /// | ||
127 | /// Buffer views may point to either already-existing GPU buffers or to data in | ||
128 | /// host memory. | ||
129 | /// | ||
130 | /// If the buffer views do not already point to GPU buffers, GPU buffers are | ||
131 | /// created for the geometry. The 'buffer_usage' field specifies the usage for | ||
132 | /// the created buffers. Use BufferStatic for static geometry and BufferDynamic | ||
133 | /// for dynamic geometry. | ||
134 | /// | ||
135 | /// Currently we support only up to 16-bit vertex indices. Might have to change | ||
136 | /// this to support a larger variety of 3D models. | ||
137 | typedef struct GeometryDesc { | ||
138 | BufferView2d positions2d; | ||
139 | BufferView3d positions3d; | ||
140 | BufferView3d normals; | ||
141 | BufferView4d tangents; | ||
142 | BufferView2d texcoords; | ||
143 | struct { | ||
144 | BufferViewU8 u8; | ||
145 | BufferViewU16 u16; | ||
146 | } joints; // uvec4. | ||
147 | struct { | ||
148 | BufferViewFloat floats; | ||
149 | BufferViewU8 u8; | ||
150 | BufferViewU16 u16; | ||
151 | } weights; // vec4 or uvec4. | ||
152 | BufferViewIdx8 indices8; | ||
153 | BufferViewIdx16 indices16; | ||
154 | VertexCount num_verts; | ||
155 | size_t num_indices; | ||
156 | PrimitiveType type; | ||
157 | BufferUsage buffer_usage; | ||
158 | aabb3 aabb; | ||
159 | } GeometryDesc; | ||
160 | |||
161 | /// Shader compiler define. | ||
162 | typedef struct ShaderCompilerDefine { | ||
163 | sstring name; | ||
164 | sstring value; | ||
165 | } ShaderCompilerDefine; | ||
166 | |||
167 | /// Shader types. | ||
168 | typedef enum { VertexShader, FragmentShader } ShaderType; | ||
169 | |||
170 | /// Describes a shader. | ||
171 | typedef struct ShaderDesc { | ||
172 | ShaderType type; | ||
173 | const char* code; | ||
174 | ShaderCompilerDefine defines[GFX_MAX_SHADER_COMPILER_DEFINES]; | ||
175 | size_t num_defines; | ||
176 | } ShaderDesc; | ||
177 | |||
178 | /// Describes a shader program. | ||
179 | typedef struct ShaderProgramDesc { | ||
180 | const Shader* vertex_shader; | ||
181 | const Shader* fragment_shader; | ||
182 | } ShaderProgramDesc; | ||
183 | |||
184 | /// Shader uniform type. | ||
185 | typedef enum { | ||
186 | UniformFloat, | ||
187 | UniformMat4, | ||
188 | UniformTexture, | ||
189 | UniformVec3, | ||
190 | UniformVec4, | ||
191 | UniformMat4Array | ||
192 | } UniformType; | ||
193 | |||
194 | /// Shader uniform. | ||
195 | /// | ||
196 | /// For uniform arrays, the client must ensure that the array is still valid by | ||
197 | /// the time the uniform data is passed to the GPU. | ||
198 | typedef struct ShaderUniform { | ||
199 | sstring name; | ||
200 | UniformType type; | ||
201 | union { | ||
202 | const Texture* texture; | ||
203 | mat4 mat4; | ||
204 | vec3 vec3; | ||
205 | vec4 vec4; | ||
206 | float scalar; | ||
207 | struct { | ||
208 | size_t count; | ||
209 | union { | ||
210 | const mat4* values; | ||
211 | }; | ||
212 | } array; | ||
213 | } value; | ||
214 | } ShaderUniform; | ||
215 | |||
216 | /// Texture dimension. | ||
217 | typedef enum { Texture2D, TextureCubeMap } TextureDimension; | ||
218 | |||
219 | /// Texture data format. | ||
220 | typedef enum { | ||
221 | TextureDepth, | ||
222 | TextureR8, | ||
223 | TextureRG16, | ||
224 | TextureRG16F, | ||
225 | TextureRGB8, | ||
226 | TextureR11G11B10F, | ||
227 | TextureRGBA8, | ||
228 | TextureSRGB8, | ||
229 | TextureSRGBA8 | ||
230 | } TextureFormat; | ||
231 | |||
232 | /// Texture filtering. | ||
233 | typedef enum { NearestFiltering, LinearFiltering } TextureFiltering; | ||
234 | |||
235 | /// Texture wrap mode. | ||
236 | typedef enum { Repeat, ClampToEdge } TextureWrapping; | ||
237 | |||
238 | /// Cubemap faces. | ||
239 | typedef enum { | ||
240 | CubemapFacePosX, | ||
241 | CubemapFaceNegX, | ||
242 | CubemapFacePosY, | ||
243 | CubemapFaceNegY, | ||
244 | CubemapFacePosZ, | ||
245 | CubemapFaceNegZ | ||
246 | } CubemapFace; | ||
247 | |||
248 | /// Texture data descriptor. | ||
249 | typedef struct TextureDataDesc { | ||
250 | union { | ||
251 | const void* pixels; | ||
252 | struct { | ||
253 | const void* pixels_pos_x; | ||
254 | const void* pixels_neg_x; | ||
255 | const void* pixels_pos_y; | ||
256 | const void* pixels_neg_y; | ||
257 | const void* pixels_pos_z; | ||
258 | const void* pixels_neg_z; | ||
259 | } cubemap; | ||
260 | }; | ||
261 | } TextureDataDesc; | ||
262 | |||
263 | /// Describes a texture. | ||
264 | typedef struct TextureDesc { | ||
265 | int width; | ||
266 | int height; | ||
267 | int depth; // Not used until 3D textures are exposed. | ||
268 | TextureDimension dimension; | ||
269 | TextureFormat format; | ||
270 | TextureFiltering filtering; | ||
271 | TextureWrapping wrap; | ||
272 | bool mipmaps; | ||
273 | TextureDataDesc data; | ||
274 | } TextureDesc; | ||
275 | |||
276 | /// Describes a renderbuffer. | ||
277 | typedef struct RenderBufferDesc { | ||
278 | int width; | ||
279 | int height; | ||
280 | TextureFormat texture_format; | ||
281 | } RenderBufferDesc; | ||
282 | |||
283 | /// Framebuffer attachment type. | ||
284 | typedef enum FrameBufferAttachmentType { | ||
285 | FrameBufferNoAttachment, | ||
286 | FrameBufferTexture, | ||
287 | FrameBufferCubemapTexture, | ||
288 | FrameBufferRenderBuffer | ||
289 | } FrameBufferAttachmentType; | ||
290 | |||
291 | /// Describes a framebuffer attachment. | ||
292 | typedef struct FrameBufferAttachment { | ||
293 | FrameBufferAttachmentType type; | ||
294 | union { | ||
295 | struct { | ||
296 | Texture* texture; | ||
297 | int mip_level; | ||
298 | } texture; | ||
299 | struct { | ||
300 | Texture* texture; | ||
301 | int mip_level; | ||
302 | CubemapFace face; | ||
303 | } cubemap; | ||
304 | RenderBuffer* renderbuffer; | ||
305 | }; | ||
306 | } FrameBufferAttachment; | ||
307 | |||
308 | /// Describes a framebuffer. | ||
309 | typedef struct FrameBufferDesc { | ||
310 | FrameBufferAttachment colour; | ||
311 | FrameBufferAttachment depth; | ||
312 | } FrameBufferDesc; | ||
313 | |||
314 | // ----------------------------------------------------------------------------- | ||
315 | // Render commands. | ||
316 | // ----------------------------------------------------------------------------- | ||
317 | |||
318 | /// Start a new frame. | ||
319 | void gfx_start_frame(GfxCore*); | ||
320 | |||
321 | /// End a frame. | ||
322 | void gfx_end_frame(GfxCore*); | ||
323 | |||
324 | /// Set the render backend's viewport dimensions. | ||
325 | void gfx_set_viewport(GfxCore*, int x, int y, int width, int height); | ||
326 | |||
327 | /// Get the render backend's viewport dimensions. | ||
328 | void gfx_get_viewport(GfxCore*, int* x, int* y, int* width, int* height); | ||
329 | |||
330 | /// Clear the viewport. | ||
331 | void gfx_clear(GfxCore*, vec4 colour); | ||
332 | |||
333 | /// Set blending state. | ||
334 | void gfx_set_blending(GfxCore*, bool enable); | ||
335 | |||
336 | /// Set depth mask. | ||
337 | void gfx_set_depth_mask(GfxCore*, bool enable); | ||
338 | |||
339 | /// Set cull mode. | ||
340 | void gfx_set_culling(GfxCore*, bool enable); | ||
341 | |||
342 | /// Set polygon offset. | ||
343 | void gfx_set_polygon_offset(GfxCore*, float scale, float bias); | ||
344 | |||
345 | /// Reset the polygon offset. | ||
346 | void gfx_reset_polygon_offset(GfxCore*); | ||
347 | |||
348 | // ----------------------------------------------------------------------------- | ||
349 | // Buffers. | ||
350 | // ----------------------------------------------------------------------------- | ||
351 | |||
352 | /// Create a buffer from raw data. | ||
353 | Buffer* gfx_make_buffer(GfxCore*, const BufferDesc*); | ||
354 | |||
355 | /// Destroy the buffer. | ||
356 | void gfx_destroy_buffer(GfxCore*, Buffer**); | ||
357 | |||
358 | /// Update the buffer's data. | ||
359 | void gfx_update_buffer(Buffer*, const BufferDataDesc*); | ||
360 | |||
361 | // ----------------------------------------------------------------------------- | ||
362 | // Geometry. | ||
363 | // ----------------------------------------------------------------------------- | ||
364 | |||
365 | /// Create geometry. | ||
366 | Geometry* gfx_make_geometry(GfxCore*, const GeometryDesc*); | ||
367 | |||
368 | /// Destroy the geometry. | ||
369 | void gfx_destroy_geometry(GfxCore*, Geometry**); | ||
370 | |||
371 | /// Upload new vertex data for the geometry. | ||
372 | /// | ||
373 | /// This is similar to gfx_make_geometry(), but the geometry need not be | ||
374 | /// entirely specified. | ||
375 | /// | ||
376 | /// Only the vertex attributes, vertex count, and index count set in the | ||
377 | /// descriptor are updated. Index data, primitive type, and other properties of | ||
378 | /// the geometry are not updated. | ||
379 | /// | ||
380 | /// New data must be given as arrays in host memory. That is, the buffer views | ||
381 | /// in the descriptor must point to CPU arrays, not GPU buffers. | ||
382 | /// | ||
383 | /// Note that the descriptor cannot specify a larger vertex or index count than | ||
384 | /// what the geometry was created with. If the geometry size or any other | ||
385 | /// attribute not handled by this update function needs to be changed, then a | ||
386 | /// new geometry must be created. | ||
387 | void gfx_update_geometry(Geometry*, const GeometryDesc*); | ||
388 | |||
389 | /// Render the geometry. | ||
390 | void gfx_render_geometry(const Geometry*); | ||
391 | |||
392 | /// Return the geometry's bounding box. | ||
393 | aabb3 gfx_get_geometry_aabb(const Geometry*); | ||
394 | |||
395 | // ----------------------------------------------------------------------------- | ||
396 | // Textures. | ||
397 | // ----------------------------------------------------------------------------- | ||
398 | |||
399 | /// Create a texture. | ||
400 | Texture* gfx_make_texture(GfxCore*, const TextureDesc*); | ||
401 | |||
402 | /// Destroy the texture. | ||
403 | void gfx_destroy_texture(GfxCore*, Texture**); | ||
404 | |||
405 | /// Update the texture. | ||
406 | void gfx_update_texture(Texture*, const TextureDataDesc*); | ||
407 | |||
408 | // ----------------------------------------------------------------------------- | ||
409 | // Renderbuffers. | ||
410 | // ----------------------------------------------------------------------------- | ||
411 | |||
412 | /// Create a renderbuffer. | ||
413 | RenderBuffer* gfx_make_renderbuffer(GfxCore*, const RenderBufferDesc*); | ||
414 | |||
415 | /// Destroy the renderbuffer. | ||
416 | void gfx_destroy_renderbuffer(GfxCore*, RenderBuffer**); | ||
417 | |||
418 | // ----------------------------------------------------------------------------- | ||
419 | // Framebuffers. | ||
420 | // ----------------------------------------------------------------------------- | ||
421 | |||
422 | /// Create a framebuffer. | ||
423 | FrameBuffer* gfx_make_framebuffer(GfxCore*, const FrameBufferDesc*); | ||
424 | |||
425 | /// Destroy the framebuffer. | ||
426 | void gfx_destroy_framebuffer(GfxCore*, FrameBuffer**); | ||
427 | |||
428 | /// Attach a colour buffer to the framebuffer. | ||
429 | bool gfx_framebuffer_attach_colour(FrameBuffer*, const FrameBufferAttachment*); | ||
430 | |||
431 | /// Attach a depth buffer to the framebuffer. | ||
432 | bool gfx_framebuffer_attach_depth(FrameBuffer*, const FrameBufferAttachment*); | ||
433 | |||
434 | /// Activate the framebuffer. | ||
435 | /// Subsequent draw calls write to this framebuffer. | ||
436 | void gfx_activate_framebuffer(const FrameBuffer*); | ||
437 | |||
438 | /// Deactivate the framebuffer. | ||
439 | /// Subsequent draw calls write to the default framebuffer. | ||
440 | void gfx_deactivate_framebuffer(const FrameBuffer*); | ||
441 | |||
442 | /// Set the framebuffer's viewport. | ||
443 | /// This function should be called every time the framebuffer is activated. | ||
444 | void gfx_framebuffer_set_viewport( | ||
445 | FrameBuffer*, int x, int y, int width, int height); | ||
446 | |||
447 | // ----------------------------------------------------------------------------- | ||
448 | // Shaders. | ||
449 | // ----------------------------------------------------------------------------- | ||
450 | |||
451 | /// Create a shader. | ||
452 | Shader* gfx_make_shader(GfxCore*, const ShaderDesc*); | ||
453 | |||
454 | /// Destroy the shader. | ||
455 | void gfx_destroy_shader(GfxCore*, Shader**); | ||
456 | |||
457 | /// Create a shader program. | ||
458 | ShaderProgram* gfx_make_shader_program(GfxCore*, const ShaderProgramDesc*); | ||
459 | |||
460 | /// Destroy the shader program. | ||
461 | void gfx_destroy_shader_program(GfxCore*, ShaderProgram**); | ||
462 | |||
463 | /// Activate the shader program. | ||
464 | void gfx_activate_shader_program(const ShaderProgram*); | ||
465 | |||
466 | /// Deactivate the shader program. | ||
467 | void gfx_deactivate_shader_program(const ShaderProgram*); | ||
468 | |||
469 | /// Apply the shader program's uniform variables. | ||
470 | /// | ||
471 | /// Calls to gfx_set_XYZ_uniform save the values of the uniform variables in the | ||
472 | /// graphics library. By calling this function, those values are passed on to | ||
473 | /// the graphics driver for rendering. | ||
474 | /// | ||
475 | /// This function should be called after setting all of the uniform variables | ||
476 | /// and prior to issuing a draw call. | ||
477 | /// | ||
478 | /// The given program must have been activated prior to this call with | ||
479 | /// gfx_activate_shader_program(). | ||
480 | void gfx_apply_uniforms(const ShaderProgram*); | ||
481 | |||
482 | /// Set the texture uniform. | ||
483 | /// Has no effect if the shader does not contain the given uniform. | ||
484 | void gfx_set_texture_uniform(ShaderProgram*, const char* name, const Texture*); | ||
485 | |||
486 | /// Set the matrix uniform. | ||
487 | /// Has no effect if the shader does not contain the given uniform. | ||
488 | void gfx_set_mat4_uniform(ShaderProgram*, const char* name, const mat4*); | ||
489 | |||
490 | /// Set the vec3 uniform. | ||
491 | /// Has no effect if the shader does not contain the given uniform. | ||
492 | void gfx_set_vec3_uniform(ShaderProgram*, const char* name, vec3); | ||
493 | |||
494 | /// Set the vec4 uniform. | ||
495 | /// Has no effect if the shader does not contain the given uniform. | ||
496 | void gfx_set_vec4_uniform(ShaderProgram*, const char* name, vec4); | ||
497 | |||
498 | /// Set the float uniform. | ||
499 | /// Has no effect if the shader does not contain the given uniform. | ||
500 | void gfx_set_float_uniform(ShaderProgram*, const char* name, float value); | ||
501 | |||
502 | /// Set the matrix array uniform. | ||
503 | /// Has no effect if the shader does not contain the given uniform. | ||
504 | void gfx_set_mat4_array_uniform( | ||
505 | ShaderProgram*, const char* name, const mat4*, size_t count); | ||
diff --git a/include/gfx/gfx.h b/include/gfx/gfx.h new file mode 100644 index 0000000..d5c25b6 --- /dev/null +++ b/include/gfx/gfx.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #pragma once | ||
2 | |||
3 | typedef struct AssetCache AssetCache; | ||
4 | typedef struct GfxCore GfxCore; | ||
5 | typedef struct ImmRenderer ImmRenderer; | ||
6 | typedef struct LLR LLR; | ||
7 | typedef struct Renderer Renderer; | ||
8 | |||
9 | typedef struct Gfx Gfx; | ||
10 | |||
11 | /// Create a new graphics system, | ||
12 | Gfx* gfx_init(void); | ||
13 | |||
14 | /// Destroy the graphics system. | ||
15 | void gfx_destroy(Gfx**); | ||
16 | |||
17 | /// Get the render backend. | ||
18 | GfxCore* gfx_get_core(Gfx*); | ||
19 | |||
20 | /// Get the scene renderer. | ||
21 | Renderer* gfx_get_renderer(Gfx*); | ||
22 | |||
23 | /// Get the immediate mode renderer. | ||
24 | ImmRenderer* gfx_get_imm_renderer(Gfx*); | ||
25 | |||
26 | /// Get the low-level renderer. | ||
27 | LLR* gfx_get_llr(Gfx*); | ||
28 | |||
29 | /// Get the asset cache. | ||
30 | AssetCache* gfx_get_asset_cache(Gfx*); | ||
31 | |||
32 | /// Remove unused resources from the scene (meshes, materials). | ||
33 | /// TODO: need to think about the interface for scene_purge(). Maybe this | ||
34 | /// should be gfx_purge() and take a list of Scenes? | ||
35 | // void gfx_purge(Scene*); | ||
diff --git a/include/gfx/llr/light.h b/include/gfx/llr/light.h new file mode 100644 index 0000000..132e344 --- /dev/null +++ b/include/gfx/llr/light.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #pragma once | ||
2 | |||
3 | typedef struct Texture Texture; | ||
4 | |||
5 | typedef struct Light Light; | ||
6 | |||
7 | /// Light type. | ||
8 | typedef enum LightType { EnvironmentLightType } LightType; | ||
9 | |||
10 | /// Describes an environment light. | ||
11 | typedef struct EnvironmentLightDesc { | ||
12 | const Texture* environment_map; | ||
13 | } EnvironmentLightDesc; | ||
14 | |||
15 | /// Describes a light. | ||
16 | typedef struct LightDesc { | ||
17 | LightType type; | ||
18 | union { | ||
19 | EnvironmentLightDesc environment; | ||
20 | } light; | ||
21 | } LightDesc; | ||
22 | |||
23 | /// Create a light. | ||
24 | Light* gfx_make_light(const LightDesc*); | ||
25 | |||
26 | /// Destroy the light. | ||
27 | /// | ||
28 | /// The light is conveniently removed from the scene graph and its parent scene | ||
29 | /// node is destroyed. | ||
30 | void gfx_destroy_light(Light**); | ||
diff --git a/include/gfx/llr/llr.h b/include/gfx/llr/llr.h new file mode 100644 index 0000000..77df33f --- /dev/null +++ b/include/gfx/llr/llr.h | |||
@@ -0,0 +1,67 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/camera.h> | ||
4 | #include <math/mat4.h> | ||
5 | #include <math/vec3.h> | ||
6 | |||
7 | typedef struct Anima Anima; | ||
8 | typedef struct Geometry Geometry; | ||
9 | typedef struct Light Light; | ||
10 | typedef struct Mesh Mesh; | ||
11 | typedef struct ShaderProgram ShaderProgram; | ||
12 | typedef struct Skeleton Skeleton; | ||
13 | |||
14 | typedef struct LLR LLR; | ||
15 | |||
16 | /// Set the shader to be used for subsequent draw calls. | ||
17 | /// The shader is not yet activated at this point. | ||
18 | void gfx_llr_set_shader(LLR*, ShaderProgram*); | ||
19 | |||
20 | /// Push a light into the lights stack. | ||
21 | void gfx_llr_push_light(LLR*, Light*); | ||
22 | |||
23 | /// Pop the last light from the lights stack. | ||
24 | void gfx_llr_pop_light(LLR*); | ||
25 | |||
26 | /// Load a skeleton. | ||
27 | /// | ||
28 | /// If a skeleton is loaded, subsequent meshes are rendered with joint data | ||
29 | /// passed to the shader. This has a cost, so if subsequent meshes are not | ||
30 | /// animated, unload the skeleton prior to rendering them. | ||
31 | void gfx_llr_set_skeleton(LLR*, const Anima*, const Skeleton*); | ||
32 | |||
33 | /// Clear the loaded skeleton. | ||
34 | void gfx_llr_clear_skeleton(LLR*); | ||
35 | |||
36 | /// Set the camera. | ||
37 | void gfx_llr_set_camera(LLR*, const Camera*); | ||
38 | |||
39 | /// Set the view-projection matrix. | ||
40 | // void gfx_llr_set_view_projection_matrix(LLR*, const mat4*); | ||
41 | |||
42 | /// Set the aspect ratio. | ||
43 | void gfx_llr_set_aspect(LLR*, float aspect); | ||
44 | |||
45 | /// Render the geometry. | ||
46 | void gfx_llr_render_geometry(LLR*, const Geometry*); | ||
47 | |||
48 | /// Render the mesh. | ||
49 | void gfx_llr_render_mesh(LLR*, const Mesh*); | ||
50 | |||
51 | // ----------------------------------------------------------------------------- | ||
52 | // Matrix stack manipulation. | ||
53 | |||
54 | /// Load an identity model matrix. Clears the matrix stack. | ||
55 | void gfx_llr_load_identity(LLR* renderer); | ||
56 | |||
57 | /// Push the given matrix to the matrix stack. | ||
58 | void gfx_llr_push_matrix(LLR* renderer, const mat4* matrix); | ||
59 | |||
60 | /// Pop the top of the matrix stack. | ||
61 | void gfx_llr_pop_matrix(LLR* renderer); | ||
62 | |||
63 | /// Push a translation matrix to the matrix stack. | ||
64 | void gfx_llr_translate(LLR* renderer, vec3 offset); | ||
65 | |||
66 | /// Set the model matrix. Clears the matrix stack. | ||
67 | void gfx_llr_set_model_matrix(LLR*, const mat4*); | ||
diff --git a/include/gfx/llr/material.h b/include/gfx/llr/material.h new file mode 100644 index 0000000..bca664e --- /dev/null +++ b/include/gfx/llr/material.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <gfx/core.h> | ||
4 | #include <gfx/sizes.h> | ||
5 | |||
6 | typedef struct Material Material; | ||
7 | |||
8 | /// Describes a material. | ||
9 | /// | ||
10 | /// A material holds a shader program and a set of shader-specific uniform | ||
11 | /// variables. Two materials can share the same shader, but shader parameters | ||
12 | /// generally give two materials a different appearance. | ||
13 | typedef struct MaterialDesc { | ||
14 | ShaderUniform uniforms[GFX_MAX_UNIFORMS_PER_MATERIAL]; | ||
15 | int num_uniforms; | ||
16 | } MaterialDesc; | ||
17 | |||
18 | /// Create a material. | ||
19 | Material* gfx_make_material(const MaterialDesc*); | ||
20 | |||
21 | /// Destroy the material. | ||
22 | /// | ||
23 | /// The caller must make sure that no Mesh points to the given Material. | ||
24 | /// For a safe purge of unused resources, see scene_purge(). | ||
25 | void gfx_destroy_material(Material**); | ||
diff --git a/include/gfx/llr/mesh.h b/include/gfx/llr/mesh.h new file mode 100644 index 0000000..0d3b4d4 --- /dev/null +++ b/include/gfx/llr/mesh.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #pragma once | ||
2 | |||
3 | typedef struct Geometry Geometry; | ||
4 | typedef struct Material Material; | ||
5 | typedef struct ShaderProgram ShaderProgram; | ||
6 | |||
7 | typedef struct Mesh Mesh; | ||
8 | |||
9 | /// Describes a mesh. | ||
10 | typedef struct MeshDesc { | ||
11 | const Geometry* geometry; | ||
12 | const Material* material; | ||
13 | ShaderProgram* shader; | ||
14 | } MeshDesc; | ||
15 | |||
16 | /// Create a mesh. | ||
17 | Mesh* gfx_make_mesh(const MeshDesc*); | ||
18 | |||
19 | /// Destroy the mesh. | ||
20 | /// | ||
21 | /// The caller must make sure that no SceneObject points to the given Mesh. | ||
22 | /// For a safe purge of unused resources, see scene_purge(). | ||
23 | void gfx_destroy_mesh(Mesh**); | ||
diff --git a/include/gfx/renderer.h b/include/gfx/renderer.h new file mode 100644 index 0000000..1da74eb --- /dev/null +++ b/include/gfx/renderer.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/defs.h> | ||
4 | |||
5 | typedef struct GfxCore GfxCore; | ||
6 | typedef struct Scene Scene; | ||
7 | typedef struct SceneCamera SceneCamera; | ||
8 | |||
9 | typedef struct Renderer Renderer; | ||
10 | |||
11 | typedef enum RenderSceneMode { | ||
12 | RenderDefault, | ||
13 | RenderDebug, | ||
14 | RenderNormals, | ||
15 | RenderNormalMappedNormals, | ||
16 | RenderTangents | ||
17 | } RenderSceneMode; | ||
18 | |||
19 | typedef struct RenderSceneParams { | ||
20 | RenderSceneMode mode; | ||
21 | const Scene* scene; | ||
22 | const SceneCamera* camera; | ||
23 | } RenderSceneParams; | ||
24 | |||
25 | /// Render the scene. | ||
26 | void gfx_render_scene(Renderer*, const RenderSceneParams*); | ||
27 | |||
28 | /// Update the scene. | ||
29 | void gfx_update(Scene*, const SceneCamera*, R t); | ||
diff --git a/include/gfx/renderer/imm_renderer.h b/include/gfx/renderer/imm_renderer.h new file mode 100644 index 0000000..db4d290 --- /dev/null +++ b/include/gfx/renderer/imm_renderer.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/aabb2.h> | ||
4 | #include <math/aabb3.h> | ||
5 | #include <math/camera.h> | ||
6 | #include <math/mat4.h> | ||
7 | #include <math/vec3.h> | ||
8 | #include <math/vec4.h> | ||
9 | |||
10 | typedef struct ImmRenderer ImmRenderer; | ||
11 | |||
12 | /// Prepare the graphics systems for immediate-mode rendering. | ||
13 | /// | ||
14 | /// Call this before issuing any immediate-mode rendering draws. | ||
15 | void gfx_imm_start(ImmRenderer*); | ||
16 | |||
17 | /// End immediate mode rendering. | ||
18 | /// | ||
19 | /// Call this after issuing immediate-mode rendering draws and before swapping | ||
20 | /// buffers. | ||
21 | void gfx_imm_end(ImmRenderer*); | ||
22 | |||
23 | /// Flush draw commands. | ||
24 | /// | ||
25 | /// This should be done when changing any state that may affect the rendering of | ||
26 | /// primitives; for example, LLR matrix stack changes. | ||
27 | void gfx_imm_flush(ImmRenderer*); | ||
28 | |||
29 | /// Draw a set of triangles. | ||
30 | void gfx_imm_draw_triangles(ImmRenderer*, const vec3[], size_t num_triangles); | ||
31 | |||
32 | /// Draw a triangle. | ||
33 | void gfx_imm_draw_triangle(ImmRenderer*, const vec3[3]); | ||
34 | |||
35 | /// Draw a bounding box. | ||
36 | void gfx_imm_draw_aabb2(ImmRenderer*, aabb2); | ||
37 | |||
38 | /// Draw a bounding box. | ||
39 | void gfx_imm_draw_aabb3(ImmRenderer*, aabb3); | ||
40 | |||
41 | /// Draw a box. | ||
42 | /// | ||
43 | /// The vertices must be given in the following order: | ||
44 | /// | ||
45 | /// 7 ----- 6 | ||
46 | /// / /| | ||
47 | /// 3 ----- 2 | | ||
48 | /// | | | | ||
49 | /// | 4 ----- 5 | ||
50 | /// |/ |/ | ||
51 | /// 0 ----- 1 | ||
52 | void gfx_imm_draw_box3(ImmRenderer* renderer, const vec3 vertices[8]); | ||
53 | |||
54 | /// Set the render colour. | ||
55 | void gfx_imm_set_colour(ImmRenderer*, vec4 colour); | ||
diff --git a/include/gfx/scene.h b/include/gfx/scene.h new file mode 100644 index 0000000..37a7e0b --- /dev/null +++ b/include/gfx/scene.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #pragma once | ||
2 | |||
3 | // TODO: Remove references to gfx/llr once the transition is complete. | ||
4 | #include <gfx/llr/light.h> | ||
5 | #include <gfx/llr/material.h> | ||
6 | #include <gfx/llr/mesh.h> | ||
7 | #include <gfx/scene/animation.h> | ||
8 | #include <gfx/scene/camera.h> | ||
9 | #include <gfx/scene/model.h> | ||
10 | #include <gfx/scene/node.h> | ||
11 | #include <gfx/scene/object.h> | ||
12 | #include <gfx/scene/scene.h> | ||
diff --git a/include/gfx/scene/animation.h b/include/gfx/scene/animation.h new file mode 100644 index 0000000..3ef0471 --- /dev/null +++ b/include/gfx/scene/animation.h | |||
@@ -0,0 +1,140 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "object.h" | ||
4 | #include <gfx/sizes.h> | ||
5 | |||
6 | #include <cstring.h> | ||
7 | #include <math/aabb3.h> | ||
8 | #include <math/defs.h> | ||
9 | #include <math/mat4.h> | ||
10 | #include <math/quat.h> | ||
11 | #include <math/vec3.h> | ||
12 | |||
13 | #include <stdbool.h> | ||
14 | #include <stddef.h> | ||
15 | #include <stdint.h> | ||
16 | |||
17 | typedef struct Buffer Buffer; | ||
18 | |||
19 | typedef struct Anima Anima; | ||
20 | typedef struct Joint Joint; | ||
21 | typedef struct Skeleton Skeleton; | ||
22 | |||
23 | /// Index type used to store relative indices into arrays. | ||
24 | typedef uint16_t joint_idx; | ||
25 | |||
26 | /// Index value denoting no index. | ||
27 | static const joint_idx INDEX_NONE = (joint_idx)-1; | ||
28 | |||
29 | typedef struct Box { | ||
30 | vec3 vertices[8]; | ||
31 | } Box; | ||
32 | |||
33 | /// Joint descriptor. | ||
34 | typedef struct JointDesc { | ||
35 | joint_idx parent; /// Parent Joint; index into Anima's joints. | ||
36 | mat4 inv_bind_matrix; /// Transforms the mesh into the joint's local space. | ||
37 | aabb3 box; /// Bounding box. | ||
38 | } JointDesc; | ||
39 | |||
40 | /// Skeleton descriptor. | ||
41 | typedef struct SkeletonDesc { | ||
42 | size_t num_joints; | ||
43 | joint_idx joints[GFX_MAX_NUM_JOINTS]; /// Indices into Anima's joints array. | ||
44 | } SkeletonDesc; | ||
45 | |||
46 | /// Animation interpolation mode. | ||
47 | typedef enum AnimationInterpolation { | ||
48 | StepInterpolation, | ||
49 | LinearInterpolation, | ||
50 | CubicSplineInterpolation | ||
51 | } AnimationInterpolation; | ||
52 | |||
53 | /// The kind of transformation applied by a Channel. | ||
54 | typedef enum ChannelType { | ||
55 | RotationChannel, | ||
56 | ScaleChannel, | ||
57 | TranslationChannel, | ||
58 | WeightsChannel | ||
59 | } ChannelType; | ||
60 | |||
61 | /// Animation keyframe descriptor. | ||
62 | /// | ||
63 | /// The arrays should have as many entries as 'num_joints' in the SkeletonDesc. | ||
64 | typedef struct KeyframeDesc { | ||
65 | R time; // Start time in [0, end animation time] | ||
66 | union { | ||
67 | vec3 translation; | ||
68 | quat rotation; | ||
69 | }; | ||
70 | } KeyframeDesc; | ||
71 | |||
72 | /// Animation channel descriptor. | ||
73 | typedef struct ChannelDesc { | ||
74 | joint_idx target; /// Index into Anima's joints array. | ||
75 | ChannelType type; | ||
76 | AnimationInterpolation interpolation; | ||
77 | size_t num_keyframes; | ||
78 | KeyframeDesc keyframes[GFX_MAX_NUM_KEYFRAMES]; | ||
79 | } ChannelDesc; | ||
80 | |||
81 | /// Animation descriptor. | ||
82 | typedef struct AnimationDesc { | ||
83 | // TODO: Store a name hash for faster comparisons. | ||
84 | sstring name; // Animation name. Required for playback. | ||
85 | size_t num_channels; // Number of channels. | ||
86 | ChannelDesc channels[GFX_MAX_NUM_CHANNELS]; | ||
87 | } AnimationDesc; | ||
88 | |||
89 | /// Anima object descriptor. | ||
90 | /// | ||
91 | /// The last joint of the joints array at index 'num_joints - 1' must be the | ||
92 | /// root of all skeletons; specifically, the root of all joints that otherwise | ||
93 | /// would have no parent (a skeleton need not have its own root and can be a set | ||
94 | /// of disjoint node hierarchies). | ||
95 | typedef struct AnimaDesc { | ||
96 | size_t num_skeletons; | ||
97 | size_t num_animations; | ||
98 | size_t num_joints; | ||
99 | SkeletonDesc skeletons[GFX_MAX_NUM_SKELETONS]; | ||
100 | AnimationDesc animations[GFX_MAX_NUM_ANIMATIONS]; | ||
101 | JointDesc joints[GFX_MAX_NUM_JOINTS]; | ||
102 | } AnimaDesc; | ||
103 | |||
104 | /// Animation play settings. | ||
105 | typedef struct AnimationPlaySettings { | ||
106 | const char* name; // Animation name. | ||
107 | bool loop; // Whether to loop the animation or just play once. | ||
108 | // TODO: Add animation speed. | ||
109 | } AnimationPlaySettings; | ||
110 | |||
111 | /// Create an anima object. | ||
112 | Anima* gfx_make_anima(const AnimaDesc*); | ||
113 | |||
114 | /// Destroy the anima. | ||
115 | void gfx_destroy_anima(Anima**); | ||
116 | |||
117 | /// Play an animation (sets the current animation). | ||
118 | bool gfx_play_animation(Anima*, const AnimationPlaySettings*); | ||
119 | |||
120 | /// Update the current animation. | ||
121 | void gfx_update_animation(Anima*, R t); | ||
122 | |||
123 | /// Stop the current animation. | ||
124 | void gfx_stop_animation(Anima*); | ||
125 | |||
126 | /// Return the anima's ith skeleton. | ||
127 | const Skeleton* gfx_get_anima_skeleton(const Anima* anima, size_t i); | ||
128 | |||
129 | /// Return the number of joints in the skeleton. | ||
130 | size_t gfx_get_skeleton_num_joints(const Skeleton*); | ||
131 | |||
132 | /// Return true if the skeleton's ith joint has a bounding box. | ||
133 | /// | ||
134 | /// IK joints that do not directly transform vertices have no bounding box. | ||
135 | bool gfx_joint_has_box(const Anima*, const Skeleton*, size_t joint); | ||
136 | |||
137 | /// Return the bounding box of the skeleton's ith joint. | ||
138 | /// | ||
139 | /// IK joints that do not directly transform vertices have no box. | ||
140 | Box gfx_get_joint_box(const Anima*, const Skeleton*, size_t joint); | ||
diff --git a/include/gfx/scene/camera.h b/include/gfx/scene/camera.h new file mode 100644 index 0000000..99d83fe --- /dev/null +++ b/include/gfx/scene/camera.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/fwd.h> | ||
4 | |||
5 | typedef struct SceneNode SceneNode; | ||
6 | |||
7 | typedef struct SceneCamera SceneCamera; | ||
8 | |||
9 | /// Create a new camera. | ||
10 | SceneCamera* gfx_make_camera(); | ||
11 | |||
12 | /// Destroy the camera. | ||
13 | /// | ||
14 | /// The camera is conveniently removed from the scene graph and its parent scene | ||
15 | /// node is destroyed. | ||
16 | void gfx_destroy_camera(SceneCamera**); | ||
17 | |||
18 | /// Set the scene camera's math camera. | ||
19 | void gfx_set_camera_camera(SceneCamera* scene_camera, Camera* camera); | ||
20 | |||
21 | /// Get the scene camera's math camera. | ||
22 | Camera* gfx_get_camera_camera(SceneCamera*); | ||
diff --git a/include/gfx/scene/model.h b/include/gfx/scene/model.h new file mode 100644 index 0000000..42f85d4 --- /dev/null +++ b/include/gfx/scene/model.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #pragma once | ||
2 | |||
3 | typedef struct Anima Anima; | ||
4 | typedef struct Model Model; | ||
5 | typedef struct SceneNode SceneNode; | ||
6 | |||
7 | /// Return the model's anima, or null if the model is not animated. | ||
8 | Anima* gfx_get_model_anima(Model*); | ||
9 | |||
10 | /// Return the model's root node. | ||
11 | const SceneNode* gfx_get_model_root(const Model*); | ||
12 | SceneNode* gfx_get_model_root_mut(Model*); | ||
diff --git a/include/gfx/scene/node.h b/include/gfx/scene/node.h new file mode 100644 index 0000000..193eb25 --- /dev/null +++ b/include/gfx/scene/node.h | |||
@@ -0,0 +1,152 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/fwd.h> | ||
4 | #include <math/mat4.h> | ||
5 | |||
6 | typedef struct Anima Anima; | ||
7 | typedef struct Light Light; | ||
8 | typedef struct Model Model; | ||
9 | typedef struct SceneCamera SceneCamera; | ||
10 | typedef struct SceneObject SceneObject; | ||
11 | |||
12 | /// Scene node type. | ||
13 | typedef enum NodeType { | ||
14 | LogicalNode, | ||
15 | AnimaNode, | ||
16 | CameraNode, | ||
17 | LightNode, | ||
18 | ModelNode, | ||
19 | ObjectNode, | ||
20 | } NodeType; | ||
21 | |||
22 | /// A node in the scene graph. | ||
23 | /// | ||
24 | /// Scene nodes take ownership of the object they are associated with (Camera, | ||
25 | /// Light, SceneObject, etc), as well as of child nodes. | ||
26 | typedef struct SceneNode SceneNode; | ||
27 | |||
28 | // ----------------------------------------------------------------------------- | ||
29 | // Constructors and destructor. | ||
30 | // ----------------------------------------------------------------------------- | ||
31 | |||
32 | /// Create a new scene node. | ||
33 | /// | ||
34 | /// This node does not contain any camera, light, object, etc. and exists simply | ||
35 | /// as a logical and spatial construct. | ||
36 | SceneNode* gfx_make_node(); | ||
37 | |||
38 | /// Create an anima node. | ||
39 | SceneNode* gfx_make_anima_node(Anima*); | ||
40 | |||
41 | /// Create a new camera node. | ||
42 | SceneNode* gfx_make_camera_node(SceneCamera*); | ||
43 | |||
44 | /// Create a new light node. | ||
45 | SceneNode* gfx_make_light_node(Light*); | ||
46 | |||
47 | /// Create a new model node. | ||
48 | SceneNode* gfx_make_model_node(Model*); | ||
49 | |||
50 | /// Create a new object node. | ||
51 | SceneNode* gfx_make_object_node(SceneObject*); | ||
52 | |||
53 | /// Make the node an anima node. | ||
54 | void gfx_construct_anima_node(SceneNode*, Anima*); | ||
55 | |||
56 | /// Make the node a camera node. | ||
57 | void gfx_construct_camera_node(SceneNode*, SceneCamera*); | ||
58 | |||
59 | /// Make the node a light node. | ||
60 | void gfx_construct_light_node(SceneNode*, Light*); | ||
61 | |||
62 | /// Make the node a model node. | ||
63 | void gfx_construct_model_node(SceneNode*, Model*); | ||
64 | |||
65 | /// Make the node an object node. | ||
66 | void gfx_construct_object_node(SceneNode*, SceneObject*); | ||
67 | |||
68 | /// Recursively destroy the scene node and its children. | ||
69 | /// | ||
70 | /// The scene node and its children are removed from the scene graph. | ||
71 | /// | ||
72 | /// Node resources -- cameras, lights, objects, etc. -- are also destroyed. | ||
73 | void gfx_destroy_node(SceneNode**); | ||
74 | |||
75 | // ----------------------------------------------------------------------------- | ||
76 | // Getters. | ||
77 | // ----------------------------------------------------------------------------- | ||
78 | |||
79 | /// Get the node's type. | ||
80 | NodeType gfx_get_node_type(const SceneNode*); | ||
81 | |||
82 | /// Get the node's anima. | ||
83 | /// | ||
84 | /// The node must be of type AnimaNode. | ||
85 | const Anima* gfx_get_node_anima(const SceneNode*); | ||
86 | Anima* gfx_get_node_anima_mut(SceneNode*); | ||
87 | |||
88 | /// Get the node's camera. | ||
89 | /// | ||
90 | /// The node must be of type CameraNode. | ||
91 | const SceneCamera* gfx_get_node_camera(const SceneNode* node); | ||
92 | SceneCamera* gfx_get_node_camera_mut(SceneNode* node); | ||
93 | |||
94 | /// Get the node's light. | ||
95 | /// | ||
96 | /// The node must be of type LightNode. | ||
97 | const Light* gfx_get_node_light(const SceneNode*); | ||
98 | Light* gfx_get_node_light_mut(SceneNode*); | ||
99 | |||
100 | /// Get the node's model. | ||
101 | /// | ||
102 | /// The node must be of type ModelNode. | ||
103 | const Model* gfx_get_node_model(const SceneNode*); | ||
104 | Model* gfx_get_node_model_mut(SceneNode*); | ||
105 | |||
106 | /// Get the node's scene object. | ||
107 | /// | ||
108 | /// The node must be of type ObjectNode. | ||
109 | const SceneObject* gfx_get_node_object(const SceneNode*); | ||
110 | SceneObject* gfx_get_node_object_mut(SceneNode*); | ||
111 | |||
112 | /// Get the node's parent. | ||
113 | const SceneNode* gfx_get_node_parent(const SceneNode*); | ||
114 | SceneNode* gfx_get_node_parent_mut(SceneNode*); | ||
115 | |||
116 | /// Get the node's first child. | ||
117 | const SceneNode* gfx_get_node_child(const SceneNode*); | ||
118 | SceneNode* gfx_get_node_child_mut(SceneNode*); | ||
119 | |||
120 | /// Get the node's immediate sibling. | ||
121 | const SceneNode* gfx_get_node_sibling(const SceneNode*); | ||
122 | SceneNode* gfx_get_node_sibling_mut(SceneNode*); | ||
123 | |||
124 | /// Get the node's (local) transform. | ||
125 | mat4 gfx_get_node_transform(const SceneNode*); | ||
126 | |||
127 | /// Get the node's global transform. | ||
128 | mat4 gfx_get_node_global_transform(const SceneNode*); | ||
129 | |||
130 | // ----------------------------------------------------------------------------- | ||
131 | // Setters. | ||
132 | // ----------------------------------------------------------------------------- | ||
133 | |||
134 | /// Set the node's parent. | ||
135 | /// | ||
136 | /// Pass in null to unwire from the existing parent, if one exists. | ||
137 | void gfx_set_node_parent(SceneNode*, SceneNode* parent_node); | ||
138 | |||
139 | /// Set the node's (local) transform. | ||
140 | void gfx_set_node_transform(SceneNode*, const mat4* transform); | ||
141 | |||
142 | /// Set the node's position. | ||
143 | void gfx_set_node_position(SceneNode*, const vec3* position); | ||
144 | |||
145 | /// Set the node's rotation. | ||
146 | void gfx_set_node_rotation(SceneNode*, const quat* rotation); | ||
147 | |||
148 | /// Set the node's rotation. | ||
149 | void gfx_set_node_rotation_mat(SceneNode*, const mat4* rotation); | ||
150 | |||
151 | /// Log the node's hierarchy. | ||
152 | void gfx_log_node_hierarchy(const SceneNode*); | ||
diff --git a/include/gfx/scene/object.h b/include/gfx/scene/object.h new file mode 100644 index 0000000..7579d29 --- /dev/null +++ b/include/gfx/scene/object.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <gfx/sizes.h> | ||
4 | |||
5 | #include <math/fwd.h> | ||
6 | |||
7 | #include <math/aabb3.h> | ||
8 | |||
9 | typedef struct Mesh Mesh; | ||
10 | typedef struct SceneNode SceneNode; | ||
11 | typedef struct Skeleton Skeleton; | ||
12 | |||
13 | typedef struct SceneObject SceneObject; | ||
14 | |||
15 | typedef struct ObjectDesc { | ||
16 | size_t num_meshes; | ||
17 | Mesh* meshes[GFX_MAX_NUM_MESHES]; | ||
18 | } ObjectDesc; | ||
19 | |||
20 | /// Create a new object. | ||
21 | SceneObject* gfx_make_object(const ObjectDesc*); | ||
22 | |||
23 | /// Destroy the object. | ||
24 | /// | ||
25 | /// The object is conveniently removed from the scene graph and its parent scene | ||
26 | /// node is destroyed. | ||
27 | void gfx_destroy_object(SceneObject**); | ||
28 | |||
29 | /// Set the object's skeleton. | ||
30 | void gfx_set_object_skeleton(SceneObject*, const Skeleton*); | ||
31 | |||
32 | /// Get the object's skeleton. | ||
33 | /// Return null if the object has no skeleton. | ||
34 | const Skeleton* gfx_get_object_skeleton(const SceneObject*); | ||
35 | |||
36 | /// Gets the object's bounding box. | ||
37 | /// | ||
38 | /// The object's bounding box is the bounding box of its mesh geometries. | ||
39 | aabb3 gfx_get_object_aabb(const SceneObject*); | ||
diff --git a/include/gfx/scene/scene.h b/include/gfx/scene/scene.h new file mode 100644 index 0000000..0d96210 --- /dev/null +++ b/include/gfx/scene/scene.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/defs.h> | ||
4 | #include <math/fwd.h> | ||
5 | |||
6 | typedef struct SceneNode SceneNode; | ||
7 | |||
8 | typedef struct Scene Scene; | ||
9 | |||
10 | /// Create a new scene. | ||
11 | Scene* gfx_make_scene(void); | ||
12 | |||
13 | /// Destroy the scene. | ||
14 | /// | ||
15 | /// This function destroys the scene and all objects that it owns (scene | ||
16 | /// objects, cameras, lights, etc), but not objects that could be shared with | ||
17 | /// other scenes (meshes, materials, etc). | ||
18 | void gfx_destroy_scene(Scene**); | ||
19 | |||
20 | /// Get the scene's root node. | ||
21 | SceneNode* gfx_get_scene_root(Scene*); | ||
diff --git a/include/gfx/sizes.h b/include/gfx/sizes.h new file mode 100644 index 0000000..3eb7481 --- /dev/null +++ b/include/gfx/sizes.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /// Size constants used throughout the library. | ||
2 | #pragma once | ||
3 | |||
4 | // Scene. | ||
5 | |||
6 | /// Maximum number of cameras. | ||
7 | #define GFX_MAX_NUM_CAMERAS 16 | ||
8 | |||
9 | /// Maximum number of lights. | ||
10 | #define GFX_MAX_NUM_LIGHTS 1024 | ||
11 | |||
12 | /// Maximum number of materials. | ||
13 | #define GFX_MAX_NUM_MATERIALS 1024 | ||
14 | |||
15 | /// Maximum number of meshes. | ||
16 | #define GFX_MAX_NUM_MESHES 1024 | ||
17 | |||
18 | /// Maximum number of mesh links. | ||
19 | #define GFX_MAX_NUM_MESH_LINKS 1024 | ||
20 | |||
21 | /// Maximum number of models. | ||
22 | #define GFX_MAX_NUM_MODELS 64 | ||
23 | |||
24 | /// Maximum number of joints per skeleton. | ||
25 | #define GFX_MAX_NUM_JOINTS 96 | ||
26 | |||
27 | /// Maximum number of keyframes per channel. | ||
28 | #define GFX_MAX_NUM_KEYFRAMES 32 | ||
29 | |||
30 | /// Maximum number of channels per animation. | ||
31 | #define GFX_MAX_NUM_CHANNELS 128 | ||
32 | |||
33 | /// Maximum number of skeletons. | ||
34 | #define GFX_MAX_NUM_SKELETONS 8 | ||
35 | |||
36 | /// Maximum number of animations. | ||
37 | #define GFX_MAX_NUM_ANIMATIONS 32 | ||
38 | |||
39 | /// Maximum number of animas. | ||
40 | #define GFX_MAX_NUM_ANIMAS 128 | ||
41 | |||
42 | /// Maximum number of nodes per scene. | ||
43 | #define GFX_MAX_NUM_NODES 1024 | ||
44 | |||
45 | /// Maximum number of objects per scene. | ||
46 | #define GFX_MAX_NUM_OBJECTS 1024 | ||
47 | |||
48 | /// Maximum number of uniforms in a Material. | ||
49 | #define GFX_MAX_UNIFORMS_PER_MATERIAL 18 | ||
50 | |||
51 | // Render. | ||
52 | |||
53 | /// Maximum number of buffers per renderer. | ||
54 | #define GFX_MAX_NUM_BUFFERS 1024 | ||
55 | |||
56 | /// Maximum number of framebuffers per renderer. | ||
57 | #define GFX_MAX_NUM_FRAMEBUFFERS 32 | ||
58 | |||
59 | /// Maximum number of geometries per renderer. | ||
60 | #define GFX_MAX_NUM_GEOMETRIES 1024 | ||
61 | |||
62 | /// Maximum number of renderbuffers per renderer. | ||
63 | #define GFX_MAX_NUM_RENDERBUFFERS (GFX_MAX_NUM_FRAMEBUFFERS * 2) | ||
64 | |||
65 | /// Maximum number of shader programs per renderer. | ||
66 | #define GFX_MAX_NUM_SHADER_PROGRAMS 128 | ||
67 | |||
68 | /// Maximum number of shaders per renderer. | ||
69 | #define GFX_MAX_NUM_SHADERS (GFX_MAX_NUM_SHADER_PROGRAMS * 2) | ||
70 | |||
71 | /// Maximum number of textures per renderer. | ||
72 | #define GFX_MAX_NUM_TEXTURES 1024 | ||
73 | |||
74 | /// Maximum number of uniforms in a ShaderProgram. | ||
75 | #define GFX_MAX_UNIFORMS_PER_SHADER (GFX_MAX_UNIFORMS_PER_MATERIAL + 8) | ||
76 | |||
77 | /// Maximum number of compiler defines in a Shader. | ||
78 | #define GFX_MAX_SHADER_COMPILER_DEFINES 16 | ||
79 | |||
80 | // Low-level renderer. | ||
81 | |||
82 | /// Maximum number of lights that the low-level renderer can enable per rendered | ||
83 | /// mesh. | ||
84 | #define GFX_LLR_MAX_NUM_LIGHTS 8 | ||
85 | |||
86 | /// Maximum number of matrices in the low-level renderer's matrix stack. | ||
87 | #define GFX_LLR_MAX_NUM_MATRICES 32 | ||
88 | |||
89 | // Immediate-mode Renderer. | ||
90 | |||
91 | /// Maximum number of triangles that the immediate-mode renderer can draw in a | ||
92 | /// frame. | ||
93 | #define GFX_IMM_MAX_NUM_TRIANGLES 1024 | ||
94 | |||
95 | // Asset Cache. | ||
96 | |||
97 | #define GFX_MAX_NUM_ASSETS 1024 | ||
98 | |||
99 | // Gfx. | ||
100 | |||
101 | #define GFX_MAX_NUM_SCENES 4 | ||
diff --git a/include/gfx/util/geometry.h b/include/gfx/util/geometry.h new file mode 100644 index 0000000..a962291 --- /dev/null +++ b/include/gfx/util/geometry.h | |||
@@ -0,0 +1,13 @@ | |||
1 | /// Functions to construct geometry procedurally. | ||
2 | #pragma once | ||
3 | |||
4 | #include <gfx/core.h> | ||
5 | |||
6 | #include <math/vec2.h> | ||
7 | #include <math/vec3.h> | ||
8 | |||
9 | /// Construct a quad with positions in the range [-1, 1]^2. | ||
10 | Geometry* gfx_make_quad_11(GfxCore*); | ||
11 | |||
12 | /// Construct a quad with positions in the range [0, 1]^2. | ||
13 | Geometry* gfx_make_quad_01(GfxCore*); | ||
diff --git a/include/gfx/util/ibl.h b/include/gfx/util/ibl.h new file mode 100644 index 0000000..6e39180 --- /dev/null +++ b/include/gfx/util/ibl.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /// Functions for image-based lighting. | ||
2 | #pragma once | ||
3 | |||
4 | typedef struct IBL IBL; | ||
5 | |||
6 | typedef struct GfxCore GfxCore; | ||
7 | typedef struct Texture Texture; | ||
8 | |||
9 | /// Create an environment map filterer for IBL. | ||
10 | IBL* gfx_make_ibl(GfxCore*); | ||
11 | |||
12 | /// Destroy the environment map filterer. | ||
13 | void gfx_destroy_ibl(GfxCore*, IBL**); | ||
14 | |||
15 | /// Create a BRDF integration map for IBL. | ||
16 | Texture* gfx_make_brdf_integration_map(IBL*, GfxCore*, int width, int height); | ||
17 | |||
18 | /// Create an irradiance map (cubemap) from an environment map for IBL. | ||
19 | Texture* gfx_make_irradiance_map( | ||
20 | IBL*, GfxCore*, const Texture* environment_map, int width, int height); | ||
21 | |||
22 | /// Create a prefiltered environment map (cubemap) for IBL. | ||
23 | Texture* gfx_make_prefiltered_environment_map( | ||
24 | IBL*, GfxCore*, const Texture* environment_map, int width, int height, | ||
25 | int* max_mip_level); | ||
diff --git a/include/gfx/util/shader.h b/include/gfx/util/shader.h new file mode 100644 index 0000000..bd058f4 --- /dev/null +++ b/include/gfx/util/shader.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /// A variety of shaders included for convenience. | ||
2 | #pragma once | ||
3 | |||
4 | #include <stddef.h> | ||
5 | |||
6 | typedef struct GfxCore GfxCore; | ||
7 | typedef struct ShaderCompilerDefine ShaderCompilerDefine; | ||
8 | typedef struct ShaderProgram ShaderProgram; | ||
9 | |||
10 | /// Create a BRDF integration map shader. | ||
11 | ShaderProgram* gfx_make_brdf_integration_map_shader(GfxCore*); | ||
12 | |||
13 | /// Create a Cook-Torrance shader. | ||
14 | ShaderProgram* gfx_make_cook_torrance_shader(GfxCore*); | ||
15 | |||
16 | /// Create a Cook-Torrance shader with additional shader compiler defines. | ||
17 | /// This function can be used to create shader permutations. | ||
18 | ShaderProgram* gfx_make_cook_torrance_shader_perm( | ||
19 | GfxCore*, const ShaderCompilerDefine*, size_t num_defines); | ||
20 | |||
21 | /// Create a 3D debugging shader. | ||
22 | ShaderProgram* gfx_make_debug3d_shader(GfxCore*); | ||
23 | |||
24 | /// Create a shader for drawing in immediate mode. | ||
25 | ShaderProgram* gfx_make_immediate_mode_shader(GfxCore*); | ||
26 | |||
27 | /// Create a shader for computing irradiance maps from cube maps. | ||
28 | ShaderProgram* gfx_make_irradiance_map_shader(GfxCore*); | ||
29 | |||
30 | /// Create a shader for computing prefiltered environment maps from cube maps. | ||
31 | ShaderProgram* gfx_make_prefiltered_environment_map_shader(GfxCore*); | ||
32 | |||
33 | /// Create a skyquad shader. | ||
34 | ShaderProgram* gfx_make_skyquad_shader(GfxCore*); | ||
35 | |||
36 | /// Create a shader to view normal-mapped normals. | ||
37 | ShaderProgram* gfx_make_view_normal_mapped_normals_shader(GfxCore*); | ||
38 | |||
39 | /// Create a shader to view vertex normals. | ||
40 | ShaderProgram* gfx_make_view_normals_shader(GfxCore*); | ||
41 | |||
42 | /// Create a shader to view vertex tangents. | ||
43 | ShaderProgram* gfx_make_view_tangents_shader(GfxCore*); | ||
44 | |||
45 | /// Create a shader to view textures. | ||
46 | ShaderProgram* gfx_make_view_texture_shader(GfxCore*); | ||
diff --git a/include/gfx/util/skyquad.h b/include/gfx/util/skyquad.h new file mode 100644 index 0000000..2b3fe17 --- /dev/null +++ b/include/gfx/util/skyquad.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /// A skyquad is like a skybox but with a single quad. | ||
2 | #pragma once | ||
3 | |||
4 | typedef struct GfxCore GfxCore; | ||
5 | typedef struct Scene Scene; | ||
6 | typedef struct SceneNode SceneNode; | ||
7 | typedef struct SceneObject SceneObject; | ||
8 | typedef struct Texture Texture; | ||
9 | |||
10 | /// Create a skyquad. | ||
11 | SceneObject* gfx_make_skyquad(GfxCore*, const Texture*); | ||
12 | |||
13 | /// Set up a skyquad in the scene. | ||
14 | /// | ||
15 | /// This function adds two scene nodes under the given root node: | ||
16 | /// - An object node to render the skyquad in the background. | ||
17 | /// - A light node to light up other objects with the skyquad. | ||
18 | /// | ||
19 | /// Return the light node under which objects affected by the light can be | ||
20 | /// rooted. | ||
21 | SceneNode* gfx_setup_skyquad( | ||
22 | GfxCore*, SceneNode* root, const Texture* environment_map); | ||