frame rate independence
[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 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 static void world_render_free(void*_)
37 {
38 vg_tex2d_free( (vg_tex2d *[]){ &tex_terrain_colours,
39 &tex_terrain_noise,
40 &tex_alphatest,
41 &tex_graffiti }, 4 );
42 }
43
44
45
46 static void render_world_depth( m4x4f projection, m4x3f camera );
47
48
49
50
51 /*
52 * Rendering
53 */
54
55 static void bind_terrain_textures(void)
56 {
57 vg_tex2d_bind( &tex_terrain_noise, 0 );
58 vg_tex2d_bind( &tex_terrain_colours, 1 );
59 }
60
61 static void render_world_vb( m4x4f projection, v3f camera )
62 {
63 m4x3f identity_matrix;
64 m4x3_identity( identity_matrix );
65
66 shader_vblend_use();
67 shader_vblend_uTexGarbage(0);
68 shader_vblend_uTexGradients(1);
69 shader_link_standard_ub( _shader_vblend.id, 2 );
70 bind_terrain_textures();
71
72 shader_vblend_uPv( projection );
73 shader_vblend_uMdl( identity_matrix );
74 shader_vblend_uCamera( camera );
75
76 scene_bind( &world.geo );
77 mdl_draw_submesh( &world.sm_geo_vb );
78
79 mesh_bind( &world.cars );
80
81 #if 0
82 for( int i=0; i<vg_list_size(world.van_man); i++ )
83 {
84 shader_vblend_uMdl( world.van_man[i].transform );
85 mdl_draw_submesh( &world.car_holden );
86 }
87 #endif
88 }
89
90 static void render_world_alphatest( m4x4f projection, v3f camera )
91 {
92 m4x3f identity_matrix;
93 m4x3_identity( identity_matrix );
94
95 shader_alphatest_use();
96 shader_alphatest_uTexGarbage(0);
97 shader_alphatest_uTexMain(1);
98 shader_link_standard_ub( _shader_alphatest.id, 2 );
99
100 vg_tex2d_bind( &tex_terrain_noise, 0 );
101 vg_tex2d_bind( &tex_alphatest, 1 );
102
103 shader_alphatest_uPv( projection );
104 shader_alphatest_uMdl( identity_matrix );
105 shader_alphatest_uCamera( camera );
106
107 glDisable(GL_CULL_FACE);
108 scene_bind( &world.foliage );
109 mdl_draw_submesh( &world.sm_foliage_alphatest );
110
111 vg_tex2d_bind( &tex_graffiti, 1 );
112 mdl_draw_submesh( &world.sm_graffiti );
113
114 glEnable(GL_CULL_FACE);
115 }
116
117 static void render_terrain( m4x4f projection, v3f camera )
118 {
119 m4x3f identity_matrix;
120 m4x3_identity( identity_matrix );
121
122 shader_terrain_use();
123 shader_terrain_uTexGarbage(0);
124 shader_terrain_uTexGradients(1);
125 shader_link_standard_ub( _shader_terrain.id, 2 );
126 bind_terrain_textures();
127
128 shader_terrain_uPv( projection );
129 shader_terrain_uMdl( identity_matrix );
130 shader_terrain_uCamera( camera );
131
132 scene_bind( &world.geo );
133 mdl_draw_submesh( &world.sm_terrain );
134 mdl_draw_submesh( &world.sm_geo_std_oob );
135 mdl_draw_submesh( &world.sm_geo_std );
136 mdl_draw_submesh( &world.sm_subworld );
137
138 /* TODO: Dont draw in reflection */
139 glDisable(GL_CULL_FACE);
140 scene_bind( &world.foliage );
141 mdl_draw_submesh( &world.sm_foliage_main );
142 glEnable(GL_CULL_FACE);
143 }
144
145 static void render_lowerdome( m4x3f camera )
146 {
147 m4x4f projection, full;
148 pipeline_projection( projection, 0.4f, 1000.0f );
149
150 m4x3f inverse;
151 m3x3_transpose( camera, inverse );
152 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
153 m4x3_expand( inverse, full );
154 m4x4_mul( projection, full, full );
155
156 m4x3f identity_matrix;
157 m4x3_identity( identity_matrix );
158
159 shader_planeinf_use();
160 shader_planeinf_uMdl(identity_matrix);
161 shader_planeinf_uPv(full);
162 shader_planeinf_uCamera(camera[3]);
163 shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f,0.0f} );
164
165 mdl_draw_submesh( &world.dome_lower );
166 }
167
168 static void render_sky(m4x3f camera)
169 {
170 m4x4f projection, full;
171 pipeline_projection( projection, 0.4f, 1000.0f );
172
173 m4x3f inverse;
174 m3x3_transpose( camera, inverse );
175 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
176 m4x3_expand( inverse, full );
177 m4x4_mul( projection, full, full );
178
179 m4x3f identity_matrix;
180 m4x3_identity( identity_matrix );
181
182 shader_sky_use();
183 shader_sky_uMdl(identity_matrix);
184 shader_sky_uPv(full);
185 shader_sky_uTexGarbage(0);
186 shader_sky_uTime( vg.time );
187
188 vg_tex2d_bind( &tex_terrain_noise, 0 );
189
190 glDepthMask( GL_FALSE );
191 glDisable( GL_DEPTH_TEST );
192
193 mesh_bind( &world.skydome );
194 mdl_draw_submesh( &world.dome_upper );
195
196 glEnable( GL_DEPTH_TEST );
197 glDepthMask( GL_TRUE );
198 }
199
200 static void render_world_gates( m4x4f projection, v3f playerco, m4x3f camera )
201 {
202 float closest = INFINITY;
203 int id = 0;
204
205 for( int i=0; i<world.routes.gate_count; i++ )
206 {
207 struct route_gate *rg = &world.routes.gates[i];
208 float dist = v3_dist2( rg->gate.co[0], camera[3] );
209
210 if( dist < closest )
211 {
212 closest = dist;
213 id = i;
214 }
215 }
216
217 render_gate( &world.routes.gates[id].gate, playerco, camera );
218 v3_lerp( world.render_gate_pos,
219 world.routes.gates[id].gate.co[0],
220 1.0f,
221 world.render_gate_pos );
222 }
223
224 static void render_world( m4x4f projection, m4x3f camera )
225 {
226 render_sky( camera );
227 render_world_routes( projection, camera[3] );
228 render_world_vb( projection, camera[3] );
229 render_world_alphatest( projection, camera[3] );
230 render_terrain( projection, camera[3] );
231
232 int closest = 0;
233 float min_dist = INFINITY;
234
235 for( int i=0; i<world.routes.route_count; i++ )
236 {
237 float dist = v3_dist2( world.routes.routes[i].scoreboard_transform[3],
238 camera[3] );
239
240 if( dist < min_dist )
241 {
242 min_dist = dist;
243 closest = i;
244 }
245 }
246
247 sfd_render( &world.sfd.tester, projection, camera[3],
248 world.routes.routes[closest].scoreboard_transform );
249 }
250
251 static void render_world_depth( m4x4f projection, m4x3f camera )
252 {
253 m4x3f identity_matrix;
254 m4x3_identity( identity_matrix );
255
256 shader_gpos_use();
257 shader_gpos_uCamera( camera[3] );
258 shader_gpos_uPv( projection );
259 shader_gpos_uMdl( identity_matrix );
260
261 scene_bind( &world.geo );
262 scene_draw( &world.geo );
263
264 #if 0
265 glDisable(GL_CULL_FACE);
266 scene_bind( &world.foliage );
267 scene_draw( &world.foliage );
268 glEnable(GL_CULL_FACE);
269 #endif
270 }
271
272 #endif /* WORLD_RENDER_H */