[gl] Implement screen warping for liquids

It's not the most efficient code (uses sin() directly), but at least it
works (and with about 75% cpu headroom at 72fps on my machine).
This commit is contained in:
Bill Currie 2022-03-26 18:13:37 +09:00
parent a0adca011f
commit 12776e487a
3 changed files with 98 additions and 4 deletions

View file

@ -56,4 +56,7 @@ void gl_R_AddTexture (struct texture_s *tx);
void gl_R_ClearTextures (void);
void gl_R_InitSurfaceChains (struct mod_brush_s *brush);
struct framebuffer_s;
void gl_WarpScreen (struct framebuffer_s *fb);
#endif // __QF_GL_rsurf_h

View file

@ -31,12 +31,13 @@
#include "QF/cvar.h"
#include "QF/sys.h"
#include "r_internal.h"
#include "QF/GL/defines.h"
#include "QF/GL/funcs.h"
#include "QF/GL/qf_rsurf.h"
#include "r_internal.h"
#include "vid_gl.h"
// speed up sin calculations - Ed
static float turbsin[] = {
# include "gl_warp_sin.h"
@ -81,3 +82,59 @@ GL_EmitWaterPolys (msurface_t *surf)
qfglEnd ();
}
}
const float S = 0.15625;
const float F = 2.5;
const float A = 0.01;
static void
warp_uv (float *uv, float time)
{
float p1 = (time * S + F * uv[1]) * 2 * M_PI;
float p2 = (time * S + F * uv[0]) * 2 * M_PI;
uv[0] = uv[0] * (1 - 2 * A) + A * (1 + sin (p1));
uv[1] = uv[1] * (1 - 2 * A) + A * (1 + sin (p2));
}
void
gl_WarpScreen (framebuffer_t *fb)
{
gl_framebuffer_t *buffer = fb->buffer;
qfglMatrixMode (GL_PROJECTION);
qfglLoadIdentity ();
qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999);
qfglMatrixMode (GL_MODELVIEW);
qfglLoadIdentity ();
qfglColor3ubv (color_white);
qfglDisable (GL_DEPTH_TEST);
qfglFrontFace (GL_CCW);
qfglBindTexture (GL_TEXTURE_2D, buffer->color);
int base_x = r_refdef.vrect.x;
int base_y = r_refdef.vrect.y;
int width = r_refdef.vrect.width;
int height = r_refdef.vrect.height;
float time = vr_data.realtime;
for (int y = 0; y < height; y += 40) {
qfglBegin (GL_QUAD_STRIP);
for (int x = 0; x <= width; x+= 40) {
int y2 = y + 40;
int xy1[] = { base_x + x, base_y + y };
int xy2[] = { base_x + x, base_y + y2};
float uv1[] = { (float) x / width, 1 - (float) y / height };
float uv2[] = { (float) x / width, 1 - (float) y2 / height };
warp_uv (uv1, time);
warp_uv (uv2, time);
qfglTexCoord2fv (uv2);
qfglVertex2iv (xy2);
qfglTexCoord2fv (uv1);
qfglVertex2iv (xy1);
}
qfglEnd ();
}
}

View file

@ -276,7 +276,7 @@ gl_post_process (framebuffer_t *src)
if (scr_fisheye->int_val) {
gl_FisheyeScreen (src);
} else if (r_dowarp) {
//gl_WarpScreen (src);
gl_WarpScreen (src);
}
}
@ -367,7 +367,41 @@ gl_create_cube_map (int side)
static framebuffer_t *
gl_create_frame_buffer (int width, int height)
{
Sys_Error ("not implemented");
size_t size = sizeof (framebuffer_t) + sizeof (gl_framebuffer_t);
framebuffer_t *fb = malloc (size);
fb->width = width;
fb->height = height;
__auto_type buffer = (gl_framebuffer_t *) &fb[1];
fb->buffer = buffer;
qfglGenFramebuffers (1, &buffer->handle);
GLuint tex[2];
qfglGenTextures (2, tex);
buffer->color = tex[0];
buffer->depth = tex[1];
qfglBindTexture (GL_TEXTURE_2D, buffer->color);
qfglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qfglBindTexture (GL_TEXTURE_2D, buffer->depth);
qfglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qfglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, buffer->color, 0);
qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, buffer->depth, 0);
qfglBindFramebuffer (GL_FRAMEBUFFER, 0);
return fb;
}
static void