diff options
author | 3gg <3gg@shellblade.net> | 2025-06-27 10:18:39 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-06-27 10:18:39 -0700 |
commit | bd57f345ed9dbed1d81683e48199626de2ea9044 (patch) | |
tree | 4221f2f2a7ad2244d2e93052bd68187ec91b8ea9 /include | |
parent | 9a82ce0083437a4f9f58108b2c23b957d2249ad8 (diff) |
Diffstat (limited to 'include')
-rw-r--r-- | include/gfx/asset.h | 99 | ||||
-rw-r--r-- | include/gfx/core.h | 501 | ||||
-rw-r--r-- | include/gfx/gfx.h | 31 | ||||
-rw-r--r-- | include/gfx/renderer.h | 104 | ||||
-rw-r--r-- | include/gfx/scene.h | 11 | ||||
-rw-r--r-- | include/gfx/scene/animation.h | 142 | ||||
-rw-r--r-- | include/gfx/scene/camera.h | 22 | ||||
-rw-r--r-- | include/gfx/scene/light.h | 30 | ||||
-rw-r--r-- | include/gfx/scene/material.h | 25 | ||||
-rw-r--r-- | include/gfx/scene/mesh.h | 23 | ||||
-rw-r--r-- | include/gfx/scene/model.h | 12 | ||||
-rw-r--r-- | include/gfx/scene/node.h | 156 | ||||
-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 | 95 | ||||
-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 |
19 files changed, 1417 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..44509c9 --- /dev/null +++ b/include/gfx/core.h | |||
@@ -0,0 +1,501 @@ | |||
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 | TextureRG16, | ||
223 | TextureRG16F, | ||
224 | TextureRGB8, | ||
225 | TextureR11G11B10F, | ||
226 | TextureRGBA8, | ||
227 | TextureSRGB8, | ||
228 | TextureSRGBA8 | ||
229 | } TextureFormat; | ||
230 | |||
231 | /// Texture filtering. | ||
232 | typedef enum { NearestFiltering, LinearFiltering } TextureFiltering; | ||
233 | |||
234 | /// Texture wrap mode. | ||
235 | typedef enum { Repeat, ClampToEdge } TextureWrapping; | ||
236 | |||
237 | /// Cubemap faces. | ||
238 | typedef enum { | ||
239 | CubemapFacePosX, | ||
240 | CubemapFaceNegX, | ||
241 | CubemapFacePosY, | ||
242 | CubemapFaceNegY, | ||
243 | CubemapFacePosZ, | ||
244 | CubemapFaceNegZ | ||
245 | } CubemapFace; | ||
246 | |||
247 | /// Texture data descriptor. | ||
248 | typedef struct TextureDataDesc { | ||
249 | union { | ||
250 | const void* pixels; | ||
251 | struct { | ||
252 | const void* pixels_pos_x; | ||
253 | const void* pixels_neg_x; | ||
254 | const void* pixels_pos_y; | ||
255 | const void* pixels_neg_y; | ||
256 | const void* pixels_pos_z; | ||
257 | const void* pixels_neg_z; | ||
258 | } cubemap; | ||
259 | }; | ||
260 | } TextureDataDesc; | ||
261 | |||
262 | /// Describes a texture. | ||
263 | typedef struct TextureDesc { | ||
264 | int width; | ||
265 | int height; | ||
266 | int depth; // Not used until 3D textures are exposed. | ||
267 | TextureDimension dimension; | ||
268 | TextureFormat format; | ||
269 | TextureFiltering filtering; | ||
270 | TextureWrapping wrap; | ||
271 | bool mipmaps; | ||
272 | TextureDataDesc data; | ||
273 | } TextureDesc; | ||
274 | |||
275 | /// Describes a renderbuffer. | ||
276 | typedef struct RenderBufferDesc { | ||
277 | int width; | ||
278 | int height; | ||
279 | TextureFormat texture_format; | ||
280 | } RenderBufferDesc; | ||
281 | |||
282 | /// Framebuffer attachment type. | ||
283 | typedef enum FrameBufferAttachmentType { | ||
284 | FrameBufferNoAttachment, | ||
285 | FrameBufferTexture, | ||
286 | FrameBufferCubemapTexture, | ||
287 | FrameBufferRenderBuffer | ||
288 | } FrameBufferAttachmentType; | ||
289 | |||
290 | /// Describes a framebuffer attachment. | ||
291 | typedef struct FrameBufferAttachment { | ||
292 | FrameBufferAttachmentType type; | ||
293 | union { | ||
294 | struct { | ||
295 | Texture* texture; | ||
296 | int mip_level; | ||
297 | } texture; | ||
298 | struct { | ||
299 | Texture* texture; | ||
300 | int mip_level; | ||
301 | CubemapFace face; | ||
302 | } cubemap; | ||
303 | RenderBuffer* renderbuffer; | ||
304 | }; | ||
305 | } FrameBufferAttachment; | ||
306 | |||
307 | /// Describes a framebuffer. | ||
308 | typedef struct FrameBufferDesc { | ||
309 | FrameBufferAttachment colour; | ||
310 | FrameBufferAttachment depth; | ||
311 | } FrameBufferDesc; | ||
312 | |||
313 | // ----------------------------------------------------------------------------- | ||
314 | // Render commands. | ||
315 | // ----------------------------------------------------------------------------- | ||
316 | |||
317 | /// Start a new frame. | ||
318 | void gfx_start_frame(GfxCore*); | ||
319 | |||
320 | /// End a frame. | ||
321 | void gfx_end_frame(GfxCore*); | ||
322 | |||
323 | /// Set the render backend's viewport dimensions. | ||
324 | void gfx_set_viewport(GfxCore*, int x, int y, int width, int height); | ||
325 | |||
326 | /// Get the render backend's viewport dimensions. | ||
327 | void gfx_get_viewport(GfxCore*, int* x, int* y, int* width, int* height); | ||
328 | |||
329 | /// Clear the viewport. | ||
330 | void gfx_clear(GfxCore*, vec4 colour); | ||
331 | |||
332 | /// Set blending state. | ||
333 | void gfx_set_blending(GfxCore*, bool enable); | ||
334 | |||
335 | /// Set depth mask. | ||
336 | void gfx_set_depth_mask(GfxCore*, bool enable); | ||
337 | |||
338 | /// Set cull mode. | ||
339 | void gfx_set_culling(GfxCore*, bool enable); | ||
340 | |||
341 | /// Set polygon offset. | ||
342 | void gfx_set_polygon_offset(GfxCore*, float scale, float bias); | ||
343 | |||
344 | /// Reset the polygon offset. | ||
345 | void gfx_reset_polygon_offset(GfxCore*); | ||
346 | |||
347 | // ----------------------------------------------------------------------------- | ||
348 | // Buffers. | ||
349 | // ----------------------------------------------------------------------------- | ||
350 | |||
351 | /// Create a buffer from raw data. | ||
352 | Buffer* gfx_make_buffer(GfxCore*, const BufferDesc*); | ||
353 | |||
354 | /// Destroy the buffer. | ||
355 | void gfx_destroy_buffer(GfxCore*, Buffer**); | ||
356 | |||
357 | /// Update the buffer's data. | ||
358 | void gfx_update_buffer(Buffer*, const BufferDataDesc*); | ||
359 | |||
360 | // ----------------------------------------------------------------------------- | ||
361 | // Geometry. | ||
362 | // ----------------------------------------------------------------------------- | ||
363 | |||
364 | /// Create geometry. | ||
365 | Geometry* gfx_make_geometry(GfxCore*, const GeometryDesc*); | ||
366 | |||
367 | /// Destroy the geometry. | ||
368 | void gfx_destroy_geometry(GfxCore*, Geometry**); | ||
369 | |||
370 | /// Upload new vertex data for the geometry. | ||
371 | /// | ||
372 | /// This is similar to gfx_make_geometry(), but the geometry need not be | ||
373 | /// entirely specified. | ||
374 | /// | ||
375 | /// Only the vertex attributes, vertex count, and index count set in the | ||
376 | /// descriptor are updated. Index data, primitive type, and other properties of | ||
377 | /// the geometry are not updated. | ||
378 | /// | ||
379 | /// New data must be given as arrays in host memory. That is, the buffer views | ||
380 | /// in the descriptor must point to CPU arrays, not GPU buffers. | ||
381 | /// | ||
382 | /// Note that the descriptor cannot specify a larger vertex or index count than | ||
383 | /// what the geometry was created with. If the geometry size or any other | ||
384 | /// attribute not handled by this update function needs to be changed, then a | ||
385 | /// new geometry must be created. | ||
386 | void gfx_update_geometry(Geometry*, const GeometryDesc*); | ||
387 | |||
388 | /// Render the geometry. | ||
389 | void gfx_render_geometry(const Geometry*); | ||
390 | |||
391 | /// Return the geometry's bounding box. | ||
392 | aabb3 gfx_get_geometry_aabb(const Geometry*); | ||
393 | |||
394 | // ----------------------------------------------------------------------------- | ||
395 | // Textures. | ||
396 | // ----------------------------------------------------------------------------- | ||
397 | |||
398 | /// Create a texture. | ||
399 | Texture* gfx_make_texture(GfxCore*, const TextureDesc*); | ||
400 | |||
401 | /// Destroy the texture. | ||
402 | void gfx_destroy_texture(GfxCore*, Texture**); | ||
403 | |||
404 | /// Update the texture. | ||
405 | void gfx_update_texture(Texture*, const TextureDataDesc*); | ||
406 | |||
407 | // ----------------------------------------------------------------------------- | ||
408 | // Renderbuffers. | ||
409 | // ----------------------------------------------------------------------------- | ||
410 | |||
411 | /// Create a renderbuffer. | ||
412 | RenderBuffer* gfx_make_renderbuffer(GfxCore*, const RenderBufferDesc*); | ||
413 | |||
414 | /// Destroy the renderbuffer. | ||
415 | void gfx_destroy_renderbuffer(GfxCore*, RenderBuffer**); | ||
416 | |||
417 | // ----------------------------------------------------------------------------- | ||
418 | // Framebuffers. | ||
419 | // ----------------------------------------------------------------------------- | ||
420 | |||
421 | /// Create a framebuffer. | ||
422 | FrameBuffer* gfx_make_framebuffer(GfxCore*, const FrameBufferDesc*); | ||
423 | |||
424 | /// Destroy the framebuffer. | ||
425 | void gfx_destroy_framebuffer(GfxCore*, FrameBuffer**); | ||
426 | |||
427 | /// Attach a colour buffer to the framebuffer. | ||
428 | bool gfx_framebuffer_attach_colour(FrameBuffer*, const FrameBufferAttachment*); | ||
429 | |||
430 | /// Attach a depth buffer to the framebuffer. | ||
431 | bool gfx_framebuffer_attach_depth(FrameBuffer*, const FrameBufferAttachment*); | ||
432 | |||
433 | /// Activate the framebuffer. | ||
434 | /// Subsequent draw calls write to this framebuffer. | ||
435 | void gfx_activate_framebuffer(const FrameBuffer*); | ||
436 | |||
437 | /// Deactivate the framebuffer. | ||
438 | /// Subsequent draw calls write to the default framebuffer. | ||
439 | void gfx_deactivate_framebuffer(const FrameBuffer*); | ||
440 | |||
441 | /// Set the framebuffer's viewport. | ||
442 | /// This function should be called every time the framebuffer is activated. | ||
443 | void gfx_framebuffer_set_viewport( | ||
444 | FrameBuffer*, int x, int y, int width, int height); | ||
445 | |||
446 | // ----------------------------------------------------------------------------- | ||
447 | // Shaders. | ||
448 | // ----------------------------------------------------------------------------- | ||
449 | |||
450 | /// Create a shader. | ||
451 | Shader* gfx_make_shader(GfxCore*, const ShaderDesc*); | ||
452 | |||
453 | /// Destroy the shader. | ||
454 | void gfx_destroy_shader(GfxCore*, Shader**); | ||
455 | |||
456 | /// Create a shader program. | ||
457 | ShaderProgram* gfx_make_shader_program(GfxCore*, const ShaderProgramDesc*); | ||
458 | |||
459 | /// Destroy the shader program. | ||
460 | void gfx_destroy_shader_program(GfxCore*, ShaderProgram**); | ||
461 | |||
462 | /// Activate the shader program. | ||
463 | void gfx_activate_shader_program(const ShaderProgram*); | ||
464 | |||
465 | /// Deactivate the shader program. | ||
466 | void gfx_deactivate_shader_program(const ShaderProgram*); | ||
467 | |||
468 | /// Apply the shader program's uniform variables. | ||
469 | /// | ||
470 | /// Calls to gfx_set_XYZ_uniform save the values of the uniform variables in the | ||
471 | /// graphics library. By calling this function, those values are passed on to | ||
472 | /// the graphics driver for rendering. | ||
473 | /// | ||
474 | /// This function should be called after setting all of the uniform variables | ||
475 | /// and prior to issuing a draw call. | ||
476 | void gfx_apply_uniforms(const ShaderProgram*); | ||
477 | |||
478 | /// Set the texture uniform. | ||
479 | /// Has no effect if the shader does not contain the given uniform. | ||
480 | void gfx_set_texture_uniform(ShaderProgram*, const char* name, const Texture*); | ||
481 | |||
482 | /// Set the matrix uniform. | ||
483 | /// Has no effect if the shader does not contain the given uniform. | ||
484 | void gfx_set_mat4_uniform(ShaderProgram*, const char* name, const mat4*); | ||
485 | |||
486 | /// Set the vec3 uniform. | ||
487 | /// Has no effect if the shader does not contain the given uniform. | ||
488 | void gfx_set_vec3_uniform(ShaderProgram*, const char* name, vec3); | ||
489 | |||
490 | /// Set the vec4 uniform. | ||
491 | /// Has no effect if the shader does not contain the given uniform. | ||
492 | void gfx_set_vec4_uniform(ShaderProgram*, const char* name, vec4); | ||
493 | |||
494 | /// Set the float uniform. | ||
495 | /// Has no effect if the shader does not contain the given uniform. | ||
496 | void gfx_set_float_uniform(ShaderProgram*, const char* name, float value); | ||
497 | |||
498 | /// Set the matrix array uniform. | ||
499 | /// Has no effect if the shader does not contain the given uniform. | ||
500 | void gfx_set_mat4_array_uniform( | ||
501 | 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..7c670a5 --- /dev/null +++ b/include/gfx/gfx.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #pragma once | ||
2 | |||
3 | typedef struct AssetCache AssetCache; | ||
4 | typedef struct GfxCore GfxCore; | ||
5 | typedef struct ImmRenderer ImmRenderer; | ||
6 | typedef struct Renderer Renderer; | ||
7 | |||
8 | typedef struct Gfx Gfx; | ||
9 | |||
10 | /// Create a new graphics system, | ||
11 | Gfx* gfx_init(void); | ||
12 | |||
13 | /// Destroy the graphics system. | ||
14 | void gfx_destroy(Gfx**); | ||
15 | |||
16 | /// Get the render backend. | ||
17 | GfxCore* gfx_get_core(Gfx*); | ||
18 | |||
19 | /// Get the renderer. | ||
20 | Renderer* gfx_get_renderer(Gfx*); | ||
21 | |||
22 | /// Get the immediate mode renderer. | ||
23 | ImmRenderer* gfx_get_imm_renderer(Gfx*); | ||
24 | |||
25 | /// Get the asset cache. | ||
26 | AssetCache* gfx_get_asset_cache(Gfx*); | ||
27 | |||
28 | /// Remove unused resources from the scene (meshes, materials). | ||
29 | /// TODO: need to think about the interface for scene_purge(). Maybe this | ||
30 | /// should be gfx_purge() and take a list of Scenes? | ||
31 | // void gfx_purge(Scene*); | ||
diff --git a/include/gfx/renderer.h b/include/gfx/renderer.h new file mode 100644 index 0000000..2a4ada1 --- /dev/null +++ b/include/gfx/renderer.h | |||
@@ -0,0 +1,104 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <math/aabb2.h> | ||
4 | #include <math/aabb3.h> | ||
5 | #include <math/camera.h> | ||
6 | #include <math/defs.h> | ||
7 | #include <math/mat4.h> | ||
8 | #include <math/vec3.h> | ||
9 | #include <math/vec4.h> | ||
10 | |||
11 | typedef struct GfxCore GfxCore; | ||
12 | typedef struct Scene Scene; | ||
13 | typedef struct SceneCamera SceneCamera; | ||
14 | |||
15 | typedef struct ImmRenderer ImmRenderer; | ||
16 | typedef struct Renderer Renderer; | ||
17 | |||
18 | // ----------------------------------------------------------------------------- | ||
19 | // Main Renderer. | ||
20 | // ----------------------------------------------------------------------------- | ||
21 | |||
22 | typedef enum RenderSceneMode { | ||
23 | RenderDefault, | ||
24 | RenderDebug, | ||
25 | RenderNormals, | ||
26 | RenderNormalMappedNormals, | ||
27 | RenderTangents | ||
28 | } RenderSceneMode; | ||
29 | |||
30 | typedef struct RenderSceneParams { | ||
31 | RenderSceneMode mode; | ||
32 | const Scene* scene; | ||
33 | const SceneCamera* camera; | ||
34 | } RenderSceneParams; | ||
35 | |||
36 | /// Render the scene. | ||
37 | void gfx_render_scene(Renderer*, const RenderSceneParams*); | ||
38 | |||
39 | /// Update the scene. | ||
40 | void gfx_update(Scene*, const SceneCamera*, R t); | ||
41 | |||
42 | // ----------------------------------------------------------------------------- | ||
43 | // Immediate Mode Renderer. | ||
44 | // ----------------------------------------------------------------------------- | ||
45 | |||
46 | /// Prepare the graphics systems for immediate-mode rendering. | ||
47 | /// | ||
48 | /// Call this before issuing any immediate-mode rendering draws. | ||
49 | void gfx_imm_start(ImmRenderer*); | ||
50 | |||
51 | /// End immediate mode rendering. | ||
52 | /// | ||
53 | /// Call this after issuing immediate-mode rendering draws and before swapping | ||
54 | /// buffers. | ||
55 | void gfx_imm_end(ImmRenderer*); | ||
56 | |||
57 | /// Draw a set of triangles. | ||
58 | void gfx_imm_draw_triangles(ImmRenderer*, const vec3[], size_t num_triangles); | ||
59 | |||
60 | /// Draw a triangle. | ||
61 | void gfx_imm_draw_triangle(ImmRenderer*, const vec3[3]); | ||
62 | |||
63 | /// Draw a bounding box. | ||
64 | void gfx_imm_draw_aabb2(ImmRenderer*, aabb2); | ||
65 | |||
66 | /// Draw a bounding box. | ||
67 | void gfx_imm_draw_aabb3(ImmRenderer*, aabb3); | ||
68 | |||
69 | /// Draw a box. | ||
70 | /// | ||
71 | /// The vertices must be given in the following order: | ||
72 | /// | ||
73 | /// 7 ----- 6 | ||
74 | /// / /| | ||
75 | /// 3 ----- 2 | | ||
76 | /// | | | | ||
77 | /// | 4 ----- 5 | ||
78 | /// |/ |/ | ||
79 | /// 0 ----- 1 | ||
80 | void gfx_imm_draw_box3(ImmRenderer* renderer, const vec3 vertices[8]); | ||
81 | |||
82 | /// Set the camera. | ||
83 | void gfx_imm_set_camera(ImmRenderer*, const Camera*); | ||
84 | |||
85 | /// Load an identity model matrix. Clears the matrix stack. | ||
86 | void gfx_imm_load_identity(ImmRenderer* renderer); | ||
87 | |||
88 | /// Push the given matrix to the matrix stack. | ||
89 | void gfx_imm_push_matrix(ImmRenderer* renderer, const mat4* matrix); | ||
90 | |||
91 | /// Pop the top of the matrix stack. | ||
92 | void gfx_imm_pop_matrix(ImmRenderer* renderer); | ||
93 | |||
94 | /// Push a translation matrix to the matrix stack. | ||
95 | void gfx_imm_translate(ImmRenderer* renderer, vec3 offset); | ||
96 | |||
97 | /// Set the model matrix. Clears the matrix stack. | ||
98 | void gfx_imm_set_model_matrix(ImmRenderer*, const mat4*); | ||
99 | |||
100 | /// Set the view-projection matrix. | ||
101 | void gfx_imm_set_view_projection_matrix(ImmRenderer*, const mat4*); | ||
102 | |||
103 | /// Set the render colour. | ||
104 | 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..abcaa70 --- /dev/null +++ b/include/gfx/scene.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <gfx/scene/animation.h> | ||
4 | #include <gfx/scene/camera.h> | ||
5 | #include <gfx/scene/light.h> | ||
6 | #include <gfx/scene/material.h> | ||
7 | #include <gfx/scene/mesh.h> | ||
8 | #include <gfx/scene/model.h> | ||
9 | #include <gfx/scene/node.h> | ||
10 | #include <gfx/scene/object.h> | ||
11 | #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..d95b895 --- /dev/null +++ b/include/gfx/scene/animation.h | |||
@@ -0,0 +1,142 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "node.h" | ||
4 | #include "object.h" | ||
5 | #include <gfx/sizes.h> | ||
6 | |||
7 | #include <cstring.h> | ||
8 | #include <math/aabb3.h> | ||
9 | #include <math/defs.h> | ||
10 | #include <math/mat4.h> | ||
11 | #include <math/quat.h> | ||
12 | #include <math/vec3.h> | ||
13 | |||
14 | #include <stdbool.h> | ||
15 | #include <stddef.h> | ||
16 | #include <stdint.h> | ||
17 | |||
18 | typedef struct Buffer Buffer; | ||
19 | typedef struct SceneNode SceneNode; | ||
20 | |||
21 | typedef struct Anima Anima; | ||
22 | typedef struct Joint Joint; | ||
23 | typedef struct Skeleton Skeleton; | ||
24 | |||
25 | /// Index type used to store relative indices into arrays. | ||
26 | typedef uint16_t joint_idx; | ||
27 | |||
28 | /// Index value denoting no index. | ||
29 | static const joint_idx INDEX_NONE = (joint_idx)-1; | ||
30 | |||
31 | typedef struct Box { | ||
32 | vec3 vertices[8]; | ||
33 | } Box; | ||
34 | |||
35 | /// Joint descriptor. | ||
36 | typedef struct JointDesc { | ||
37 | joint_idx parent; /// Parent Joint; index into Anima's joints. | ||
38 | mat4 inv_bind_matrix; /// Transforms the mesh into the joint's local space. | ||
39 | aabb3 box; /// Bounding box. | ||
40 | } JointDesc; | ||
41 | |||
42 | /// Skeleton descriptor. | ||
43 | typedef struct SkeletonDesc { | ||
44 | size_t num_joints; | ||
45 | joint_idx joints[GFX_MAX_NUM_JOINTS]; /// Indices into Anima's joints array. | ||
46 | } SkeletonDesc; | ||
47 | |||
48 | /// Animation interpolation mode. | ||
49 | typedef enum AnimationInterpolation { | ||
50 | StepInterpolation, | ||
51 | LinearInterpolation, | ||
52 | CubicSplineInterpolation | ||
53 | } AnimationInterpolation; | ||
54 | |||
55 | /// The kind of transformation applied by a Channel. | ||
56 | typedef enum ChannelType { | ||
57 | RotationChannel, | ||
58 | ScaleChannel, | ||
59 | TranslationChannel, | ||
60 | WeightsChannel | ||
61 | } ChannelType; | ||
62 | |||
63 | /// Animation keyframe descriptor. | ||
64 | /// | ||
65 | /// The arrays should have as many entries as 'num_joints' in the SkeletonDesc. | ||
66 | typedef struct KeyframeDesc { | ||
67 | R time; // Start time in [0, end animation time] | ||
68 | union { | ||
69 | vec3 translation; | ||
70 | quat rotation; | ||
71 | }; | ||
72 | } KeyframeDesc; | ||
73 | |||
74 | /// Animation channel descriptor. | ||
75 | typedef struct ChannelDesc { | ||
76 | joint_idx target; /// Index into Anima's joints array. | ||
77 | ChannelType type; | ||
78 | AnimationInterpolation interpolation; | ||
79 | size_t num_keyframes; | ||
80 | KeyframeDesc keyframes[GFX_MAX_NUM_KEYFRAMES]; | ||
81 | } ChannelDesc; | ||
82 | |||
83 | /// Animation descriptor. | ||
84 | typedef struct AnimationDesc { | ||
85 | // TODO: Store a name hash for faster comparisons. | ||
86 | sstring name; // Animation name. Required for playback. | ||
87 | size_t num_channels; // Number of channels. | ||
88 | ChannelDesc channels[GFX_MAX_NUM_CHANNELS]; | ||
89 | } AnimationDesc; | ||
90 | |||
91 | /// Anima object descriptor. | ||
92 | /// | ||
93 | /// The last joint of the joints array at index 'num_joints - 1' must be the | ||
94 | /// root of all skeletons; specifically, the root of all joints that otherwise | ||
95 | /// would have no parent (a skeleton need not have its own root and can be a set | ||
96 | /// of disjoint node hierarchies). | ||
97 | typedef struct AnimaDesc { | ||
98 | size_t num_skeletons; | ||
99 | size_t num_animations; | ||
100 | size_t num_joints; | ||
101 | SkeletonDesc skeletons[GFX_MAX_NUM_SKELETONS]; | ||
102 | AnimationDesc animations[GFX_MAX_NUM_ANIMATIONS]; | ||
103 | JointDesc joints[GFX_MAX_NUM_JOINTS]; | ||
104 | } AnimaDesc; | ||
105 | |||
106 | /// Animation play settings. | ||
107 | typedef struct AnimationPlaySettings { | ||
108 | const char* name; // Animation name. | ||
109 | bool loop; // Whether to loop the animation or just play once. | ||
110 | // TODO: Add animation speed. | ||
111 | } AnimationPlaySettings; | ||
112 | |||
113 | /// Create an anima object. | ||
114 | Anima* gfx_make_anima(const AnimaDesc*); | ||
115 | |||
116 | /// Destroy the anima. | ||
117 | void gfx_destroy_anima(Anima**); | ||
118 | |||
119 | /// Play an animation (sets the current animation). | ||
120 | bool gfx_play_animation(Anima*, const AnimationPlaySettings*); | ||
121 | |||
122 | /// Update the current animation. | ||
123 | void gfx_update_animation(Anima*, R t); | ||
124 | |||
125 | /// Stop the current animation. | ||
126 | void gfx_stop_animation(Anima*); | ||
127 | |||
128 | /// Return the anima's ith skeleton. | ||
129 | const Skeleton* gfx_get_anima_skeleton(const Anima* anima, size_t i); | ||
130 | |||
131 | /// Return the number of joints in the skeleton. | ||
132 | size_t gfx_get_skeleton_num_joints(const Skeleton*); | ||
133 | |||
134 | /// Return true if the skeleton's ith joint has a bounding box. | ||
135 | /// | ||
136 | /// IK joints that do not directly transform vertices have no bounding box. | ||
137 | bool gfx_joint_has_box(const Anima*, const Skeleton*, size_t joint); | ||
138 | |||
139 | /// Return the bounding box of the skeleton's ith joint. | ||
140 | /// | ||
141 | /// IK joints that do not directly transform vertices have no box. | ||
142 | 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/light.h b/include/gfx/scene/light.h new file mode 100644 index 0000000..132e344 --- /dev/null +++ b/include/gfx/scene/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/scene/material.h b/include/gfx/scene/material.h new file mode 100644 index 0000000..bca664e --- /dev/null +++ b/include/gfx/scene/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/scene/mesh.h b/include/gfx/scene/mesh.h new file mode 100644 index 0000000..0d3b4d4 --- /dev/null +++ b/include/gfx/scene/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/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..a2c2836 --- /dev/null +++ b/include/gfx/scene/node.h | |||
@@ -0,0 +1,156 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include "animation.h" | ||
4 | |||
5 | #include <math/fwd.h> | ||
6 | #include <math/mat4.h> | ||
7 | |||
8 | #include <stdint.h> | ||
9 | |||
10 | typedef struct Anima Anima; | ||
11 | typedef struct Light Light; | ||
12 | typedef struct Model Model; | ||
13 | typedef struct SceneCamera SceneCamera; | ||
14 | typedef struct SceneObject SceneObject; | ||
15 | |||
16 | /// Scene node type. | ||
17 | typedef enum NodeType { | ||
18 | LogicalNode, | ||
19 | AnimaNode, | ||
20 | CameraNode, | ||
21 | LightNode, | ||
22 | ModelNode, | ||
23 | ObjectNode, | ||
24 | } NodeType; | ||
25 | |||
26 | /// A node in the scene graph. | ||
27 | /// | ||
28 | /// Scene nodes take ownership of the object they are associated with (Camera, | ||
29 | /// Light, SceneObject, etc), as well as of child nodes. | ||
30 | typedef struct SceneNode SceneNode; | ||
31 | |||
32 | // ----------------------------------------------------------------------------- | ||
33 | // Constructors and destructor. | ||
34 | // ----------------------------------------------------------------------------- | ||
35 | |||
36 | /// Create a new scene node. | ||
37 | /// | ||
38 | /// This node does not contain any camera, light, object, etc. and exists simply | ||
39 | /// as a logical and spatial construct. | ||
40 | SceneNode* gfx_make_node(); | ||
41 | |||
42 | /// Create an anima node. | ||
43 | SceneNode* gfx_make_anima_node(Anima*); | ||
44 | |||
45 | /// Create a new camera node. | ||
46 | SceneNode* gfx_make_camera_node(SceneCamera*); | ||
47 | |||
48 | /// Create a new light node. | ||
49 | SceneNode* gfx_make_light_node(Light*); | ||
50 | |||
51 | /// Create a new model node. | ||
52 | SceneNode* gfx_make_model_node(Model*); | ||
53 | |||
54 | /// Create a new object node. | ||
55 | SceneNode* gfx_make_object_node(SceneObject*); | ||
56 | |||
57 | /// Make the node an anima node. | ||
58 | void gfx_construct_anima_node(SceneNode*, Anima*); | ||
59 | |||
60 | /// Make the node a camera node. | ||
61 | void gfx_construct_camera_node(SceneNode*, SceneCamera*); | ||
62 | |||
63 | /// Make the node a light node. | ||
64 | void gfx_construct_light_node(SceneNode*, Light*); | ||
65 | |||
66 | /// Make the node a model node. | ||
67 | void gfx_construct_model_node(SceneNode*, Model*); | ||
68 | |||
69 | /// Make the node an object node. | ||
70 | void gfx_construct_object_node(SceneNode*, SceneObject*); | ||
71 | |||
72 | /// Recursively destroy the scene node and its children. | ||
73 | /// | ||
74 | /// The scene node and its children are removed from the scene graph. | ||
75 | /// | ||
76 | /// Node resources -- cameras, lights, objects, etc. -- are also destroyed. | ||
77 | void gfx_destroy_node(SceneNode**); | ||
78 | |||
79 | // ----------------------------------------------------------------------------- | ||
80 | // Getters. | ||
81 | // ----------------------------------------------------------------------------- | ||
82 | |||
83 | /// Get the node's type. | ||
84 | NodeType gfx_get_node_type(const SceneNode*); | ||
85 | |||
86 | /// Get the node's anima. | ||
87 | /// | ||
88 | /// The node must be of type AnimaNode. | ||
89 | const Anima* gfx_get_node_anima(const SceneNode*); | ||
90 | Anima* gfx_get_node_anima_mut(SceneNode*); | ||
91 | |||
92 | /// Get the node's camera. | ||
93 | /// | ||
94 | /// The node must be of type CameraNode. | ||
95 | const SceneCamera* gfx_get_node_camera(const SceneNode* node); | ||
96 | SceneCamera* gfx_get_node_camera_mut(SceneNode* node); | ||
97 | |||
98 | /// Get the node's light. | ||
99 | /// | ||
100 | /// The node must be of type LightNode. | ||
101 | const Light* gfx_get_node_light(const SceneNode*); | ||
102 | Light* gfx_get_node_light_mut(SceneNode*); | ||
103 | |||
104 | /// Get the node's model. | ||
105 | /// | ||
106 | /// The node must be of type ModelNode. | ||
107 | const Model* gfx_get_node_model(const SceneNode*); | ||
108 | Model* gfx_get_node_model_mut(SceneNode*); | ||
109 | |||
110 | /// Get the node's scene object. | ||
111 | /// | ||
112 | /// The node must be of type ObjectNode. | ||
113 | const SceneObject* gfx_get_node_object(const SceneNode*); | ||
114 | SceneObject* gfx_get_node_object_mut(SceneNode*); | ||
115 | |||
116 | /// Get the node's parent. | ||
117 | const SceneNode* gfx_get_node_parent(const SceneNode*); | ||
118 | SceneNode* gfx_get_node_parent_mut(SceneNode*); | ||
119 | |||
120 | /// Get the node's first child. | ||
121 | const SceneNode* gfx_get_node_child(const SceneNode*); | ||
122 | SceneNode* gfx_get_node_child_mut(SceneNode*); | ||
123 | |||
124 | /// Get the node's immediate sibling. | ||
125 | const SceneNode* gfx_get_node_sibling(const SceneNode*); | ||
126 | SceneNode* gfx_get_node_sibling_mut(SceneNode*); | ||
127 | |||
128 | /// Get the node's (local) transform. | ||
129 | mat4 gfx_get_node_transform(const SceneNode*); | ||
130 | |||
131 | /// Get the node's global transform. | ||
132 | mat4 gfx_get_node_global_transform(const SceneNode*); | ||
133 | |||
134 | // ----------------------------------------------------------------------------- | ||
135 | // Setters. | ||
136 | // ----------------------------------------------------------------------------- | ||
137 | |||
138 | /// Set the node's parent. | ||
139 | /// | ||
140 | /// Pass in null to unwire from the existing parent, if one exists. | ||
141 | void gfx_set_node_parent(SceneNode*, SceneNode* parent_node); | ||
142 | |||
143 | /// Set the node's (local) transform. | ||
144 | void gfx_set_node_transform(SceneNode*, const mat4* transform); | ||
145 | |||
146 | /// Set the node's position. | ||
147 | void gfx_set_node_position(SceneNode*, const vec3* position); | ||
148 | |||
149 | /// Set the node's rotation. | ||
150 | void gfx_set_node_rotation(SceneNode*, const quat* rotation); | ||
151 | |||
152 | /// Set the node's rotation. | ||
153 | void gfx_set_node_rotation_mat(SceneNode*, const mat4* rotation); | ||
154 | |||
155 | /// Log the node's hierarchy. | ||
156 | 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..076113c --- /dev/null +++ b/include/gfx/sizes.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /// Size constants used throughout the library. | ||
2 | #pragma once | ||
3 | |||
4 | // Scene. | ||
5 | |||
6 | /// Maximum number of cameras per scene. | ||
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 128 | ||
35 | |||
36 | /// Maximum number of animations. | ||
37 | #define GFX_MAX_NUM_ANIMATIONS 128 | ||
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 | // Renderer. | ||
81 | |||
82 | /// Maximum number of triangles that the immediate-mode renderer can draw in a | ||
83 | /// frame. | ||
84 | #define IMM_MAX_NUM_TRIANGLES 1024 | ||
85 | |||
86 | /// Maximum number of matrices in the immediate-mode renderer's matrix stack. | ||
87 | #define IMM_MAX_NUM_MATRICES 32 | ||
88 | |||
89 | // Asset Manager. | ||
90 | |||
91 | #define GFX_MAX_NUM_ASSETS 1024 | ||
92 | |||
93 | // Gfx. | ||
94 | |||
95 | #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); | ||