now we're doing a bunch of them
[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 render_world_depth( world_instance *world, camera *cam );
96
97 /*
98 * Rendering
99 */
100
101 VG_STATIC void bind_terrain_noise(void)
102 {
103 vg_tex2d_bind( &tex_terrain_noise, 0 );
104 }
105
106 typedef void (*func_bind_point)( world_instance *world,
107 struct world_material *mat );
108
109 VG_STATIC void world_render_if( world_instance *world,
110 enum mdl_shader shader,
111 enum geo_type geo_type,
112 func_bind_point bind_point )
113 {
114
115 for( int i=0; i<world->material_count; i++ )
116 {
117 struct world_material *mat = &world->materials[i];
118
119 if( mat->info.shader == shader )
120 {
121 mdl_submesh *sm;
122
123 if( geo_type == k_geo_type_solid )
124 sm = &mat->sm_geo;
125 else
126 sm = &mat->sm_no_collide;
127
128 if( !sm->indice_count )
129 continue;
130
131 bind_point( world, mat );
132 mdl_draw_submesh( sm );
133 }
134 }
135 }
136
137 VG_STATIC
138 void world_render_both_stages( world_instance *world,
139 enum mdl_shader shader,
140 func_bind_point bind_point )
141 {
142 mesh_bind( &world->mesh_geo );
143 world_render_if( world, shader, k_geo_type_solid, bind_point );
144
145 glDisable( GL_CULL_FACE );
146 mesh_bind( &world->mesh_no_collide );
147 world_render_if( world, shader, k_geo_type_nonsolid, bind_point );
148 glEnable( GL_CULL_FACE );
149 }
150
151 VG_STATIC void bindpoint_diffuse_texture1( world_instance *world,
152 struct world_material *mat )
153 {
154 glActiveTexture( GL_TEXTURE1 );
155 glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
156 }
157
158 VG_STATIC void render_world_vb( world_instance *world, camera *cam )
159 {
160 m4x3f identity_matrix;
161 m4x3_identity( identity_matrix );
162
163 shader_scene_vertex_blend_use();
164 shader_scene_vertex_blend_uTexGarbage(0);
165 shader_scene_vertex_blend_uTexGradients(1);
166 world_link_lighting_ub( world, _shader_scene_vertex_blend.id );
167 world_bind_position_texture( world, _shader_scene_vertex_blend.id,
168 _uniform_scene_vertex_blend_g_world_depth, 2 );
169 world_bind_light_array( world, _shader_scene_vertex_blend.id,
170 _uniform_scene_vertex_blend_uLightsArray, 3 );
171
172 vg_tex2d_bind( &tex_terrain_noise, 0 );
173
174 shader_scene_vertex_blend_uPv( cam->mtx.pv );
175 shader_scene_vertex_blend_uPvmPrev( cam->mtx_prev.pv );
176 shader_scene_vertex_blend_uMdl( identity_matrix );
177 shader_scene_vertex_blend_uCamera( cam->transform[3] );
178 shader_scene_vertex_blend_uBoard0( TEMP_BOARD_0 );
179 shader_scene_vertex_blend_uBoard1( TEMP_BOARD_1 );
180
181 world_render_both_stages( world, k_shader_standard_vertex_blend,
182 bindpoint_diffuse_texture1 );
183 }
184
185 VG_STATIC void render_world_standard( world_instance *world, camera *cam )
186 {
187 m4x3f identity_matrix;
188 m4x3_identity( identity_matrix );
189
190 shader_scene_standard_use();
191 shader_scene_standard_uTexGarbage(0);
192 shader_scene_standard_uTexMain(1);
193 shader_scene_standard_uPv( cam->mtx.pv );
194 shader_scene_standard_uPvmPrev( cam->mtx_prev.pv );
195
196 world_link_lighting_ub( world, _shader_scene_standard.id );
197 world_bind_position_texture( world, _shader_scene_standard.id,
198 _uniform_scene_standard_g_world_depth, 2 );
199 world_bind_light_array( world, _shader_scene_standard.id,
200 _uniform_scene_standard_uLightsArray, 3 );
201
202 bind_terrain_noise();
203
204 shader_scene_standard_uMdl( identity_matrix );
205 shader_scene_standard_uCamera( cam->transform[3] );
206 shader_scene_standard_uBoard0( TEMP_BOARD_0 );
207 shader_scene_standard_uBoard1( TEMP_BOARD_1 );
208
209 world_render_both_stages( world, k_shader_standard,
210 bindpoint_diffuse_texture1 );
211 }
212
213 VG_STATIC void render_world_alphatest( world_instance *world, camera *cam )
214 {
215 m4x3f identity_matrix;
216 m4x3_identity( identity_matrix );
217
218 shader_scene_standard_alphatest_use();
219 shader_scene_standard_alphatest_uTexGarbage(0);
220 shader_scene_standard_alphatest_uTexMain(1);
221 shader_scene_standard_alphatest_uPv( cam->mtx.pv );
222 shader_scene_standard_alphatest_uPvmPrev( cam->mtx_prev.pv );
223
224 world_link_lighting_ub( world, _shader_scene_standard_alphatest.id );
225 world_bind_position_texture( world, _shader_scene_standard_alphatest.id,
226 _uniform_scene_standard_alphatest_g_world_depth, 2 );
227 world_bind_light_array( world, _shader_scene_standard_alphatest.id,
228 _uniform_scene_standard_alphatest_uLightsArray, 3 );
229
230
231 bind_terrain_noise();
232
233 shader_scene_standard_alphatest_uMdl( identity_matrix );
234 shader_scene_standard_alphatest_uCamera( cam->transform[3] );
235 shader_scene_standard_alphatest_uBoard0( TEMP_BOARD_0 );
236 shader_scene_standard_alphatest_uBoard1( TEMP_BOARD_1 );
237
238 glDisable(GL_CULL_FACE);
239
240 world_render_both_stages( world, k_shader_standard_cutout,
241 bindpoint_diffuse_texture1 );
242
243 glEnable(GL_CULL_FACE);
244 }
245
246 VG_STATIC void bindpoint_terrain( world_instance *world,
247 struct world_material *mat )
248 {
249 glActiveTexture( GL_TEXTURE1 );
250 glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] );
251
252 shader_scene_terrain_uSandColour( mat->info.colour );
253 shader_scene_terrain_uBlendOffset( mat->info.colour1 );
254 }
255
256 VG_STATIC void render_terrain( world_instance *world, camera *cam )
257 {
258 m4x3f identity_matrix;
259 m4x3_identity( identity_matrix );
260
261 shader_scene_terrain_use();
262 shader_scene_terrain_uTexGarbage(0);
263 shader_scene_terrain_uTexGradients(1);
264
265 world_link_lighting_ub( world, _shader_scene_terrain.id );
266 world_bind_position_texture( world, _shader_scene_terrain.id,
267 _uniform_scene_terrain_g_world_depth, 2 );
268 world_bind_light_array( world, _shader_scene_terrain.id,
269 _uniform_scene_terrain_uLightsArray, 3 );
270
271 vg_tex2d_bind( &tex_terrain_noise, 0 );
272
273 shader_scene_terrain_uPv( cam->mtx.pv );
274 shader_scene_terrain_uPvmPrev( cam->mtx_prev.pv );
275
276 shader_scene_terrain_uMdl( identity_matrix );
277 shader_scene_terrain_uCamera( cam->transform[3] );
278 shader_scene_terrain_uBoard0( TEMP_BOARD_0 );
279 shader_scene_terrain_uBoard1( TEMP_BOARD_1 );
280
281 world_render_both_stages( world, k_shader_terrain_blend, bindpoint_terrain );
282 }
283
284 VG_STATIC void render_sky( camera *cam )
285 {
286 /*
287 * Modify matrix to remove clipping and view translation
288 */
289 m4x4f v,
290 v_prev,
291 pv,
292 pv_prev;
293
294 m4x4_copy( cam->mtx.v, v );
295 m4x4_copy( cam->mtx_prev.v, v_prev );
296 v3_zero( v[3] );
297 v3_zero( v_prev[3] );
298
299 m4x4_copy( cam->mtx.p, pv );
300 m4x4_copy( cam->mtx_prev.p, pv_prev );
301 m4x4_reset_clipping( pv, cam->farz, cam->nearz );
302 m4x4_reset_clipping( pv_prev, cam->farz, cam->nearz );
303
304 m4x4_mul( pv, v, pv );
305 m4x4_mul( pv_prev, v_prev, pv_prev );
306
307 m4x3f identity_matrix;
308 m4x3_identity( identity_matrix );
309
310 /*
311 * Draw
312 */
313 shader_model_sky_use();
314 shader_model_sky_uMdl( identity_matrix );
315 shader_model_sky_uPv( pv );
316 shader_model_sky_uPvmPrev( pv_prev );
317 shader_model_sky_uTexGarbage(0);
318 shader_model_sky_uTime( world_global.sky_time );
319
320 vg_tex2d_bind( &tex_terrain_noise, 0 );
321
322 glDepthMask( GL_FALSE );
323 glDisable( GL_DEPTH_TEST );
324
325 mesh_bind( &world_global.skydome );
326 mdl_draw_submesh( &world_global.dome_upper );
327
328 glEnable( GL_DEPTH_TEST );
329 glDepthMask( GL_TRUE );
330 }
331
332 VG_STATIC void render_world_gates( world_instance *world, camera *cam )
333 {
334 float closest = INFINITY;
335
336 struct teleport_gate *gate = NULL;
337 world_instance *dest_world = world;
338
339 for( int i=0; i<world->gate_count; i++ )
340 {
341 struct route_gate *rg = &world->gates[i];
342 float dist = v3_dist2( rg->gate.co[0], cam->transform[3] );
343
344 vg_line_pt3( rg->gate.co[0], 0.25f, VG__BLUE );
345
346 if( dist < closest )
347 {
348 closest = dist;
349 gate = &rg->gate;
350 dest_world = world;
351 }
352 }
353
354 for( int i=0; i<world->nonlocalgate_count; i++ )
355 {
356 struct nonlocal_gate *nlg = &world->nonlocal_gates[i];
357
358 if( !nlg->working )
359 {
360 vg_line_pt3( nlg->gate.co[0], 0.25f, VG__RED );
361 continue;
362 }
363 else
364 vg_line_pt3( nlg->gate.co[0], 0.25f, VG__GREEN );
365
366 float dist = v3_dist2( nlg->gate.co[0], cam->transform[3] );
367
368 if( dist < closest )
369 {
370 closest = dist;
371 gate = &nlg->gate;
372 dest_world = &world_global.worlds[ nlg->target_map_index ];
373 }
374 }
375
376 if( gate )
377 render_gate( dest_world, gate, cam );
378 }
379
380 VG_STATIC void render_world( world_instance *world, camera *cam )
381 {
382 render_sky( cam );
383
384 render_world_routes( world, cam );
385 render_world_standard( world, cam );
386 render_world_vb( world, cam );
387 render_world_alphatest( world, cam );
388 render_terrain( world, cam );
389
390 /* Render SFD's */
391 int closest = 0;
392 float min_dist = INFINITY;
393
394 if( !world->route_count )
395 return;
396
397 for( int i=0; i<world->route_count; i++ )
398 {
399 float dist = v3_dist2(world->routes[i].scoreboard_transform[3], cam->pos);
400
401 if( dist < min_dist )
402 {
403 min_dist = dist;
404 closest = i;
405 }
406 }
407
408 sfd_render( cam, world->routes[closest].scoreboard_transform );
409 }
410
411 VG_STATIC void render_world_depth( world_instance *world, camera *cam )
412 {
413 m4x3f identity_matrix;
414 m4x3_identity( identity_matrix );
415
416 shader_scene_depth_use();
417 shader_scene_depth_uCamera( cam->transform[3] );
418 shader_scene_depth_uPv( cam->mtx.pv );
419 shader_scene_depth_uPvmPrev( cam->mtx_prev.pv );
420 shader_scene_depth_uMdl( identity_matrix );
421 world_link_lighting_ub( world, _shader_scene_depth.id );
422
423 mesh_bind( &world->mesh_geo );
424 mesh_draw( &world->mesh_geo );
425 }
426
427 VG_STATIC void render_world_position( world_instance *world, camera *cam )
428 {
429 m4x3f identity_matrix;
430 m4x3_identity( identity_matrix );
431
432 shader_scene_position_use();
433 shader_scene_position_uCamera( cam->transform[3] );
434 shader_scene_position_uPv( cam->mtx.pv );
435 shader_scene_position_uPvmPrev( cam->mtx_prev.pv );
436 shader_scene_position_uMdl( identity_matrix );
437 world_link_lighting_ub( world, _shader_scene_position.id );
438
439 mesh_bind( &world->mesh_geo );
440 mesh_draw( &world->mesh_geo );
441 }
442
443 #endif /* WORLD_RENDER_H */