2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
9 #include "world_render.h"
13 static int ccmd_set_time( int argc
, const char *argv
[] ){
15 world_instance
*world
= world_current_instance();
16 world
->time
= atof( argv
[0] );
19 vg_error( "Usage set_time <0-1.0>\n" );
24 VG_STATIC
void async_world_render_init( void *payload
, u32 size
)
26 vg_info( "Allocate uniform buffers\n" );
27 for( int i
=0; i
<4; i
++ ){
28 world_instance
*world
= &world_static
.instances
[i
];
29 world
->ubo_bind_point
= i
;
31 glGenBuffers( 1, &world
->ubo_lighting
);
32 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
33 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
34 NULL
, GL_DYNAMIC_DRAW
);
36 glBindBufferBase( GL_UNIFORM_BUFFER
, i
, world
->ubo_lighting
);
40 vg_info( "Allocate frame buffers\n" );
41 for( int i
=0; i
<4; i
++ ){
42 world_instance
*world
= &world_static
.instances
[i
];
43 struct framebuffer
*fb
= &world
->heightmap
;
45 fb
->display_name
= NULL
;
49 fb
->resolution_div
= 0;
51 fb
->attachments
[0].display_name
= NULL
;
52 fb
->attachments
[0].purpose
= k_framebuffer_attachment_type_texture
;
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
;
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
;
63 render_fb_allocate( fb
);
67 VG_STATIC
void world_render_init(void)
69 VG_VAR_F32( k_day_length
);
70 VG_VAR_I32( k_debug_light_indices
);
71 VG_VAR_I32( k_debug_light_complexity
);
72 VG_VAR_I32( k_light_preview
);
73 vg_console_reg_cmd( "set_time", ccmd_set_time
, NULL
);
75 world_render
.sky_rate
= 1.0;
76 world_render
.sky_target_rate
= 1.0;
78 shader_scene_standard_register();
79 shader_scene_standard_alphatest_register();
80 shader_scene_cubemapped_register();
81 shader_scene_fxglow_register();
82 shader_scene_vertex_blend_register();
83 shader_scene_terrain_register();
84 shader_scene_depth_register();
85 shader_scene_position_register();
86 shader_model_sky_register();
88 vg_info( "Loading world resources\n" );
89 vg_linear_clear( vg_mem
.scratch
);
92 mdl_open( &msky
, "models/rs_skydome.mdl", vg_mem
.scratch
);
93 mdl_load_metadata_block( &msky
, vg_mem
.scratch
);
94 mdl_async_load_glmesh( &msky
, &world_render
.skydome
);
97 vg_info( "Loading default world textures\n" );
98 vg_tex2d_load_qoi_async_file( "textures/garbage.qoi",
99 VG_TEX2D_NEAREST
|VG_TEX2D_REPEAT
,
100 &world_render
.tex_terrain_noise
);
102 vg_async_call( async_world_render_init
, NULL
, 0 );
105 VG_STATIC
void world_link_lighting_ub( world_instance
*world
, GLuint shader
)
107 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
108 glUniformBlockBinding( shader
, idx
, world
->ubo_bind_point
);
111 VG_STATIC
void world_bind_position_texture( world_instance
*world
,
112 GLuint shader
, GLuint location
,
115 render_fb_bind_texture( &world
->heightmap
, 0, slot
);
116 glUniform1i( location
, slot
);
119 VG_STATIC
void world_bind_light_array( world_instance
*world
,
120 GLuint shader
, GLuint location
,
123 glActiveTexture( GL_TEXTURE0
+ slot
);
124 glBindTexture( GL_TEXTURE_BUFFER
, world
->tex_light_entities
);
125 glUniform1i( location
, slot
);
128 VG_STATIC
void world_bind_light_index( world_instance
*world
,
129 GLuint shader
, GLuint location
,
132 glActiveTexture( GL_TEXTURE0
+ slot
);
133 glBindTexture( GL_TEXTURE_3D
, world
->tex_light_cubes
);
134 glUniform1i( location
, slot
);
137 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
);
143 VG_STATIC
void bind_terrain_noise(void)
145 glActiveTexture( GL_TEXTURE0
);
146 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
151 enum mdl_shader shader
;
152 enum world_geo_type geo_type
;
154 void (*fn_bind_textures
)( world_instance
*world
,
155 struct world_surface
*mat
);
156 void (*fn_set_mdl
)( m4x3f mdl
);
157 void (*fn_set_uPvmPrev
)( m4x4f pvm
);
161 void world_render_traffic( world_instance
*world
, u32 material_id
,
162 struct world_pass
*pass
){
163 if( !mdl_arrcount( &world
->ent_traffic
) ) return;
165 /* HACK: use the first material for every traffic entity */
166 ent_traffic
*first
= mdl_arritm( &world
->ent_traffic
, 0 );
167 if( !first
->submesh_count
) return;
169 mdl_submesh
*sm
= mdl_arritm( &world
->meta
.submeshs
, first
->submesh_start
);
170 if( sm
->material_id
!= material_id
) return;
172 struct world_surface
*mat
= &world
->surfaces
[ material_id
];
173 pass
->fn_bind_textures( world
, mat
);
175 for( u32 j
=0; j
<mdl_arrcount( &world
->ent_traffic
); j
++ ){
176 ent_traffic
*traffic
= mdl_arritm( &world
->ent_traffic
, j
);
178 for( u32 k
=0; k
<traffic
->submesh_count
; k
++ ){
179 sm
= mdl_arritm( &world
->meta
.submeshs
,
180 traffic
->submesh_start
+k
);
183 q_m3x3( traffic
->transform
.q
, mmdl
);
184 v3_copy( traffic
->transform
.co
, mmdl
[3] );
187 m4x3_expand( mmdl
, m4mdl
);
188 m4x4_mul( pass
->cam
->mtx_prev
.pv
, m4mdl
, m4mdl
);
190 pass
->fn_set_mdl( mmdl
);
191 pass
->fn_set_uPvmPrev( m4mdl
);
193 mdl_draw_submesh( sm
);
199 void world_render_pass( world_instance
*world
, struct world_pass
*pass
){
200 for( int i
=0; i
<world
->surface_count
; i
++ ){
201 struct world_surface
*mat
= &world
->surfaces
[i
];
203 if( mat
->info
.shader
== pass
->shader
){
206 if( pass
->geo_type
== k_world_geo_type_solid
){
210 world_render_traffic( world
, i
, pass
);
211 sm
= &mat
->sm_no_collide
;
214 if( !sm
->indice_count
)
218 m4x3_identity( mmdl
);
219 pass
->fn_set_mdl( mmdl
);
220 pass
->fn_set_uPvmPrev( pass
->cam
->mtx_prev
.pv
);
222 pass
->fn_bind_textures( world
, mat
);
223 mdl_draw_submesh( sm
);
229 void world_render_both_stages( world_instance
*world
, struct world_pass
*pass
)
231 mesh_bind( &world
->mesh_geo
);
232 pass
->geo_type
= k_world_geo_type_solid
;
233 world_render_pass( world
, pass
);
235 glDisable( GL_CULL_FACE
);
236 mesh_bind( &world
->mesh_no_collide
);
237 pass
->geo_type
= k_world_geo_type_nonsolid
;
238 world_render_pass( world
, pass
);
239 glEnable( GL_CULL_FACE
);
242 VG_STATIC
void bindpoint_diffuse_texture1( world_instance
*world
,
243 struct world_surface
*mat
)
246 glActiveTexture( GL_TEXTURE1
);
247 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
250 VG_STATIC
void bindpoint_diffuse1_and_cubemap10( world_instance
*world
,
251 struct world_surface
*mat
){
252 glActiveTexture( GL_TEXTURE1
);
253 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
255 u32 cubemap_id
= mat
->info
.tex_none0
,
258 if( mdl_entity_id_type( cubemap_id
) == k_ent_cubemap
){
259 cubemap_index
= mdl_entity_id_id( cubemap_id
);
262 ent_cubemap
*cm
= mdl_arritm( &world
->ent_cubemap
, cubemap_index
);
263 glActiveTexture( GL_TEXTURE10
);
264 glBindTexture( GL_TEXTURE_CUBE_MAP
, cm
->texture_id
);
266 shader_scene_cubemapped_uColour( mat
->info
.colour
);
269 VG_STATIC
void render_world_vb( world_instance
*world
, camera
*cam
)
271 shader_scene_vertex_blend_use();
272 shader_scene_vertex_blend_uTexGarbage(0);
273 shader_scene_vertex_blend_uTexGradients(1);
274 world_link_lighting_ub( world
, _shader_scene_vertex_blend
.id
);
275 world_bind_position_texture( world
, _shader_scene_vertex_blend
.id
,
276 _uniform_scene_vertex_blend_g_world_depth
, 2 );
277 world_bind_light_array( world
, _shader_scene_vertex_blend
.id
,
278 _uniform_scene_vertex_blend_uLightsArray
, 3 );
279 world_bind_light_index( world
, _shader_scene_vertex_blend
.id
,
280 _uniform_scene_vertex_blend_uLightsIndex
, 4 );
282 glActiveTexture( GL_TEXTURE0
);
283 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
285 shader_scene_vertex_blend_uPv( cam
->mtx
.pv
);
286 shader_scene_vertex_blend_uCamera( cam
->transform
[3] );
288 struct world_pass pass
= {
289 .shader
= k_shader_standard_vertex_blend
,
291 .fn_bind_textures
= bindpoint_diffuse_texture1
,
292 .fn_set_mdl
= shader_scene_vertex_blend_uMdl
,
293 .fn_set_uPvmPrev
= shader_scene_vertex_blend_uPvmPrev
,
296 world_render_both_stages( world
, &pass
);
299 VG_STATIC
void world_shader_standard_bind( world_instance
*world
, camera
*cam
){
300 shader_scene_standard_use();
301 shader_scene_standard_uTexGarbage(0);
302 shader_scene_standard_uTexMain(1);
303 shader_scene_standard_uPv( cam
->mtx
.pv
);
305 world_link_lighting_ub( world
, _shader_scene_standard
.id
);
306 world_bind_position_texture( world
, _shader_scene_standard
.id
,
307 _uniform_scene_standard_g_world_depth
, 2 );
308 world_bind_light_array( world
, _shader_scene_standard
.id
,
309 _uniform_scene_standard_uLightsArray
, 3 );
310 world_bind_light_index( world
, _shader_scene_standard
.id
,
311 _uniform_scene_standard_uLightsIndex
, 4 );
313 bind_terrain_noise();
314 shader_scene_standard_uCamera( cam
->transform
[3] );
317 VG_STATIC
void render_world_standard( world_instance
*world
, camera
*cam
){
318 world_shader_standard_bind( world
, cam
);
319 struct world_pass pass
= {
320 .shader
= k_shader_standard
,
322 .fn_bind_textures
= bindpoint_diffuse_texture1
,
323 .fn_set_mdl
= shader_scene_standard_uMdl
,
324 .fn_set_uPvmPrev
= shader_scene_standard_uPvmPrev
,
327 world_render_both_stages( world
, &pass
);
330 VG_STATIC
void render_world_cubemapped( world_instance
*world
, camera
*cam
,
332 if( !mdl_arrcount( &world
->ent_cubemap
) )
335 if( layer_depth
== -1 ){
336 world_shader_standard_bind( world
, cam
);
338 struct world_pass pass
= {
339 .shader
= k_shader_cubemap
,
341 .fn_bind_textures
= bindpoint_diffuse_texture1
,
342 .fn_set_mdl
= shader_scene_standard_uMdl
,
343 .fn_set_uPvmPrev
= shader_scene_standard_uPvmPrev
,
346 world_render_both_stages( world
, &pass
);
349 shader_scene_cubemapped_use();
350 shader_scene_cubemapped_uTexGarbage(0);
351 shader_scene_cubemapped_uTexMain(1);
352 shader_scene_cubemapped_uTexCubemap(10);
353 shader_scene_cubemapped_uPv( cam
->mtx
.pv
);
355 world_link_lighting_ub( world
, _shader_scene_cubemapped
.id
);
356 world_bind_position_texture( world
, _shader_scene_cubemapped
.id
,
357 _uniform_scene_cubemapped_g_world_depth
, 2 );
358 world_bind_light_array( world
, _shader_scene_cubemapped
.id
,
359 _uniform_scene_cubemapped_uLightsArray
, 3 );
360 world_bind_light_index( world
, _shader_scene_cubemapped
.id
,
361 _uniform_scene_cubemapped_uLightsIndex
, 4 );
363 bind_terrain_noise();
364 shader_scene_cubemapped_uCamera( cam
->transform
[3] );
366 struct world_pass pass
= {
367 .shader
= k_shader_cubemap
,
369 .fn_bind_textures
= bindpoint_diffuse1_and_cubemap10
,
370 .fn_set_mdl
= shader_scene_cubemapped_uMdl
,
371 .fn_set_uPvmPrev
= shader_scene_cubemapped_uPvmPrev
,
374 world_render_both_stages( world
, &pass
);
378 VG_STATIC
void render_world_alphatest( world_instance
*world
, camera
*cam
){
379 shader_scene_standard_alphatest_use();
380 shader_scene_standard_alphatest_uTexGarbage(0);
381 shader_scene_standard_alphatest_uTexMain(1);
382 shader_scene_standard_alphatest_uPv( cam
->mtx
.pv
);
384 world_link_lighting_ub( world
, _shader_scene_standard_alphatest
.id
);
385 world_bind_position_texture( world
, _shader_scene_standard_alphatest
.id
,
386 _uniform_scene_standard_alphatest_g_world_depth
, 2 );
387 world_bind_light_array( world
, _shader_scene_standard_alphatest
.id
,
388 _uniform_scene_standard_alphatest_uLightsArray
, 3 );
389 world_bind_light_index( world
, _shader_scene_standard_alphatest
.id
,
390 _uniform_scene_standard_alphatest_uLightsIndex
, 4 );
393 bind_terrain_noise();
396 shader_scene_standard_alphatest_uCamera( cam
->transform
[3] );
398 glDisable(GL_CULL_FACE
);
400 struct world_pass pass
= {
401 .shader
= k_shader_standard_cutout
,
403 .fn_bind_textures
= bindpoint_diffuse_texture1
,
404 .fn_set_mdl
= shader_scene_standard_alphatest_uMdl
,
405 .fn_set_uPvmPrev
= shader_scene_standard_alphatest_uPvmPrev
,
408 world_render_both_stages( world
, &pass
);
410 glEnable(GL_CULL_FACE
);
414 void world_render_challenges( world_instance
*world
, struct world_pass
*pass
,
415 v3f pos
, int layer_depth
){
419 const f32 radius
= 40.0f
;
421 bh_iter_init_range( 0, &it
, pos
, radius
);
424 u32 challenge_list
[ 32 ],
427 u32 challenge_count
= 0,
430 while( bh_next( world
->entity_bh
, &it
, &idx
) ){
431 u32 id
= world
->entity_list
[ idx
],
432 type
= mdl_entity_id_type( id
),
433 index
= mdl_entity_id_id( id
);
435 if( type
== k_ent_challenge
) {
436 if( challenge_count
< vg_list_size(challenge_list
) )
437 challenge_list
[ challenge_count
++ ] = index
;
439 else if( type
== k_ent_unlock
){
440 if( unlock_count
< vg_list_size(unlock_list
) )
441 unlock_list
[ unlock_count
++ ] = index
;
445 /* render challenges */
446 glDisable( GL_CULL_FACE
);
447 mesh_bind( &world
->mesh_no_collide
);
448 u32 last_material
= 0;
449 for( u32 i
=0; i
<challenge_count
; i
++ ){
450 u32 index
= challenge_list
[ i
];
451 ent_challenge
*challenge
= mdl_arritm( &world
->ent_challenge
, index
);
452 if( challenge
->flags
& k_ent_challenge_hidden
) continue;
454 f32 dist
= v3_dist( challenge
->transform
.co
, pos
) * (1.0f
/radius
),
455 scale
= vg_smoothstepf( vg_clampf( 10.0f
-dist
*10.0f
, 0.0f
,1.0f
) );
457 v3_fill( challenge
->transform
.s
, scale
);
460 mdl_transform_m4x3( &challenge
->transform
, mmdl
);
461 shader_scene_fxglow_uMdl( mmdl
);
463 for( u32 j
=0; j
<challenge
->submesh_count
; j
++ ){
464 mdl_submesh
*sm
= mdl_arritm( &world
->meta
.submeshs
,
465 challenge
->submesh_start
+ j
);
467 if( sm
->material_id
!= last_material
){
468 last_material
= sm
->material_id
;
470 pass
->fn_bind_textures( world
, &world
->surfaces
[sm
->material_id
] );
473 mdl_draw_submesh( sm
);
478 font3d_bind( &gui
.font
, &skaterift
.cam
);
479 shader_model_font_uColour( (v4f
){1.0f
,1.0f
,1.0f
,1.0f
} );
481 for( u32 i
=0; i
<unlock_count
; i
++ ){
482 u32 index
= unlock_list
[ i
];
483 ent_unlock
*unlock
= mdl_arritm( &world
->ent_unlock
, index
);
485 mdl_transform_m4x3( &unlock
->transform
, mmdl
);
486 font3d_simple_draw( &gui
.font
, 0, "Test!", &skaterift
.cam
, mmdl
);
490 VG_STATIC
void render_world_fxglow( world_instance
*world
, camera
*cam
,
492 shader_scene_fxglow_use();
493 shader_scene_fxglow_uTexMain(1);
494 shader_scene_fxglow_uPv( cam
->mtx
.pv
);
496 world_link_lighting_ub( world
, _shader_scene_fxglow
.id
);
497 world_bind_position_texture( world
, _shader_scene_fxglow
.id
,
498 _uniform_scene_fxglow_g_world_depth
, 2 );
499 world_bind_light_array( world
, _shader_scene_fxglow
.id
,
500 _uniform_scene_fxglow_uLightsArray
, 3 );
501 world_bind_light_index( world
, _shader_scene_fxglow
.id
,
502 _uniform_scene_fxglow_uLightsIndex
, 4 );
504 shader_scene_fxglow_uCamera( cam
->transform
[3] );
505 glDisable(GL_CULL_FACE
);
507 struct world_pass pass
= {
508 .shader
= k_shader_fxglow
,
510 .fn_bind_textures
= bindpoint_diffuse_texture1
,
511 .fn_set_mdl
= shader_scene_fxglow_uMdl
,
512 .fn_set_uPvmPrev
= shader_scene_fxglow_uPvmPrev
,
515 world_render_both_stages( world
, &pass
);
516 world_render_challenges( world
, &pass
, cam
->pos
, layer_depth
);
518 glEnable(GL_CULL_FACE
);
521 VG_STATIC
void bindpoint_terrain( world_instance
*world
,
522 struct world_surface
*mat
)
524 glActiveTexture( GL_TEXTURE1
);
525 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
527 shader_scene_terrain_uSandColour( mat
->info
.colour
);
528 shader_scene_terrain_uBlendOffset( mat
->info
.colour1
);
531 VG_STATIC
void render_terrain( world_instance
*world
, camera
*cam
)
533 shader_scene_terrain_use();
534 shader_scene_terrain_uTexGarbage(0);
535 shader_scene_terrain_uTexGradients(1);
537 world_link_lighting_ub( world
, _shader_scene_terrain
.id
);
538 world_bind_position_texture( world
, _shader_scene_terrain
.id
,
539 _uniform_scene_terrain_g_world_depth
, 2 );
540 world_bind_light_array( world
, _shader_scene_terrain
.id
,
541 _uniform_scene_terrain_uLightsArray
, 3 );
542 world_bind_light_index( world
, _shader_scene_terrain
.id
,
543 _uniform_scene_terrain_uLightsIndex
, 4 );
545 glActiveTexture( GL_TEXTURE0
);
546 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
548 shader_scene_terrain_uPv( cam
->mtx
.pv
);
549 shader_scene_terrain_uCamera( cam
->transform
[3] );
551 struct world_pass pass
= {
552 .shader
= k_shader_terrain_blend
,
554 .fn_bind_textures
= bindpoint_terrain
,
555 .fn_set_mdl
= shader_scene_terrain_uMdl
,
556 .fn_set_uPvmPrev
= shader_scene_terrain_uPvmPrev
,
559 world_render_both_stages( world
, &pass
);
562 VG_STATIC
void render_sky( world_instance
*world
, camera
*cam
)
565 * Modify matrix to remove clipping and view translation
572 m4x4_copy( cam
->mtx
.v
, v
);
573 m4x4_copy( cam
->mtx_prev
.v
, v_prev
);
575 v3_zero( v_prev
[3] );
577 m4x4_copy( cam
->mtx
.p
, pv
);
578 m4x4_copy( cam
->mtx_prev
.p
, pv_prev
);
579 m4x4_reset_clipping( pv
, cam
->farz
, cam
->nearz
);
580 m4x4_reset_clipping( pv_prev
, cam
->farz
, cam
->nearz
);
582 m4x4_mul( pv
, v
, pv
);
583 m4x4_mul( pv_prev
, v_prev
, pv_prev
);
585 m4x3f identity_matrix
;
586 m4x3_identity( identity_matrix
);
591 shader_model_sky_use();
592 shader_model_sky_uMdl( identity_matrix
);
593 shader_model_sky_uPv( pv
);
594 shader_model_sky_uPvmPrev( pv_prev
);
595 shader_model_sky_uTexGarbage(0);
596 world_link_lighting_ub( world
, _shader_model_sky
.id
);
598 glActiveTexture( GL_TEXTURE0
);
599 glBindTexture( GL_TEXTURE_2D
, world_render
.tex_terrain_noise
);
601 glDepthMask( GL_FALSE
);
602 glDisable( GL_DEPTH_TEST
);
604 mesh_bind( &world_render
.skydome
);
605 mesh_draw( &world_render
.skydome
);
607 glEnable( GL_DEPTH_TEST
);
608 glDepthMask( GL_TRUE
);
611 VG_STATIC
void render_world_gates( world_instance
*world
, camera
*cam
,
614 float closest
= INFINITY
;
615 struct ent_gate
*gate
= NULL
;
617 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_gate
); i
++ ){
618 ent_gate
*gi
= mdl_arritm( &world
->ent_gate
, i
);
620 if( !(gi
->flags
& k_ent_gate_linked
) )
623 float dist
= v3_dist2( gi
->co
[0], cam
->transform
[3] );
625 vg_line_point( gi
->co
[0], 0.25f
, VG__BLUE
);
627 if( dist
< closest
){
633 world
->rendering_gate
= gate
;
635 if( gate
->flags
& k_ent_gate_locked
) return;
637 if( gate
->flags
& k_ent_gate_nonlocal
){
638 if( world_static
.load_state
!= k_world_loader_none
){
639 world
->rendering_gate
= NULL
;
643 world_instance
*dest_world
= &world_static
.instances
[ gate
->target
];
644 render_gate( world
, dest_world
, gate
, cam
, layer_depth
);
647 render_gate( world
, world
, gate
, cam
, layer_depth
);
652 VG_STATIC
void world_prerender( world_instance
*world
)
655 if( mdl_arrcount( &world
->ent_light
) ){
656 f32 rate
= vg_maxf(0.1f
, fabsf(k_day_length
)) * vg_signf(k_day_length
);
657 world
->time
+= vg
.time_delta
* (1.0/(rate
*60.0));
663 struct ub_world_lighting
*state
= &world
->ub_lighting
;
665 state
->g_time
= world
->time
;
666 state
->g_realtime
= vg
.time
;
667 state
->g_debug_indices
= k_debug_light_indices
;
668 state
->g_light_preview
= k_light_preview
;
669 state
->g_debug_complexity
= k_debug_light_complexity
;
670 state
->g_time_of_day
= vg_fractf( world
->time
);
671 state
->g_day_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 2.0f
);
672 state
->g_sunset_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 4.0f
+ VG_PIf
);
674 state
->g_day_phase
= state
->g_day_phase
* 0.5f
+ 0.5f
;
675 state
->g_sunset_phase
= powf( state
->g_sunset_phase
* 0.5f
+ 0.5f
, 6.0f
);
677 float a
= state
->g_time_of_day
* VG_PIf
* 2.0f
;
678 state
->g_sun_dir
[0] = sinf( a
);
679 state
->g_sun_dir
[1] = cosf( a
);
680 state
->g_sun_dir
[2] = 0.2f
;
681 v3_normalize( state
->g_sun_dir
);
683 world
->probabilities
[ k_probability_curve_constant
] = 1.0f
;
684 float dp
= state
->g_day_phase
;
686 world
->probabilities
[ k_probability_curve_wildlife_day
] =
687 (dp
*dp
*0.8f
+state
->g_sunset_phase
)*0.8f
;
688 world
->probabilities
[ k_probability_curve_wildlife_night
] =
689 1.0f
-powf(fabsf((state
->g_time_of_day
-0.5f
)*5.0f
),5.0f
);
691 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
692 glBufferSubData( GL_UNIFORM_BUFFER
, 0,
693 sizeof(struct ub_world_lighting
), &world
->ub_lighting
);
696 VG_STATIC
void skateshop_render(void);
697 VG_STATIC
void render_world( world_instance
*world
, camera
*cam
,
700 render_sky( world
, cam
);
702 render_world_routes( world
, cam
, layer_depth
);
703 render_world_standard( world
, cam
);
704 render_world_cubemapped( world
, cam
, layer_depth
);
706 render_world_vb( world
, cam
);
707 render_world_alphatest( world
, cam
);
708 render_world_fxglow( world
, cam
, layer_depth
);
709 render_terrain( world
, cam
);
711 if( layer_depth
== 0 ){
716 float min_dist
= INFINITY
;
718 if( !mdl_arrcount( &world
->ent_route
) )
721 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_route
); i
++ ){
722 ent_route
*route
= mdl_arritm( &world
->ent_route
, i
);
723 float dist
= v3_dist2( route
->board_transform
[3], cam
->pos
);
725 if( dist
< min_dist
){
731 ent_route
*route
= mdl_arritm( &world
->ent_route
, closest
);
732 sfd_render( world
, cam
, route
->board_transform
);
736 VG_STATIC
void render_cubemap_side( world_instance
*world
, ent_cubemap
*cm
,
739 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
740 GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ side
, cm
->texture_id
, 0 );
741 glClear( GL_DEPTH_BUFFER_BIT
);
744 { -1.0f
, 0.0f
, 0.0f
},
745 { 1.0f
, 0.0f
, 0.0f
},
746 { 0.0f
, -1.0f
, 0.0f
},
747 { 0.0f
, 1.0f
, 0.0f
},
748 { 0.0f
, 0.0f
, -1.0f
},
752 { 0.0f
, -1.0f
, 0.0f
},
753 { 0.0f
, -1.0f
, 0.0f
},
754 { 0.0f
, 0.0f
, 1.0f
},
755 { 0.0f
, 0.0f
, -1.0f
},
756 { 0.0f
, -1.0f
, 0.0f
},
757 { 0.0f
, -1.0f
, 0.0f
}
760 v3_zero( cam
.angles
);
761 v3_copy( cm
->co
, cam
.pos
);
763 v3_copy( forward
[side
], cam
.transform
[2] );
764 v3_copy( up
[side
], cam
.transform
[1] );
765 v3_cross( up
[side
], forward
[side
], cam
.transform
[0] );
766 v3_copy( cm
->co
, cam
.transform
[3] );
767 m4x3_invert_affine( cam
.transform
, cam
.transform_inverse
);
769 camera_update_view( &cam
);
774 m4x4_copy( cam
.mtx
.p
, cam
.mtx_prev
.p
);
775 m4x4_projection( cam
.mtx
.p
, cam
.fov
, 1.0f
, cam
.nearz
, cam
.farz
);
776 camera_finalize( &cam
);
777 camera_finalize( &cam
);
779 render_world( world
, &cam
, -1 );
782 VG_STATIC
void render_world_cubemaps( world_instance
*world
){
783 if( world
->cubemap_cooldown
)
784 world
->cubemap_cooldown
--;
786 world
->cubemap_cooldown
= 60;
788 glViewport( 0, 0, WORLD_CUBEMAP_RES
, WORLD_CUBEMAP_RES
);
789 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_cubemap
); i
++ ){
790 ent_cubemap
*cm
= mdl_arritm( &world
->ent_cubemap
, i
);
791 glBindFramebuffer( GL_FRAMEBUFFER
, cm
->framebuffer_id
);
793 world
->cubemap_side
++;
794 if( world
->cubemap_side
>= 6 )
795 world
->cubemap_side
= 0;
797 render_cubemap_side( world
, cm
, world
->cubemap_side
);
802 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
)
804 m4x3f identity_matrix
;
805 m4x3_identity( identity_matrix
);
807 shader_scene_depth_use();
808 shader_scene_depth_uCamera( cam
->transform
[3] );
809 shader_scene_depth_uPv( cam
->mtx
.pv
);
810 shader_scene_depth_uPvmPrev( cam
->mtx_prev
.pv
);
811 shader_scene_depth_uMdl( identity_matrix
);
812 world_link_lighting_ub( world
, _shader_scene_depth
.id
);
814 mesh_bind( &world
->mesh_geo
);
815 mesh_draw( &world
->mesh_geo
);
818 VG_STATIC
void render_world_position( world_instance
*world
, camera
*cam
)
820 m4x3f identity_matrix
;
821 m4x3_identity( identity_matrix
);
823 shader_scene_position_use();
824 shader_scene_position_uCamera( cam
->transform
[3] );
825 shader_scene_position_uPv( cam
->mtx
.pv
);
826 shader_scene_position_uPvmPrev( cam
->mtx_prev
.pv
);
827 shader_scene_position_uMdl( identity_matrix
);
828 world_link_lighting_ub( world
, _shader_scene_position
.id
);
830 mesh_bind( &world
->mesh_geo
);
831 mesh_draw( &world
->mesh_geo
);