fix nq bob (also fixes show_speed in nq)
tweaked waterwarp+bloom to use fbos. this fixes any issues with viewsize 10 or whatever, but depends upon npot. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4727 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
23b7a15980
commit
54c0810d41
11 changed files with 183 additions and 665 deletions
|
@ -1561,7 +1561,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
|
|||
|
||||
CL_ProxyMenuHooks();
|
||||
|
||||
if (cls.demoplayback != DPB_NONE)
|
||||
if (cls.demoplayback != DPB_NONE || cls.netchan.remote_address.type == NA_INVALID)
|
||||
{
|
||||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
{
|
||||
|
|
|
@ -3373,6 +3373,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
|
|||
void CLNQ_ParseClientdata (void)
|
||||
{
|
||||
int i;
|
||||
player_state_t *pl = &cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[0].playernum];
|
||||
|
||||
unsigned int bits;
|
||||
|
||||
|
@ -3393,7 +3394,6 @@ void CLNQ_ParseClientdata (void)
|
|||
/*else
|
||||
cl.idealpitch = 0;*/
|
||||
|
||||
// VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if (bits & (SU_PUNCH1<<i) )
|
||||
|
@ -3408,21 +3408,21 @@ void CLNQ_ParseClientdata (void)
|
|||
// else
|
||||
// cl.punchvector[i] = 0;
|
||||
|
||||
if (bits & (SU_VELOCITY1<<i) )
|
||||
if (bits & (SU_VELOCITY1<<i))
|
||||
{
|
||||
if (CPNQ_IS_DP)
|
||||
/*cl.simvel[0][i] =*/ MSG_ReadFloat();
|
||||
pl->velocity[i] = MSG_ReadFloat();
|
||||
else
|
||||
/*cl.mvelocity[0][i] =*/ MSG_ReadChar()/**16*/;
|
||||
pl->velocity[i] = MSG_ReadChar()*16;
|
||||
}
|
||||
// else
|
||||
// cl.mvelocity[0][i] = 0;
|
||||
else
|
||||
pl->velocity[i] = 0;
|
||||
}
|
||||
|
||||
if ((bits & SU_ITEMS) || cls.protocol_nq == CPNQ_ID) //hipnotic bug - hipnotic demos don't always have SU_ITEMS set, yet they update STAT_ITEMS anyway.
|
||||
CL_SetStatInt(0, STAT_ITEMS, MSG_ReadLong());
|
||||
|
||||
// cl.onground = (bits & SU_ONGROUND) != 0;
|
||||
pl->onground = (bits & SU_ONGROUND) != 0;
|
||||
// cl.inwater = (bits & SU_INWATER) != 0;
|
||||
|
||||
if (cls.protocol_nq == CPNQ_DP5)
|
||||
|
|
|
@ -699,6 +699,9 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
|
|||
{
|
||||
vec3_t a;
|
||||
int pmtype;
|
||||
qboolean onground = plstate->onground;
|
||||
vec3_t vel;
|
||||
VectorCopy(plstate->velocity, vel);
|
||||
memset(plstate, 0, sizeof(*plstate));
|
||||
switch(state->u.q1.pmovetype)
|
||||
{
|
||||
|
@ -732,7 +735,13 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
|
|||
|
||||
plstate->pm_type = pmtype;
|
||||
VectorCopy(state->origin, plstate->origin);
|
||||
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
|
||||
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))
|
||||
{ //nq is annoying, this stuff wasn't part of the entity state, so don't break it
|
||||
VectorCopy(vel, plstate->velocity);
|
||||
plstate->onground = onground;
|
||||
}
|
||||
else
|
||||
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
|
||||
VectorCopy(state->angles, plstate->viewangles);
|
||||
plstate->viewangles[0] *= -3;
|
||||
|
||||
|
@ -1178,7 +1187,10 @@ void CL_PredictMovePNum (int seat)
|
|||
}
|
||||
}
|
||||
}
|
||||
CL_CatagorizePosition(pv, tostate->origin);
|
||||
if (cls.protocol == CP_NETQUAKE && nopred)
|
||||
pv->onground = tostate->onground;
|
||||
else
|
||||
CL_CatagorizePosition(pv, tostate->origin);
|
||||
|
||||
if (le)
|
||||
{
|
||||
|
|
|
@ -1301,9 +1301,9 @@ texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfm
|
|||
}
|
||||
else
|
||||
{
|
||||
tid = R_FindTexture(id, IF_NOMIPMAP);
|
||||
tid = R_FindTexture(id, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR);
|
||||
if (!TEXVALID(tid))
|
||||
tid = R_AllocNewTexture(id, 0, 0, IF_NOMIPMAP);
|
||||
tid = R_AllocNewTexture(id, 0, 0, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR);
|
||||
}
|
||||
if (rtfmt)
|
||||
{
|
||||
|
@ -1317,7 +1317,7 @@ texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfm
|
|||
case 6: rtfmt = TF_DEPTH32; break;
|
||||
default:rtfmt = TF_INVALID; break;
|
||||
}
|
||||
R_Upload(tid, id, rtfmt, NULL, NULL, width, height, IF_NOMIPMAP);
|
||||
R_Upload(tid, id, rtfmt, NULL, NULL, width, height, IF_NOMIPMAP|IF_CLAMP|IF_LINEAR);
|
||||
tid.ref->width = width;
|
||||
tid.ref->height = height;
|
||||
}
|
||||
|
|
|
@ -1986,6 +1986,9 @@ void Surf_SetupFrame(void)
|
|||
mleaf_t *leaf;
|
||||
vec3_t temp, pvsorg;
|
||||
|
||||
if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap))
|
||||
r_refdef.flags |= RDF_NOWORLDMODEL;
|
||||
|
||||
R_AnimateLight();
|
||||
r_framecount++;
|
||||
|
||||
|
|
|
@ -1153,13 +1153,19 @@ typedef struct q1usercmd_s
|
|||
#define RF_FORCECOLOURMOD (1u<<22) //forces BEF_FORCECOLOURMOD
|
||||
|
||||
// player_state_t->refdef flags
|
||||
#define Q2RDF_UNDERWATER 1 // warp the screen as apropriate
|
||||
#define RDF_NOWORLDMODEL 2 // used for player configuration screen
|
||||
#define RDF_UNDERWATER (1u<<0) // warp the screen as apropriate (fov trick)
|
||||
#define RDF_NOWORLDMODEL (1u<<1) // used for player configuration screen
|
||||
//ROGUE
|
||||
#define Q2RDF_IRGOGGLES (1u<<2) //ents with Q2RF_IR_VISIBLE show up pure red.
|
||||
#define Q2RDF_UVGOGGLES (1u<<3) //usused / reserved
|
||||
//ROGUE
|
||||
#define RDF_BLOOM (1u<<16)
|
||||
#define RDF_FISHEYE (1u<<17)
|
||||
#define RDF_WATERWARP (1u<<18)
|
||||
#define RDF_CUSTOMPOSTPROC (1u<<19)
|
||||
|
||||
#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC) //these flags require rendering to an fbo for the various different post-processing shaders.
|
||||
|
||||
//ROGUE
|
||||
#define Q2RDF_IRGOGGLES 4 //ents with Q2RF_IR_VISIBLE show up pure red.
|
||||
#define Q2RDF_UVGOGGLES 8 //usused / reserved
|
||||
//ROGUE
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ static shader_t *bloomblur;
|
|||
static shader_t *bloomfinal;
|
||||
|
||||
#define MAXLEVELS 3
|
||||
texid_t scrtex;
|
||||
texid_t pingtex[2][MAXLEVELS];
|
||||
fbostate_t fbo_bloom;
|
||||
static int scrwidth, scrheight;
|
||||
|
@ -69,7 +68,6 @@ static void R_InitBloomTextures(void)
|
|||
bloomfinal = NULL;
|
||||
scrwidth = 0, scrheight = 0;
|
||||
|
||||
scrtex = r_nulltex;
|
||||
for (i = 0; i < MAXLEVELS; i++)
|
||||
{
|
||||
pingtex[0][i] = r_nulltex;
|
||||
|
@ -108,17 +106,6 @@ static void R_SetupBloomTextures(int w, int h)
|
|||
texheight[i] = h;
|
||||
}
|
||||
|
||||
/*we should be doing this outside of this code*/
|
||||
if (!TEXVALID(scrtex))
|
||||
scrtex = GL_AllocNewTexture("", scrwidth, scrheight, IF_NOMIPMAP|IF_NOPICMIP);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, scrtex);
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, scrwidth, scrheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
/*top level uses nearest sampling*/
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
/*now create textures for each level*/
|
||||
for (j = 0; j < MAXLEVELS; j++)
|
||||
{
|
||||
|
@ -127,7 +114,7 @@ static void R_SetupBloomTextures(int w, int h)
|
|||
if (!TEXVALID(pingtex[i][j]))
|
||||
{
|
||||
sprintf(name, "***bloom*%c*%i***", 'a'+i, j);
|
||||
TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_NOMIPMAP|IF_NOPICMIP));
|
||||
TEXASSIGN(pingtex[i][j], GL_AllocNewTexture(name, texwidth[j], texheight[j], IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
|
||||
}
|
||||
GL_MTBind(0, GL_TEXTURE_2D, pingtex[i][j]);
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texwidth[j], texheight[j], 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
@ -185,30 +172,31 @@ static void R_SetupBloomTextures(int w, int h)
|
|||
bloomfinal->defaulttextures.loweroverlay = pingtex[0][1];
|
||||
bloomfinal->defaulttextures.upperoverlay = pingtex[0][2];
|
||||
}
|
||||
void R_BloomBlend (void)
|
||||
qboolean R_CanBloom(void)
|
||||
{
|
||||
if (!r_bloom.value)
|
||||
return false;
|
||||
if (!gl_config.ext_framebuffer_objects)
|
||||
return false;
|
||||
if (!gl_config.arb_shader_objects)
|
||||
return false;
|
||||
if (!r_config.texture_non_power_of_two)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_BloomBlend (texid_t source, int x, int y, int w, int h)
|
||||
{
|
||||
int i;
|
||||
int oldfbo = 0;
|
||||
|
||||
if (!gl_config.ext_framebuffer_objects)
|
||||
return;
|
||||
if (!gl_config.arb_shader_objects)
|
||||
return;
|
||||
if (!r_config.texture_non_power_of_two)
|
||||
return;
|
||||
|
||||
/*whu?*/
|
||||
if (!r_refdef.pxrect.width || !r_refdef.pxrect.height)
|
||||
if (!w || !h)
|
||||
return;
|
||||
|
||||
/*update textures if we need to resize them*/
|
||||
R_SetupBloomTextures(r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
|
||||
/*grab the screen, because we failed to do it earlier*/
|
||||
GL_MTBind(0, GL_TEXTURE_2D, scrtex);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height), r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
R_SetupBloomTextures(w, h);
|
||||
|
||||
for (i = 0; i < MAXLEVELS; i++)
|
||||
{
|
||||
|
@ -216,7 +204,7 @@ void R_BloomBlend (void)
|
|||
{
|
||||
/*filter the screen into a downscaled image*/
|
||||
oldfbo = GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][0], 1, r_nulltex, 0, 0);
|
||||
GLBE_FBO_Sources(scrtex, r_nulltex);
|
||||
GLBE_FBO_Sources(source, r_nulltex);
|
||||
qglViewport (0, 0, texwidth[0], texheight[0]);
|
||||
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter);
|
||||
}
|
||||
|
@ -256,8 +244,8 @@ void R_BloomBlend (void)
|
|||
|
||||
/*combine them onto the screen*/
|
||||
GLBE_FBO_Pop(oldfbo);
|
||||
GLBE_FBO_Sources(scrtex, r_nulltex);
|
||||
R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y + r_refdef.vrect.height, r_refdef.vrect.width, -r_refdef.vrect.height, bloomfinal);
|
||||
GLBE_FBO_Sources(source, r_nulltex);
|
||||
R2D_ScalePic(x, y + h, w, -h, bloomfinal);
|
||||
}
|
||||
void R_BloomShutdown(void)
|
||||
{
|
||||
|
@ -266,562 +254,4 @@ void R_BloomShutdown(void)
|
|||
R_InitBloomTextures();
|
||||
}
|
||||
|
||||
#elif defined(GLQUAKE)
|
||||
#include "glquake.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
LIGHT BLOOMS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects)");
|
||||
cvar_t r_bloom_alpha = CVAR("r_bloom_alpha", "0.5");
|
||||
cvar_t r_bloom_diamond_size = CVAR("r_bloom_diamond_size", "8");
|
||||
cvar_t r_bloom_intensity = CVAR("r_bloom_intensity", "1");
|
||||
cvar_t r_bloom_darken = CVAR("r_bloom_darken", "3");
|
||||
cvar_t r_bloom_sample_size = CVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH);
|
||||
cvar_t r_bloom_fast_sample = CVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH);
|
||||
|
||||
typedef struct {
|
||||
//texture numbers
|
||||
texid_t tx_screen; /*a copy of the screen*/
|
||||
texid_t tx_effect; /*blured copy of bright pixels*/
|
||||
texid_t tx_backup; /*a copy of the screen to replace the pixels that we'll clobber. FIXME: use a FBO instead*/
|
||||
texid_t tx_downsample;
|
||||
|
||||
//the viewport dimensions
|
||||
int vp_x;
|
||||
int vp_y;
|
||||
int vp_w;
|
||||
int vp_h;
|
||||
|
||||
//texture coordinates of screen data inside screentexture
|
||||
float scr_s;
|
||||
float scr_t;
|
||||
|
||||
//dimensions of the screen texture (power of two)
|
||||
int scr_w;
|
||||
int scr_h;
|
||||
|
||||
//downsampled dimensions (will always be smaller than viewport)
|
||||
int smp_w;
|
||||
int smp_h;
|
||||
//tex coords to be used for the sample
|
||||
float smp_s;
|
||||
float smp_t;
|
||||
|
||||
int size_downsample;
|
||||
int size_backup;
|
||||
int size_sample;
|
||||
} bloomstate_t;
|
||||
|
||||
static bloomstate_t bs;
|
||||
|
||||
//this macro is in sample size workspace coordinates
|
||||
#define R_Bloom_SamplePass( xpos, ypos ) \
|
||||
qglBegin(GL_QUADS); \
|
||||
qglTexCoord2f( 0, bs.smp_t); \
|
||||
qglVertex2f( xpos, ypos); \
|
||||
qglTexCoord2f( 0, 0); \
|
||||
qglVertex2f( xpos, ypos+bs.smp_h); \
|
||||
qglTexCoord2f( bs.smp_s, 0); \
|
||||
qglVertex2f( xpos+bs.smp_w, ypos+bs.smp_h); \
|
||||
qglTexCoord2f( bs.smp_s, bs.smp_t); \
|
||||
qglVertex2f( xpos+bs.smp_w, ypos); \
|
||||
qglEnd();
|
||||
|
||||
#define R_Bloom_Quad( x, y, width, height, textwidth, textheight ) \
|
||||
qglBegin(GL_QUADS); \
|
||||
qglTexCoord2f( 0, textheight); \
|
||||
qglVertex2f( x, y); \
|
||||
qglTexCoord2f( 0, 0); \
|
||||
qglVertex2f( x, y+height); \
|
||||
qglTexCoord2f( textwidth, 0); \
|
||||
qglVertex2f( x+width, y+height); \
|
||||
qglTexCoord2f( textwidth, textheight); \
|
||||
qglVertex2f( x+width, y); \
|
||||
qglEnd();
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_InitBackUpTexture
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_InitBackUpTexture(int widthheight)
|
||||
{
|
||||
qbyte *data;
|
||||
|
||||
data = Z_Malloc(widthheight * widthheight * 4);
|
||||
|
||||
bs.size_backup = widthheight;
|
||||
bs.tx_backup = GL_LoadTexture32("***bs.tx_backup***", bs.size_backup, bs.size_backup, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA);
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_InitEffectTexture
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_InitEffectTexture(void)
|
||||
{
|
||||
qbyte *data;
|
||||
float bloomsizecheck;
|
||||
|
||||
if (r_bloom_sample_size.value < 32)
|
||||
Cvar_SetValue (&r_bloom_sample_size, 32);
|
||||
|
||||
//make sure bloom size is a power of 2
|
||||
bs.size_sample = min(r_bloom_sample_size.value, gl_max_size.value);
|
||||
bloomsizecheck = (float)bs.size_sample;
|
||||
while (bloomsizecheck > 1.0f) bloomsizecheck /= 2.0f;
|
||||
if (bloomsizecheck != 1.0f)
|
||||
{
|
||||
bs.size_sample = 32;
|
||||
while (bs.size_sample < r_bloom_sample_size.value)
|
||||
bs.size_sample *= 2;
|
||||
}
|
||||
|
||||
//make sure bloom size doesn't have stupid values
|
||||
if (bs.size_sample > bs.scr_w ||
|
||||
bs.size_sample > bs.scr_h)
|
||||
bs.size_sample = min(bs.scr_w, bs.scr_h);
|
||||
|
||||
if (bs.size_sample != r_bloom_sample_size.value)
|
||||
Cvar_SetValue (&r_bloom_sample_size, bs.size_sample);
|
||||
|
||||
data = Z_Malloc(bs.size_sample * bs.size_sample * 4);
|
||||
|
||||
bs.tx_effect = GL_LoadTexture32("***bs.tx_effect***", bs.size_sample, bs.size_sample, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA);
|
||||
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_InitTextures
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_InitTextures(void)
|
||||
{
|
||||
qbyte *data;
|
||||
int size;
|
||||
int maxtexsize;
|
||||
|
||||
//find closer power of 2 to screen size
|
||||
for (bs.scr_w = 1;bs.scr_w < vid.pixelwidth;bs.scr_w *= 2);
|
||||
for (bs.scr_h = 1;bs.scr_h < vid.pixelheight;bs.scr_h *= 2);
|
||||
|
||||
//disable blooms if we can't handle a texture of that size
|
||||
qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize);
|
||||
if (bs.scr_w > maxtexsize ||
|
||||
bs.scr_h > maxtexsize)
|
||||
{
|
||||
bs.scr_w = bs.scr_h = 0;
|
||||
Cvar_SetValue (&r_bloom, 0);
|
||||
Con_Printf("WARNING: 'R_InitBloomScreenTexture' too high resolution for Light Bloom. Effect disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//init the screen texture
|
||||
size = bs.scr_w * bs.scr_h * 4;
|
||||
data = Z_Malloc(size);
|
||||
memset(data, 255, size);
|
||||
if (!TEXVALID(bs.tx_screen))
|
||||
bs.tx_screen = GL_AllocNewTexture("***bloom screen***", bs.scr_w, bs.scr_h);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen);
|
||||
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
Z_Free (data);
|
||||
|
||||
|
||||
//validate bloom size and init the bloom effect texture
|
||||
R_Bloom_InitEffectTexture ();
|
||||
|
||||
//if screensize is more than 2x the bloom effect texture, set up for stepped downsampling
|
||||
bs.tx_downsample = r_nulltex;
|
||||
bs.size_downsample = 0;
|
||||
if (vid.pixelwidth > (bs.size_sample * 2) && !r_bloom_fast_sample.value)
|
||||
{
|
||||
bs.size_downsample = (int)(bs.size_sample * 2);
|
||||
data = Z_Malloc(bs.size_downsample * bs.size_downsample * 4);
|
||||
bs.tx_downsample = GL_LoadTexture32("***bs.tx_downsample***", bs.size_downsample, bs.size_downsample, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA);
|
||||
Z_Free (data);
|
||||
}
|
||||
|
||||
//Init the screen backup texture
|
||||
if (bs.size_downsample)
|
||||
R_Bloom_InitBackUpTexture(bs.size_downsample);
|
||||
else
|
||||
R_Bloom_InitBackUpTexture(bs.size_sample);
|
||||
}
|
||||
|
||||
void R_BloomRegister(void)
|
||||
{
|
||||
Cvar_Register (&r_bloom, "bloom");
|
||||
Cvar_Register (&r_bloom_alpha, "bloom");
|
||||
Cvar_Register (&r_bloom_diamond_size, "bloom");
|
||||
Cvar_Register (&r_bloom_intensity, "bloom");
|
||||
Cvar_Register (&r_bloom_darken, "bloom");
|
||||
Cvar_Register (&r_bloom_sample_size, "bloom");
|
||||
Cvar_Register (&r_bloom_fast_sample, "bloom");
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_InitBloomTextures
|
||||
=================
|
||||
*/
|
||||
void R_InitBloomTextures(void)
|
||||
{
|
||||
bs.size_sample = 0;
|
||||
if (!r_bloom.ival)
|
||||
return;
|
||||
|
||||
bs.tx_screen = r_nulltex; //this came from a vid_restart, where none of the textures are valid any more.
|
||||
R_Bloom_InitTextures ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_DrawEffect
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_DrawEffect(void)
|
||||
{
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_effect);
|
||||
qglEnable(GL_BLEND);
|
||||
qglBlendFunc(GL_ONE, GL_ONE);
|
||||
qglColor4f(r_bloom_alpha.value, r_bloom_alpha.value, r_bloom_alpha.value, 1.0f);
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
qglBegin(GL_QUADS);
|
||||
qglTexCoord2f (0, bs.smp_t);
|
||||
qglVertex2f (bs.vp_x, bs.vp_y);
|
||||
qglTexCoord2f (0, 0);
|
||||
qglVertex2f (bs.vp_x, bs.vp_y + bs.vp_h);
|
||||
qglTexCoord2f (bs.smp_s, 0);
|
||||
qglVertex2f (bs.vp_x + bs.vp_w, bs.vp_y + bs.vp_h);
|
||||
qglTexCoord2f (bs.smp_s, bs.smp_t);
|
||||
qglVertex2f (bs.vp_x + bs.vp_w, bs.vp_y);
|
||||
qglEnd();
|
||||
|
||||
qglDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
=================
|
||||
R_Bloom_GeneratexCross - alternative bluring method
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_GeneratexCross(void)
|
||||
{
|
||||
int i;
|
||||
static int BLOOM_BLUR_RADIUS = 8;
|
||||
//static float BLOOM_BLUR_INTENSITY = 2.5f;
|
||||
float BLOOM_BLUR_INTENSITY;
|
||||
static float intensity;
|
||||
static float range;
|
||||
|
||||
//set up sample size workspace
|
||||
qglViewport( 0, 0, bs.smp_w, bs.smp_h );
|
||||
qglMatrixMode( GL_PROJECTION );
|
||||
qglLoadIdentity ();
|
||||
qglOrtho(0, bs.smp_w, bs.smp_h, 0, -10, 100);
|
||||
qglMatrixMode( GL_MODELVIEW );
|
||||
qglLoadIdentity ();
|
||||
|
||||
//copy small scene into bs.tx_effect
|
||||
GL_Bind(0, bs.tx_effect);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
|
||||
//start modifying the small scene corner
|
||||
qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
qglEnable(GL_BLEND);
|
||||
|
||||
//darkening passes
|
||||
if( r_bloom_darken.value )
|
||||
{
|
||||
qglBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
|
||||
for(i=0; i<r_bloom_darken->integer ;i++) {
|
||||
R_Bloom_SamplePass( 0, 0 );
|
||||
}
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
}
|
||||
|
||||
//bluring passes
|
||||
if( BLOOM_BLUR_RADIUS ) {
|
||||
|
||||
qglBlendFunc(GL_ONE, GL_ONE);
|
||||
|
||||
range = (float)BLOOM_BLUR_RADIUS;
|
||||
|
||||
BLOOM_BLUR_INTENSITY = r_bloom_intensity.value;
|
||||
//diagonal-cross draw 4 passes to add initial smooth
|
||||
qglColor4f( 0.5f, 0.5f, 0.5f, 1.0);
|
||||
R_Bloom_SamplePass( 1, 1 );
|
||||
R_Bloom_SamplePass( -1, 1 );
|
||||
R_Bloom_SamplePass( -1, -1 );
|
||||
R_Bloom_SamplePass( 1, -1 );
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
|
||||
for(i=-(BLOOM_BLUR_RADIUS+1);i<BLOOM_BLUR_RADIUS;i++) {
|
||||
intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range));
|
||||
if( intensity < 0.05f ) continue;
|
||||
qglColor4f( intensity, intensity, intensity, 1.0f);
|
||||
R_Bloom_SamplePass( i, 0 );
|
||||
//R_Bloom_SamplePass( -i, 0 );
|
||||
}
|
||||
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
|
||||
//for(i=0;i<BLOOM_BLUR_RADIUS;i++) {
|
||||
for(i=-(BLOOM_BLUR_RADIUS+1);i<BLOOM_BLUR_RADIUS;i++) {
|
||||
intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range));
|
||||
if( intensity < 0.05f ) continue;
|
||||
qglColor4f( intensity, intensity, intensity, 1.0f);
|
||||
R_Bloom_SamplePass( 0, i );
|
||||
//R_Bloom_SamplePass( 0, -i );
|
||||
}
|
||||
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
}
|
||||
|
||||
//restore full screen workspace
|
||||
qglViewport( 0, 0, glState.width, glState.height );
|
||||
qglMatrixMode( GL_PROJECTION );
|
||||
qglLoadIdentity ();
|
||||
qglOrtho(0, glState.width, glState.height, 0, -10, 100);
|
||||
qglMatrixMode( GL_MODELVIEW );
|
||||
qglLoadIdentity ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_GeneratexDiamonds
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_GeneratexDiamonds(void)
|
||||
{
|
||||
int i, j;
|
||||
float intensity;
|
||||
|
||||
//set up sample size workspace
|
||||
qglViewport(0, 0, bs.smp_w, bs.smp_h);
|
||||
qglMatrixMode(GL_PROJECTION);
|
||||
qglLoadIdentity();
|
||||
qglOrtho(0, bs.smp_w, bs.smp_h, 0, -10, 100);
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglLoadIdentity();
|
||||
|
||||
//copy small scene into bs.tx_effect
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_effect);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
|
||||
//start modifying the small scene corner
|
||||
qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
qglEnable(GL_BLEND);
|
||||
|
||||
//darkening passes
|
||||
if (r_bloom_darken.value)
|
||||
{
|
||||
qglBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
GL_TexEnv(GL_MODULATE);
|
||||
|
||||
for (i=0; i<r_bloom_darken.value ;i++)
|
||||
{
|
||||
R_Bloom_SamplePass(0, 0);
|
||||
}
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
}
|
||||
|
||||
//bluring passes
|
||||
//qglBlendFunc(GL_ONE, GL_ONE);
|
||||
qglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
{
|
||||
int size = r_bloom_diamond_size.value;
|
||||
float rad = r_bloom_diamond_size.value / 2.0f;
|
||||
float point = (r_bloom_diamond_size.value - 1) / 2.0f;
|
||||
float mult = min(1.0f, r_bloom_intensity.value * 2.0f / rad);
|
||||
|
||||
for (i=0; i<size; i++)
|
||||
{
|
||||
for (j=0; j<size; j++)
|
||||
{
|
||||
float f = ((point + 1.0f) - (fabs(point - i) + fabs(point - j))) / (point + 1.0f);
|
||||
//float f = 1.0f - (fabs(point - i) * fabs(point - j) / (point * point)); // circle/cross?
|
||||
intensity = mult * f;
|
||||
if (intensity < 0.005f)
|
||||
continue;
|
||||
qglColor4f(intensity, intensity, intensity, 1.0);
|
||||
R_Bloom_SamplePass( i-rad, j-rad );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h);
|
||||
|
||||
//restore full screen workspace
|
||||
qglViewport(0, 0, vid.pixelwidth, vid.pixelheight);
|
||||
qglMatrixMode(GL_PROJECTION);
|
||||
qglLoadIdentity ();
|
||||
qglOrtho(0, vid.pixelwidth, vid.pixelheight, 0, -10, 100);
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglLoadIdentity ();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_Bloom_DownsampleView
|
||||
=================
|
||||
*/
|
||||
void R_Bloom_DownsampleView( void )
|
||||
{
|
||||
qglDisable(GL_BLEND);
|
||||
qglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
//stepped downsample
|
||||
if (bs.size_downsample)
|
||||
{
|
||||
int midsample_width = bs.size_downsample * bs.smp_s;
|
||||
int midsample_height = bs.size_downsample * bs.smp_t;
|
||||
|
||||
//copy the screen and draw resized
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bs.vp_x, vid.pixelheight - (bs.vp_y + bs.vp_h), bs.vp_w, bs.vp_h);
|
||||
|
||||
R_Bloom_Quad(0, vid.pixelheight-midsample_height, midsample_width, midsample_height, bs.scr_s, bs.scr_t);
|
||||
|
||||
//now copy into Downsampling (mid-sized) texture
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_downsample);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height);
|
||||
|
||||
//now draw again in bloom size
|
||||
qglColor4f(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
R_Bloom_Quad(0, vid.pixelheight-bs.smp_h, bs.smp_w, bs.smp_h, bs.smp_s, bs.smp_t);
|
||||
|
||||
//now blend the big screen texture into the bloom generation space (hoping it adds some blur)
|
||||
qglEnable(GL_BLEND);
|
||||
qglBlendFunc(GL_ONE, GL_ONE);
|
||||
qglColor4f(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen);
|
||||
R_Bloom_Quad(0, vid.pixelheight-bs.smp_h, bs.smp_w, bs.smp_h, bs.scr_s, bs.scr_t);
|
||||
qglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
qglDisable(GL_BLEND);
|
||||
}
|
||||
else
|
||||
{ //downsample simple
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bs.vp_x, vid.pixelheight - (bs.vp_y + bs.vp_h), bs.vp_w, bs.vp_h);
|
||||
R_Bloom_Quad(0, vid.pixelheight-bs.smp_h, bs.smp_w, bs.smp_h, bs.scr_s, bs.scr_t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_BloomBlend
|
||||
=================
|
||||
*/
|
||||
void R_BloomBlend (void)
|
||||
{
|
||||
int buw, buh;
|
||||
|
||||
if (!bs.size_sample || bs.scr_w < vid.pixelwidth || bs.scr_h < vid.pixelheight)
|
||||
R_Bloom_InitTextures();
|
||||
|
||||
if (bs.scr_w < bs.size_sample ||
|
||||
bs.scr_h < bs.size_sample)
|
||||
return;
|
||||
|
||||
PPL_RevertToKnownState();
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("Note: Bloom doesn't use the backend.")
|
||||
#endif
|
||||
|
||||
//set up full screen workspace
|
||||
qglViewport(0, 0, vid.pixelwidth, vid.pixelheight);
|
||||
qglDisable(GL_DEPTH_TEST);
|
||||
qglMatrixMode(GL_PROJECTION);
|
||||
qglLoadIdentity();
|
||||
qglOrtho(0, vid.pixelwidth, vid.pixelheight, 0, -10, 100);
|
||||
qglMatrixMode(GL_MODELVIEW);
|
||||
qglLoadIdentity();
|
||||
GL_CullFace(0);
|
||||
|
||||
qglDisable(GL_BLEND);
|
||||
qglEnable(GL_TEXTURE_2D);
|
||||
|
||||
qglColor4f(1, 1, 1, 1);
|
||||
|
||||
//set up current sizes
|
||||
bs.vp_x = r_refdef.pxrect.x;
|
||||
bs.vp_y = vid.pixelheight - r_refdef.pxrect.y;
|
||||
bs.vp_w = r_refdef.pxrect.width;
|
||||
bs.vp_h = r_refdef.pxrect.height;
|
||||
bs.scr_s = (float)bs.vp_w / (float)bs.scr_w;
|
||||
bs.scr_t = (float)bs.vp_h / (float)bs.scr_h;
|
||||
if (bs.vp_h > bs.vp_w)
|
||||
{
|
||||
bs.smp_s = (float)bs.vp_w / (float)bs.vp_h;
|
||||
bs.smp_t = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs.smp_s = 1.0f;
|
||||
bs.smp_t = (float)bs.vp_h / (float)bs.vp_w;
|
||||
}
|
||||
bs.smp_w = bs.size_sample * bs.smp_s;
|
||||
bs.smp_h = bs.size_sample * bs.smp_t;
|
||||
|
||||
bs.smp_s = (float)bs.smp_w/bs.size_sample;
|
||||
bs.smp_t = (float)bs.smp_h/bs.size_sample;
|
||||
|
||||
buw = bs.size_backup * bs.smp_s;
|
||||
buh = bs.size_backup * bs.smp_t;
|
||||
|
||||
//copy the screen space we'll use to work into the backup texture
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup);
|
||||
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, buw, buh);
|
||||
|
||||
//create the bloom image
|
||||
R_Bloom_DownsampleView();
|
||||
|
||||
R_Bloom_GeneratexDiamonds();
|
||||
//R_Bloom_GeneratexCross();
|
||||
|
||||
//restore the screen-backup to the screen
|
||||
qglDisable(GL_BLEND);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_backup);
|
||||
qglColor4f(1, 1, 1, 1);
|
||||
R_Bloom_Quad(0,
|
||||
vid.pixelheight - (buh),
|
||||
buw,
|
||||
buh,
|
||||
bs.smp_s,
|
||||
bs.smp_t);
|
||||
|
||||
R_Bloom_DrawEffect();
|
||||
|
||||
|
||||
qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
checkglerror();
|
||||
|
||||
PPL_RevertToKnownState();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -98,6 +98,7 @@ texid_t scenepp_postproc_cube;
|
|||
int scenepp_postproc_cube_size;
|
||||
|
||||
fbostate_t fbo_gameview;
|
||||
fbostate_t fbo_postproc;
|
||||
|
||||
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
|
||||
// I put it here so that only this file need be changed when messing with the post
|
||||
|
@ -111,7 +112,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void)
|
|||
"{\n"
|
||||
"program underwaterwarp\n"
|
||||
"{\n"
|
||||
"map $currentrender\n"
|
||||
"map $sourcecolour\n"
|
||||
"}\n"
|
||||
"{\n"
|
||||
"map $upperoverlay\n"
|
||||
|
@ -129,6 +130,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void)
|
|||
void GL_ShutdownPostProcessing(void)
|
||||
{
|
||||
GLBE_FBO_Destroy(&fbo_gameview);
|
||||
GLBE_FBO_Destroy(&fbo_postproc);
|
||||
R_BloomShutdown();
|
||||
}
|
||||
|
||||
|
@ -388,7 +390,16 @@ void R_SetupGL (float stereooffset)
|
|||
//
|
||||
// set up viewpoint
|
||||
//
|
||||
if (*r_refdef.rt_destcolour[0].texname)
|
||||
if (r_refdef.flags & (RDF_ALLPOSTPROC))
|
||||
{
|
||||
//with fbo postprocessing, we disable all viewport.
|
||||
r_refdef.pxrect.x = 0;
|
||||
r_refdef.pxrect.y = 0;
|
||||
r_refdef.pxrect.width = vid.fbpwidth;
|
||||
r_refdef.pxrect.height = vid.fbpheight;
|
||||
r_refdef.pxrect.maxheight = vid.fbpheight;
|
||||
}
|
||||
else if (*r_refdef.rt_destcolour[0].texname)
|
||||
{
|
||||
//with fbo rendering, we disable all virtual scaling.
|
||||
x = r_refdef.vrect.x;
|
||||
|
@ -407,18 +418,18 @@ void R_SetupGL (float stereooffset)
|
|||
}
|
||||
else
|
||||
{
|
||||
x = r_refdef.vrect.x * (int)vid.pixelwidth/(int)vid.width;
|
||||
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.pixelwidth/(int)vid.width;
|
||||
y = (r_refdef.vrect.y) * (int)vid.pixelheight/(int)vid.height;
|
||||
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.pixelheight/(int)vid.height;
|
||||
x = r_refdef.vrect.x * (int)vid.fbpwidth/(int)vid.width;
|
||||
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * (int)vid.fbpwidth/(int)vid.width;
|
||||
y = (r_refdef.vrect.y) * (int)vid.fbpheight/(int)vid.height;
|
||||
y2 = (r_refdef.vrect.y + r_refdef.vrect.height) * (int)vid.fbpheight/(int)vid.height;
|
||||
|
||||
|
||||
// fudge around because of frac screen scale
|
||||
if (x > 0)
|
||||
x--;
|
||||
if (x2 < vid.pixelwidth)
|
||||
if (x2 < vid.fbpwidth)
|
||||
x2++;
|
||||
if (y2 < vid.pixelheight)
|
||||
if (y2 < vid.fbpheight)
|
||||
y2++;
|
||||
if (y > 0)
|
||||
y--;
|
||||
|
@ -430,21 +441,21 @@ void R_SetupGL (float stereooffset)
|
|||
{
|
||||
w /= 2;
|
||||
if (stereooffset > 0)
|
||||
x += vid.pixelwidth/2;
|
||||
x += vid.fbpwidth/2;
|
||||
}
|
||||
|
||||
r_refdef.pxrect.x = x;
|
||||
r_refdef.pxrect.y = y;
|
||||
r_refdef.pxrect.width = w;
|
||||
r_refdef.pxrect.height = h;
|
||||
r_refdef.pxrect.maxheight = vid.pixelheight;
|
||||
r_refdef.pxrect.maxheight = vid.fbpheight;
|
||||
}
|
||||
fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
|
||||
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
|
||||
|
||||
GL_ViewportUpdate();
|
||||
|
||||
if ((r_waterwarp.value<0 || (r_waterwarp.value && !R_GameRectIsFullscreen())) && (r_viewcontents & FTECONTENTS_FLUID))
|
||||
if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
|
||||
{
|
||||
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
|
||||
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
|
||||
|
@ -510,6 +521,7 @@ void R_SetupGL (float stereooffset)
|
|||
}
|
||||
|
||||
void Surf_SetupFrame(void);
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderScene
|
||||
|
@ -524,8 +536,6 @@ void R_RenderScene (void)
|
|||
int stereomode;
|
||||
int i;
|
||||
int tmpvisents = cl_numvisedicts; /*world rendering is allowed to add additional ents, but we don't want to keep them for recursive views*/
|
||||
if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap))
|
||||
r_refdef.flags |= RDF_NOWORLDMODEL;
|
||||
|
||||
stereomode = r_stereo_method.ival;
|
||||
if (stereomode == 1)
|
||||
|
@ -569,7 +579,7 @@ void R_RenderScene (void)
|
|||
qglDrawBuffer(GL_BACK_RIGHT);
|
||||
break;
|
||||
#endif
|
||||
case 2: //red/cyan
|
||||
case 2: //red/cyan(green+blue)
|
||||
if (stereooffset[i] < 0)
|
||||
qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
else
|
||||
|
@ -593,8 +603,6 @@ void R_RenderScene (void)
|
|||
if (i)
|
||||
qglClear (GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
Surf_SetupFrame();
|
||||
|
||||
TRACE(("dbg: calling R_SetupGL\n"));
|
||||
R_SetupGL (stereooffset[i]);
|
||||
|
||||
|
@ -1320,6 +1328,7 @@ static void R_RenderMotionBlur(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*FIXME: we could use geometry shaders to draw to all 6 faces at once*/
|
||||
qboolean R_RenderScene_Cubemap(void)
|
||||
{
|
||||
|
@ -1490,6 +1499,34 @@ qboolean R_RenderScene_Cubemap(void)
|
|||
*/
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
texid_t R_RenderPostProcess (texid_t sourcetex, int type, shader_t *shader, char *restexname)
|
||||
{
|
||||
if (r_refdef.flags & type)
|
||||
{
|
||||
r_refdef.flags &= ~type;
|
||||
GLBE_FBO_Sources(sourcetex, r_nulltex);
|
||||
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{ //there's other post-processing passes that still need to be applied.
|
||||
//thus we need to write this output to a texture.
|
||||
int w = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
|
||||
int h = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
|
||||
sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32);
|
||||
GLBE_FBO_Update(&fbo_postproc, 0, &sourcetex, 1, r_nulltex, w, h);
|
||||
R2D_ScalePic(0, vid.pixelheight-r_refdef.vrect.height, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp);
|
||||
GLBE_RenderToTextureUpdate2d(true);
|
||||
}
|
||||
else
|
||||
{ //yay, dump it to the screen
|
||||
//update stuff now that we're not rendering the 3d scene
|
||||
R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp);
|
||||
}
|
||||
}
|
||||
|
||||
return sourcetex;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -1502,12 +1539,16 @@ void GLR_RenderView (void)
|
|||
{
|
||||
int dofbo = *r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname;
|
||||
double time1 = 0, time2;
|
||||
texid_t sourcetex = r_nulltex;
|
||||
shader_t *custompostproc = NULL;
|
||||
|
||||
checkglerror();
|
||||
|
||||
if (r_norefresh.value || !vid.pixelwidth || !vid.pixelheight)
|
||||
return;
|
||||
|
||||
//when loading/bugged, its possible that the world is still loading.
|
||||
//in this case, don't act as a wallhack (unless the world is meant to be hidden anyway)
|
||||
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
|
||||
{
|
||||
//FIXME: fbo stuff
|
||||
|
@ -1522,6 +1563,43 @@ void GLR_RenderView (void)
|
|||
// Sys_Error ("R_RenderView: NULL worldmodel");
|
||||
}
|
||||
|
||||
//check if we're underwater (this also limits damage from stereo wallhacks).
|
||||
Surf_SetupFrame();
|
||||
r_refdef.flags &= ~RDF_ALLPOSTPROC;
|
||||
|
||||
//if bloom is
|
||||
if (R_CanBloom())
|
||||
r_refdef.flags |= RDF_BLOOM;
|
||||
|
||||
//check if we can do underwater warp
|
||||
if (cls.protocol != CP_QUAKE2) //quake2 tells us directly
|
||||
{
|
||||
if (r_viewcontents & FTECONTENTS_FLUID)
|
||||
r_refdef.flags |= RDF_UNDERWATER;
|
||||
else
|
||||
r_refdef.flags &= ~RDF_UNDERWATER;
|
||||
}
|
||||
if (r_refdef.flags & RDF_UNDERWATER)
|
||||
{
|
||||
if (!r_waterwarp.value)
|
||||
r_refdef.flags &= ~RDF_UNDERWATER; //no warp at all
|
||||
else if (r_waterwarp.value > 0 && scenepp_waterwarp)
|
||||
r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
|
||||
}
|
||||
|
||||
//
|
||||
if (*r_postprocshader.string)
|
||||
{
|
||||
custompostproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL);
|
||||
if (custompostproc)
|
||||
r_refdef.flags |= RDF_CUSTOMPOSTPROC;
|
||||
}
|
||||
|
||||
//disable stuff if its simply not supported.
|
||||
if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !r_config.texture_non_power_of_two)
|
||||
r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff
|
||||
|
||||
|
||||
BE_Scissor(NULL);
|
||||
if (dofbo)
|
||||
{
|
||||
|
@ -1569,6 +1647,17 @@ void GLR_RenderView (void)
|
|||
flags |= FBO_RB_DEPTH;
|
||||
GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight);
|
||||
}
|
||||
else if (r_refdef.flags & (RDF_ALLPOSTPROC))
|
||||
{
|
||||
//the game needs to be drawn to a texture for post processing
|
||||
vid.fbvwidth = vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
|
||||
vid.fbvheight = vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
|
||||
|
||||
sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, TF_RGBA32);
|
||||
|
||||
GLBE_FBO_Update(&fbo_gameview, FBO_RB_DEPTH, &sourcetex, 1, r_nulltex, vid.fbpwidth, vid.fbpheight);
|
||||
dofbo = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
vid.fbvwidth = vid.width;
|
||||
|
@ -1604,11 +1693,11 @@ void GLR_RenderView (void)
|
|||
time1 = Sys_DoubleTime ();
|
||||
}
|
||||
|
||||
if (!dofbo && !(r_refdef.flags & RDF_NOWORLDMODEL) && R_RenderScene_Cubemap())
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
// if (!dofbo && !(r_refdef.flags & RDF_NOWORLDMODEL) && R_RenderScene_Cubemap())
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// else
|
||||
{
|
||||
GL_SetShaderState2D(false);
|
||||
|
||||
|
@ -1643,40 +1732,17 @@ void GLR_RenderView (void)
|
|||
GL_Set2D (false);
|
||||
}
|
||||
|
||||
//FIXME: support bloom+waterwarp even when drawing to an fbo?
|
||||
//FIXME: force waterwarp to a temp fbo always
|
||||
if ((r_refdef.flags & RDF_NOWORLDMODEL) || dofbo)
|
||||
return;
|
||||
|
||||
if (!R_GameRectIsFullscreen())
|
||||
return;
|
||||
|
||||
if (r_bloom.value)
|
||||
R_BloomBlend();
|
||||
|
||||
// SCENE POST PROCESSING
|
||||
// we check if we need to use any shaders - currently it's just waterwarp
|
||||
if ((r_waterwarp.value>0 && (r_viewcontents & FTECONTENTS_WATER)))
|
||||
{
|
||||
if (scenepp_waterwarp)
|
||||
{
|
||||
R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp);
|
||||
}
|
||||
}
|
||||
|
||||
sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped");
|
||||
sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced");
|
||||
if (r_refdef.flags & RDF_BLOOM)
|
||||
R_BloomBlend(sourcetex, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
|
||||
|
||||
GLBE_FBO_Sources(r_nulltex, r_nulltex);
|
||||
|
||||
if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D)
|
||||
R_RenderMotionBlur();
|
||||
|
||||
if (*r_postprocshader.string)
|
||||
{
|
||||
shader_t *postproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL);
|
||||
if (postproc)
|
||||
{
|
||||
R2D_ScalePic(0, 0, vid.width, vid.height, postproc);
|
||||
}
|
||||
}
|
||||
// if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D)
|
||||
// R_RenderMotionBlur();
|
||||
|
||||
checkglerror();
|
||||
}
|
||||
|
|
|
@ -423,7 +423,8 @@ void D3_GenerateAreas(model_t *mod);
|
|||
//gl_bloom.c
|
||||
#ifdef GLQUAKE
|
||||
void R_BloomRegister(void);
|
||||
void R_BloomBlend(void);
|
||||
qboolean R_CanBloom(void);
|
||||
void R_BloomBlend (texid_t source, int x, int y, int w, int h);
|
||||
void R_BloomShutdown(void);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2291,7 +2291,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"void main ()\n"
|
||||
"{\n"
|
||||
"gl_Position = ftetransform();\n"
|
||||
"v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n"
|
||||
"v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);\n"
|
||||
"v_warp.s = e_time * 0.25 + v_texcoord.s;\n"
|
||||
"v_warp.t = e_time * 0.25 + v_texcoord.t;\n"
|
||||
"v_edge = v_texcoord.xy;\n"
|
||||
|
|
|
@ -12,7 +12,7 @@ uniform float e_time;
|
|||
void main ()
|
||||
{
|
||||
gl_Position = ftetransform();
|
||||
v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;
|
||||
v_stc = vec2(v_texcoord.x, 1.0-v_texcoord.y);
|
||||
v_warp.s = e_time * 0.25 + v_texcoord.s;
|
||||
v_warp.t = e_time * 0.25 + v_texcoord.t;
|
||||
v_edge = v_texcoord.xy;
|
||||
|
|
Loading…
Reference in a new issue