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