R_SHADOW_RENDERMODE_LIGHT_GLSL,
R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
R_SHADOW_RENDERMODE_VISIBLELIGHTING,
- R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
R_SHADOW_RENDERMODE_SHADOWMAP2D,
+ R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
}
r_shadow_rendermode_t;
+typedef enum r_shadow_shadowmode_e
+{
+ R_SHADOW_SHADOWMODE_STENCIL,
+ R_SHADOW_SHADOWMODE_SHADOWMAP2D,
+ R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
+ R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
+}
+r_shadow_shadowmode_t;
+
r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
int r_shadow_shadowmapside;
float r_shadow_shadowmap_texturescale[2];
float r_shadow_shadowmap_parameters[4];
+#if 0
int r_shadow_drawbuffer;
int r_shadow_readbuffer;
-int r_shadow_cullface;
+#endif
+int r_shadow_cullface_front, r_shadow_cullface_back;
GLuint r_shadow_fborectangle;
-GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6];
+GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
GLuint r_shadow_fbo2d;
-int r_shadow_shadowmode;
+r_shadow_shadowmode_t r_shadow_shadowmode;
int r_shadow_shadowmapfilterquality;
int r_shadow_shadowmaptexturetype;
-int r_shadow_shadowmapprecision;
+int r_shadow_shadowmapdepthbits;
int r_shadow_shadowmapmaxsize;
qboolean r_shadow_shadowmapvsdct;
qboolean r_shadow_shadowmapsampler;
cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
+cvar_t r_shadow_dot3 = {CVAR_SAVE, "r_shadow_dot3", "0", "enables use of (slow) per pixel lighting on GL1.3 hardware"};
cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
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_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"};
cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
-cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "0", "shadowmap texture types: 0 = auto-select, 1 = 2D, 2 = rectangle, 3 = cubemap"};
+cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
-cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "24", "requested minimum shadowmap texture precision"};
+cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
-cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
+cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
+//cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
+//cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
+cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
+cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
cachepic_t *r_editlights_sprcubemaplight;
cachepic_t *r_editlights_sprcubemapnoshadowlight;
cachepic_t *r_editlights_sprselection;
+extern cvar_t gl_max_size;
void R_Shadow_SetShadowMode(void)
{
- r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
+ r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4);
r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
- r_shadow_shadowmapprecision = r_shadow_shadowmapping_precision.integer;
+ r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
r_shadow_shadowmaplod = -1;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
- r_shadow_shadowmode = 0;
- if(r_shadow_shadowmapping.integer)
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
+ if(r_shadow_shadowmapping.integer && r_glsl.integer && gl_support_fragment_shader && gl_support_ext_framebuffer_object)
{
if(r_shadow_shadowmapfilterquality < 0)
{
break;
}
}
- r_shadow_shadowmode = r_shadow_shadowmaptexturetype;
- if(r_shadow_shadowmode <= 0)
- {
+ switch (r_shadow_shadowmaptexturetype)
+ {
+ case 0:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
+ break;
+ case 1:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
+ break;
+ case 2:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
+ break;
+ default:
if((gl_support_amd_texture_texture4 || gl_support_arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
- r_shadow_shadowmode = 1;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
else if(gl_texturerectangle)
- r_shadow_shadowmode = 2;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
else
- r_shadow_shadowmode = 1;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
+ break;
}
}
}
r_shadow_fbo2d = 0;
CHECKGLERROR
for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
- if (r_shadow_fbocubeside[i][0])
- qglDeleteFramebuffersEXT(6, r_shadow_fbocubeside[i]);
+ if (r_shadow_fbocubeside[i])
+ qglDeleteFramebuffersEXT(1, &r_shadow_fbocubeside[i]);
memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
CHECKGLERROR
r_shadow_attenuationgradienttexture = NULL;
r_shadow_attenuation2dtexture = NULL;
r_shadow_attenuation3dtexture = NULL;
- r_shadow_shadowmode = 0;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
r_shadow_shadowmaprectangletexture = NULL;
r_shadow_shadowmap2dtexture = NULL;
memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmaplod = 0;
- r_shadow_shadowmapfilterquality = 0;
- r_shadow_shadowmaptexturetype = 0;
- r_shadow_shadowmapprecision = 0;
+ r_shadow_shadowmapfilterquality = -1;
+ r_shadow_shadowmaptexturetype = -1;
+ r_shadow_shadowmapdepthbits = 0;
r_shadow_shadowmapvsdct = false;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
{
Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+ Cvar_RegisterVariable(&r_shadow_dot3);
Cvar_RegisterVariable(&r_shadow_usenormalmap);
Cvar_RegisterVariable(&r_shadow_debuglight);
Cvar_RegisterVariable(&r_shadow_gloss);
Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
- Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
- Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
+// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
+// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
Cvar_RegisterVariable(&r_shadow_culltriangles);
Cvar_RegisterVariable(&r_shadow_polygonfactor);
Cvar_RegisterVariable(&r_shadow_polygonoffset);
return mask;
}
-int R_Shadow_FrustumCullSides(rtlight_t *rtlight, float size, float border)
+int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
{
- static const vec3_t lightnormals[6] = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 } };
- vec3_t frustumdir;
- int i, j;
- int sides = 0x3F;
- // cos(45 + bias)
- float scale = 0.707106781186548*size/(size - 2*border);
+ int i;
+ vec3_t p, n;
+ int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
+ float scale = (size - 2*border)/size, len;
+ float bias = border / (float)(size - border), dp, dn, ap, an;
+ // check if cone enclosing side would cross frustum plane
+ scale = 2 / (scale*scale + 2);
for (i = 0;i < 5;i++)
{
if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
continue;
- Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, frustumdir);
- VectorNormalize(frustumdir);
- for (j = 0;j < 6;j++)
- if(DotProduct(frustumdir, lightnormals[j]) < -scale)
- sides &= ~(1 << j);
- }
- if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) > r_refdef.farclip - r_refdef.nearclip + 0.03125)
+ Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
+ len = scale*VectorLength2(n);
+ if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
+ if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
+ if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
+ }
+ if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
+ {
+ Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
+ len = scale*VectorLength(n);
+ if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
+ if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
+ if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
+ }
+ // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
+ // check if frustum corners/origin cross plane sides
+ for (i = 0;i < 5;i++)
{
- Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, frustumdir);
- VectorNormalize(frustumdir);
- for (j = 0;j < 6;j++)
- if (DotProduct(frustumdir, lightnormals[j]) > scale)
- sides &= ~(1 << j);
- }
- return sides;
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
+ dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn),
+ masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+ dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn),
+ masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+ dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn),
+ masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ }
+ return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
}
int R_Shadow_ChooseSidesFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const matrix4x4_t *worldtolight, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs, int *totals)
int x, y, z;
float intensity, dist;
unsigned int *data;
+ R_Shadow_FreeShadowMaps();
R_FreeTexturePool(&r_shadow_texturepool);
r_shadow_texturepool = R_AllocTexturePool();
r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
void R_Shadow_RenderMode_Begin(void)
{
+#if 0
GLint drawbuffer;
GLint readbuffer;
+#endif
R_Shadow_ValidateCvars();
if (!r_shadow_attenuation2dtexture
if (r_glsl.integer && gl_support_fragment_shader)
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
- else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil)
+ else if (gl_dot3arb && gl_texturecubemap && r_shadow_dot3.integer && gl_stencil)
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_DOT3;
else
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
CHECKGLERROR
+#if 0
qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
r_shadow_drawbuffer = drawbuffer;
r_shadow_readbuffer = readbuffer;
- r_shadow_cullface = r_refdef.view.cullface_back;
+#endif
+ r_shadow_cullface_front = r_refdef.view.cullface_front;
+ r_shadow_cullface_back = r_refdef.view.cullface_back;
}
void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
{
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
}
+#if 0
qglDrawBuffer(r_shadow_drawbuffer);CHECKGLERROR
qglReadBuffer(r_shadow_readbuffer);CHECKGLERROR
+#endif
R_SetViewport(&r_refdef.view.viewport);
GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
R_Mesh_ColorPointer(NULL, 0, 0);
qglStencilMask(~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
- r_refdef.view.cullface_back = r_shadow_cullface;
+ r_refdef.view.cullface_front = r_shadow_cullface_front;
+ r_refdef.view.cullface_back = r_shadow_cullface_back;
GL_CullFace(r_refdef.view.cullface_back);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
{
- int i;
int status;
int maxsize;
float nearclip, farclip, bias;
r_viewport_t viewport;
+ GLuint fbo = 0;
CHECKGLERROR
maxsize = r_shadow_shadowmapmaxsize;
nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
r_shadow_shadowmapside = side;
r_shadow_shadowmapsize = size;
- if (r_shadow_shadowmode == 1)
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
{
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
+
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
{
#if 1
int w = maxsize*2, h = gl_support_arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
- r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+ r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
-#endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmap2dtexture)
- {
- // render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
+ // render depth into the fbo, do not render color at all
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+#endif
}
- R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ CHECKGLERROR
+ if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
}
- else if (r_shadow_shadowmode == 2)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
{
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
+
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
if (!r_shadow_shadowmaprectangletexture)
{
#if 1
- r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+ r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
-#endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmaprectangletexture)
- {
// render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+#endif
}
- R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ CHECKGLERROR
+ if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
r_shadow_shadowmap_texturescale[0] = 1.0f;
r_shadow_shadowmap_texturescale[1] = 1.0f;
- r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
}
- else if (r_shadow_shadowmode == 3)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
{
+ r_shadow_shadowmap_parameters[0] = 1.0f;
+ r_shadow_shadowmap_parameters[1] = 1.0f;
+ R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
+
// simple cube approach
if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
{
#if 1
- r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
- qglGenFramebuffersEXT(6, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
- for (i = 0;i < 6;i++)
- {
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][i]);CHECKGLERROR
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
- }
- #endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
- {
+ r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+ qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
// render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][side]);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+ #endif
}
- R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
- r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- r_shadow_shadowmap_parameters[0] = 1.0f;
- r_shadow_shadowmap_parameters[1] = 1.0f;
+ CHECKGLERROR
+ if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
+ r_shadow_shadowmap_texturescale[0] = 0.0f;
+ r_shadow_shadowmap_texturescale[1] = 0.0f;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
}
- CHECKGLERROR
- R_SetViewport(&viewport);
- GL_PolygonOffset(0, 0);
- if(r_shadow_shadowmode >= 1 && r_shadow_shadowmode <= 2)
+
+ R_Shadow_RenderMode_Reset();
+ if (fbo)
{
- static qboolean cullfront[6] = { false, true, false, true, true, false };
- if(cullfront[side]) r_refdef.view.cullface_back = r_refdef.view.cullface_front;
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
+ R_SetupDepthOrShadowShader();
}
- GL_CullFace(r_refdef.view.cullface_back);
- GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+ else
+ {
+ R_SetupShowDepthShader();
+ qglClearColor(1,1,1,1);CHECKGLERROR
+ }
+ CHECKGLERROR
+ GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
- qglClearDepth(1);CHECKGLERROR
+ qglClearDepth(1);
CHECKGLERROR
+
+init_done:
+ R_SetViewport(&viewport);
+ GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+ if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE)
+ {
+ int flipped = (side&1)^(side>>2);
+ r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
+ r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
+ GL_CullFace(r_refdef.view.cullface_back);
+ }
+ else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE)
+ {
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
+ }
if (clear)
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
CHECKGLERROR
void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
{
+ if (transparent)
+ {
+ r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
+ r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
+ r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
+ r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
+ }
CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
CHECKGLERROR
if (shadowmapping)
{
- if (r_shadow_shadowmode == 1)
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
{
r_shadow_usingshadowmap2d = true;
R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
CHECKGLERROR
}
- else if (r_shadow_shadowmode == 2)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
{
r_shadow_usingshadowmaprect = true;
R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
CHECKGLERROR
}
- else if (r_shadow_shadowmode == 3)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
{
r_shadow_usingshadowmapcube = true;
R_Mesh_TexBindCubeMap(GL20TU_SHADOWMAPCUBE, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
}
else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_VERTEX)
R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ //GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
CHECKGLERROR
}
static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
{
- float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
- float *normal3f = rsurface.normal3f + 3 * firstvertex;
+ const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
+ const float *normal3f = rsurface.normal3f + 3 * firstvertex;
float *color4f = rsurface.array_color4f + 4 * firstvertex;
float dist, dot, distintensity, shadeintensity, v[3], n[3];
if (r_textureunits.integer >= 3)
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
color4f[3] = 1;
{
float f;
Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
color4f[3] = 1;
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
{
VectorSubtract(rsurface.entitylightorigin, vertex3f, lightdir);
VectorNormalize(lightdir);
- VectorSubtract(rsurface.modelorg, vertex3f, eyedir);
+ VectorSubtract(rsurface.localvieworigin, vertex3f, eyedir);
VectorNormalize(eyedir);
VectorAdd(lightdir, eyedir, halfdir);
// the cubemap normalizes this for us
m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
if (r_textureunits.integer >= 3)
{
- // Voodoo4 or Kyro (or Geforce3/Radeon with gl_combine off)
+ // Voodoo4 or Kyro (or Geforce3/Radeon with r_shadow_dot3 off)
m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
m.texmatrix[2] = rsurface.entitytoattenuationz;
m.pointer_texcoord3f[2] = rsurface.vertex3f;
void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
{
float ambientscale, diffusescale, specularscale;
+ qboolean negated;
vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
rtexture_t *nmap;
// calculate colors to render this texture with
}
if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
return;
+ negated = (lightcolorbase[0] + lightcolorbase[1] + lightcolorbase[2] < 0) && gl_support_ext_blend_subtract;
+ if(negated)
+ {
+ VectorNegate(lightcolorbase, lightcolorbase);
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ }
RSurf_SetupDepthAndCulling();
nmap = rsurface.texture->currentskinframe->nmap;
if (gl_lightmaps.integer)
break;
}
}
+ if(negated)
+ qglBlendEquationEXT(GL_FUNC_ADD_EXT);
}
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)
// compile the light
rtlight->compiled = true;
- rtlight->shadowmode = rtlight->shadow ? r_shadow_shadowmode : -1;
+ rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
rtlight->static_numleafs = 0;
rtlight->static_numleafpvsbytes = 0;
rtlight->static_leaflist = NULL;
memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
if (rtlight->static_numlighttrispvsbytes)
memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
- if (rtlight->shadowmode <= 0)
- {
- if (model->CompileShadowVolume && rtlight->shadow)
- model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
- }
- else
+ switch (rtlight->shadowmode)
{
+ case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+ case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+ case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
if (model->CompileShadowMap && rtlight->shadow)
model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
+ break;
+ default:
+ if (model->CompileShadowVolume && rtlight->shadow)
+ model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
+ break;
}
// now we're done compiling the rtlight
r_shadow_compilingrtlight = NULL;
// all at once at the start of a level, not when it stalls gameplay.
// (especially important to benchmarks)
// compile light
- if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
+ if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
{
if (rtlight->compiled)
R_RTLight_Uncompile(rtlight);
nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
distance = VectorDistance(nearestpoint, r_refdef.view.origin);
- lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
- lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapping_maxsize.integer);
- if (castshadows && r_shadow_shadowmode >= 1 && r_shadow_shadowmode <= 3 && r_glsl.integer && gl_support_fragment_shader)
+ lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance/rtlight->radius));
+ //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
+ lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
+
+ if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
{
float borderbias;
int side;
r_shadow_shadowmaplod = 0;
for (i = 1;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
- if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
+ if ((r_shadow_shadowmapmaxsize >> i) > lodlinear)
r_shadow_shadowmaplod = i;
- size = r_shadow_shadowmode == 3 ? r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod : lodlinear;
- size = bound(1, size, 2048);
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
+ size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod);
+ else
+ size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
+
borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
if (numsurfaces)
receivermask |= R_Shadow_CalcEntitySideMask(lightentities[lightentities_noselfshadow - i], &rtlight->matrix_worldtolight, &radiustolight, borderbias);
}
- receivermask &= R_Shadow_FrustumCullSides(rtlight, size, r_shadow_shadowmapborder);
+ receivermask &= R_Shadow_CullFrustumSides(rtlight, size, r_shadow_shadowmapborder);
if (receivermask)
{
for (side = 0;side < 6;side++) if ((receivermask & castermask) & (1 << side))
{
R_Shadow_RenderMode_ShadowMap(side, false, size);
- for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides[shadowentities_noselfshadow - i] && (1 << side))
+ for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides[shadowentities_noselfshadow - i] & (1 << side))
R_Shadow_DrawEntityShadow(shadowentities[shadowentities_noselfshadow - i]);
}
}
size_t lightindex;
dlight_t *light;
size_t range;
+ float f;
- if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) ||
- (r_shadow_shadowmode != 0) != (r_shadow_shadowmapping.integer != 0) ||
+ if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4) ||
+ (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer && r_glsl.integer && gl_support_fragment_shader && gl_support_ext_framebuffer_object) ||
r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) ||
r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
- r_shadow_shadowmapprecision != r_shadow_shadowmapping_precision.integer ||
+ r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
R_Shadow_FreeShadowMaps();
}
}
if (r_refdef.scene.rtdlight)
+ {
for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
R_DrawRTLight(r_refdef.scene.lights[lnum], visible);
+ }
+ else if(gl_flashblend.integer)
+ {
+ for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
+ {
+ rtlight_t *rtlight = r_refdef.scene.lights[lnum];
+ f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+ VectorScale(rtlight->color, f, rtlight->currentcolor);
+ }
+ }
R_Shadow_RenderMode_End();
}
qglStencilFunc(GL_NOTEQUAL, 128, ~0);CHECKGLERROR
// apply the blend to the shadowed areas
- R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
// restore the viewport
R_SetViewport(&r_refdef.view.viewport);
float zdist;
vec3_t centerorigin;
// if it's too close, skip it
- if (VectorLength(rtlight->color) < (1.0f / 256.0f))
+ if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
return;
zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
if (zdist < 32)
if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
return;
}
- VectorScale(rtlight->color, cscale, color);
+ VectorScale(rtlight->currentcolor, cscale, color);
if (VectorLength(color) > (1.0f / 256.0f))
+ {
+ qboolean negated = (color[0] + color[1] + color[2] < 0) && gl_support_ext_blend_subtract;
+ if(negated)
+ {
+ VectorNegate(color, color);
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ }
R_DrawSprite(GL_ONE, GL_ONE, r_shadow_lightcorona, NULL, true, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, color[0], color[1], color[2], 1);
+ if(negated)
+ qglBlendEquationEXT(GL_FUNC_ADD_EXT);
+ }
}
void R_DrawCoronas(void)
light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
+ /*
light->color[0] = max(color[0], 0);
light->color[1] = max(color[1], 0);
light->color[2] = max(color[2], 0);
+ */
+ light->color[0] = color[0];
+ light->color[1] = color[1];
+ light->color[2] = color[2];
light->radius = max(radius, 0);
light->style = style;
light->shadow = shadowenable;