" vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
" //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
" vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
-" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
+" float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
" gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
"}\n"
"\n"
"#ifdef USEDIFFUSE\n"
" // get the surface normal and the gloss color\n"
"# ifdef USEVERTEXTEXTUREBLEND\n"
-" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5));\n"
+" myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
"# ifdef USESPECULAR\n"
-" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord), myhalf3(texture2D(Texture_Gloss, TexCoord)), TexCoord), terrainblend);\n"
+" myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
"# endif\n"
"# else\n"
" myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
typedef enum shaderpermutation_e
{
- SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<0, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
- SHADERPERMUTATION_COLORMAPPING = 1<<1, // indicates this is a colormapped skin
- SHADERPERMUTATION_CONTRASTBOOST = 1<<2, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
- SHADERPERMUTATION_FOG = 1<<3, // tint the color by fog color or black if using additive blend mode
- SHADERPERMUTATION_CUBEFILTER = 1<<4, // (lightsource) use cubemap light filter
- SHADERPERMUTATION_GLOW = 1<<5, // (lightmap) blend in an additive glow texture
- SHADERPERMUTATION_DIFFUSE = 1<<6, // (lightsource) whether to use directional shading
+ SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
+ SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
+ SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
+ SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
+ SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
+ SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
+ SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
// NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
{
+ {"#define USEDIFFUSE\n", " diffuse"},
{"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
{"#define USECOLORMAPPING\n", " colormapping"},
{"#define USECONTRASTBOOST\n", " contrastboost"},
{"#define USEFOG\n", " fog"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
- {"#define USEDIFFUSE\n", " diffuse"},
{"#define USESPECULAR\n", " specular"},
{"#define USEREFLECTION\n", " reflection"},
{"#define USEOFFSETMAPPING\n", " offsetmapping"},
{
int i;
double slopex, slopey;
+ vec3_t forward, left, up, origin;
- // break apart the view matrix into vectors for various purposes
- Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
- VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // we can't trust r_refdef.view.forward and friends in reflected scenes
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
#if 0
r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
{
slopex = 1.0 / r_refdef.view.frustum_x;
slopey = 1.0 / r_refdef.view.frustum_y;
- VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
- VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
- VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal);
- VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal);
- VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
+ VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
+ VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
+ VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
+ VectorCopy(forward, r_refdef.view.frustum[4].normal);
// Leaving those out was a mistake, those were in the old code, and they
// fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
VectorNormalize(r_refdef.view.frustum[3].normal);
// calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[0]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[1]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[2]);
- VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[3]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
+ VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
}
else
{
- VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
- VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
- VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
- VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
- VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
+ VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
+ VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
+ VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
+ VectorCopy(forward, r_refdef.view.frustum[4].normal);
r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
// Quake2 has it disabled as well.
// rotate R_VIEWFORWARD right by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
//r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
//PlaneClassify(&frustum[0]);
// rotate R_VIEWFORWARD left by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
//r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
//PlaneClassify(&frustum[1]);
// rotate R_VIEWFORWARD up by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
//r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
//PlaneClassify(&frustum[2]);
// rotate R_VIEWFORWARD down by FOV_X/2 degrees
- //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
+ //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
//r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
//PlaneClassify(&frustum[3]);
// nearclip plane
- //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
+ //VectorCopy(forward, r_refdef.view.frustum[4].normal);
//r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
//PlaneClassify(&frustum[4]);
}
R_View_UpdateEntityVisible();
}
-void R_SetupView(void)
+void R_SetupView(qboolean allowwaterclippingplane)
{
if (!r_refdef.view.useperspective)
GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
- if (r_refdef.view.useclipplane)
+ if (r_refdef.view.useclipplane && allowwaterclippingplane)
{
// LordHavoc: couldn't figure out how to make this approach the
vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
- R_SetupView();
+ R_SetupView(true);
GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
{
// render reflected scene and copy into texture
Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
+ // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
+ Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
r_refdef.view.clipplane = p->plane;
// reverse the cullface settings for this render
r_refdef.view.cullface_front = GL_FRONT;
r_refdef.view.colorscale = r_hdr_scenebrightness.value;
+ // break apart the view matrix into vectors for various purposes
+ // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
+ // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
+ Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
+ VectorNegate(r_refdef.view.left, r_refdef.view.right);
+ // make an inverted copy of the view matrix for tracking sprites
+ Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+
R_Shadow_UpdateWorldLightSelection();
R_Bloom_StartFrame();
static void R_DrawEntityBBoxes(void);
void R_RenderScene(qboolean addwaterplanes)
{
- Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
+ r_refdef.stats.renders++;
+
R_UpdateFogColor();
if (addwaterplanes)
}
else
GL_CullFace(r_refdef.view.cullface_back);
+ GL_CullFace(GL_NONE);
GL_DepthMask(false);
GL_DepthRange(0, depthshort ? 0.0625 : 1);
t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
if (ent->flags & RENDER_VIEWMODEL)
t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
+ if (t->backgroundnumskinframes)
+ t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
{
if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
}
else
- {
- if (t->backgroundnumskinframes)
- t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
- }
- // make sure that the waterscroll matrix is used on water surfaces when
// there is no tcmod
if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
t->currenttexmatrix = r_waterscrollmatrix;
if (skyrendernow)
{
skyrendernow = false;
+ // we have to force off the water clipping plane while rendering sky
+ R_SetupView(false);
R_Sky();
+ R_SetupView(true);
// restore entity matrix
R_Mesh_Matrix(&rsurface.matrix);
}