diff --git a/include/QF/GLSL/qf_funcs_list.h b/include/QF/GLSL/qf_funcs_list.h index 7eab3ecdf..26adfea69 100644 --- a/include/QF/GLSL/qf_funcs_list.h +++ b/include/QF/GLSL/qf_funcs_list.h @@ -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)) diff --git a/include/QF/GLSL/qf_warp.h b/include/QF/GLSL/qf_warp.h new file mode 100644 index 000000000..3b91b7183 --- /dev/null +++ b/include/QF/GLSL/qf_warp.h @@ -0,0 +1,37 @@ +/* + qf_warp.h + + GLSL screen warp + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + 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 diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index c842cb050..1edf58746 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -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 = \ diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 065f7f0a0..0230080f4 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -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 diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 8e62fbb07..f494c2ef6 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -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 (); } diff --git a/libs/video/renderer/glsl/glsl_warp.c b/libs/video/renderer/glsl/glsl_warp.c new file mode 100644 index 000000000..d0e16727d --- /dev/null +++ b/libs/video/renderer/glsl/glsl_warp.c @@ -0,0 +1,114 @@ +/* + glsl_warp.c + + GLSL screen warp + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + 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 +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#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); +} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 2a912fcb0..2a92840d4 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -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); +} diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 19c8d3c95..02166fd1a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -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 = { diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index a29b01d74..30bf0aa19 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -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