2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
11 VG_STATIC GLuint tex_terrain_noise
;
13 VG_STATIC
void async_world_render_init( void *payload
, u32 size
)
15 vg_info( "Allocate uniform buffers\n" );
16 for( int i
=0; i
<4; i
++ ){
17 world_instance
*world
= &world_global
.worlds
[i
];
18 world
->ubo_bind_point
= i
;
20 glGenBuffers( 1, &world
->ubo_lighting
);
21 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
22 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
23 NULL
, GL_DYNAMIC_DRAW
);
25 glBindBufferBase( GL_UNIFORM_BUFFER
, i
, world
->ubo_lighting
);
29 vg_info( "Allocate frame buffers\n" );
30 for( int i
=0; i
<4; i
++ ){
31 world_instance
*world
= &world_global
.worlds
[i
];
32 struct framebuffer
*fb
= &world
->heightmap
;
34 fb
->display_name
= NULL
;
38 fb
->resolution_div
= 0;
40 fb
->attachments
[0].display_name
= NULL
;
41 fb
->attachments
[0].purpose
= k_framebuffer_attachment_type_texture
;
42 fb
->attachments
[0].internalformat
= GL_RG16F
;
43 fb
->attachments
[0].format
= GL_RG
;
44 fb
->attachments
[0].type
= GL_FLOAT
;
45 fb
->attachments
[0].attachment
= GL_COLOR_ATTACHMENT0
;
47 fb
->attachments
[1].purpose
= k_framebuffer_attachment_type_none
;
48 fb
->attachments
[2].purpose
= k_framebuffer_attachment_type_none
;
49 fb
->attachments
[3].purpose
= k_framebuffer_attachment_type_none
;
50 fb
->attachments
[4].purpose
= k_framebuffer_attachment_type_none
;
52 render_fb_allocate( fb
);
56 VG_STATIC
void world_render_init(void)
58 vg_info( "Loading default world textures\n" );
60 vg_tex2d_load_qoi_async_file( "textures/garbage.qoi",
61 VG_TEX2D_NEAREST
|VG_TEX2D_REPEAT
,
64 vg_async_call( async_world_render_init
, NULL
, 0 );
67 VG_STATIC
void world_link_lighting_ub( world_instance
*world
, GLuint shader
)
69 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
70 glUniformBlockBinding( shader
, idx
, world
->ubo_bind_point
);
73 VG_STATIC
void world_bind_position_texture( world_instance
*world
,
74 GLuint shader
, GLuint location
,
77 render_fb_bind_texture( &world
->heightmap
, 0, slot
);
78 glUniform1i( location
, slot
);
81 VG_STATIC
void world_bind_light_array( world_instance
*world
,
82 GLuint shader
, GLuint location
,
85 glActiveTexture( GL_TEXTURE0
+ slot
);
86 glBindTexture( GL_TEXTURE_BUFFER
, world
->tex_light_entities
);
87 glUniform1i( location
, slot
);
90 VG_STATIC
void world_bind_light_index( world_instance
*world
,
91 GLuint shader
, GLuint location
,
94 glActiveTexture( GL_TEXTURE0
+ slot
);
95 glBindTexture( GL_TEXTURE_3D
, world
->tex_light_cubes
);
96 glUniform1i( location
, slot
);
99 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
);
105 VG_STATIC
void bind_terrain_noise(void)
107 glActiveTexture( GL_TEXTURE0
);
108 glBindTexture( GL_TEXTURE_2D
, tex_terrain_noise
);
113 enum mdl_shader shader
;
114 enum geo_type geo_type
;
116 void (*fn_bind_textures
)( world_instance
*world
,
117 struct world_surface
*mat
);
118 void (*fn_set_mdl
)( m4x3f mdl
);
119 void (*fn_set_uPvmPrev
)( m4x4f pvm
);
122 VG_STATIC
void world_render_if( world_instance
*world
, struct world_pass
*pass
)
124 for( int i
=0; i
<world
->surface_count
; i
++ ){
125 struct world_surface
*mat
= &world
->surfaces
[i
];
127 if( mat
->info
.shader
== pass
->shader
){
130 if( pass
->geo_type
== k_geo_type_solid
)
133 sm
= &mat
->sm_no_collide
;
135 if( !sm
->indice_count
)
139 m4x3_identity( mmdl
);
140 pass
->fn_set_mdl( mmdl
);
141 pass
->fn_set_uPvmPrev( pass
->cam
->mtx_prev
.pv
);
143 pass
->fn_bind_textures( world
, mat
);
144 mdl_draw_submesh( sm
);
146 for( u32 j
=0; j
<mdl_arrcount( &world
->ent_traffic
); j
++ ){
147 ent_traffic
*traffic
= mdl_arritm( &world
->ent_traffic
, j
);
149 for( u32 k
=0; k
<traffic
->submesh_count
; k
++ ){
150 sm
= mdl_arritm( &world
->meta
.submeshs
,
151 traffic
->submesh_start
+k
);
153 q_m3x3( traffic
->transform
.q
, mmdl
);
154 v3_copy( traffic
->transform
.co
, mmdl
[3] );
157 m4x3_expand( mmdl
, m4mdl
);
158 m4x4_mul( pass
->cam
->mtx_prev
.pv
, m4mdl
, m4mdl
);
160 pass
->fn_set_mdl( mmdl
);
161 pass
->fn_set_uPvmPrev( m4mdl
);
163 mdl_draw_submesh( sm
);
171 void world_render_both_stages( world_instance
*world
, struct world_pass
*pass
)
173 mesh_bind( &world
->mesh_geo
);
174 pass
->geo_type
= k_geo_type_solid
;
175 world_render_if( world
, pass
);
177 glDisable( GL_CULL_FACE
);
178 mesh_bind( &world
->mesh_no_collide
);
179 pass
->geo_type
= k_geo_type_nonsolid
;
180 world_render_if( world
, pass
);
181 glEnable( GL_CULL_FACE
);
184 VG_STATIC
void bindpoint_diffuse_texture1( world_instance
*world
,
185 struct world_surface
*mat
)
188 glActiveTexture( GL_TEXTURE1
);
189 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
192 VG_STATIC
void render_world_vb( world_instance
*world
, camera
*cam
)
194 shader_scene_vertex_blend_use();
195 shader_scene_vertex_blend_uTexGarbage(0);
196 shader_scene_vertex_blend_uTexGradients(1);
197 world_link_lighting_ub( world
, _shader_scene_vertex_blend
.id
);
198 world_bind_position_texture( world
, _shader_scene_vertex_blend
.id
,
199 _uniform_scene_vertex_blend_g_world_depth
, 2 );
200 world_bind_light_array( world
, _shader_scene_vertex_blend
.id
,
201 _uniform_scene_vertex_blend_uLightsArray
, 3 );
202 world_bind_light_index( world
, _shader_scene_vertex_blend
.id
,
203 _uniform_scene_vertex_blend_uLightsIndex
, 4 );
205 glActiveTexture( GL_TEXTURE0
);
206 glBindTexture( GL_TEXTURE_2D
, tex_terrain_noise
);
208 shader_scene_vertex_blend_uPv( cam
->mtx
.pv
);
209 shader_scene_vertex_blend_uCamera( cam
->transform
[3] );
211 struct world_pass pass
= {
212 .shader
= k_shader_standard_vertex_blend
,
214 .fn_bind_textures
= bindpoint_diffuse_texture1
,
215 .fn_set_mdl
= shader_scene_vertex_blend_uMdl
,
216 .fn_set_uPvmPrev
= shader_scene_vertex_blend_uPvmPrev
,
219 world_render_both_stages( world
, &pass
);
222 VG_STATIC
void render_world_standard( world_instance
*world
, camera
*cam
)
224 shader_scene_standard_use();
225 shader_scene_standard_uTexGarbage(0);
226 shader_scene_standard_uTexMain(1);
227 shader_scene_standard_uPv( cam
->mtx
.pv
);
229 world_link_lighting_ub( world
, _shader_scene_standard
.id
);
230 world_bind_position_texture( world
, _shader_scene_standard
.id
,
231 _uniform_scene_standard_g_world_depth
, 2 );
232 world_bind_light_array( world
, _shader_scene_standard
.id
,
233 _uniform_scene_standard_uLightsArray
, 3 );
234 world_bind_light_index( world
, _shader_scene_standard
.id
,
235 _uniform_scene_standard_uLightsIndex
, 4 );
237 bind_terrain_noise();
238 shader_scene_standard_uCamera( cam
->transform
[3] );
240 struct world_pass pass
= {
241 .shader
= k_shader_standard
,
243 .fn_bind_textures
= bindpoint_diffuse_texture1
,
244 .fn_set_mdl
= shader_scene_standard_uMdl
,
245 .fn_set_uPvmPrev
= shader_scene_standard_uPvmPrev
,
248 world_render_both_stages( world
, &pass
);
251 VG_STATIC
void render_world_alphatest( world_instance
*world
, camera
*cam
)
253 shader_scene_standard_alphatest_use();
254 shader_scene_standard_alphatest_uTexGarbage(0);
255 shader_scene_standard_alphatest_uTexMain(1);
256 shader_scene_standard_alphatest_uPv( cam
->mtx
.pv
);
258 world_link_lighting_ub( world
, _shader_scene_standard_alphatest
.id
);
259 world_bind_position_texture( world
, _shader_scene_standard_alphatest
.id
,
260 _uniform_scene_standard_alphatest_g_world_depth
, 2 );
261 world_bind_light_array( world
, _shader_scene_standard_alphatest
.id
,
262 _uniform_scene_standard_alphatest_uLightsArray
, 3 );
263 world_bind_light_index( world
, _shader_scene_standard_alphatest
.id
,
264 _uniform_scene_standard_alphatest_uLightsIndex
, 4 );
267 bind_terrain_noise();
270 shader_scene_standard_alphatest_uCamera( cam
->transform
[3] );
272 glDisable(GL_CULL_FACE
);
274 struct world_pass pass
= {
275 .shader
= k_shader_standard_cutout
,
277 .fn_bind_textures
= bindpoint_diffuse_texture1
,
278 .fn_set_mdl
= shader_scene_standard_alphatest_uMdl
,
279 .fn_set_uPvmPrev
= shader_scene_standard_alphatest_uPvmPrev
,
282 world_render_both_stages( world
, &pass
);
284 glEnable(GL_CULL_FACE
);
287 VG_STATIC
void bindpoint_terrain( world_instance
*world
,
288 struct world_surface
*mat
)
290 glActiveTexture( GL_TEXTURE1
);
291 glBindTexture( GL_TEXTURE_2D
, world
->textures
[ mat
->info
.tex_diffuse
] );
293 shader_scene_terrain_uSandColour( mat
->info
.colour
);
294 shader_scene_terrain_uBlendOffset( mat
->info
.colour1
);
297 VG_STATIC
void render_terrain( world_instance
*world
, camera
*cam
)
299 shader_scene_terrain_use();
300 shader_scene_terrain_uTexGarbage(0);
301 shader_scene_terrain_uTexGradients(1);
303 world_link_lighting_ub( world
, _shader_scene_terrain
.id
);
304 world_bind_position_texture( world
, _shader_scene_terrain
.id
,
305 _uniform_scene_terrain_g_world_depth
, 2 );
306 world_bind_light_array( world
, _shader_scene_terrain
.id
,
307 _uniform_scene_terrain_uLightsArray
, 3 );
308 world_bind_light_index( world
, _shader_scene_terrain
.id
,
309 _uniform_scene_terrain_uLightsIndex
, 4 );
311 glActiveTexture( GL_TEXTURE0
);
312 glBindTexture( GL_TEXTURE_2D
, tex_terrain_noise
);
314 shader_scene_terrain_uPv( cam
->mtx
.pv
);
315 shader_scene_terrain_uCamera( cam
->transform
[3] );
317 struct world_pass pass
= {
318 .shader
= k_shader_terrain_blend
,
320 .fn_bind_textures
= bindpoint_terrain
,
321 .fn_set_mdl
= shader_scene_terrain_uMdl
,
322 .fn_set_uPvmPrev
= shader_scene_terrain_uPvmPrev
,
325 world_render_both_stages( world
, &pass
);
328 VG_STATIC
void render_sky( world_instance
*world
, camera
*cam
)
331 * Modify matrix to remove clipping and view translation
338 m4x4_copy( cam
->mtx
.v
, v
);
339 m4x4_copy( cam
->mtx_prev
.v
, v_prev
);
341 v3_zero( v_prev
[3] );
343 m4x4_copy( cam
->mtx
.p
, pv
);
344 m4x4_copy( cam
->mtx_prev
.p
, pv_prev
);
345 m4x4_reset_clipping( pv
, cam
->farz
, cam
->nearz
);
346 m4x4_reset_clipping( pv_prev
, cam
->farz
, cam
->nearz
);
348 m4x4_mul( pv
, v
, pv
);
349 m4x4_mul( pv_prev
, v_prev
, pv_prev
);
351 m4x3f identity_matrix
;
352 m4x3_identity( identity_matrix
);
357 shader_model_sky_use();
358 shader_model_sky_uMdl( identity_matrix
);
359 shader_model_sky_uPv( pv
);
360 shader_model_sky_uPvmPrev( pv_prev
);
361 shader_model_sky_uTexGarbage(0);
362 world_link_lighting_ub( world
, _shader_model_sky
.id
);
364 glActiveTexture( GL_TEXTURE0
);
365 glBindTexture( GL_TEXTURE_2D
, tex_terrain_noise
);
367 glDepthMask( GL_FALSE
);
368 glDisable( GL_DEPTH_TEST
);
370 mesh_bind( &world_global
.skydome
);
371 mesh_draw( &world_global
.skydome
);
373 glEnable( GL_DEPTH_TEST
);
374 glDepthMask( GL_TRUE
);
377 VG_STATIC
void render_world_gates( world_instance
*world
, camera
*cam
,
380 float closest
= INFINITY
;
381 struct ent_gate
*gate
= NULL
;
383 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_gate
); i
++ ){
384 ent_gate
*gi
= mdl_arritm( &world
->ent_gate
, i
);
386 if( gi
->type
== k_gate_type_unlinked
)
389 float dist
= v3_dist2( gi
->co
[0], cam
->transform
[3] );
391 vg_line_pt3( gi
->co
[0], 0.25f
, VG__BLUE
);
393 if( dist
< closest
){
400 /* should really be set in fixed update since its used in the physics
401 * of most systems. too bad! */
402 world
->rendering_gate
= gate
;
404 if( gate
->type
== k_gate_type_teleport
){
405 render_gate( world
, gate
, cam
, layer_depth
);
407 else if( gate
->type
== k_gate_type_nonlocel
){
408 world_instance
*dest_world
= &world_global
.worlds
[ gate
->target
];
409 render_gate( dest_world
, gate
, cam
, layer_depth
);
412 world
->rendering_gate
= NULL
;
416 VG_STATIC
void world_prerender( world_instance
*world
)
418 static double g_time
= 0.0;
419 g_time
+= vg
.time_delta
* (1.0/(k_day_length
*60.0));
421 struct ub_world_lighting
*state
= &world
->ub_lighting
;
423 state
->g_time
= g_time
;
424 state
->g_realtime
= vg
.time
;
425 state
->g_debug_indices
= k_debug_light_indices
;
426 state
->g_light_preview
= k_light_preview
;
427 state
->g_debug_complexity
= k_debug_light_complexity
;
428 state
->g_time_of_day
= vg_fractf( g_time
);
429 state
->g_day_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 2.0f
);
430 state
->g_sunset_phase
= cosf( state
->g_time_of_day
* VG_PIf
* 4.0f
+ VG_PIf
);
432 state
->g_day_phase
= state
->g_day_phase
* 0.5f
+ 0.5f
;
433 state
->g_sunset_phase
= powf( state
->g_sunset_phase
* 0.5f
+ 0.5f
, 6.0f
);
435 float a
= state
->g_time_of_day
* VG_PIf
* 2.0f
;
436 state
->g_sun_dir
[0] = sinf( a
);
437 state
->g_sun_dir
[1] = cosf( a
);
438 state
->g_sun_dir
[2] = 0.2f
;
439 v3_normalize( state
->g_sun_dir
);
442 world
->probabilities
[ k_probability_curve_constant
] = 1.0f
;
444 float dp
= state
->g_day_phase
;
446 world
->probabilities
[ k_probability_curve_wildlife_day
] =
447 (dp
*dp
*0.8f
+state
->g_sunset_phase
)*0.8f
;
448 world
->probabilities
[ k_probability_curve_wildlife_night
] =
449 1.0f
-powf(fabsf((state
->g_time_of_day
-0.5f
)*5.0f
),5.0f
);
452 glBindBuffer( GL_UNIFORM_BUFFER
, world
->ubo_lighting
);
453 glBufferSubData( GL_UNIFORM_BUFFER
, 0,
454 sizeof(struct ub_world_lighting
), &world
->ub_lighting
);
457 VG_STATIC
void render_world( world_instance
*world
, camera
*cam
,
460 render_sky( world
, cam
);
462 render_world_routes( world
, cam
, layer_depth
);
463 render_world_standard( world
, cam
);
464 render_world_vb( world
, cam
);
465 render_world_alphatest( world
, cam
);
466 render_terrain( world
, cam
);
470 float min_dist
= INFINITY
;
472 if( !mdl_arrcount( &world
->ent_route
) )
475 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_route
); i
++ ){
476 ent_route
*route
= mdl_arritm( &world
->ent_route
, i
);
477 float dist
= v3_dist2( route
->board_transform
[3], cam
->pos
);
479 if( dist
< min_dist
){
485 ent_route
*route
= mdl_arritm( &world
->ent_route
, closest
);
486 sfd_render( world
, cam
, route
->board_transform
);
489 VG_STATIC
void render_world_depth( world_instance
*world
, camera
*cam
)
491 m4x3f identity_matrix
;
492 m4x3_identity( identity_matrix
);
494 shader_scene_depth_use();
495 shader_scene_depth_uCamera( cam
->transform
[3] );
496 shader_scene_depth_uPv( cam
->mtx
.pv
);
497 shader_scene_depth_uPvmPrev( cam
->mtx_prev
.pv
);
498 shader_scene_depth_uMdl( identity_matrix
);
499 world_link_lighting_ub( world
, _shader_scene_depth
.id
);
501 mesh_bind( &world
->mesh_geo
);
502 mesh_draw( &world
->mesh_geo
);
505 VG_STATIC
void render_world_position( world_instance
*world
, camera
*cam
)
507 m4x3f identity_matrix
;
508 m4x3_identity( identity_matrix
);
510 shader_scene_position_use();
511 shader_scene_position_uCamera( cam
->transform
[3] );
512 shader_scene_position_uPv( cam
->mtx
.pv
);
513 shader_scene_position_uPvmPrev( cam
->mtx_prev
.pv
);
514 shader_scene_position_uMdl( identity_matrix
);
515 world_link_lighting_ub( world
, _shader_scene_position
.id
);
517 mesh_bind( &world
->mesh_geo
);
518 mesh_draw( &world
->mesh_geo
);
521 #endif /* WORLD_RENDER_H */