scraped a small amount of crap
[carveJwlIkooP6JGAAIwe30JlM.git] / world_render.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #ifndef WORLD_RENDER_H
6 #define WORLD_RENDER_H
7
8 #include "camera.h"
9 #include "world.h"
10
11 /* FIXME */
12 VG_STATIC vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
13 .flags = VG_TEXTURE_NEAREST };
14
15 VG_STATIC void world_render_init(void)
16 {
17 vg_info( "Loading default world textures\n" );
18
19 vg_acquire_thread_sync();
20 {
21 vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_noise }, 1 );
22
23
24 vg_info( "Allocate uniform buffers\n" );
25 for( int i=0; i<4; i++ )
26 {
27 world_instance *world = &world_global.worlds[i];
28 world->ubo_bind_point = i;
29
30 glGenBuffers( 1, &world->ubo_lighting );
31 glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
32 glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
33 NULL, GL_DYNAMIC_DRAW );
34
35 glBindBufferBase( GL_UNIFORM_BUFFER, i, world->ubo_lighting );
36 VG_CHECK_GL_ERR();
37 }
38
39 vg_info( "Allocate frame buffers\n" );
40 for( int i=0; i<4; i++ )
41 {
42 world_instance *world = &world_global.worlds[i];
43 struct framebuffer *fb = &world->heightmap;
44
45 fb->display_name = NULL;
46 fb->link = NULL;
47 fb->fixed_w = 1024;
48 fb->fixed_h = 1024;
49 fb->resolution_div = 0;
50
51 fb->attachments[0].display_name = NULL;
52 fb->attachments[0].purpose = k_framebuffer_attachment_type_colour;
53 fb->attachments[0].internalformat = GL_RG16F;
54 fb->attachments[0].format = GL_RG;
55 fb->attachments[0].type = GL_FLOAT;
56 fb->attachments[0].attachment = GL_COLOR_ATTACHMENT0;
57
58 fb->attachments[1].purpose = k_framebuffer_attachment_type_none;
59 fb->attachments[2].purpose = k_framebuffer_attachment_type_none;
60 fb->attachments[3].purpose = k_framebuffer_attachment_type_none;
61 fb->attachments[4].purpose = k_framebuffer_attachment_type_none;
62
63 render_fb_allocate( fb );
64 }
65 }
66 vg_release_thread_sync();
67 }
68
69 VG_STATIC void world_link_lighting_ub( world_instance *world, GLuint shader )
70 {
71 GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
72 glUniformBlockBinding( shader, idx, world->ubo_bind_point );
73 }
74
75 VG_STATIC void world_bind_position_texture( world_instance *world,
76 GLuint shader, GLuint location,
77 int slot )
78 {
79 render_fb_bind_texture( &world->heightmap, 0, slot );
80 glUniform1i( location, slot );
81 }
82
83 VG_STATIC void world_bind_light_array( world_instance *world,
84 GLuint shader, GLuint location,
85 int slot )
86 {
87 glActiveTexture( GL_TEXTURE0 + slot );
88 glBindTexture( GL_TEXTURE_BUFFER, world->tex_light_entities );
89 glUniform1i( location, slot );
90 }
91
92 VG_STATIC void world_bind_light_index( world_instance *world,
93 GLuint shader, GLuint location,
94 int slot )
95 {
96 glActiveTexture( GL_TEXTURE0 + slot );
97 glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
98 glUniform1i( location, slot );
99 }
100
101 VG_STATIC void render_world_depth( world_instance *world, camera *cam );
102
103 /*
104 * Rendering
105 */
106
107 VG_STATIC void bind_terrain_noise(void)
108 {
109 vg_tex2d_bind( &tex_terrain_noise, 0 );
110 }
111
112 typedef void (*func_bind_point)( world_instance *world,
113 struct world_surface *mat );
114
115 VG_STATIC void world_render_if( world_instance *world,
116 enum mdl_shader shader,
117 enum geo_type geo_type,
118 func_bind_point bind_point )
119 {
120
121 for( int i=0; i<world->surface_count; i++ )
122 {
123 struct world_surface *mat = &world->surfaces[i];
124
125 if( mat->info.shader == shader )
126 {
127 mdl_submesh *sm;
128
129 if( geo_type == k_geo_type_solid )
130 sm = &mat->sm_geo;
131 else
132 sm = &mat->sm_no_collide;
133
134 if( !sm->indice_count )
135 continue;
136
137 bind_point( world, mat );
138 mdl_draw_submesh( sm );
139 }
140 }
141 }
142
143 VG_STATIC
144 void world_render_both_stages( world_instance *world,
145 enum mdl_shader shader,
146 func_bind_point bind_point )
147 {
148 mesh_bind( &world->mesh_geo );
149 world_render_if( world, shader, k_geo_type_solid, bind_point );
150
151 glDisable( GL_CULL_FACE );
152 mesh_bind( &world->mesh_no_collide );
153 world_render_if( world, shader, k_geo_type_nonsolid, bind_point );
154 glEnable( GL_CULL_FACE );
155 }
156
157 VG_STATIC void bindpoint_diffuse_texture1( world_instance *world,
158 struct world_surface *mat )
159 {
160 glActiveTexture( GL_TEXTURE1 );
161 glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
162 }
163
164 VG_STATIC void render_world_vb( world_instance *world, camera *cam )
165 {
166 m4x3f identity_matrix;
167 m4x3_identity( identity_matrix );
168
169 shader_scene_vertex_blend_use();
170 shader_scene_vertex_blend_uTexGarbage(0);
171 shader_scene_vertex_blend_uTexGradients(1);
172 world_link_lighting_ub( world, _shader_scene_vertex_blend.id );
173 world_bind_position_texture( world, _shader_scene_vertex_blend.id,
174 _uniform_scene_vertex_blend_g_world_depth, 2 );
175 world_bind_light_array( world, _shader_scene_vertex_blend.id,
176 _uniform_scene_vertex_blend_uLightsArray, 3 );
177 world_bind_light_index( world, _shader_scene_vertex_blend.id,
178 _uniform_scene_vertex_blend_uLightsIndex, 4 );
179
180 vg_tex2d_bind( &tex_terrain_noise, 0 );
181
182 shader_scene_vertex_blend_uPv( cam->mtx.pv );
183 shader_scene_vertex_blend_uPvmPrev( cam->mtx_prev.pv );
184 shader_scene_vertex_blend_uMdl( identity_matrix );
185 shader_scene_vertex_blend_uCamera( cam->transform[3] );
186 shader_scene_vertex_blend_uBoard0( TEMP_BOARD_0 );
187 shader_scene_vertex_blend_uBoard1( TEMP_BOARD_1 );
188
189 world_render_both_stages( world, k_shader_standard_vertex_blend,
190 bindpoint_diffuse_texture1 );
191 }
192
193 VG_STATIC void render_world_standard( world_instance *world, camera *cam )
194 {
195 m4x3f identity_matrix;
196 m4x3_identity( identity_matrix );
197
198 shader_scene_standard_use();
199 shader_scene_standard_uTexGarbage(0);
200 shader_scene_standard_uTexMain(1);
201 shader_scene_standard_uPv( cam->mtx.pv );
202 shader_scene_standard_uPvmPrev( cam->mtx_prev.pv );
203
204 world_link_lighting_ub( world, _shader_scene_standard.id );
205 world_bind_position_texture( world, _shader_scene_standard.id,
206 _uniform_scene_standard_g_world_depth, 2 );
207 world_bind_light_array( world, _shader_scene_standard.id,
208 _uniform_scene_standard_uLightsArray, 3 );
209 world_bind_light_index( world, _shader_scene_standard.id,
210 _uniform_scene_standard_uLightsIndex, 4 );
211
212 bind_terrain_noise();
213
214 shader_scene_standard_uMdl( identity_matrix );
215 shader_scene_standard_uCamera( cam->transform[3] );
216 shader_scene_standard_uBoard0( TEMP_BOARD_0 );
217 shader_scene_standard_uBoard1( TEMP_BOARD_1 );
218
219 world_render_both_stages( world, k_shader_standard,
220 bindpoint_diffuse_texture1 );
221 }
222
223 VG_STATIC void render_world_alphatest( world_instance *world, camera *cam )
224 {
225 m4x3f identity_matrix;
226 m4x3_identity( identity_matrix );
227
228 shader_scene_standard_alphatest_use();
229 shader_scene_standard_alphatest_uTexGarbage(0);
230 shader_scene_standard_alphatest_uTexMain(1);
231 shader_scene_standard_alphatest_uPv( cam->mtx.pv );
232 shader_scene_standard_alphatest_uPvmPrev( cam->mtx_prev.pv );
233
234 world_link_lighting_ub( world, _shader_scene_standard_alphatest.id );
235 world_bind_position_texture( world, _shader_scene_standard_alphatest.id,
236 _uniform_scene_standard_alphatest_g_world_depth, 2 );
237 world_bind_light_array( world, _shader_scene_standard_alphatest.id,
238 _uniform_scene_standard_alphatest_uLightsArray, 3 );
239 world_bind_light_index( world, _shader_scene_standard_alphatest.id,
240 _uniform_scene_standard_alphatest_uLightsIndex, 4 );
241
242
243 bind_terrain_noise();
244
245 shader_scene_standard_alphatest_uMdl( identity_matrix );
246 shader_scene_standard_alphatest_uCamera( cam->transform[3] );
247 shader_scene_standard_alphatest_uBoard0( TEMP_BOARD_0 );
248 shader_scene_standard_alphatest_uBoard1( TEMP_BOARD_1 );
249
250 glDisable(GL_CULL_FACE);
251
252 world_render_both_stages( world, k_shader_standard_cutout,
253 bindpoint_diffuse_texture1 );
254
255 glEnable(GL_CULL_FACE);
256 }
257
258 VG_STATIC void bindpoint_terrain( world_instance *world,
259 struct world_surface *mat )
260 {
261 glActiveTexture( GL_TEXTURE1 );
262 glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
263
264 shader_scene_terrain_uSandColour( mat->info.colour );
265 shader_scene_terrain_uBlendOffset( mat->info.colour1 );
266 }
267
268 VG_STATIC void render_terrain( world_instance *world, camera *cam )
269 {
270 m4x3f identity_matrix;
271 m4x3_identity( identity_matrix );
272
273 shader_scene_terrain_use();
274 shader_scene_terrain_uTexGarbage(0);
275 shader_scene_terrain_uTexGradients(1);
276
277 world_link_lighting_ub( world, _shader_scene_terrain.id );
278 world_bind_position_texture( world, _shader_scene_terrain.id,
279 _uniform_scene_terrain_g_world_depth, 2 );
280 world_bind_light_array( world, _shader_scene_terrain.id,
281 _uniform_scene_terrain_uLightsArray, 3 );
282 world_bind_light_index( world, _shader_scene_terrain.id,
283 _uniform_scene_terrain_uLightsIndex, 4 );
284
285 vg_tex2d_bind( &tex_terrain_noise, 0 );
286
287 shader_scene_terrain_uPv( cam->mtx.pv );
288 shader_scene_terrain_uPvmPrev( cam->mtx_prev.pv );
289
290 shader_scene_terrain_uMdl( identity_matrix );
291 shader_scene_terrain_uCamera( cam->transform[3] );
292 shader_scene_terrain_uBoard0( TEMP_BOARD_0 );
293 shader_scene_terrain_uBoard1( TEMP_BOARD_1 );
294
295 world_render_both_stages( world, k_shader_terrain_blend, bindpoint_terrain );
296 }
297
298 VG_STATIC void render_sky( world_instance *world, camera *cam )
299 {
300 /*
301 * Modify matrix to remove clipping and view translation
302 */
303 m4x4f v,
304 v_prev,
305 pv,
306 pv_prev;
307
308 m4x4_copy( cam->mtx.v, v );
309 m4x4_copy( cam->mtx_prev.v, v_prev );
310 v3_zero( v[3] );
311 v3_zero( v_prev[3] );
312
313 m4x4_copy( cam->mtx.p, pv );
314 m4x4_copy( cam->mtx_prev.p, pv_prev );
315 m4x4_reset_clipping( pv, cam->farz, cam->nearz );
316 m4x4_reset_clipping( pv_prev, cam->farz, cam->nearz );
317
318 m4x4_mul( pv, v, pv );
319 m4x4_mul( pv_prev, v_prev, pv_prev );
320
321 m4x3f identity_matrix;
322 m4x3_identity( identity_matrix );
323
324 /*
325 * Draw
326 */
327 shader_model_sky_use();
328 shader_model_sky_uMdl( identity_matrix );
329 shader_model_sky_uPv( pv );
330 shader_model_sky_uPvmPrev( pv_prev );
331 shader_model_sky_uTexGarbage(0);
332 world_link_lighting_ub( world, _shader_model_sky.id );
333
334 vg_tex2d_bind( &tex_terrain_noise, 0 );
335
336 glDepthMask( GL_FALSE );
337 glDisable( GL_DEPTH_TEST );
338
339 mesh_bind( &world_global.skydome );
340 mesh_draw( &world_global.skydome );
341
342 glEnable( GL_DEPTH_TEST );
343 glDepthMask( GL_TRUE );
344 }
345
346 VG_STATIC void render_world_gates( world_instance *world, camera *cam,
347 int layer_depth )
348 {
349 float closest = INFINITY;
350
351 struct ent_gate *gate = NULL;
352
353 for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
354 ent_gate *gi = mdl_arritm( &world->ent_gate, i );
355
356 if( gi->type == k_gate_type_unlinked )
357 continue;
358
359 float dist = v3_dist2( gi->co[0], cam->transform[3] );
360
361 vg_line_pt3( gi->co[0], 0.25f, VG__BLUE );
362
363 if( dist < closest ){
364 closest = dist;
365 gate = gi;
366 }
367 }
368
369 if( gate ){
370 #if 0
371 world_instance *dest_world = &world_global.worlds[ gate->world_index ];
372 render_gate( dest_world, gate, cam, layer_depth );
373 #else
374 render_gate( world, gate, cam, layer_depth );
375 #endif
376
377 /* should really be set in fixed update since its used in the physics
378 * of most systems. too bad! */
379 world->rendering_gate = gate;
380 }
381 }
382
383 VG_STATIC void render_world( world_instance *world, camera *cam,
384 int layer_depth )
385 {
386 render_sky( world, cam );
387
388 render_world_routes( world, cam, layer_depth );
389 render_world_standard( world, cam );
390 render_world_vb( world, cam );
391 render_world_alphatest( world, cam );
392 render_terrain( world, cam );
393
394 /* Render SFD's */
395 u32 closest = 0;
396 float min_dist = INFINITY;
397
398 if( !mdl_arrcount( &world->ent_route ) )
399 return;
400
401 for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
402 ent_route *route = mdl_arritm( &world->ent_route, i );
403 float dist = v3_dist2( route->board_transform[3], cam->pos );
404
405 if( dist < min_dist ){
406 min_dist = dist;
407 closest = i;
408 }
409 }
410
411 ent_route *route = mdl_arritm( &world->ent_route, closest );
412 sfd_render( world, cam, route->board_transform );
413 }
414
415 VG_STATIC void render_world_depth( world_instance *world, camera *cam )
416 {
417 m4x3f identity_matrix;
418 m4x3_identity( identity_matrix );
419
420 shader_scene_depth_use();
421 shader_scene_depth_uCamera( cam->transform[3] );
422 shader_scene_depth_uPv( cam->mtx.pv );
423 shader_scene_depth_uPvmPrev( cam->mtx_prev.pv );
424 shader_scene_depth_uMdl( identity_matrix );
425 world_link_lighting_ub( world, _shader_scene_depth.id );
426
427 mesh_bind( &world->mesh_geo );
428 mesh_draw( &world->mesh_geo );
429 }
430
431 VG_STATIC void render_world_position( world_instance *world, camera *cam )
432 {
433 m4x3f identity_matrix;
434 m4x3_identity( identity_matrix );
435
436 shader_scene_position_use();
437 shader_scene_position_uCamera( cam->transform[3] );
438 shader_scene_position_uPv( cam->mtx.pv );
439 shader_scene_position_uPvmPrev( cam->mtx_prev.pv );
440 shader_scene_position_uMdl( identity_matrix );
441 world_link_lighting_ub( world, _shader_scene_position.id );
442
443 mesh_bind( &world->mesh_geo );
444 mesh_draw( &world->mesh_geo );
445 }
446
447 #endif /* WORLD_RENDER_H */