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