mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[glsl] Implement fisheye rendering
The code dealing with state is a bit of a mess, but everything is working nicely. Get around 400fps when all 6 faces need to be rendered (no surprise: it should be about 1/6 of that for normal rendering). The messy state handling code did not come as a surprise as I suspected there were various mistakes in my scene rendering "recipe", and fisheye highlighted them nicely (I'm sure getting this stuff working in Vulkan will highlight even more issues).
This commit is contained in:
parent
18aae8205e
commit
286344c7b6
9 changed files with 269 additions and 16 deletions
37
include/QF/GLSL/qf_fisheye.h
Normal file
37
include/QF/GLSL/qf_fisheye.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
qf_fisheye.h
|
||||
|
||||
GLSL screen fisheye
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2022/3/25
|
||||
|
||||
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_fisheye_h
|
||||
#define __QF_GLSL_qf_fisheye_h
|
||||
|
||||
void glsl_InitFisheye (void);
|
||||
struct framebuffer_s;
|
||||
void glsl_FisheyeScreen (struct framebuffer_s *fb);
|
||||
|
||||
#endif//__QF_GLSL_qf_fisheye_h
|
|
@ -101,6 +101,7 @@ include_qf_glsl = \
|
|||
include/QF/GLSL/qf_alias.h \
|
||||
include/QF/GLSL/qf_bsp.h \
|
||||
include/QF/GLSL/qf_draw.h \
|
||||
include/QF/GLSL/qf_fisheye.h \
|
||||
include/QF/GLSL/qf_funcs_list.h \
|
||||
include/QF/GLSL/qf_iqm.h \
|
||||
include/QF/GLSL/qf_lightmap.h \
|
||||
|
|
|
@ -81,13 +81,15 @@ int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec,
|
|||
mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite,
|
||||
const animation_t *animation);
|
||||
|
||||
// These correspond to the standard box sides for OpenGL cube maps
|
||||
// These correspond to the standard box sides for OpenGL cube maps but with
|
||||
// TOP and BOTTOM swapped due to lelt/right handed systems (quake/gl are right,
|
||||
// cube maps are left)
|
||||
#define BOX_FRONT 4
|
||||
#define BOX_RIGHT 0
|
||||
#define BOX_BEHIND 5
|
||||
#define BOX_LEFT 1
|
||||
#define BOX_TOP 2
|
||||
#define BOX_BOTTOM 3
|
||||
#define BOX_TOP 3
|
||||
#define BOX_BOTTOM 2
|
||||
void R_RenderFisheye (framebuffer_t *cube);
|
||||
|
||||
#endif//__r_internal_h
|
||||
|
|
|
@ -110,6 +110,7 @@ libs_video_renderer_librender_glsl_la_SOURCES = \
|
|||
libs/video/renderer/glsl/glsl_alias.c \
|
||||
libs/video/renderer/glsl/glsl_bsp.c \
|
||||
libs/video/renderer/glsl/glsl_draw.c \
|
||||
libs/video/renderer/glsl/glsl_fisheye.c \
|
||||
libs/video/renderer/glsl/glsl_iqm.c \
|
||||
libs/video/renderer/glsl/glsl_lightmap.c \
|
||||
libs/video/renderer/glsl/glsl_main.c \
|
||||
|
|
121
libs/video/renderer/glsl/glsl_fisheye.c
Normal file
121
libs/video/renderer/glsl/glsl_fisheye.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
glsl_fisheye.c
|
||||
|
||||
GLSL screen fisheye
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2022/3/25
|
||||
|
||||
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_fisheye.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "vid_gl.h"
|
||||
|
||||
static const char *fisheye_vert_effects[] =
|
||||
{
|
||||
"QuakeForge.Vertex.fstri",
|
||||
0
|
||||
};
|
||||
|
||||
static const char *fisheye_frag_effects[] =
|
||||
{
|
||||
"QuakeForge.Math.const",
|
||||
"QuakeForge.Fragment.screen.fisheye",
|
||||
0
|
||||
};
|
||||
|
||||
static struct {
|
||||
int program;
|
||||
GLuint vao;
|
||||
shaderparam_t screenTex;
|
||||
shaderparam_t fov;
|
||||
shaderparam_t aspect;
|
||||
} fisheye = {
|
||||
.screenTex = {"screenTex", 1},
|
||||
.fov = {"fov", 1},
|
||||
.aspect = {"aspect", 1},
|
||||
};
|
||||
|
||||
void
|
||||
glsl_InitFisheye (void)
|
||||
{
|
||||
shader_t *vert_shader, *frag_shader;
|
||||
int vert;
|
||||
int frag;
|
||||
|
||||
vert_shader = GLSL_BuildShader (fisheye_vert_effects);
|
||||
frag_shader = GLSL_BuildShader (fisheye_frag_effects);
|
||||
vert = GLSL_CompileShader ("scrfisheye.vert", vert_shader,
|
||||
GL_VERTEX_SHADER);
|
||||
frag = GLSL_CompileShader ("scrfisheye.frag", frag_shader,
|
||||
GL_FRAGMENT_SHADER);
|
||||
fisheye.program = GLSL_LinkProgram ("scrfisheye", vert, frag);
|
||||
GLSL_ResolveShaderParam (fisheye.program, &fisheye.screenTex);
|
||||
GLSL_ResolveShaderParam (fisheye.program, &fisheye.fov);
|
||||
GLSL_ResolveShaderParam (fisheye.program, &fisheye.aspect);
|
||||
GLSL_FreeShader (vert_shader);
|
||||
GLSL_FreeShader (frag_shader);
|
||||
|
||||
qfeglCreateVertexArrays (1, &fisheye.vao);
|
||||
}
|
||||
|
||||
void
|
||||
glsl_FisheyeScreen (framebuffer_t *fb)
|
||||
{
|
||||
qfeglUseProgram (fisheye.program);
|
||||
|
||||
qfeglUniform1f (fisheye.fov.location, scr_ffov->value * M_PI / 360);
|
||||
qfeglUniform1f (fisheye.aspect.location,
|
||||
(float) r_refdef.vrect.height / r_refdef.vrect.width);
|
||||
|
||||
gl_framebuffer_t *buffer = fb->buffer;
|
||||
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
||||
qfeglBindTexture (GL_TEXTURE_CUBE_MAP, buffer->color);
|
||||
|
||||
qfeglBindVertexArray (fisheye.vao);
|
||||
qfeglDrawArrays (GL_TRIANGLES, 0, 3);
|
||||
qfeglBindVertexArray (0);
|
||||
|
||||
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
||||
qfeglDisable (GL_TEXTURE_2D);
|
||||
}
|
|
@ -52,6 +52,7 @@
|
|||
#include "QF/GLSL/qf_alias.h"
|
||||
#include "QF/GLSL/qf_bsp.h"
|
||||
#include "QF/GLSL/qf_draw.h"
|
||||
#include "QF/GLSL/qf_fisheye.h"
|
||||
#include "QF/GLSL/qf_iqm.h"
|
||||
#include "QF/GLSL/qf_lightmap.h"
|
||||
#include "QF/GLSL/qf_main.h"
|
||||
|
@ -212,6 +213,7 @@ glsl_R_Init (void)
|
|||
glsl_R_InitIQM ();
|
||||
glsl_R_InitSprites ();
|
||||
glsl_R_InitParticles ();
|
||||
glsl_InitFisheye ();
|
||||
glsl_InitWarp ();
|
||||
Skin_Init ();
|
||||
}
|
||||
|
|
|
@ -586,3 +586,24 @@ main ()
|
|||
vec4 c = texture2D (screenTex, uv);
|
||||
gl_FragColor = c;//vec4(uv, c.x, 1);
|
||||
}
|
||||
|
||||
-- Fragment.screen.fisheye
|
||||
|
||||
uniform samplerCube screenTex;
|
||||
uniform float fov;
|
||||
uniform float aspect;
|
||||
|
||||
in vec2 uv;
|
||||
|
||||
void
|
||||
main ()
|
||||
{
|
||||
// slight offset on y is to avoid the singularity straight aheat
|
||||
vec2 xy = (2.0 * uv - vec2 (1, 1.00002)) * (vec2(1, -aspect));
|
||||
float r = sqrt (dot (xy, xy));
|
||||
vec2 cs = vec2 (cos (r * fov), sin (r * fov));
|
||||
vec3 dir = vec3 (cs.y * xy / r, cs.x);
|
||||
|
||||
vec4 c = textureCube(screenTex, dir);
|
||||
gl_FragColor = c;// * 0.001 + vec4(dir, 1);
|
||||
}
|
||||
|
|
|
@ -209,6 +209,10 @@ render_side (int side)
|
|||
r_refdef.frame.mat[2] = r_refdef.camera[2];
|
||||
r_refdef.frame.mat[3] = r_refdef.camera[3];
|
||||
|
||||
refdef_t *refdef = r_data->refdef;
|
||||
R_SetFrustum (refdef->frustum, &refdef->frame,
|
||||
refdef->fov_x, refdef->fov_y);
|
||||
|
||||
r_data->refdef->fov_x = r_data->refdef->fov_y = 90;
|
||||
r_funcs->bind_framebuffer (&fisheye_cube_map[side]);
|
||||
render_scene ();
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
|
||||
#include "QF/plugin/general.h"
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
|
@ -35,6 +37,7 @@
|
|||
#include "QF/GLSL/defines.h"
|
||||
#include "QF/GLSL/qf_bsp.h"
|
||||
#include "QF/GLSL/qf_draw.h"
|
||||
#include "QF/GLSL/qf_fisheye.h"
|
||||
#include "QF/GLSL/qf_main.h"
|
||||
#include "QF/GLSL/qf_particles.h"
|
||||
#include "QF/GLSL/qf_vid.h"
|
||||
|
@ -218,6 +221,7 @@ glsl_begin_frame (void)
|
|||
static void
|
||||
glsl_render_view (void)
|
||||
{
|
||||
qfeglClear (GL_DEPTH_BUFFER_BIT);
|
||||
glsl_R_RenderView ();
|
||||
}
|
||||
|
||||
|
@ -227,18 +231,22 @@ glsl_draw_transparent (void)
|
|||
glsl_R_DrawWaterSurfaces ();
|
||||
}
|
||||
|
||||
static void glsl_bind_framebuffer (framebuffer_t *fb);
|
||||
|
||||
static void
|
||||
glsl_post_process (framebuffer_t *src)
|
||||
{
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
if (r_dowarp) {
|
||||
glsl_bind_framebuffer (0);
|
||||
float x = r_refdef.vrect.x;
|
||||
float y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height));
|
||||
float w = r_refdef.vrect.width;
|
||||
float h = r_refdef.vrect.height;
|
||||
qfeglViewport (x, y, w, h);
|
||||
if (scr_fisheye->int_val) {
|
||||
glsl_FisheyeScreen (src);
|
||||
} else 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
|
||||
|
@ -260,9 +268,53 @@ glsl_end_frame (void)
|
|||
}
|
||||
|
||||
static framebuffer_t *
|
||||
glsl_create_cube_map (int size)
|
||||
glsl_create_cube_map (int side)
|
||||
{
|
||||
Sys_Error ("not implemented");
|
||||
GLuint tex[2];
|
||||
qfeglGenTextures (2, tex);
|
||||
|
||||
qfeglBindTexture (GL_TEXTURE_CUBE_MAP, tex[0]);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA,
|
||||
side, side, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
qfeglBindTexture (GL_TEXTURE_2D, tex[1]);
|
||||
qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, side, side, 0,
|
||||
GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
|
||||
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
size_t size = sizeof (framebuffer_t) * 6;
|
||||
size += sizeof (gl_framebuffer_t) * 6;
|
||||
|
||||
framebuffer_t *cube = malloc (size);
|
||||
__auto_type buffer_base = (gl_framebuffer_t *) &cube[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cube[i].width = side;
|
||||
cube[i].height = side;
|
||||
__auto_type buffer = buffer_base + i;
|
||||
cube[i].buffer = buffer;
|
||||
|
||||
buffer->color = tex[0];
|
||||
buffer->depth = tex[1];
|
||||
qfeglGenFramebuffers (1, &buffer->handle);
|
||||
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
|
||||
qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||
buffer->color, 0);
|
||||
qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||
GL_TEXTURE_2D, buffer->depth, 0);
|
||||
}
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
return cube;
|
||||
}
|
||||
|
||||
static framebuffer_t *
|
||||
|
@ -287,10 +339,13 @@ glsl_create_frame_buffer (int width, int height)
|
|||
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);
|
||||
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
|
||||
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
|
||||
qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
|
@ -305,12 +360,21 @@ glsl_create_frame_buffer (int width, int height)
|
|||
static void
|
||||
glsl_bind_framebuffer (framebuffer_t *framebuffer)
|
||||
{
|
||||
gl_framebuffer_t *buffer = framebuffer->buffer;
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
|
||||
unsigned width = vr_data.vid->width;
|
||||
unsigned height = vr_data.vid->height;
|
||||
if (!framebuffer) {
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
} else {
|
||||
gl_framebuffer_t *buffer = framebuffer->buffer;
|
||||
qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle);
|
||||
|
||||
vrect_t r = { 0, 0, framebuffer->width, framebuffer->height };
|
||||
width = framebuffer->width;
|
||||
height = framebuffer->height;
|
||||
}
|
||||
|
||||
vrect_t r = { 0, 0, width, height };
|
||||
R_SetVrect (&r, &r_refdef.vrect, 0);
|
||||
R_ViewChanged ();
|
||||
glsl_R_ViewChanged ();
|
||||
}
|
||||
|
||||
vid_render_funcs_t glsl_vid_render_funcs = {
|
||||
|
|
Loading…
Reference in a new issue