4 static void water_register(void);
5 static void water_init(void);
6 static void water_fb_resize(void);
7 static void water_set_surface( glmesh
*surf
, float height
);
8 static float water_height(void);
15 #include "shaders/water.h"
18 vg_tex2d tex_water_surf
= { .path
= "textures/water_surf.qoi" };
22 struct framebuffer fbreflect
, fbdepth
;
34 .fbreflect
= { .format
= GL_RGB
, .div
= 3 },
35 .fbdepth
= { .format
= GL_RGBA
, .div
= 4 }
38 static float water_height(void)
40 return wrender
.height
;
43 static void water_register(void)
45 shader_water_register();
48 static void water_init(void)
50 /* TODO: probably dont do this every time */
53 fb_init( &wrender
.fbreflect
);
54 fb_init( &wrender
.fbdepth
);
57 static void water_fb_resize(void)
59 if( !wrender
.enabled
)
62 fb_resize( &wrender
.fbreflect
);
63 fb_resize( &wrender
.fbdepth
);
67 static void water_compute_depth( boxf bounds
)
69 if( !wrender
.enabled
)
75 int const kres
= 1024;
78 vg_info( "Computing depth map\n" );
79 float *img
= malloc( kres
*kres
*sizeof(float) );
82 v3_add(bounds
[0],(v3f
){1.0f
,1.0f
,1.0f
},interior
[0]);
83 v3_sub(bounds
[1],(v3f
){1.0f
,1.0f
,1.0f
},interior
[1]);
86 v3_sub( interior
[1], interior
[0], volume
);
87 box_copy( interior
, wrender
.depthbounds
);
89 for( int y
=0; y
<kres
; y
++ )
91 for( int x
=0; x
<kres
; x
++ )
93 v3f pos
= { x
, 0.0f
, y
};
96 v3_divs( pos
, kres
+1, pos
);
97 v3_muladd( interior
[0], pos
, volume
, pos
);
102 float *dst
= &img
[ y
*kres
+x
];
104 if( ray_world( pos
, (v3f
){0.0f
,-1.0f
,0.0f
}, &hit
))
115 if( wrender
.depth_computed
)
116 glDeleteTextures( 1, &wrender
.depthmap
);
118 glGenTextures( 1, &wrender
.depthmap
);
119 glBindTexture( GL_TEXTURE_2D
, wrender
.depthmap
);
120 glTexImage2D( GL_TEXTURE_2D
, 0, GL_R32F
, kres
, kres
, 0,
121 GL_RED
, GL_FLOAT
, img
);
124 vg_tex2d_linear_mipmap();
127 wrender
.depth_computed
= 1;
129 vg_success( "Done.\n" );
133 static void water_set_surface( glmesh
*surf
, float height
)
136 wrender
.height
= height
;
138 v4_copy( (v4f
){ 0.0f
, 1.0f
, 0.0f
, height
}, wrender
.plane
);
141 static void render_water_texture( m4x3f camera
)
143 if( !wrender
.enabled
)
146 /* Draw reflection buffa */
147 fb_use( &wrender
.fbreflect
);
148 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
150 m4x3f new_cam
, inverse
;
151 v3_copy( camera
[3], new_cam
[3] );
152 new_cam
[3][1] -= 2.0f
* (camera
[3][1] - wrender
.height
);
155 m3x3_identity( flip
);
157 m3x3_mul( flip
, camera
, new_cam
);
161 m3x3_mulv( new_cam
, (v3f
){0.0f
,0.0f
,-1.0f
}, p0
);
162 v3_add( new_cam
[3], p0
, p0
);
163 vg_line( new_cam
[3], p0
, 0xffffffff );
166 vg_line_pt3( new_cam
[3], 0.3f
, 0xff00ffff );
168 m4x3_invert_affine( new_cam
, inverse
);
169 m4x3_expand( inverse
, view
);
171 v4f clippa
= { 0.0f
, 1.0f
, 0.0f
, wrender
.height
-0.1f
};
172 m4x3_mulp( inverse
, clippa
, clippa
);
176 m4x4_projection( projection
,
178 (float)vg_window_x
/ (float)vg_window_y
,
180 plane_clip_projection( projection
, clippa
);
181 m4x4_mul( projection
, view
, projection
);
183 glCullFace( GL_FRONT
);
184 render_world( projection
, new_cam
);
185 glCullFace( GL_BACK
);
188 /* Draw beneath texture */
189 fb_use( &wrender
.fbdepth
);
190 glClear( GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT
);
192 m4x3_invert_affine( camera
, inverse
);
193 m4x3_expand( inverse
, view
);
195 float bias
= -(camera
[3][1]-wrender
.height
)*0.1f
;
196 v4f clippb
= { 0.0f
, -1.0f
, 0.0f
, -(wrender
.height
) + bias
};
197 m4x3_mulp( inverse
, clippb
, clippb
);
200 m4x4_projection( projection
,
202 (float)vg_window_x
/ (float)vg_window_y
,
205 plane_clip_projection( projection
, clippb
);
206 m4x4_mul( projection
, view
, projection
);
207 render_world_depth( projection
, camera
);
209 glViewport( 0, 0, vg_window_x
, vg_window_y
);
212 static void render_water_surface( m4x4f pv
, m4x3f camera
)
214 if( !wrender
.enabled
)
220 fb_bindtex( &wrender
.fbreflect
, 0 );
221 shader_water_uTexMain( 0 );
223 vg_tex2d_bind( &tex_water_surf
, 1 );
224 shader_water_uTexDudv( 1 );
225 shader_water_uInvRes( (v2f
){
226 1.0f
/ (float)vg_window_x
,
227 1.0f
/ (float)vg_window_y
});
229 shader_link_standard_ub( _shader_water
.id
, 2 );
231 fb_bindtex( &wrender
.fbdepth
, 3 );
232 shader_water_uTexBack( 3 );
233 shader_water_uTime( vg_time
);
234 shader_water_uCamera( camera
[3] );
235 shader_water_uSurfaceY( wrender
.height
);
237 shader_water_uPv( pv
);
240 m4x3_identity( full
);
241 full
[3][1] = wrender
.height
;
243 shader_water_uMdl( full
);
246 glBlendFunc(GL_SRC_ALPHA
,GL_ONE_MINUS_SRC_ALPHA
);
247 glBlendEquation(GL_FUNC_ADD
);
249 mesh_bind( &wrender
.mdl
);
250 mesh_draw( &wrender
.mdl
);