af20830cd0f6d388ca7abcdb58bba139769d5bf9
[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 vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
12 .flags = VG_TEXTURE_NEAREST };
13
14 VG_STATIC void world_render_init(void)
15 {
16 vg_info( "Loading default world textures\n" );
17
18 vg_acquire_thread_sync();
19 {
20 vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_noise }, 1 );
21 }
22 vg_release_thread_sync();
23 }
24
25 VG_STATIC void render_world_depth( camera *cam );
26
27 /*
28 * Rendering
29 */
30
31 VG_STATIC void bind_terrain_noise(void)
32 {
33 vg_tex2d_bind( &tex_terrain_noise, 0 );
34 }
35
36 VG_STATIC void world_render_if( enum mdl_shader shader,
37 enum geo_type geo_type,
38 void (*bind_point)(struct world_material *mat))
39 {
40
41 for( int i=0; i<world.material_count; i++ )
42 {
43 struct world_material *mat = &world.materials[i];
44
45 if( mat->info.shader == shader )
46 {
47 mdl_submesh *sm;
48
49 if( geo_type == k_geo_type_solid )
50 sm = &mat->sm_geo;
51 else
52 sm = &mat->sm_no_collide;
53
54 if( !sm->indice_count )
55 continue;
56
57 bind_point( mat );
58 mdl_draw_submesh( sm );
59 }
60 }
61 }
62
63 VG_STATIC void world_render_both_stages( enum mdl_shader shader,
64 void (*bind_point)(struct world_material *mat))
65 {
66 mesh_bind( &world.mesh_geo );
67 world_render_if( shader, k_geo_type_solid, bind_point );
68
69 glDisable( GL_CULL_FACE );
70 mesh_bind( &world.mesh_no_collide );
71 world_render_if( shader, k_geo_type_nonsolid, bind_point );
72 glEnable( GL_CULL_FACE );
73 }
74
75 VG_STATIC void bindpoint_diffuse_texture1( struct world_material *mat )
76 {
77 glActiveTexture( GL_TEXTURE1 );
78 glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] );
79 }
80
81 VG_STATIC void render_world_vb( camera *cam )
82 {
83 m4x3f identity_matrix;
84 m4x3_identity( identity_matrix );
85
86 shader_vblend_use();
87 shader_vblend_uTexGarbage(0);
88 shader_vblend_uTexGradients(1);
89 shader_link_standard_ub( _shader_vblend.id, 2 );
90 vg_tex2d_bind( &tex_terrain_noise, 0 );
91
92 shader_vblend_uPv( cam->mtx.pv );
93 shader_vblend_uPvmPrev( cam->mtx_prev.pv );
94 shader_vblend_uMdl( identity_matrix );
95 shader_vblend_uCamera( cam->transform[3] );
96
97 world_render_both_stages( k_shader_standard_vertex_blend,
98 bindpoint_diffuse_texture1 );
99 }
100
101 VG_STATIC void render_world_standard( camera *cam )
102 {
103 m4x3f identity_matrix;
104 m4x3_identity( identity_matrix );
105
106 shader_standard_use();
107 shader_standard_uTexGarbage(0);
108 shader_standard_uTexMain(1);
109 shader_standard_uPv( cam->mtx.pv );
110 shader_standard_uPvmPrev( cam->mtx_prev.pv );
111 shader_link_standard_ub( _shader_standard.id, 2 );
112 bind_terrain_noise();
113
114 shader_standard_uMdl( identity_matrix );
115 shader_standard_uCamera( cam->transform[3] );
116
117 world_render_both_stages( k_shader_standard,
118 bindpoint_diffuse_texture1 );
119 }
120
121 VG_STATIC void render_world_alphatest( camera *cam )
122 {
123 m4x3f identity_matrix;
124 m4x3_identity( identity_matrix );
125
126 shader_alphatest_use();
127 shader_alphatest_uTexGarbage(0);
128 shader_alphatest_uTexMain(1);
129 shader_alphatest_uPv( cam->mtx.pv );
130 shader_alphatest_uPvmPrev( cam->mtx_prev.pv );
131 shader_link_standard_ub( _shader_alphatest.id, 2 );
132 bind_terrain_noise();
133
134 shader_alphatest_uMdl( identity_matrix );
135 shader_alphatest_uCamera( cam->transform[3] );
136
137 glDisable(GL_CULL_FACE);
138
139 world_render_both_stages( k_shader_standard_cutout,
140 bindpoint_diffuse_texture1 );
141
142 glEnable(GL_CULL_FACE);
143 }
144
145 VG_STATIC void bindpoint_terrain( struct world_material *mat )
146 {
147 glActiveTexture( GL_TEXTURE1 );
148 glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] );
149
150 shader_terrain_uSandColour( mat->info.colour );
151 shader_terrain_uBlendOffset( mat->info.colour1 );
152 }
153
154 VG_STATIC void render_terrain( camera *cam )
155 {
156 m4x3f identity_matrix;
157 m4x3_identity( identity_matrix );
158
159 shader_terrain_use();
160 shader_terrain_uTexGarbage(0);
161 shader_terrain_uTexGradients(1);
162 shader_link_standard_ub( _shader_terrain.id, 2 );
163
164 vg_tex2d_bind( &tex_terrain_noise, 0 );
165
166 shader_terrain_uPv( cam->mtx.pv );
167 shader_terrain_uPvmPrev( cam->mtx_prev.pv );
168
169 shader_terrain_uMdl( identity_matrix );
170 shader_terrain_uCamera( cam->transform[3] );
171
172 world_render_both_stages( k_shader_terrain_blend, bindpoint_terrain );
173 }
174
175 VG_STATIC void render_sky( camera *cam )
176 {
177 /*
178 * Modify matrix to remove clipping and view translation
179 */
180 m4x4f v,
181 v_prev,
182 pv,
183 pv_prev;
184
185 m4x4_copy( cam->mtx.v, v );
186 m4x4_copy( cam->mtx_prev.v, v_prev );
187 v3_zero( v[3] );
188 v3_zero( v_prev[3] );
189
190 m4x4_copy( cam->mtx.p, pv );
191 m4x4_copy( cam->mtx_prev.p, pv_prev );
192 m4x4_reset_clipping( pv, cam->farz, cam->nearz );
193 m4x4_reset_clipping( pv_prev, cam->farz, cam->nearz );
194
195 m4x4_mul( pv, v, pv );
196 m4x4_mul( pv_prev, v_prev, pv_prev );
197
198 m4x3f identity_matrix;
199 m4x3_identity( identity_matrix );
200
201 /*
202 * Draw
203 */
204 shader_sky_use();
205 shader_sky_uMdl( identity_matrix );
206 shader_sky_uPv( pv );
207 shader_sky_uPvmPrev( pv_prev );
208 shader_sky_uTexGarbage(0);
209 shader_sky_uTime( world.sky_time );
210
211 vg_tex2d_bind( &tex_terrain_noise, 0 );
212
213 glDepthMask( GL_FALSE );
214 glDisable( GL_DEPTH_TEST );
215
216 mesh_bind( &world.skydome );
217 mdl_draw_submesh( &world.dome_upper );
218
219 glEnable( GL_DEPTH_TEST );
220 glDepthMask( GL_TRUE );
221 }
222
223 VG_STATIC void render_world_gates( camera *cam )
224 {
225 if( !world.gate_count )
226 return;
227
228 float closest = INFINITY;
229 int id = 0;
230
231 for( int i=0; i<world.gate_count; i++ )
232 {
233 struct route_gate *rg = &world.gates[i];
234 float dist = v3_dist2( rg->gate.co[0], cam->transform[3] );
235
236 if( dist < closest )
237 {
238 closest = dist;
239 id = i;
240 }
241 }
242
243 render_gate( &world.gates[id].gate, cam );
244 v3_lerp( world.render_gate_pos,
245 world.gates[id].gate.co[0],
246 1.0f,
247 world.render_gate_pos );
248 }
249
250 VG_STATIC void render_world( camera *cam )
251 {
252 render_sky( cam );
253
254 render_world_routes( cam );
255 render_world_standard( cam );
256 render_world_vb( cam );
257 render_world_alphatest( cam );
258 render_terrain( cam );
259
260 /* Render SFD's */
261 int closest = 0;
262 float min_dist = INFINITY;
263
264 if( !world.route_count )
265 return;
266
267 for( int i=0; i<world.route_count; i++ )
268 {
269 float dist = v3_dist2(world.routes[i].scoreboard_transform[3], cam->pos);
270
271 if( dist < min_dist )
272 {
273 min_dist = dist;
274 closest = i;
275 }
276 }
277
278 sfd_render( cam, world.routes[closest].scoreboard_transform );
279 }
280
281 VG_STATIC void render_world_depth( camera *cam )
282 {
283 m4x3f identity_matrix;
284 m4x3_identity( identity_matrix );
285
286 shader_gpos_use();
287 shader_gpos_uCamera( cam->transform[3] );
288 shader_gpos_uPv( cam->mtx.pv );
289 shader_gpos_uPvmPrev( cam->mtx_prev.pv );
290 shader_gpos_uMdl( identity_matrix );
291
292 mesh_bind( &world.mesh_geo );
293 mesh_draw( &world.mesh_geo );
294
295 #if 0
296 glDisable(GL_CULL_FACE);
297 scene_bind( &world.foliage );
298 scene_draw( &world.foliage );
299 glEnable(GL_CULL_FACE);
300 #endif
301 }
302
303 #endif /* WORLD_RENDER_H */