cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
-cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "1", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
+cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
else
R_Mesh_ColorPointer(NULL, 0, 0);
R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
+ R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
+ R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
}
//R_Mesh_TexBindCubeMap(GL20TU_CUBE, R_GetTexture(rsurface.rtlight->currentcubemap));
R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
}
}
-void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, qboolean shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
+void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
{
matrix4x4_t tempmatrix = *matrix;
Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
}
else if (numsurfaces)
r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight_cullmins, rsurface.rtlight_cullmaxs);
+
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
void R_Shadow_DrawEntityShadow(entity_render_t *ent)
relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
- ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->surfacelist, relativeshadowmins, relativeshadowmaxs);
+ ent->model->DrawShadowVolume(ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
void R_Shadow_SetupEntityLight(const entity_render_t *ent)
R_Mesh_TexMatrix(3, &rsurface.entitytolight);
r_refdef.scene.worldmodel->DrawLight(r_refdef.scene.worldentity, numsurfaces, surfacelist, trispvs);
+
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
void R_Shadow_DrawEntityLight(entity_render_t *ent)
R_Shadow_SetupEntityLight(ent);
- model->DrawLight(ent, model->nummodelsurfaces, model->surfacelist, NULL);
+ model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
+
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
void R_DrawRTLight(rtlight_t *rtlight, qboolean visible)
extern void R_SetupView(qboolean allowwaterclippingplane);
extern cvar_t r_shadows;
+extern cvar_t r_shadows_darken;
+extern cvar_t r_shadows_drawafterrtlightning;
+extern cvar_t r_shadows_castfrombmodels;
extern cvar_t r_shadows_throwdistance;
+extern cvar_t r_shadows_throwdirection;
void R_DrawModelShadows(void)
{
int i;
vec3_t relativelightorigin;
vec3_t relativelightdirection;
vec3_t relativeshadowmins, relativeshadowmaxs;
- vec3_t tmp;
+ vec3_t tmp, shadowdir;
float vertex3f[12];
if (!r_drawentities.integer || !gl_stencil)
r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
}
+ // get shadow dir
+ if (r_shadows.integer == 2)
+ {
+ Math_atov(r_shadows_throwdirection.string, shadowdir);
+ VectorNormalize(shadowdir);
+ }
+
R_Shadow_ClearStencil();
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
- // cast shadows from anything that is not a submodel of the map
- if (ent->model && ent->model->DrawShadowVolume != NULL && !ent->model->brush.submodel && (ent->flags & RENDER_SHADOW))
+
+ // cast shadows from anything of the map (submodels are optional)
+ if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
{
relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
-
- if(r_shadows.integer == 2)
- {
- // 2: simpler mode, throw shadows always DOWN
- VectorSet(tmp, 0, 0, -1);
- Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
- }
+ if (r_shadows.integer == 2) // 2: simpler mode, throw shadows always in same direction
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
else
{
if(ent->entitynumber != 0)
VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
RSurf_ActiveModelEntity(ent, false, false);
- ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->surfacelist, relativeshadowmins, relativeshadowmaxs);
+ ent->model->DrawShadowVolume(ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
}
R_Mesh_VertexPointer(vertex3f, 0, 0);
R_Mesh_ColorPointer(NULL, 0, 0);
- // set up a 50% darkening blend on shadowed areas
+ // set up a darkening blend on shadowed areas
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthRange(0, 1);
GL_DepthTest(false);
GL_DepthMask(false);
GL_PolygonOffset(0, 0);CHECKGLERROR
- GL_Color(0, 0, 0, 0.5);
+ GL_Color(0, 0, 0, r_shadows_darken.value);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
qglDepthFunc(GL_ALWAYS);CHECKGLERROR
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery)
{
+ float zdist;
+ vec3_t centerorigin;
// if it's too close, skip it
if (VectorLength(rtlight->color) < (1.0f / 256.0f))
return;
- if (VectorDistance2(rtlight->shadoworigin, r_refdef.view.origin) < 32.0f * 32.0f)
- return;
+ zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
+ if (zdist < 32)
+ return;
if (usequery && r_numqueries + 2 <= r_maxqueries)
{
rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
+ VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
+
CHECKGLERROR
// NOTE: we can't disable depth testing using R_DrawSprite's depthdisable argument, which calls GL_DepthTest, as that's broken in the ATI drivers
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
qglDepthFunc(GL_ALWAYS);
- R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
+ R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
qglDepthFunc(GL_LEQUAL);
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
}
- rtlight->corona_visibility = 1;
+ rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
}
void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
//Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
if (visiblepixels < 1 || allpixels < 1)
return;
- rtlight->corona_visibility *= (float)visiblepixels / (float)allpixels;
+ rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
cscale *= rtlight->corona_visibility;
}
else
if (usequery)
{
GL_ColorMask(0,0,0,0);
- if (r_maxqueries < range + r_refdef.scene.numlights)
+ if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
if (r_maxqueries < R_MAX_OCCLUSION_QUERIES)
{
i = r_maxqueries;
- r_maxqueries = (range + r_refdef.scene.numlights) * 2;
+ r_maxqueries = (range + r_refdef.scene.numlights) * 4;
r_maxqueries = min(r_maxqueries, R_MAX_OCCLUSION_QUERIES);
CHECKGLERROR
qglGenQueriesARB(r_maxqueries - i, r_queries + i);