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