move location of main camera to g_render
[carveJwlIkooP6JGAAIwe30JlM.git] / world_water.c
1 /*
2 * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #include "world_water.h"
6 #include "world_render.h"
7 #include "render.h"
8 #include "shaders/scene_water.h"
9 #include "shaders/scene_water_fast.h"
10 #include "scene.h"
11 #include "player.h"
12 #include "player_walk.h"
13 #include "player_dead.h"
14
15 struct world_water world_water;
16
17 void world_water_init(void)
18 {
19 vg_info( "world_water_init\n" );
20
21 vg_tex2d_load_qoi_async_file( "textures/water_surf.qoi",
22 VG_TEX2D_LINEAR|VG_TEX2D_REPEAT,
23 &world_water.tex_water_surf );
24
25 vg_success( "done\n" );
26 }
27
28 void water_set_surface( world_instance *world, float height )
29 {
30 world->water.height = height;
31 v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane );
32 }
33
34 void world_link_lighting_ub( world_instance *world, GLuint shader );
35 void world_bind_position_texture( world_instance *world,
36 GLuint shader, GLuint location,
37 int slot );
38 void world_bind_light_array( world_instance *world,
39 GLuint shader, GLuint location,
40 int slot );
41 void world_bind_light_index( world_instance *world,
42 GLuint shader, GLuint location,
43 int slot );
44
45 /*
46 * Does not write motion vectors
47 */
48 void render_water_texture( world_instance *world, vg_camera *cam )
49 {
50 if( !world->water.enabled || (vg.quality_profile == k_quality_profile_low) )
51 return;
52
53 /* Draw reflection buffa */
54 vg_framebuffer_bind( g_render.fb_water_reflection, k_render_scale );
55 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
56
57 /*
58 * Create flipped view matrix. Don't care about motion vectors
59 */
60 float cam_height = cam->transform[3][1] - world->water.height;
61
62 vg_camera water_cam;
63 water_cam.farz = cam->farz;
64 water_cam.nearz = cam->nearz;
65 v3_copy( cam->transform[3], water_cam.transform[3] );
66 water_cam.transform[3][1] -= 2.0f * cam_height;
67
68 m3x3f flip;
69 m3x3_identity( flip );
70 flip[1][1] = -1.0f;
71 m3x3_mul( flip, cam->transform, water_cam.transform );
72
73 vg_camera_update_view( &water_cam );
74
75 /*
76 * Create clipped projection
77 */
78 v4f clippa = { 0.0f, 1.0f, 0.0f, world->water.height-0.1f };
79 m4x3_mulp( water_cam.transform_inverse, clippa, clippa );
80 clippa[3] *= -1.0f;
81
82 m4x4_copy( cam->mtx.p, water_cam.mtx.p );
83 m4x4_clip_projection( water_cam.mtx.p, clippa );
84
85 vg_camera_finalize( &water_cam );
86
87 /*
88 * Draw world
89 */
90 glEnable( GL_DEPTH_TEST );
91 glDisable( GL_BLEND );
92 glCullFace( GL_FRONT );
93 render_world( world, &water_cam, 0, 1, 0, 1 );
94 glCullFace( GL_BACK );
95
96 /*
97 * Create beneath view matrix
98 */
99 vg_camera beneath_cam;
100 vg_framebuffer_bind( g_render.fb_water_beneath, k_render_scale );
101 glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
102 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
103
104 m4x3_copy( cam->transform, beneath_cam.transform );
105 vg_camera_update_view( &beneath_cam );
106
107 float bias = -(cam->transform[3][1]-world->water.height)*0.1f;
108
109 v4f clippb = { 0.0f, -1.0f, 0.0f, -(world->water.height) + bias };
110 m4x3_mulp( beneath_cam.transform_inverse, clippb, clippb );
111 clippb[3] *= -1.0f;
112
113 m4x4_copy( cam->mtx.p, beneath_cam.mtx.p );
114 m4x4_clip_projection( beneath_cam.mtx.p, clippb );
115 vg_camera_finalize( &beneath_cam );
116
117 glEnable( GL_DEPTH_TEST );
118 glDisable( GL_BLEND );
119 render_world_depth( world, &beneath_cam );
120 //glViewport( 0,0, g_render_x, g_render_y );
121 }
122
123 void render_water_surface( world_instance *world, vg_camera *cam )
124 {
125 if( !world->water.enabled )
126 return;
127
128 if( vg.quality_profile == k_quality_profile_high )
129 {
130 /* Draw surface */
131 shader_scene_water_use();
132
133 vg_framebuffer_bind_texture( g_render.fb_water_reflection, 0, 0 );
134 shader_scene_water_uTexMain( 0 );
135
136 glActiveTexture( GL_TEXTURE1 );
137 glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
138 shader_scene_water_uTexDudv( 1 );
139
140 shader_scene_water_uInvRes( (v2f){
141 1.0f / (float)vg.window_x,
142 1.0f / (float)vg.window_y });
143
144 WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water );
145
146 vg_framebuffer_bind_texture( g_render.fb_water_beneath, 0, 5 );
147 shader_scene_water_uTexBack( 5 );
148 shader_scene_water_uTime( world_static.time );
149 shader_scene_water_uCamera( cam->transform[3] );
150 shader_scene_water_uSurfaceY( world->water.height );
151
152 shader_scene_water_uPv( cam->mtx.pv );
153 shader_scene_water_uPvmPrev( cam->mtx_prev.pv );
154
155 m4x3f full;
156 m4x3_identity( full );
157 shader_scene_water_uMdl( full );
158
159 glEnable(GL_BLEND);
160 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
161 glBlendEquation(GL_FUNC_ADD);
162
163 mesh_bind( &world->mesh_no_collide );
164
165 for( int i=0; i<world->surface_count; i++ )
166 {
167 struct world_surface *mat = &world->surfaces[i];
168 struct shader_props_water *props = mat->info.props.compiled;
169
170 if( mat->info.shader == k_shader_water )
171 {
172 shader_scene_water_uShoreColour( props->shore_colour );
173 shader_scene_water_uOceanColour( props->deep_colour );
174 shader_scene_water_uFresnel( props->fresnel );
175 shader_scene_water_uWaterScale( props->water_sale );
176 shader_scene_water_uWaveSpeed( props->wave_speed );
177
178 mdl_draw_submesh( &mat->sm_no_collide );
179 }
180 }
181
182 glDisable(GL_BLEND);
183 }
184 else if( (vg.quality_profile == k_quality_profile_low) ||
185 (vg.quality_profile == k_quality_profile_min) )
186 {
187 shader_scene_water_fast_use();
188
189 glActiveTexture( GL_TEXTURE1 );
190 glBindTexture( GL_TEXTURE_2D, world_water.tex_water_surf );
191 shader_scene_water_fast_uTexDudv( 1 );
192
193 shader_scene_water_fast_uTime( world_static.time );
194 shader_scene_water_fast_uCamera( cam->transform[3] );
195 shader_scene_water_fast_uSurfaceY( world->water.height );
196
197 WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, scene_water_fast );
198
199 m4x3f full;
200 m4x3_identity( full );
201 shader_scene_water_fast_uMdl( full );
202 shader_scene_water_fast_uPv( cam->mtx.pv );
203 shader_scene_water_fast_uPvmPrev( cam->mtx_prev.pv );
204
205 glEnable(GL_BLEND);
206 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
207 glBlendEquation(GL_FUNC_ADD);
208
209 mesh_bind( &world->mesh_no_collide );
210
211 for( int i=0; i<world->surface_count; i++ )
212 {
213 struct world_surface *mat = &world->surfaces[i];
214 struct shader_props_water *props = mat->info.props.compiled;
215
216 if( mat->info.shader == k_shader_water )
217 {
218 shader_scene_water_fast_uShoreColour( props->shore_colour );
219 shader_scene_water_fast_uOceanColour( props->deep_colour );
220
221 mdl_draw_submesh( &mat->sm_no_collide );
222 }
223 }
224
225 glDisable(GL_BLEND);
226 }
227 }
228
229 static void world_water_drown(void)
230 {
231 if( localplayer.drowned ) return;
232 player__networked_sfx( k_player_subsystem_walk, 32,
233 k_player_walk_soundeffect_splash,
234 localplayer.rb.co, 1.0f );
235 vg_info( "player fell of due to walking into walker\n" );
236 localplayer.drowned = 1;
237 player__dead_transition( k_player_die_type_generic );
238 }
239
240 bool world_water_player_safe( world_instance *world, f32 allowance )
241 {
242 if( !world->water.enabled ) return 1;
243 if( world->info.flags & 0x2 ) return 1;
244
245 if( localplayer.rb.co[1]+allowance < world->water.height )
246 {
247 world_water_drown();
248 return 0;
249 }
250
251 return 1;
252 }
253
254 entity_call_result ent_water_call( world_instance *world, ent_call *call )
255 {
256 if( call->function == 0 )
257 {
258 world_water_drown();
259 return k_entity_call_result_OK;
260 }
261
262 return k_entity_call_result_unhandled;
263 }