OpenGL Shader Object Waterwarp:

Fixed to use textures for warp, and for determining distance from the edge of the screen. The second siginificantly improves performance over calculating it in the shader.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@808 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
KrimZon 2005-01-17 18:06:45 +00:00
parent 6b9650f045
commit 4e2299ef64
3 changed files with 161 additions and 37 deletions

View file

@ -917,7 +917,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n"));
cachedcrosshair=0;
crosshairimage.modified = true;
scenepp_texture = texture_extension_number++;
GL_SetupSceneProcessingTextures();
start = Hunk_LowMark ();
conback = default_conback;

View file

@ -137,12 +137,13 @@ extern cvar_t scr_fov;
// post processing stuff
int scenepp_texture;
int scenepp_texture_warp;
int scenepp_texture_edge;
int scenepp_ww_program;
int scenepp_ww_parm_texturei;
int scenepp_ww_parm_timef;
int scenepp_ww_parm_xscalef;
int scenepp_ww_parm_yscalef;
int scenepp_ww_parm_texture0i;
int scenepp_ww_parm_texture1i;
int scenepp_ww_parm_texture2i;
int scenepp_ww_parm_ampscalef;
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
@ -153,28 +154,41 @@ void GL_InitSceneProcessingShaders (void)
int vert, frag;
char *genericvert = "\
varying vec2 v_texCoord;\
varying vec2 v_texCoord0;\
varying vec2 v_texCoord1;\
varying vec2 v_texCoord2;\
void main (void)\
{\
vec4 v = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 );\
gl_Position = gl_ModelViewProjectionMatrix * v;\
v_texCoord = gl_MultiTexCoord0.xy;\
v_texCoord0 = gl_MultiTexCoord0.xy;\
v_texCoord1 = gl_MultiTexCoord1.xy;\
v_texCoord2 = gl_MultiTexCoord2.xy;\
}\
";
char *wwfrag = "\
varying vec2 v_texCoord;\
uniform sampler2D texture;\
uniform float time;\
uniform float xscale;\
uniform float yscale;\
varying vec2 v_texCoord0;\
varying vec2 v_texCoord1;\
varying vec2 v_texCoord2;\
uniform sampler2D theTexture0;\
uniform sampler2D theTexture1;\
uniform sampler2D theTexture2;\
uniform float ampscale;\
void main (void)\
{\
float amptemp;\
vec3 edge;\
edge = texture2D( theTexture2, v_texCoord2 );\
amptemp = ampscale * edge.x;\
vec3 offset;\
offset = texture2D( theTexture1, v_texCoord1 );\
offset.x = (offset.x - 0.5) * 2.0;\
offset.y = (offset.y - 0.5) * 2.0;\
vec2 temp;\
temp.x = v_texCoord.x + sin((v_texCoord.y * xscale) + time) * ampscale;\
temp.y = v_texCoord.y + cos((v_texCoord.x * yscale) + time) * ampscale;\
gl_FragColor = texture2D( texture, temp );\
temp.x = v_texCoord0.x + offset.x * amptemp;\
temp.y = v_texCoord0.y + offset.y * amptemp;\
gl_FragColor = texture2D( theTexture0, temp );\
}\
";
@ -186,15 +200,16 @@ void GL_InitSceneProcessingShaders (void)
scenepp_ww_program = GLSlang_CreateProgram(vert, frag);
// scenepp_ww_parm_texturei = GLSlang_GetUniformLocation(scenepp_ww_program, "texture");
scenepp_ww_parm_timef = GLSlang_GetUniformLocation(scenepp_ww_program, "time");
scenepp_ww_parm_xscalef = GLSlang_GetUniformLocation(scenepp_ww_program, "xscale");
scenepp_ww_parm_yscalef = GLSlang_GetUniformLocation(scenepp_ww_program, "yscale");
scenepp_ww_parm_texture0i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture0");
scenepp_ww_parm_texture1i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture1");
scenepp_ww_parm_texture2i = GLSlang_GetUniformLocation(scenepp_ww_program, "theTexture2");
scenepp_ww_parm_ampscalef = GLSlang_GetUniformLocation(scenepp_ww_program, "ampscale");
GLSlang_UseProgram(scenepp_ww_program);
// GLSlang_SetUniform1i(scenepp_ww_parm_texturei, 0);
GLSlang_SetUniform1i(scenepp_ww_parm_texture0i, 0);
GLSlang_SetUniform1i(scenepp_ww_parm_texture1i, 1);
GLSlang_SetUniform1i(scenepp_ww_parm_texture2i, 2);
GLSlang_UseProgram(0);
@ -202,6 +217,87 @@ void GL_InitSceneProcessingShaders (void)
Con_Printf("GL Error initing shader object\n");
}
#define PP_WARP_TEX_SIZE 64
#define PP_AMP_TEX_SIZE 64
#define PP_AMP_TEX_BORDER 4
void GL_SetupSceneProcessingTextures (void)
{
int i, x, y;
unsigned char pp_warp_tex[PP_WARP_TEX_SIZE*PP_WARP_TEX_SIZE*3];
unsigned char pp_edge_tex[PP_AMP_TEX_SIZE*PP_AMP_TEX_SIZE*3];
scenepp_texture = texture_extension_number++;
scenepp_texture_warp = texture_extension_number++;
scenepp_texture_edge = texture_extension_number++;
// init warp texture - this specifies offset in
for (y=0; y<PP_WARP_TEX_SIZE; y++)
{
for (x=0; x<PP_WARP_TEX_SIZE; x++)
{
float fx, fy;
i = (x + y*PP_WARP_TEX_SIZE) * 3;
fx = sin(((double)y / PP_WARP_TEX_SIZE) * M_PI * 2);
fy = cos(((double)x / PP_WARP_TEX_SIZE) * M_PI * 2);
pp_warp_tex[i ] = (fx+1.0f)*127.0f;
pp_warp_tex[i+1] = (fy+1.0f)*127.0f;
pp_warp_tex[i+2] = 0;
}
}
GL_Bind(scenepp_texture_warp);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_warp_tex);
// TODO: init edge texture - this is ampscale * 2, with ampscale calculated
// init warp texture - this specifies offset in
for (y=0; y<PP_AMP_TEX_SIZE; y++)
{
for (x=0; x<PP_AMP_TEX_SIZE; x++)
{
float fx = 1, fy = 1;
i = (x + y*PP_AMP_TEX_SIZE) * 3;
if (x < PP_AMP_TEX_BORDER)
{
fx = (float)x / PP_AMP_TEX_BORDER;
}
if (x > PP_AMP_TEX_SIZE - PP_AMP_TEX_BORDER)
{
fx = (PP_AMP_TEX_SIZE - (float)x) / PP_AMP_TEX_BORDER;
}
if (y < PP_AMP_TEX_BORDER)
{
fy = (float)y / PP_AMP_TEX_BORDER;
}
if (y > PP_AMP_TEX_SIZE - PP_AMP_TEX_BORDER)
{
fy = (PP_AMP_TEX_SIZE - (float)y) / PP_AMP_TEX_BORDER;
}
if (fx < fy)
{
fy = fx;
}
pp_edge_tex[i ] = fy * 255;
pp_edge_tex[i+1] = 0;
pp_edge_tex[i+2] = 0;
}
}
GL_Bind(scenepp_texture_edge);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_edge_tex);
}
/*
=================
R_CullBox
@ -1763,7 +1859,7 @@ void GLR_RenderView (void)
// SCENE POST PROCESSING
// we check if we need to use any shaders - currently it's just waterwarp
if ((gl_config.arb_shader_objects) && (r_waterwarp.value && r_viewleaf&&r_viewleaf->contents <= Q1CONTENTS_WATER))
if ((gl_config.arb_shader_objects) && (r_waterwarp.value && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER))
{
extern int char_texture;
float vwidth = 1, vheight = 1;
@ -1817,31 +1913,59 @@ void GLR_RenderView (void)
// Here we apply the shaders - currently just waterwarp
GLSlang_UseProgram(scenepp_ww_program);
//just keep the ratio of x and y scales the same as that of the screen
GLSlang_SetUniform1f(scenepp_ww_parm_xscalef, 4 / vs);
GLSlang_SetUniform1f(scenepp_ww_parm_yscalef, ((4 / glwidth)*glheight)/vt);
//keep the amp proportional to the size of the scene in texture coords
// WARNING - waterwarp can change the amplitude, but if it's too big it'll exceed
// the size determined by the edge texture, after which black bits will be shown.
// Suggest clamping to a suitable range.
GLSlang_SetUniform1f(scenepp_ww_parm_ampscalef, (0.005 / 0.625) * vs*r_waterwarp.value);
GLSlang_SetUniform1f(scenepp_ww_parm_timef, cl.time);
if (qglGetError())
Con_Printf("GL Error after GLSlang_UseProgram\n");
qglBegin(GL_QUADS);
{
float xmin, xmax, ymin, ymax;
qglTexCoord2f(0, 0);
qglVertex2f(0, 0);
xmin = cl.time * 0.25;
ymin = cl.time * 0.25;
xmax = xmin + 1;
ymax = ymin + 1/vt*vs;
qglTexCoord2f(vs, 0);
qglVertex2f(glwidth, 0);
GL_EnableMultitexture();
GL_Bind (scenepp_texture_warp);
qglTexCoord2f(vs, vt);
qglVertex2f(glwidth, glheight);
GL_SelectTexture(mtexid1+1);
qglEnable(GL_TEXTURE_2D);
GL_Bind(scenepp_texture_edge);
qglTexCoord2f(0, vt);
qglVertex2f(0, glheight);
qglEnd();
qglBegin(GL_QUADS);
qglMTexCoord2fSGIS (mtexid0, 0, 0);
qglMTexCoord2fSGIS (mtexid1, xmin, ymin);
qglMTexCoord2fSGIS (mtexid1+1, 0, 0);
qglVertex2f(0, 0);
qglMTexCoord2fSGIS (mtexid0, vs, 0);
qglMTexCoord2fSGIS (mtexid1, xmax, ymin);
qglMTexCoord2fSGIS (mtexid1+1, 1, 0);
qglVertex2f(glwidth, 0);
qglMTexCoord2fSGIS (mtexid0, vs, vt);
qglMTexCoord2fSGIS (mtexid1, xmax, ymax);
qglMTexCoord2fSGIS (mtexid1+1, 1, 1);
qglVertex2f(glwidth, glheight);
qglMTexCoord2fSGIS (mtexid0, 0, vt);
qglMTexCoord2fSGIS (mtexid1, xmin, ymax);
qglMTexCoord2fSGIS (mtexid1+1, 0, 1);
qglVertex2f(0, glheight);
qglEnd();
qglDisable(GL_TEXTURE_2D);
GL_SelectTexture(mtexid1);
GL_DisableMultitexture();
}
// Disable shaders
GLSlang_UseProgram(0);

View file

@ -288,7 +288,7 @@ void R_RotateForEntity (entity_t *e);
void R_DrawAliasModel (entity_t *e);
void GL_InitSceneProcessingShaders (void);
extern int scenepp_texture;
void GL_SetupSceneProcessingTextures (void);
//gl_alias.c
void R_DrawGAliasModel (entity_t *e);