[glsl] Implement screen warp when in liquids

Finally, after a decade :P Looks pretty good, too, and is (almost)
properly scaled to the resolution (almost because the effect is a little
squashed, but I think the sw renderer does the same).
This commit is contained in:
Bill Currie 2022-03-25 01:24:38 +09:00
parent e263521330
commit 18aae8205e
9 changed files with 240 additions and 2 deletions

View file

@ -57,6 +57,8 @@ QFGL_NEED (void, glDepthMask, (GLboolean flag))
QFGL_NEED (void, glDepthRangef, (GLclampf zNear, GLclampf zFar))
QFGL_NEED (void, glDetachShader, (GLuint program, GLuint shader))
QFGL_NEED (void, glDisable, (GLenum cap))
QFGL_NEED (void, glCreateVertexArrays, (GLsizei n, GLuint *arrays))
QFGL_NEED (void, glBindVertexArray, (GLuint array))
QFGL_NEED (void, glDisableVertexAttribArray, (GLuint index))
QFGL_NEED (void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
QFGL_NEED (void, glDrawElements, (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices))

37
include/QF/GLSL/qf_warp.h Normal file
View file

@ -0,0 +1,37 @@
/*
qf_warp.h
GLSL screen warp
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/3/24
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_GLSL_qf_warp_h
#define __QF_GLSL_qf_warp_h
void glsl_InitWarp (void);
struct framebuffer_s;
void glsl_WarpScreen (struct framebuffer_s *fb);
#endif//__QF_GLSL_qf_warp_h

View file

@ -109,6 +109,7 @@ include_qf_glsl = \
include/QF/GLSL/qf_sprite.h \
include/QF/GLSL/qf_textures.h \
include/QF/GLSL/qf_vid.h \
include/QF/GLSL/qf_warp.h \
include/QF/GLSL/types.h
include_qf_input = \

View file

@ -118,6 +118,7 @@ libs_video_renderer_librender_glsl_la_SOURCES = \
libs/video/renderer/glsl/glsl_shader.c \
libs/video/renderer/glsl/glsl_sprite.c \
libs/video/renderer/glsl/glsl_textures.c \
libs/video/renderer/glsl/glsl_warp.c \
libs/video/renderer/glsl/qfglsl.c \
libs/video/renderer/glsl/quakeforge.glsl \
libs/video/renderer/glsl/vid_common_glsl.c

View file

@ -58,6 +58,7 @@
#include "QF/GLSL/qf_particles.h"
#include "QF/GLSL/qf_sprite.h"
#include "QF/GLSL/qf_textures.h"
#include "QF/GLSL/qf_warp.h"
#include "mod_internal.h"
#include "r_internal.h"
@ -211,6 +212,7 @@ glsl_R_Init (void)
glsl_R_InitIQM ();
glsl_R_InitSprites ();
glsl_R_InitParticles ();
glsl_InitWarp ();
Skin_Init ();
}

View file

@ -0,0 +1,114 @@
/*
glsl_warp.c
GLSL screen warp
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/3/24
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/cvar.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/GLSL/defines.h"
#include "QF/GLSL/funcs.h"
#include "QF/GLSL/qf_vid.h"
#include "QF/GLSL/qf_warp.h"
#include "r_internal.h"
#include "vid_gl.h"
static const char *warp_vert_effects[] =
{
"QuakeForge.Vertex.fstri",
0
};
static const char *warp_frag_effects[] =
{
"QuakeForge.Math.const",
"QuakeForge.Fragment.screen.warp",
0
};
static struct {
int program;
GLuint vao;
shaderparam_t screenTex;
shaderparam_t time;
} warp = {
.screenTex = {"screenTex", 1},
.time = {"time", 1},
};
void
glsl_InitWarp (void)
{
shader_t *vert_shader, *frag_shader;
int vert;
int frag;
vert_shader = GLSL_BuildShader (warp_vert_effects);
frag_shader = GLSL_BuildShader (warp_frag_effects);
vert = GLSL_CompileShader ("scrwarp.vert", vert_shader, GL_VERTEX_SHADER);
frag = GLSL_CompileShader ("scrwarp.frag", frag_shader, GL_FRAGMENT_SHADER);
warp.program = GLSL_LinkProgram ("scrwarp", vert, frag);
GLSL_ResolveShaderParam (warp.program, &warp.screenTex);
GLSL_ResolveShaderParam (warp.program, &warp.time);
GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader);
qfeglCreateVertexArrays (1, &warp.vao);
}
void
glsl_WarpScreen (framebuffer_t *fb)
{
qfeglUseProgram (warp.program);
qfeglUniform1f (warp.time.location, vr_data.realtime);
gl_framebuffer_t *buffer = fb->buffer;
qfeglActiveTexture (GL_TEXTURE0 + 0);
qfeglBindTexture (GL_TEXTURE_2D, buffer->color);
qfeglBindVertexArray (warp.vao);
qfeglDrawArrays (GL_TRIANGLES, 0, 3);
qfeglBindVertexArray (0);
qfeglActiveTexture (GL_TEXTURE0 + 0);
qfeglDisable (GL_TEXTURE_2D);
}

View file

@ -551,3 +551,38 @@ main (void)
col = texture2D (texture, st) * color * vec4 (l, 1.0);
gl_FragColor = fogBlend (col);
}
-- Vertex.fstri
#version 130
out vec2 uv;
void
main ()
{
// quake uses clockwise triangle order
float x = (gl_VertexID & 2);
float y = (gl_VertexID & 1);
uv = vec2(x, y*2);
gl_Position = vec4 (2, 4, 0, 0) * vec4 (x, y, 0, 0) - vec4 (1, 1, 0, -1);
}
-- Fragment.screen.warp
uniform sampler2D screenTex;
uniform float time;
in vec2 uv;
const float S = 0.15625;
const float F = 2.5;
const float A = 0.01;
const vec2 B = vec2 (1, 1);
void
main ()
{
uv = uv * (1.0 - 2.0*A) + A * (B + sin ((time * S + F * uv.yx) * 2.0*PI));
vec4 c = texture2D (screenTex, uv);
gl_FragColor = c;//vec4(uv, c.x, 1);
}

View file

@ -38,6 +38,7 @@
#include "QF/GLSL/qf_main.h"
#include "QF/GLSL/qf_particles.h"
#include "QF/GLSL/qf_vid.h"
#include "QF/GLSL/qf_warp.h"
#include "mod_internal.h"
#include "r_internal.h"
@ -229,6 +230,15 @@ glsl_draw_transparent (void)
static void
glsl_post_process (framebuffer_t *src)
{
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
if (r_dowarp) {
glsl_WarpScreen (src);
gl_framebuffer_t *buffer = src->buffer;
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
qfeglClear (GL_DEPTH_BUFFER_BIT);
}
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
}
static void
@ -258,12 +268,49 @@ glsl_create_cube_map (int size)
static framebuffer_t *
glsl_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;
qfeglGenFramebuffers (1, &buffer->handle);
GLuint tex[2];
qfeglGenTextures (2, tex);
buffer->color = tex[0];
buffer->depth = tex[1];
qfeglBindTexture (GL_TEXTURE_2D, buffer->color);
qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qfeglBindTexture (GL_TEXTURE_2D, buffer->depth);
qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, buffer->color, 0);
qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, buffer->depth, 0);
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
return fb;
}
static void
glsl_bind_framebuffer (framebuffer_t *framebuffer)
{
gl_framebuffer_t *buffer = framebuffer->buffer;
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
vrect_t r = { 0, 0, framebuffer->width, framebuffer->height };
R_SetVrect (&r, &r_refdef.vrect, 0);
R_ViewChanged ();
}
vid_render_funcs_t glsl_vid_render_funcs = {

View file

@ -189,7 +189,6 @@ glx_choose_visual (gl_ctx_t *ctx)
Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual");
}
x_vis = x_visinfo->visual;
printf ("%p\n", x_vis);
}
static void