From 12776e487a1541758e5d702bf178bf9664e9fa21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 18:13:37 +0900 Subject: [PATCH] [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). --- include/QF/GL/qf_rsurf.h | 3 ++ libs/video/renderer/gl/gl_warp.c | 61 ++++++++++++++++++++++++++++- libs/video/renderer/vid_render_gl.c | 38 +++++++++++++++++- 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index f2f300f1e..8a2d012ad 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -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 diff --git a/libs/video/renderer/gl/gl_warp.c b/libs/video/renderer/gl/gl_warp.c index 3f08d83d7..4ae963cf7 100644 --- a/libs/video/renderer/gl/gl_warp.c +++ b/libs/video/renderer/gl/gl_warp.c @@ -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 (); + } +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index e1ccfe1e4..7d31c65d2 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -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