2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
9 #include "world_render.h"
11 static int ccmd_set_time( int argc
, const char *argv
[] ){
13 world_instance
*world
= world_current_instance();
14 world
->time
= atof( argv
[0] );
17 vg_error( "Usage set_time <0-1.0>\n" );
22 VG_STATIC
void async_world_render_init( void *payload
, u32 size
)
24 vg_info( "Allocate uniform buffers\n" );
25 for( int i
=0; i
<4; i
++ ){
26 world_instance
*world
= &world_static
.worlds
[i
];
27 world
->ubo_bind_point
= i
;
29 glGenBuffers( 1, &world
->ubo_lighting
);
30 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
31 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
32 NULL
, GL_DYNAMIC_DRAW
);
34 glBindBufferBase( GL_UNIFORM_BUFFER
, i
, world
->ubo_lighting
);
38 vg_info( "Allocate frame buffers\n" );
39 for( int i
=0; i
<4; i
++ ){
40 world_instance
*world
= &world_static
.worlds
[i
];
41 struct framebuffer
*fb
= &world
->heightmap
;
43 fb
->display_name
= NULL
;
47 fb
->resolution_div
= 0;
49 fb
->attachments
[0].display_name
= NULL
;
50 fb
->attachments
[0].purpose
= k_framebuffer_attachment_type_texture
;
51 fb
->attachments
[0].internalformat
= GL_RG16F
;
52 fb
->attachments
[0].format
= GL_RG
;
53 fb
->attachments
[0].type
= GL_FLOAT
;
54 fb
->attachments
[0].attachment
= GL_COLOR_ATTACHMENT0
;
56 fb
->attachments
[1].purpose
= k_framebuffer_attachment_type_none
;
57 fb
->attachments
[2].purpose
= k_framebuffer_attachment_type_none
;
58 fb
->attachments
[3].purpose
= k_framebuffer_attachment_type_none
;
59 fb
->attachments
[4].purpose
= k_framebuffer_attachment_type_none
;
61 render_fb_allocate( fb
);
65 VG_STATIC
void world_render_init(void)
67 VG_VAR_F32( k_day_length
);
68 VG_VAR_I32( k_debug_light_indices
);
69 VG_VAR_I32( k_debug_light_complexity
);
70 VG_VAR_I32( k_light_preview
);
71 vg_console_reg_cmd( "set_time", ccmd_set_time
, NULL
);
73 world_render
.sky_rate
= 1.0;
74 world_render
.sky_target_rate
= 1.0;
76 shader_scene_standard_register();
77 shader_scene_standard_alphatest_register();
78 shader_scene_fxglow_register();
79 shader_scene_vertex_blend_register();
80 shader_scene_terrain_register();
81 shader_scene_depth_register();
82 shader_scene_position_register();
83 shader_model_sky_register();
85 vg_info( "Loading world resources\n" );
86 vg_linear_clear( vg_mem
.scratch
);
89 mdl_open( &msky
, "models/rs_skydome.mdl", vg_mem
.scratch
);
90 mdl_load_metadata_block( &msky
, vg_mem
.scratch
);
91 mdl_async_load_glmesh( &msky
, &world_render
.skydome
);
94 vg_info( "Loading default world textures\n" );
95 vg_tex2d_load_qoi_async_file( "textures/garbage.qoi",
96 VG_TEX2D_NEAREST
|VG_TEX2D_REPEAT
,
97 &world_render
.tex_terrain_noise
);
99 vg_async_call( async_world_render_init
, NULL
, 0 );
102 VG_STATIC
void world_link_lighting_ub( world_instance
*world
, GLuint shader
)
104 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
105 glUniformBlockBinding( shader
, idx
, world
->ubo_bind_point
);
108 VG_STATIC
void world_bind_position_texture( world_instance
*world
,
109 GLuint shader
, GLuint location
,
112 render_fb_bind_texture( &world
->heightmap
, 0, slot
);
113 glUniform1i( location
, slot
);
116 VG_STATIC
void world_bind_light_array( world_instance
*world
,
117 GLuint shader
, GLuint location
,
120 glActiveTexture( GL_TEXTURE0
+ slot
);
121 glBindTexture( GL_TEXTURE_BUFFER
, world
->tex_light_entities
);
122 glUniform1i( location
, slot
);
125 VG_STATIC
void world_bind_light_index( world_instance
*world
,
126 GLuint shader
, GLuint location
,
129 glActiveTexture( GL_TEXTURE0
+ slot
);
130 glBindTexture( GL_TEXTURE_3D
, world
->tex_light_cubes
);
131 glUniform1i( location
, slot
);
134 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
);
140 VG_STATIC
void bind_terrain_noise(void)
142 glActiveTexture( GL_TEXTURE0
);
143 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
148 enum mdl_shader shader
;
149 enum world_geo_type geo_type
;
151 void (*fn_bind_textures
)( world_instance
*world
,
152 struct world_surface
*mat
);
153 void (*fn_set_mdl
)( m4x3f mdl
);
154 void (*fn_set_uPvmPrev
)( m4x4f pvm
);
157 VG_STATIC
void world_render_if( world_instance
*world
, struct world_pass
*pass
)
159 for( int i
=0; i
<world
->surface_count
; i
++ ){
160 struct world_surface
*mat
= &world
->surfaces
[i
];
162 if( mat
->info
.shader
== pass
->shader
){
165 if( pass
->geo_type
== k_world_geo_type_solid
)
168 sm
= &mat
->sm_no_collide
;
170 if( !sm
->indice_count
)
174 m4x3_identity( mmdl
);
175 pass
->fn_set_mdl( mmdl
);
176 pass
->fn_set_uPvmPrev( pass
->cam
->mtx_prev
.pv
);
178 pass
->fn_bind_textures( world
, mat
);
179 mdl_draw_submesh( sm
);
181 for( u32 j
=0; j
<mdl_arrcount( &world
->ent_traffic
); j
++ ){
182 ent_traffic
*traffic
= mdl_arritm( &world
->ent_traffic
, j
);
184 for( u32 k
=0; k
<traffic
->submesh_count
; k
++ ){
185 sm
= mdl_arritm( &world
->meta
.submeshs
,
186 traffic
->submesh_start
+k
);
188 q_m3x3( traffic
->transform
.q
, mmdl
);
189 v3_copy( traffic
->transform
.co
, mmdl
[3] );
192 m4x3_expand( mmdl
, m4mdl
);
193 m4x4_mul( pass
->cam
->mtx_prev
.pv
, m4mdl
, m4mdl
);
195 pass
->fn_set_mdl( mmdl
);
196 pass
->fn_set_uPvmPrev( m4mdl
);
198 mdl_draw_submesh( sm
);
206 void world_render_both_stages( world_instance
*world
, struct world_pass
*pass
)
208 mesh_bind( &world
->mesh_geo
);
209 pass
->geo_type
= k_world_geo_type_solid
;
210 world_render_if( world
, pass
);
212 glDisable( GL_CULL_FACE
);
213 mesh_bind( &world
->mesh_no_collide
);
214 pass
->geo_type
= k_world_geo_type_nonsolid
;
215 world_render_if( world
, pass
);
216 glEnable( GL_CULL_FACE
);
219 VG_STATIC
void bindpoint_diffuse_texture1( world_instance
*world
,
220 struct world_surface
*mat
)
223 glActiveTexture( GL_TEXTURE1
);
224 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
227 VG_STATIC
void render_world_vb( world_instance
*world
, camera
*cam
)
229 shader_scene_vertex_blend_use();
230 shader_scene_vertex_blend_uTexGarbage(0);
231 shader_scene_vertex_blend_uTexGradients(1);
232 world_link_lighting_ub( world
, _shader_scene_vertex_blend
.id
);
233 world_bind_position_texture( world
, _shader_scene_vertex_blend
.id
,
234 _uniform_scene_vertex_blend_g_world_depth
, 2 );
235 world_bind_light_array( world
, _shader_scene_vertex_blend
.id
,
236 _uniform_scene_vertex_blend_uLightsArray
, 3 );
237 world_bind_light_index( world
, _shader_scene_vertex_blend
.id
,
238 _uniform_scene_vertex_blend_uLightsIndex
, 4 );
240 glActiveTexture( GL_TEXTURE0
);
241 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
243 shader_scene_vertex_blend_uPv( cam
->mtx
.pv
);
244 shader_scene_vertex_blend_uCamera( cam
->transform
[3] );
246 struct world_pass pass
= {
247 .shader
= k_shader_standard_vertex_blend
,
249 .fn_bind_textures
= bindpoint_diffuse_texture1
,
250 .fn_set_mdl
= shader_scene_vertex_blend_uMdl
,
251 .fn_set_uPvmPrev
= shader_scene_vertex_blend_uPvmPrev
,
254 world_render_both_stages( world
, &pass
);
257 VG_STATIC
void render_world_standard( world_instance
*world
, camera
*cam
)
259 shader_scene_standard_use();
260 shader_scene_standard_uTexGarbage(0);
261 shader_scene_standard_uTexMain(1);
262 shader_scene_standard_uPv( cam
->mtx
.pv
);
264 world_link_lighting_ub( world
, _shader_scene_standard
.id
);
265 world_bind_position_texture( world
, _shader_scene_standard
.id
,
266 _uniform_scene_standard_g_world_depth
, 2 );
267 world_bind_light_array( world
, _shader_scene_standard
.id
,
268 _uniform_scene_standard_uLightsArray
, 3 );
269 world_bind_light_index( world
, _shader_scene_standard
.id
,
270 _uniform_scene_standard_uLightsIndex
, 4 );
272 bind_terrain_noise();
273 shader_scene_standard_uCamera( cam
->transform
[3] );
275 struct world_pass pass
= {
276 .shader
= k_shader_standard
,
278 .fn_bind_textures
= bindpoint_diffuse_texture1
,
279 .fn_set_mdl
= shader_scene_standard_uMdl
,
280 .fn_set_uPvmPrev
= shader_scene_standard_uPvmPrev
,
283 world_render_both_stages( world
, &pass
);
286 VG_STATIC
void render_world_alphatest( world_instance
*world
, camera
*cam
)
288 shader_scene_standard_alphatest_use();
289 shader_scene_standard_alphatest_uTexGarbage(0);
290 shader_scene_standard_alphatest_uTexMain(1);
291 shader_scene_standard_alphatest_uPv( cam
->mtx
.pv
);
293 world_link_lighting_ub( world
, _shader_scene_standard_alphatest
.id
);
294 world_bind_position_texture( world
, _shader_scene_standard_alphatest
.id
,
295 _uniform_scene_standard_alphatest_g_world_depth
, 2 );
296 world_bind_light_array( world
, _shader_scene_standard_alphatest
.id
,
297 _uniform_scene_standard_alphatest_uLightsArray
, 3 );
298 world_bind_light_index( world
, _shader_scene_standard_alphatest
.id
,
299 _uniform_scene_standard_alphatest_uLightsIndex
, 4 );
302 bind_terrain_noise();
305 shader_scene_standard_alphatest_uCamera( cam
->transform
[3] );
307 glDisable(GL_CULL_FACE
);
309 struct world_pass pass
= {
310 .shader
= k_shader_standard_cutout
,
312 .fn_bind_textures
= bindpoint_diffuse_texture1
,
313 .fn_set_mdl
= shader_scene_standard_alphatest_uMdl
,
314 .fn_set_uPvmPrev
= shader_scene_standard_alphatest_uPvmPrev
,
317 world_render_both_stages( world
, &pass
);
319 glEnable(GL_CULL_FACE
);
322 VG_STATIC
void render_world_fxglow( world_instance
*world
, camera
*cam
){
323 glDrawBuffers( 1, (GLenum
[]){ GL_COLOR_ATTACHMENT0
} );
325 shader_scene_fxglow_use();
326 shader_scene_fxglow_uTexMain(1);
327 shader_scene_fxglow_uPv( cam
->mtx
.pv
);
329 world_link_lighting_ub( world
, _shader_scene_fxglow
.id
);
330 world_bind_position_texture( world
, _shader_scene_fxglow
.id
,
331 _uniform_scene_fxglow_g_world_depth
, 2 );
332 world_bind_light_array( world
, _shader_scene_fxglow
.id
,
333 _uniform_scene_fxglow_uLightsArray
, 3 );
334 world_bind_light_index( world
, _shader_scene_fxglow
.id
,
335 _uniform_scene_fxglow_uLightsIndex
, 4 );
337 shader_scene_fxglow_uCamera( cam
->transform
[3] );
338 glDisable(GL_CULL_FACE
);
340 struct world_pass pass
= {
341 .shader
= k_shader_fxglow
,
343 .fn_bind_textures
= bindpoint_diffuse_texture1
,
344 .fn_set_mdl
= shader_scene_fxglow_uMdl
,
345 .fn_set_uPvmPrev
= shader_scene_fxglow_uPvmPrev
,
348 world_render_both_stages( world
, &pass
);
350 glEnable(GL_CULL_FACE
);
351 glDrawBuffers( 2, (GLenum
[]){ GL_COLOR_ATTACHMENT0
, GL_COLOR_ATTACHMENT1
} );
354 VG_STATIC
void bindpoint_terrain( world_instance
*world
,
355 struct world_surface
*mat
)
357 glActiveTexture( GL_TEXTURE1
);
358 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
360 shader_scene_terrain_uSandColour( mat
->info
.colour
);
361 shader_scene_terrain_uBlendOffset( mat
->info
.colour1
);
364 VG_STATIC
void render_terrain( world_instance
*world
, camera
*cam
)
366 shader_scene_terrain_use();
367 shader_scene_terrain_uTexGarbage(0);
368 shader_scene_terrain_uTexGradients(1);
370 world_link_lighting_ub( world
, _shader_scene_terrain
.id
);
371 world_bind_position_texture( world
, _shader_scene_terrain
.id
,
372 _uniform_scene_terrain_g_world_depth
, 2 );
373 world_bind_light_array( world
, _shader_scene_terrain
.id
,
374 _uniform_scene_terrain_uLightsArray
, 3 );
375 world_bind_light_index( world
, _shader_scene_terrain
.id
,
376 _uniform_scene_terrain_uLightsIndex
, 4 );
378 glActiveTexture( GL_TEXTURE0
);
379 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
381 shader_scene_terrain_uPv( cam
->mtx
.pv
);
382 shader_scene_terrain_uCamera( cam
->transform
[3] );
384 struct world_pass pass
= {
385 .shader
= k_shader_terrain_blend
,
387 .fn_bind_textures
= bindpoint_terrain
,
388 .fn_set_mdl
= shader_scene_terrain_uMdl
,
389 .fn_set_uPvmPrev
= shader_scene_terrain_uPvmPrev
,
392 world_render_both_stages( world
, &pass
);
395 VG_STATIC
void render_sky( world_instance
*world
, camera
*cam
)
398 * Modify matrix to remove clipping and view translation
405 m4x4_copy( cam
->mtx
.v
, v
);
406 m4x4_copy( cam
->mtx_prev
.v
, v_prev
);
408 v3_zero( v_prev
[3] );
410 m4x4_copy( cam
->mtx
.p
, pv
);
411 m4x4_copy( cam
->mtx_prev
.p
, pv_prev
);
412 m4x4_reset_clipping( pv
, cam
->farz
, cam
->nearz
);
413 m4x4_reset_clipping( pv_prev
, cam
->farz
, cam
->nearz
);
415 m4x4_mul( pv
, v
, pv
);
416 m4x4_mul( pv_prev
, v_prev
, pv_prev
);
418 m4x3f identity_matrix
;
419 m4x3_identity( identity_matrix
);
424 shader_model_sky_use();
425 shader_model_sky_uMdl( identity_matrix
);
426 shader_model_sky_uPv( pv
);
427 shader_model_sky_uPvmPrev( pv_prev
);
428 shader_model_sky_uTexGarbage(0);
429 world_link_lighting_ub( world
, _shader_model_sky
.id
);
431 glActiveTexture( GL_TEXTURE0
);
432 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
434 glDepthMask( GL_FALSE
);
435 glDisable( GL_DEPTH_TEST
);
437 mesh_bind( &world_render
.skydome
);
438 mesh_draw( &world_render
.skydome
);
440 glEnable( GL_DEPTH_TEST
);
441 glDepthMask( GL_TRUE
);
444 VG_STATIC
void render_world_gates( world_instance
*world
, camera
*cam
,
447 float closest
= INFINITY
;
448 struct ent_gate
*gate
= NULL
;
450 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_gate
); i
++ ){
451 ent_gate
*gi
= mdl_arritm( &world
->ent_gate
, i
);
453 if( gi
->type
== k_gate_type_unlinked
)
456 float dist
= v3_dist2( gi
->co
[0], cam
->transform
[3] );
458 vg_line_point( gi
->co
[0], 0.25f
, VG__BLUE
);
460 if( dist
< closest
){
467 /* should really be set in fixed update since its used in the physics
468 * of most systems. too bad! */
469 world
->rendering_gate
= gate
;
471 if( gate
->type
== k_gate_type_teleport
){
472 render_gate( world
, gate
, cam
, layer_depth
);
474 else if( gate
->type
== k_gate_type_nonlocel
){
475 if( world_loader
.state
!= k_world_loader_none
){
476 world
->rendering_gate
= NULL
;
480 world_instance
*dest_world
= &world_static
.worlds
[ gate
->target
];
481 render_gate( dest_world
, gate
, cam
, layer_depth
);
484 world
->rendering_gate
= NULL
;
488 VG_STATIC
void world_prerender( world_instance
*world
)
491 if( mdl_arrcount( &world
->ent_light
) ){
492 f32 rate
= vg_maxf(0.1f
, fabsf(k_day_length
)) * vg_signf(k_day_length
);
493 world
->time
+= vg
.time_delta
* (1.0/(rate
*60.0));
499 struct ub_world_lighting
*state
= &world
->ub_lighting
;
501 state
->g_time
= world
->time
;
502 state
->g_realtime
= vg
.time
;
503 state
->g_debug_indices
= k_debug_light_indices
;
504 state
->g_light_preview
= k_light_preview
;
505 state
->g_debug_complexity
= k_debug_light_complexity
;
506 state
->g_time_of_day
= vg_fractf( world
->time
);
507 state
->g_day_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 2.0f
);
508 state
->g_sunset_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 4.0f
+ VG_PIf
);
510 state
->g_day_phase
= state
->g_day_phase
* 0.5f
+ 0.5f
;
511 state
->g_sunset_phase
= powf( state
->g_sunset_phase
* 0.5f
+ 0.5f
, 6.0f
);
513 float a
= state
->g_time_of_day
* VG_PIf
* 2.0f
;
514 state
->g_sun_dir
[0] = sinf( a
);
515 state
->g_sun_dir
[1] = cosf( a
);
516 state
->g_sun_dir
[2] = 0.2f
;
517 v3_normalize( state
->g_sun_dir
);
519 world
->probabilities
[ k_probability_curve_constant
] = 1.0f
;
520 float dp
= state
->g_day_phase
;
522 world
->probabilities
[ k_probability_curve_wildlife_day
] =
523 (dp
*dp
*0.8f
+state
->g_sunset_phase
)*0.8f
;
524 world
->probabilities
[ k_probability_curve_wildlife_night
] =
525 1.0f
-powf(fabsf((state
->g_time_of_day
-0.5f
)*5.0f
),5.0f
);
527 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
528 glBufferSubData( GL_UNIFORM_BUFFER
, 0,
529 sizeof(struct ub_world_lighting
), &world
->ub_lighting
);
532 VG_STATIC
void skateshop_render(void);
533 VG_STATIC
void render_world( world_instance
*world
, camera
*cam
,
536 render_sky( world
, cam
);
538 render_world_routes( world
, cam
, layer_depth
);
539 render_world_standard( world
, cam
);
540 render_world_vb( world
, cam
);
541 render_world_alphatest( world
, cam
);
542 render_world_fxglow( world
, cam
);
543 render_terrain( world
, cam
);
545 if( layer_depth
== 0 ){
550 float min_dist
= INFINITY
;
552 if( !mdl_arrcount( &world
->ent_route
) )
555 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_route
); i
++ ){
556 ent_route
*route
= mdl_arritm( &world
->ent_route
, i
);
557 float dist
= v3_dist2( route
->board_transform
[3], cam
->pos
);
559 if( dist
< min_dist
){
565 ent_route
*route
= mdl_arritm( &world
->ent_route
, closest
);
566 sfd_render( world
, cam
, route
->board_transform
);
570 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
)
572 m4x3f identity_matrix
;
573 m4x3_identity( identity_matrix
);
575 shader_scene_depth_use();
576 shader_scene_depth_uCamera( cam
->transform
[3] );
577 shader_scene_depth_uPv( cam
->mtx
.pv
);
578 shader_scene_depth_uPvmPrev( cam
->mtx_prev
.pv
);
579 shader_scene_depth_uMdl( identity_matrix
);
580 world_link_lighting_ub( world
, _shader_scene_depth
.id
);
582 mesh_bind( &world
->mesh_geo
);
583 mesh_draw( &world
->mesh_geo
);
586 VG_STATIC
void render_world_position( world_instance
*world
, camera
*cam
)
588 m4x3f identity_matrix
;
589 m4x3_identity( identity_matrix
);
591 shader_scene_position_use();
592 shader_scene_position_uCamera( cam
->transform
[3] );
593 shader_scene_position_uPv( cam
->mtx
.pv
);
594 shader_scene_position_uPvmPrev( cam
->mtx_prev
.pv
);
595 shader_scene_position_uMdl( identity_matrix
);
596 world_link_lighting_ub( world
, _shader_scene_position
.id
);
598 mesh_bind( &world
->mesh_geo
);
599 mesh_draw( &world
->mesh_geo
);