aboutsummaryrefslogtreecommitdiff
path: root/src/render/imm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/imm.c')
-rw-r--r--src/render/imm.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/render/imm.c b/src/render/imm.c
new file mode 100644
index 0000000..7ab8d62
--- /dev/null
+++ b/src/render/imm.c
@@ -0,0 +1,194 @@
1#include "imm_impl.h"
2
3#include <gfx/core.h>
4#include <gfx/render/imm.h>
5#include <gfx/render/llr.h>
6#include <gfx/util/shader.h>
7
8#include <math/aabb3.h>
9
10#include <assert.h>
11#include <string.h> // memcpy
12
13bool gfx_imm_make(Imm* renderer, GfxCore* gfxcore, LLR* llr) {
14 assert(renderer);
15 assert(gfxcore);
16 assert(llr);
17
18 const size_t num_triangle_verts = GFX_IMM_MAX_NUM_TRIANGLES * 3;
19
20 renderer->gfxcore = gfxcore;
21 renderer->llr = llr;
22
23 renderer->triangles = gfx_make_geometry(
24 gfxcore, &(GeometryDesc){
25 .type = Triangles,
26 .buffer_usage = BufferDynamic,
27 .num_verts = num_triangle_verts,
28 .positions3d = (BufferView3d){
29 .size_bytes = num_triangle_verts * sizeof(vec3),
30 .count = num_triangle_verts}
31 });
32 if (!renderer->triangles) {
33 goto cleanup;
34 }
35
36 renderer->shader = gfx_make_immediate_mode_shader(gfxcore);
37 if (!renderer->shader) {
38 goto cleanup;
39 }
40
41 gfx_imm_set_colour(renderer, vec4_make(0.0f, 0.0f, 0.0f, 1.0f));
42
43 return true;
44
45cleanup:
46 gfx_imm_destroy(renderer);
47 return false;
48}
49
50void gfx_imm_destroy(Imm* renderer) {
51 assert(renderer);
52 assert(renderer->gfxcore);
53
54 if (renderer->triangles) {
55 gfx_destroy_geometry(renderer->gfxcore, &renderer->triangles);
56 // TODO: Could also destroy the geometry's buffers here.
57 }
58
59 if (renderer->shader) {
60 gfx_destroy_shader_program(renderer->gfxcore, &renderer->shader);
61 }
62}
63
64void gfx_imm_flush(Imm* renderer) {
65 assert(renderer);
66
67 if (renderer->num_triangle_verts > 0) {
68 gfx_update_geometry(
69 renderer->triangles,
70 &(GeometryDesc){
71 .num_verts = renderer->num_triangle_verts,
72 .positions3d = (BufferView3d){
73 .data = renderer->triangle_verts,
74 .size_bytes = renderer->num_triangle_verts * sizeof(vec3)}
75 });
76
77 gfx_llr_render_geometry(renderer->llr, renderer->triangles);
78
79 renderer->num_triangle_verts = 0;
80 }
81}
82
83void gfx_imm_start(Imm* renderer) {
84 assert(renderer);
85
86 // Shader uniforms are applied lazily.
87 // TODO: In the event that gfx_activate_shader_program() activates uniforms
88 // automatically for convenience, call an overload here that doesn't do so.
89 // gfx_activate_shader_program(renderer->shader);
90 gfx_llr_set_shader(renderer->llr, renderer->shader);
91}
92
93void gfx_imm_end(Imm* renderer) {
94 assert(renderer);
95
96 gfx_imm_flush(renderer);
97 // gfx_deactivate_shader_program(renderer->shader);
98 gfx_llr_set_shader(renderer->llr, 0);
99}
100
101void gfx_imm_draw_triangles(
102 Imm* renderer, const vec3 verts[], size_t num_triangles) {
103 assert(renderer);
104 assert(verts);
105 const size_t new_verts = num_triangles * 3;
106 assert(
107 renderer->num_triangle_verts + new_verts <
108 (GFX_IMM_MAX_NUM_TRIANGLES * 3));
109
110 memcpy(
111 renderer->triangle_verts + renderer->num_triangle_verts, verts,
112 new_verts * sizeof(vec3));
113
114 renderer->num_triangle_verts += new_verts;
115}
116
117void gfx_imm_draw_triangle(Imm* renderer, const vec3 verts[3]) {
118 gfx_imm_draw_triangles(renderer, verts, 1);
119}
120
121void gfx_imm_draw_aabb2(Imm* renderer, aabb2 box) {
122 assert(renderer);
123
124 // clang-format off
125 const vec3 verts[4] = {
126 vec3_make(box.min.x, box.min.y, 0), // 3 ---- 2
127 vec3_make(box.max.x, box.min.y, 0), // | |
128 vec3_make(box.max.x, box.max.y, 0), // | |
129 vec3_make(box.min.x, box.max.y, 0)}; // 0 ---- 1
130 // clang-format on
131
132#define tri(i0, i1, i2) verts[i0], verts[i1], verts[i2]
133 const vec3 tris[6] = {tri(0, 1, 2), tri(0, 2, 3)};
134#undef tri
135
136 gfx_imm_draw_triangles(renderer, tris, 2);
137}
138
139void gfx_imm_draw_aabb3(Imm* renderer, aabb3 box) {
140 assert(renderer);
141
142 // clang-format off
143 const vec3 vertices[8] = {
144 vec3_make(box.min.x, box.min.y, box.max.z), // 7 ----- 6
145 vec3_make(box.max.x, box.min.y, box.max.z), // / /|
146 vec3_make(box.max.x, box.max.y, box.max.z), // 3 ----- 2 |
147 vec3_make(box.min.x, box.max.y, box.max.z), // | | |
148 vec3_make(box.min.x, box.min.y, box.min.z), // | 4 ----- 5
149 vec3_make(box.max.x, box.min.y, box.min.z), // |/ |/
150 vec3_make(box.max.x, box.max.y, box.min.z), // 0 ----- 1
151 vec3_make(box.min.x, box.max.y, box.min.z)};
152 // clang-format on
153
154 gfx_imm_draw_box3(renderer, vertices);
155}
156
157void gfx_imm_draw_box3(Imm* renderer, const vec3 vertices[8]) {
158 assert(renderer);
159 assert(vertices);
160
161 // 7 ----- 6
162 // / /|
163 // 3 ----- 2 |
164 // | | |
165 // | 4 ----- 5
166 // |/ |/
167 // 0 ----- 1
168
169#define tri(i0, i1, i2) vertices[i0], vertices[i1], vertices[i2]
170 const vec3 tris[36] = {
171 // Front.
172 tri(0, 1, 2), tri(0, 2, 3),
173 // Right.
174 tri(1, 5, 6), tri(1, 6, 2),
175 // Back.
176 tri(5, 4, 7), tri(5, 7, 6),
177 // Left.
178 tri(4, 0, 03), tri(4, 3, 7),
179 // Top.
180 tri(3, 2, 6), tri(3, 6, 7),
181 // Bottom.
182 tri(0, 4, 5), tri(0, 5, 1)};
183
184 gfx_imm_draw_triangles(renderer, tris, 12);
185}
186
187void gfx_imm_set_colour(Imm* renderer, vec4 colour) {
188 assert(renderer);
189 assert(renderer->shader);
190
191 gfx_imm_flush(renderer);
192
193 gfx_set_vec4_uniform(renderer->shader, "Colour", colour);
194}