cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
+cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
+cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
+cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
+cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
+
cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
extern cvar_t v_glslgamma;
{"#define USEFOGINSIDE\n", " foginside"},
{"#define USEFOGOUTSIDE\n", " fogoutside"},
{"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
+ {"#define USEFOGALPHAHACK\n", " fogalphahack"},
{"#define USEGAMMARAMPS\n", " gammaramps"},
{"#define USECUBEFILTER\n", " cubefilter"},
{"#define USEGLOW\n", " glow"},
{"#define USEREFLECTCUBE\n", " reflectcube"},
{"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
{"#define USEBOUNCEGRID\n", " bouncegrid"},
+ {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
};
// NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
int loc_LightColor;
int loc_LightDir;
int loc_LightPosition;
- int loc_OffsetMapping_Scale;
+ int loc_OffsetMapping_ScaleSteps;
int loc_PixelSize;
int loc_ReflectColor;
int loc_ReflectFactor;
SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
- SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
+ SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
+ SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
};
-#define SHADERSTATICPARMS_COUNT 6
+#define SHADERSTATICPARMS_COUNT 7
static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
static int shaderstaticparms_count = 0;
// detect all
if (r_glsl_saturation_redcompensate.integer)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
+ if (r_glsl_vertextextureblend_usebothalphas.integer)
+ R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
if (r_shadow_glossexact.integer)
R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
if (r_glsl_postprocess.integer)
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
+ R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
}
/// information about each possible shader permutation
strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
+ // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
+ if(vid.support.gl20shaders130)
+ {
+ vertstrings_list[vertstrings_count++] = "#version 130\n";
+ geomstrings_list[geomstrings_count++] = "#version 130\n";
+ fragstrings_list[fragstrings_count++] = "#version 130\n";
+ vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
+ geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
+ fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
+ }
+
// the first pretext is which type of shader to compile as
// (later these will all be bound together as a program object)
vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
- p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
+ p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
D3DPSREGISTER_LightColor = 21,
D3DPSREGISTER_LightDir = 22, // unused
D3DPSREGISTER_LightPosition = 23,
- D3DPSREGISTER_OffsetMapping_Scale = 24,
+ D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
D3DPSREGISTER_PixelSize = 25,
D3DPSREGISTER_ReflectColor = 26,
D3DPSREGISTER_ReflectFactor = 27,
extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
extern rtexture_t *r_shadow_prepasslightingspeculartexture;
-static qboolean R_BlendFuncAllowsColormod(int src, int dst)
+
+#define BLENDFUNC_ALLOWS_COLORMOD 1
+#define BLENDFUNC_ALLOWS_FOG 2
+#define BLENDFUNC_ALLOWS_FOG_HACK0 4
+#define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
+#define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
+static int R_BlendFuncFlags(int src, int dst)
{
+ int r = 0;
+
// a blendfunc allows colormod if:
// a) it can never keep the destination pixel invariant, or
// b) it can keep the destination pixel invariant, and still can do so if colormodded
// this is to prevent unintended side effects from colormod
- // in formulas:
- // IF there is a (s, sa) for which for all (d, da),
- // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
- // THEN, for this (s, sa) and all (colormod, d, da):
- // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
- // OBVIOUSLY, this means that
- // s*colormod * src(s*colormod, d, sa, da) = 0
- // dst(s*colormod, d, sa, da) = 1
-
- // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
-
- // main condition to leave dst color invariant:
- // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
- // src == GL_ZERO:
- // s * 0 + d * dst(s, d, sa, da) == d
- // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is a problem for GL_SRC_COLOR only
- // src == GL_ONE:
- // s + d * dst(s, d, sa, da) == d
- // => s == 0
- // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is never problematic for these
- // src == GL_SRC_COLOR:
- // s*s + d * dst(s, d, sa, da) == d
- // => s == 0
- // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is never problematic for these
- // src == GL_ONE_MINUS_SRC_COLOR:
- // s*(1-s) + d * dst(s, d, sa, da) == d
- // => s == 0 or s == 1
- // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is a problem for GL_SRC_COLOR only
- // src == GL_DST_COLOR
- // s*d + d * dst(s, d, sa, da) == d
- // => s == 1
- // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is always a problem
- // or
- // => s == 0
- // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is never problematic for these
- // => BUT, we do not know s! We must assume it is problematic
- // then... except in GL_ONE case, where we know all invariant
- // cases are fine
- // src == GL_ONE_MINUS_DST_COLOR
- // s*(1-d) + d * dst(s, d, sa, da) == d
- // => s == 0 (1-d is impossible to handle for our desired result)
- // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is never problematic for these
- // src == GL_SRC_ALPHA
- // s*sa + d * dst(s, d, sa, da) == d
- // => s == 0, or sa == 0
- // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod breaks in the case GL_SRC_COLOR only
- // src == GL_ONE_MINUS_SRC_ALPHA
- // s*(1-sa) + d * dst(s, d, sa, da) == d
- // => s == 0, or sa == 1
- // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod breaks in the case GL_SRC_COLOR only
- // src == GL_DST_ALPHA
- // s*da + d * dst(s, d, sa, da) == d
- // => s == 0
- // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
- // => colormod is never problematic for these
-
- switch(src)
- {
- case GL_ZERO:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- if(dst == GL_SRC_COLOR)
- return false;
- return true;
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- return true;
- case GL_DST_COLOR:
- if(dst == GL_ONE)
- return true;
- return false;
- default:
- return false;
- }
+ // a blendfunc allows fog if:
+ // blend(fog(src), fog(dst)) == fog(blend(src, dst))
+ // this is to prevent unintended side effects from fog
+
+ // these checks are the output of fogeval.pl
+
+ r |= BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+ if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+ if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
+ if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+ if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+ if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+ if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
+ if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
+ if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
+
+ return r;
}
+
void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
{
// select a permutation of the lighting shader appropriate to this
// fragment shader on features that are not being used
unsigned int permutation = 0;
unsigned int mode = 0;
- qboolean allow_colormod;
+ int blendfuncflags;
static float dummy_colormod[3] = {1, 1, 1};
float *colormod = rsurface.colormod;
float m16f[16];
r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
permutation |= SHADERPERMUTATION_ALPHAKILL;
+ if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
+ permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
if (rsurfacepass == RSURFPASS_BACKGROUND)
{
// distorted background
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
{
mode = SHADERMODE_WATER;
- if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
- permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
{
// this is the right thing to do for wateralpha
GL_BlendFunc(GL_ONE, GL_ZERO);
- allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+ blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
}
else
{
// this is the right thing to do for entity alpha
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
{
mode = SHADERMODE_REFRACTION;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
mode = SHADERMODE_GENERIC;
permutation |= SHADERPERMUTATION_DIFFUSE;
GL_BlendFunc(GL_ONE, GL_ZERO);
- allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+ blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
}
}
else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
GL_BlendFunc(GL_ONE, GL_ZERO);
- allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
+ blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
}
else if (rsurfacepass == RSURFPASS_RTLIGHT)
{
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
+ blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
{
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
{
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
if (r_shadow_bouncegridtexture)
+ {
permutation |= SHADERPERMUTATION_BOUNCEGRID;
+ if (r_shadow_bouncegriddirectional)
+ permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+ }
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
{
if (rsurface.texture->reflectmasktexture)
permutation |= SHADERPERMUTATION_REFLECTCUBE;
if (r_shadow_bouncegridtexture)
+ {
permutation |= SHADERPERMUTATION_BOUNCEGRID;
+ if (r_shadow_bouncegriddirectional)
+ permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+ }
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
else
{
mode = SHADERMODE_VERTEXCOLOR;
}
if (r_shadow_bouncegridtexture)
+ {
permutation |= SHADERPERMUTATION_BOUNCEGRID;
+ if (r_shadow_bouncegriddirectional)
+ permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
+ }
GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
- allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
+ blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
}
- if(!allow_colormod)
+ if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
colormod = dummy_colormod;
+ if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
+ permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
+ if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
+ permutation |= SHADERPERMUTATION_FOGALPHAHACK;
switch(vid.renderpath)
{
case RENDERPATH_D3D9:
hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
}
// additive passes are only darkened by fog, not tinted
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+ if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
else
hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
- hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
+ hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
// additive passes are only darkened by fog, not tinted
if (r_glsl_permutation->loc_FogColor >= 0)
{
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+ if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
else
qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
- if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
+ if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
- if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
+ if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
}
// additive passes are only darkened by fog, not tinted
- if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
+ if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
else
DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
- DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
+ DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
permutation |= SHADERPERMUTATION_CUBEFILTER;
if (diffusescale > 0)
permutation |= SHADERPERMUTATION_DIFFUSE;
- if (specularscale > 0)
+ if (specularscale > 0 && r_shadow_gloss.integer > 0)
permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
if (r_shadow_usingshadowmap2d)
{
r_qwskincache = NULL;
r_qwskincache_size = 0;
+ // due to caching of texture_t references, the collision cache must be reset
+ Collision_Cache_Reset(true);
+
// set up r_skinframe loading system for textures
memset(&r_skinframe, 0, sizeof(r_skinframe));
r_skinframe.loadsequence = 1;
Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
Cvar_RegisterVariable(&r_fog_exp2);
+ Cvar_RegisterVariable(&r_fog_clear);
Cvar_RegisterVariable(&r_drawfog);
Cvar_RegisterVariable(&r_transparentdepthmasking);
Cvar_RegisterVariable(&r_texture_dds_load);
Cvar_RegisterVariable(&r_glsl);
Cvar_RegisterVariable(&r_glsl_deluxemapping);
Cvar_RegisterVariable(&r_glsl_offsetmapping);
+ Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
+ Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
Cvar_RegisterVariable(&r_glsl_postprocess);
Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
Cvar_RegisterVariable(&r_test);
Cvar_RegisterVariable(&r_glsl_saturation);
Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
+ Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
Cvar_RegisterVariable(&r_framedatasize);
if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
Cvar_SetValue("r_fullbrights", 0);
{
if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
org[2] = org[2] + r_overheadsprites_pushback.value;
- R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
+ R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
}
else
R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
blendfunc2 = GL_ZERO;
}
// don't colormod evilblend textures
- if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
+ if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
VectorSet(t->lightmapcolor, 1, 1, 1);
depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
float f;
const float *v;
float *c;
+
+ // fake shading
+ rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
+ rsurface.passcolor4f_vertexbuffer = 0;
+ rsurface.passcolor4f_bufferoffset = 0;
+
for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
{
f = 1 - RSurf_FogVertex(v);
vertex3f = rsurface.modelvertex3f;
normal3f = rsurface.modelnormal3f;
- for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ if (normal3f)
+ {
+ for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ {
+ index = 3*e[cornerindex];
+ VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
+ }
+ }
+ else
{
- index = 3*e[cornerindex];
- VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
+ for (cornerindex = 0;cornerindex < 3;cornerindex++)
+ {
+ index = 3*e[cornerindex];
+ VectorCopy(vertex3f + index, v[cornerindex]);
+ }
}
+
// cull backfaces
//TriangleNormal(v[0], v[1], v[2], normal);
//if (DotProduct(normal, localnormal) < 0.0f)