Underwater / dead / hit / UI blur. Frustum culling for the sun flare.

This commit is contained in:
Andrei Drexler 2011-03-30 20:34:34 +00:00
parent 61f08e2ddd
commit 4c7007f694
11 changed files with 204 additions and 26 deletions

View file

@ -2710,6 +2710,25 @@ Makro - changed to 0..1 instead of 0/1
*/
#define MAX_DAMAGE_ALPHA 0.75
#define MAX_BLEND_TIME 1500
static float CG_GetDamageBlendAlpha( void )
{
float dmg, blend = Com_Clamp(0, 1, cg_RQ3_painblend.value);
if (cg.rq3_blendTime <= 0.f)
return 0.f;
//Clamp blend time
if (cg.rq3_blendTime > MAX_BLEND_TIME)
cg.rq3_blendTime = MAX_BLEND_TIME;
dmg = cg.rq3_trueDamage;
dmg = blend * MAX_DAMAGE_ALPHA * (dmg / 100.0) * (1.0 - (cg.time - cg.damageTime) / cg.rq3_blendTime);
dmg = Com_Clamp(0.f, MAX_DAMAGE_ALPHA, dmg);
return dmg;
}
static void CG_DrawDamageBlend( void )
{
float dmg, blend = Com_Clamp(0, 1, cg_RQ3_painblend.value);
@ -2863,6 +2882,36 @@ void CG_DrawBigPolygon(void) {
trap_R_AddPolyToScene(cgs.media.blackHackShader, 4, Corners);
}
static qboolean CG_UnderWater( void )
{
return 0 != (CG_PointContents(cg.refdef.vieworg, -1) & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA));
}
static qboolean CG_IsDead( void )
{
return cg.snap && cg.snap->ps.stats[STAT_HEALTH] <= 0;
}
static void CG_SetupPostProcess( void )
{
cg.refdefex.blurFactor = CG_GetDamageBlendAlpha();
if (CG_UnderWater() || CG_IsDead())
cg.refdefex.blurFactor = 1.f;
if (CG_IsDead())
cg.refdefex.blurFactor = 1.f;
if (trap_Key_GetCatcher() & KEYCATCH_UI)
cg.refdefex.blurFactor = 1.f;
cg.refdefex.blurFactor = Com_Clamp(0.f, 1.f, cg.refdefex.blurFactor);
if (cg.refdefex.blurFactor > 0.f)
{
cg.refdef.rdflags |= RDF_EXTRA;
}
}
/*
=====================
CG_DrawActive
@ -2894,6 +2943,8 @@ void CG_DrawActive(stereoFrame_t stereoView)
//Makro - sun flare
CG_AddLensFlare(qtrue);
CG_SetupPostProcess();
// draw 3D view
trap_R_RenderScene(&cg.refdef);

View file

@ -1002,6 +1002,7 @@ typedef struct {
// view rendering
refdef_t refdef;
refdefex_t refdefex; // Makro - extra data to be sent to the renderer; it absolutely needs to follow refdef
vec3_t refdefViewAngles; // will be converted to refdef.viewaxis
// zoom key

View file

@ -492,6 +492,8 @@ void CG_ParseSkyPortal(const char *str)
cgs.sunDir[0] = atof(Info_ValueForKey(str, "lx"));
cgs.sunDir[1] = atof(Info_ValueForKey(str, "ly"));
cgs.sunDir[2] = atof(Info_ValueForKey(str, "lz"));
VectorNormalize(cgs.sunDir);
alphamin = Com_Clamp(0.0f, 1.0f, atof(Info_ValueForKey(str, "lamin")));
alphamax = Com_Clamp(0.0f, 1.0f, atof(Info_ValueForKey(str, "lamax")));
sizemin = atof(Info_ValueForKey(str, "lsmin"));

View file

@ -48,6 +48,11 @@
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
#define RDF_HYPERSPACE 4 // teleportation effect
#define RDF_NOFOG 8
#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t
typedef struct {
float blurFactor;
} refdefex_t;
typedef struct {
vec3_t xyz;

View file

@ -412,6 +412,19 @@ void GL_State( unsigned long stateBits )
}
}
//
// color mask
//
if ( diff & GLS_COLORMASK_BITS )
{
qglColorMask(
(stateBits & GLS_REDMASK_FALSE) == 0,
(stateBits & GLS_GREENMASK_FALSE) == 0,
(stateBits & GLS_BLUEMASK_FALSE) == 0,
(stateBits & GLS_ALPHAMASK_FALSE) == 0
);
}
glState.glStateBits = stateBits;
}
@ -700,7 +713,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, tr.sunFlareQuery[tr.sunFlareQueryIndex]);
}
backEnd.hasSunFlare = qtrue;
//backEnd.hasSunFlare = qtrue;
sunflare = qtrue;
} else {
depthRange = qtrue;

View file

@ -1545,6 +1545,8 @@ typedef struct {
float floatTime; // tr.refdef.time / 1000.0
float blurFactor;
// text messages for deform text shaders
char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
@ -2555,12 +2557,13 @@ void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * tr
#define CULL_IN 0 // completely unclipped
#define CULL_CLIP 1 // clipped by one or more planes
#define CULL_OUT 2 // completely outside the clipping planes
void R_LocalNormalToWorld (vec3_t local, vec3_t world);
void R_LocalPointToWorld (vec3_t local, vec3_t world);
void R_LocalNormalToWorld (const vec3_t local, vec3_t world);
void R_LocalPointToWorld (const vec3_t local, vec3_t world);
int R_CullBox (vec3_t bounds[2]);
int R_CullLocalBox (vec3_t bounds[2]);
int R_CullPointAndRadius( vec3_t origin, float radius );
int R_CullLocalPointAndRadius( vec3_t origin, float radius );
int R_CullPointAndRadiusEx( const vec3_t origin, float radius, const cplane_t* frustum, int numPlanes );
int R_CullPointAndRadius( const vec3_t origin, float radius );
int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum);
void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or );

View file

@ -270,7 +270,7 @@ int R_CullBox(vec3_t worldBounds[2]) {
/*
** R_CullLocalPointAndRadius
*/
int R_CullLocalPointAndRadius( vec3_t pt, float radius )
int R_CullLocalPointAndRadius( const vec3_t pt, float radius )
{
vec3_t transformed;
@ -280,13 +280,14 @@ int R_CullLocalPointAndRadius( vec3_t pt, float radius )
}
/*
** R_CullPointAndRadius
** R_CullPointAndRadiusEx
*/
int R_CullPointAndRadius( vec3_t pt, float radius )
int R_CullPointAndRadiusEx( const vec3_t pt, float radius, const cplane_t* frustum, int numPlanes )
{
int i;
float dist;
cplane_t *frust;
const cplane_t *frust;
qboolean mightBeClipped = qfalse;
if ( r_nocull->integer ) {
@ -294,9 +295,9 @@ int R_CullPointAndRadius( vec3_t pt, float radius )
}
// check against frustum planes
for (i = 0 ; i < 4 ; i++)
for (i = 0 ; i < numPlanes ; i++)
{
frust = &tr.viewParms.frustum[i];
frust = &frustum[i];
dist = DotProduct( pt, frust->normal) - frust->dist;
if ( dist < -radius )
@ -317,6 +318,14 @@ int R_CullPointAndRadius( vec3_t pt, float radius )
return CULL_IN; // completely inside frustum
}
/*
** R_CullPointAndRadius
*/
int R_CullPointAndRadius( const vec3_t pt, float radius )
{
return R_CullPointAndRadiusEx(pt, radius, tr.viewParms.frustum, ARRAY_LEN(tr.viewParms.frustum));
}
/*
=================
@ -324,7 +333,7 @@ R_LocalNormalToWorld
=================
*/
void R_LocalNormalToWorld (vec3_t local, vec3_t world) {
void R_LocalNormalToWorld (const vec3_t local, vec3_t world) {
world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0];
world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1];
world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2];
@ -336,7 +345,7 @@ R_LocalPointToWorld
=================
*/
void R_LocalPointToWorld (vec3_t local, vec3_t world) {
void R_LocalPointToWorld (const vec3_t local, vec3_t world) {
world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0] + tr.or.origin[0];
world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1] + tr.or.origin[1];
world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2] + tr.or.origin[2];
@ -348,7 +357,7 @@ R_WorldToLocal
=================
*/
void R_WorldToLocal (vec3_t world, vec3_t local) {
void R_WorldToLocal (const vec3_t world, vec3_t local) {
local[0] = DotProduct(world, tr.or.axis[0]);
local[1] = DotProduct(world, tr.or.axis[1]);
local[2] = DotProduct(world, tr.or.axis[2]);

View file

@ -287,13 +287,13 @@ static void RB_GodRays(void)
}
}
static void RB_BlurAxis(float w, float h, qboolean horizontal)
static void RB_BlurAxis(float w, float h, float strength, qboolean horizontal)
{
float dx, dy;
float xmul, ymul;
float weights[3] = {
0.316216216f,
0.227027027f,
0.316216216f,
0.070270270f,
};
float offsets[3] = {
@ -308,34 +308,104 @@ static void RB_BlurAxis(float w, float h, qboolean horizontal)
xmul /= w;
ymul /= h;
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
xmul *= strength;
ymul *= strength;
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_ALPHAMASK_FALSE );
RB_Color4f(weights[0], weights[0], weights[0], 1.f);
RB_Color4f(weights[0], weights[0], weights[0], 0.f);
RB_DrawQuad(0.f, 0.f, w, h, 0.f, 0.f, 1.f, 1.f);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_ALPHAMASK_FALSE );
RB_Color4f(weights[1], weights[1], weights[1], 1.f);
RB_Color4f(weights[1], weights[1], weights[1], 0.f);
dx = offsets[1] * xmul;
dy = offsets[1] * ymul;
RB_DrawQuad(0.f, 0.f, w, h, dx, dy, 1.f+dx, 1.f+dy);
RB_DrawQuad(0.f, 0.f, w, h, -dx, -dy, 1.f-dx, 1.f-dy);
RB_Color4f(weights[2], weights[2], weights[2], 1.f);
RB_Color4f(weights[2], weights[2], weights[2], 0.f);
dx = offsets[2] * xmul;
dy = offsets[2] * ymul;
RB_DrawQuad(0.f, 0.f, w, h, dx, dy, 1.f+dx, 1.f+dy);
RB_DrawQuad(0.f, 0.f, w, h, -dx, -dy, 1.f-dx, 1.f-dy);
}
static void RB_HBlur(float w, float h)
static void RB_HBlur(float w, float h, float strength)
{
RB_BlurAxis(w, h, qtrue);
RB_BlurAxis(w, h, strength, qtrue);
}
static void RB_VBlur(float w, float h)
static void RB_VBlur(float w, float h, float strength)
{
RB_BlurAxis(w, h, qfalse);
RB_BlurAxis(w, h, strength, qfalse);
}
static void RB_Blur(void)
{
float w, h, w2, h2, w4, h4;
float mul = 1.f;
float factor = Com_Clamp(0.f, 1.f, backEnd.refdef.blurFactor);
int i;
if (factor <= 0.f)
return;
// viewport dimensions
w = glConfig.vidWidth;
h = glConfig.vidHeight;
w2 = glConfig.vidWidth / 2;
h2 = glConfig.vidHeight / 2;
w4 = glConfig.vidWidth / 4;
h4 = glConfig.vidHeight / 4;
RB_SetGL2D_Level(1);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
RB_Color4f(mul, mul, mul, 1.f);
// first, downsample the main framebuffers
R_FBO_Bind(tr.fbo.quarter[0]);
R_FBO_BindColorBuffer(tr.fbo.full[0], 0);
RB_DrawQuad(0.f, 0.f, w2, h2, 0.f, 0.f, 1.f, 1.f);
RB_SetGL2D_Level(2);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
RB_Color4f(mul, mul, mul, 1.f);
R_FBO_Bind(tr.fbo.tiny[0]);
R_FBO_BindColorBuffer(tr.fbo.quarter[0], 0);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
mul = 1.f;
RB_Color4f(mul, mul, mul, 1.f);
RB_DrawQuad(0.f, 0.f, w4, h4, 0.f, 0.f, 1.f, 1.f);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_REDMASK_FALSE | GLS_BLUEMASK_FALSE | GLS_GREENMASK_FALSE );
GL_Bind(tr.whiteImage);
mul = 1.f;
RB_Color4f(mul, mul, mul, 1.f);
RB_DrawQuad(0.f, 0.f, w4, h4, 0.f, 0.f, 1.f, 1.f);
//for (i=0; i<2; ++i)
{
R_FBO_Bind(tr.fbo.tiny[1]);
R_FBO_BindColorBuffer(tr.fbo.tiny[0], 0);
RB_HBlur(w4, h4, factor);
R_FBO_Bind(tr.fbo.tiny[0]);
R_FBO_BindColorBuffer(tr.fbo.tiny[1], 0);
RB_VBlur(w4, h4, factor);
}
RB_SetGL2D_Level(0);
R_FBO_BindColorBuffer(R_FBO_Bind(tr.fbo.full[0]), 0);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
mul = 1.f;
RB_Color4f(mul, mul, mul, factor);
RB_DrawQuad(0.f, 0.f, w, h, 0.f, 0.f, 1.f, 1.f);
GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
}
void RB_FBO_Set2D(void)
@ -363,7 +433,7 @@ void RB_FBO_Set2D(void)
GLSL_SetUniform_Texture0Matrix(sp, matrix);
GLSL_SetUniform_Texture1Env(sp, 0);
GLSL_SetUniform_ColorGen(sp, CGEN_CONST);
GLSL_SetUniform_AlphaGen(sp, AGEN_IDENTITY);
GLSL_SetUniform_AlphaGen(sp, AGEN_CONST);
RB_Color4f = &GLSL_Color4f;
}
@ -429,4 +499,5 @@ void RB_PostProcess(void)
RB_FBO_Set2D();
RB_GodRays();
RB_Blur();
}

View file

@ -360,6 +360,13 @@ void RE_RenderScene( const refdef_t *fd ) {
}
}
// Makro - copy exta info if present
if (fd->rdflags & RDF_EXTRA) {
const refdefex_t* extra = (const refdefex_t*) (fd+1);
tr.refdef.blurFactor = extra->blurFactor;
} else {
tr.refdef.blurFactor = 0.f;
}
// derived info

View file

@ -289,9 +289,17 @@ static void RB_SurfaceSprite( void ) {
}
if (ent->e.renderfx & RF_SUNFLARE) {
if (backEnd.hasSunFlare)
{
ri.Printf(PRINT_WARNING, "Multiple sun flares not supported\n");
return;
}
if (R_CullPointAndRadiusEx(ent->e.origin, ent->e.radius, backEnd.viewParms.frustum, ARRAY_LEN(backEnd.viewParms.frustum)) == CULL_OUT)
return;
colors[0] = colors[1] = colors[2] = colors[3] = ent->e.shaderRGBA[glRefConfig.framebufferObject];
if (colors[0] == 0)
return;
backEnd.hasSunFlare = qtrue;
} else {
Vector4Copy(ent->e.shaderRGBA, colors);
}

View file

@ -56,6 +56,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define RDF_HYPERSPACE 0x0004 // teleportation effect
// JBravo: Fox fixes
#define RDF_NOFOG 0x0008 // don't apply fog
#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t
// Makro - this should mirror the definition in cgame
// TODO: single tr_types.h file!
typedef struct {
float blurFactor;
} refdefex_t;
typedef struct {
vec3_t xyz;