typedef enum r_shadow_shadowmode_e
{
- R_SHADOW_SHADOWMODE_STENCIL,
- R_SHADOW_SHADOWMODE_SHADOWMAP2D
+ R_SHADOW_SHADOWMODE_STENCIL,
+ R_SHADOW_SHADOWMODE_SHADOWMAP2D
}
r_shadow_shadowmode_t;
int r_shadow_shadowmapmaxsize;
qboolean r_shadow_shadowmapvsdct;
qboolean r_shadow_shadowmapsampler;
+qboolean r_shadow_shadowmapshadowsampler;
int r_shadow_shadowmappcf;
int r_shadow_shadowmapborder;
matrix4x4_t r_shadow_shadowmapmatrix;
int r_shadow_lightscissor[4];
qboolean r_shadow_usingdeferredprepass;
-
+qboolean r_shadow_shadowmapdepthtexture;
int maxshadowtriangles;
int *shadowelements;
rtexture_t *r_shadow_attenuation2dtexture;
rtexture_t *r_shadow_attenuation3dtexture;
skinframe_t *r_shadow_lightcorona;
-rtexture_t *r_shadow_shadowmap2dtexture;
-rtexture_t *r_shadow_shadowmap2dcolortexture;
+rtexture_t *r_shadow_shadowmap2ddepthbuffer;
+rtexture_t *r_shadow_shadowmap2ddepthtexture;
rtexture_t *r_shadow_shadowmapvsdcttexture;
int r_shadow_shadowmapsize; // changes for each light based on distance
int r_shadow_shadowmaplod; // changes for each light based on distance
GLuint r_shadow_prepasslightingdiffusefbo;
int r_shadow_prepass_width;
int r_shadow_prepass_height;
-rtexture_t *r_shadow_prepassgeometrydepthtexture;
-rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
+rtexture_t *r_shadow_prepassgeometrydepthbuffer;
rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
rtexture_t *r_shadow_prepasslightingdiffusetexture;
rtexture_t *r_shadow_prepasslightingspeculartexture;
// lights are reloaded when this changes
char r_shadow_mapname[MAX_QPATH];
+// buffer for doing corona fading
+unsigned int r_shadow_occlusion_buf = 0;
+
// used only for light filters (cubemaps)
rtexturepool_t *r_shadow_filters_texturepool;
-#ifndef USE_GLES2
-static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
-#endif
-
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_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
-cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "4", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
-//cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
cvar_t r_shadow_usebihculling = {0, "r_shadow_usebihculling", "1", "use BIH (Bounding Interval Hierarchy) for culling lit surfaces instead of BSP (Binary Space Partitioning)"};
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_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", "1", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
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_useshadowsampler = {CVAR_SAVE, "r_shadow_shadowmapping_useshadowsampler", "1", "whether to use sampler2DShadow if available"};
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_bouncegrid_x = {CVAR_SAVE, "r_shadow_bouncegrid_x", "64", "maximum texture size of bouncegrid on X axis"};
cvar_t r_shadow_bouncegrid_y = {CVAR_SAVE, "r_shadow_bouncegrid_y", "64", "maximum texture size of bouncegrid on Y axis"};
cvar_t r_shadow_bouncegrid_z = {CVAR_SAVE, "r_shadow_bouncegrid_z", "32", "maximum texture size of bouncegrid on Z axis"};
-cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
+cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "0", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksum the proportion of hidden pixels controls corona intensity"};
-cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
+cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "0", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility) - bad performance (synchronous rendering) - worse on multi-gpu!"};
cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
+cvar_t r_editlights_drawproperties = {0, "r_editlights_drawproperties", "1", "draw properties of currently selected light"};
+cvar_t r_editlights_current_origin = {0, "r_editlights_current_origin", "0 0 0", "origin of selected light"};
+cvar_t r_editlights_current_angles = {0, "r_editlights_current_angles", "0 0 0", "angles of selected light"};
+cvar_t r_editlights_current_color = {0, "r_editlights_current_color", "1 1 1", "color of selected light"};
+cvar_t r_editlights_current_radius = {0, "r_editlights_current_radius", "0", "radius of selected light"};
+cvar_t r_editlights_current_corona = {0, "r_editlights_current_corona", "0", "corona intensity of selected light"};
+cvar_t r_editlights_current_coronasize = {0, "r_editlights_current_coronasize", "0", "corona size of selected light"};
+cvar_t r_editlights_current_style = {0, "r_editlights_current_style", "0", "style of selected light"};
+cvar_t r_editlights_current_shadows = {0, "r_editlights_current_shadows", "0", "shadows flag of selected light"};
+cvar_t r_editlights_current_cubemap = {0, "r_editlights_current_cubemap", "0", "cubemap of selected light"};
+cvar_t r_editlights_current_ambient = {0, "r_editlights_current_ambient", "0", "ambient intensity of selected light"};
+cvar_t r_editlights_current_diffuse = {0, "r_editlights_current_diffuse", "1", "diffuse intensity of selected light"};
+cvar_t r_editlights_current_specular = {0, "r_editlights_current_specular", "1", "specular intensity of selected light"};
+cvar_t r_editlights_current_normalmode = {0, "r_editlights_current_normalmode", "0", "normalmode flag of selected light"};
+cvar_t r_editlights_current_realtimemode = {0, "r_editlights_current_realtimemode", "0", "realtimemode flag of selected light"};
+
typedef struct r_shadow_bouncegrid_settings_s
{
r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20;
r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
+ r_shadow_shadowmapshadowsampler = r_shadow_shadowmapping_useshadowsampler.integer != 0;
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_shadowmapdepthtexture = r_fb.usedepthtextures;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
{
case RENDERPATH_GL20:
if(r_shadow_shadowmapfilterquality < 0)
{
- if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+ if (!r_fb.usedepthtextures)
r_shadow_shadowmappcf = 1;
- else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD"))
+ else if((strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) && vid.support.arb_shadow && r_shadow_shadowmapshadowsampler)
{
- r_shadow_shadowmapsampler = vid.support.arb_shadow;
+ r_shadow_shadowmapsampler = true;
r_shadow_shadowmappcf = 1;
}
- else if(strstr(gl_vendor, "ATI"))
+ else if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
+ r_shadow_shadowmappcf = 1;
+ else if((strstr(gl_vendor, "ATI") || strstr(gl_vendor, "Advanced Micro Devices")) && !strstr(gl_renderer, "Mesa") && !strstr(gl_version, "Mesa"))
r_shadow_shadowmappcf = 1;
else
- r_shadow_shadowmapsampler = vid.support.arb_shadow;
+ r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
}
else
{
+ r_shadow_shadowmapsampler = vid.support.arb_shadow && r_shadow_shadowmapshadowsampler;
switch (r_shadow_shadowmapfilterquality)
{
case 1:
- r_shadow_shadowmapsampler = vid.support.arb_shadow;
break;
case 2:
- r_shadow_shadowmapsampler = vid.support.arb_shadow;
r_shadow_shadowmappcf = 1;
break;
case 3:
break;
}
}
+ if (!r_fb.usedepthtextures)
+ r_shadow_shadowmapsampler = false;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
break;
case RENDERPATH_D3D9:
break;
}
}
+
+ if(R_CompileShader_CheckStaticParms())
+ R_GLSL_Restart_f();
}
qboolean R_Shadow_ShadowMappingEnabled(void)
r_shadow_fbo2d = 0;
- if (r_shadow_shadowmap2dtexture)
- R_FreeTexture(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap2dtexture = NULL;
+ if (r_shadow_shadowmap2ddepthtexture)
+ R_FreeTexture(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap2ddepthtexture = NULL;
- if (r_shadow_shadowmap2dcolortexture)
- R_FreeTexture(r_shadow_shadowmap2dcolortexture);
- r_shadow_shadowmap2dcolortexture = NULL;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_FreeTexture(r_shadow_shadowmap2ddepthbuffer);
+ r_shadow_shadowmap2ddepthbuffer = NULL;
if (r_shadow_shadowmapvsdcttexture)
R_FreeTexture(r_shadow_shadowmapvsdcttexture);
r_shadow_attenuation2dtexture = NULL;
r_shadow_attenuation3dtexture = NULL;
r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
- r_shadow_shadowmap2dtexture = NULL;
- r_shadow_shadowmap2dcolortexture = NULL;
+ r_shadow_shadowmap2ddepthtexture = NULL;
+ r_shadow_shadowmap2ddepthbuffer = NULL;
r_shadow_shadowmapvsdcttexture = NULL;
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
Cvar_RegisterVariable(&r_shadow_usenormalmap);
Cvar_RegisterVariable(&r_shadow_debuglight);
Cvar_RegisterVariable(&r_shadow_deferred);
- Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
-// Cvar_RegisterVariable(&r_shadow_deferred_fp);
Cvar_RegisterVariable(&r_shadow_gloss);
Cvar_RegisterVariable(&r_shadow_gloss2intensity);
Cvar_RegisterVariable(&r_shadow_glossintensity);
Cvar_RegisterVariable(&r_shadow_shadowmapping);
Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_useshadowsampler);
Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
void R_Shadow_PrepareShadowSides(int numtris)
{
- if (maxshadowsides < numtris)
- {
- maxshadowsides = numtris;
- if (shadowsides)
+ if (maxshadowsides < numtris)
+ {
+ maxshadowsides = numtris;
+ if (shadowsides)
Mem_Free(shadowsides);
if (shadowsideslist)
Mem_Free(shadowsideslist);
v[2] = invertex3f + e[2] * 3;
TriangleNormal(v[0], v[1], v[2], normal);
if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
v[1] = invertex3f + e[1] * 3;
v[2] = invertex3f + e[2] * 3;
if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
shadowmarklist[numshadowmark++] = t;
}
}
else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
{
tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
- R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
}
else
tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
else
tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
- r_refdef.stats.lights_dynamicshadowtriangles += tris;
- r_refdef.stats.lights_shadowtriangles += tris;
+ r_refdef.stats[r_stat_lights_dynamicshadowtriangles] += tris;
+ r_refdef.stats[r_stat_lights_shadowtriangles] += tris;
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
{
// increment stencil if frontface is infront of depthbuffer
GL_CullFace(r_refdef.view.cullface_back);
R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
}
- R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(outverts, shadowvertex3f, NULL, 0);
R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
}
}
int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
{
- // p1, p2, p3 are in the cubemap's local coordinate system
- // bias = border/(size - border)
+ // p1, p2, p3 are in the cubemap's local coordinate system
+ // bias = border/(size - border)
int mask = 0x3F;
- float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
+ float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<4)
+ mask &= (3<<4)
| (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
| (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
- dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
- if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
+ dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
+ if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
return mask;
}
int mask = 0x3F;
VectorSubtract(maxs, mins, radius);
- VectorScale(radius, 0.5f, radius);
- VectorAdd(mins, radius, center);
- Matrix4x4_Transform(worldtolight, center, lightcenter);
+ VectorScale(radius, 0.5f, radius);
+ VectorAdd(mins, radius, center);
+ Matrix4x4_Transform(worldtolight, center, lightcenter);
Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
VectorSubtract(lightcenter, lightradius, pmin);
VectorAdd(lightcenter, lightradius, pmax);
- dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<4)
- | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
- | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<4)
- | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
- | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
-
- dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<0)
- | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
- | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<0)
- | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
- | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
-
- dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
- dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
- if(ap1 > bias*an1 && ap2 > bias*an2)
- mask &= (3<<2)
- | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
- | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
- if(an1 > bias*ap1 && an2 > bias*ap2)
- mask &= (3<<2)
- | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
- | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
-
- return mask;
+ dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<4)
+ | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
+ | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<4)
+ | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
+ | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
+
+ dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<0)
+ | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
+ | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<0)
+ | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
+ | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
+
+ dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
+ dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
+ if(ap1 > bias*an1 && ap2 > bias*an2)
+ mask &= (3<<2)
+ | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
+ | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
+ if(an1 > bias*ap1 && an2 > bias*ap2)
+ mask &= (3<<2)
+ | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
+ | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
+
+ return mask;
}
#define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
{
- // p is in the cubemap's local coordinate system
- // bias = border/(size - border)
- float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
- float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
- float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
- int mask = 0x3F;
- if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
- if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
- if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
- if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
- if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
- if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
- return mask;
+ // p is in the cubemap's local coordinate system
+ // bias = border/(size - border)
+ float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
+ float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
+ float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
+ int mask = 0x3F;
+ if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
+ if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
+ if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
+ if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
+ if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
+ if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
+ return mask;
}
static int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
{
int i;
- vec3_t p, n;
+ vec3_t o, 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);
+ Matrix4x4_OriginFromMatrix(&rtlight->matrix_lighttoworld, o);
for (i = 0;i < 5;i++)
{
- if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
+ if (PlaneDiff(o, &r_refdef.view.frustum[i]) > -0.03125)
continue;
Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
len = scale*VectorLength2(n);
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)
+ if (PlaneDiff(o, &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);
+ Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].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);
// 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
#if 1
- // infinite version, assumes frustum corners merely give direction and extend to infinite distance
- Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, 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));
- for (i = 0;i < 4;i++)
- {
- Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
- VectorSubtract(n, p, n);
- dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
- if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
- dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
- if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
- dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
- if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
- if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
- }
+ // infinite version, assumes frustum corners merely give direction and extend to infinite distance
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, 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));
+ for (i = 0;i < 4;i++)
+ {
+ Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
+ VectorSubtract(n, p, n);
+ dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
+ if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
+ dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
+ if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
+ dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
+ if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
+ if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
+ }
#else
- // finite version, assumes corners are a finite distance from origin dependent on far plane
+ // finite version, assumes corners are a finite distance from origin dependent on far plane
for (i = 0;i < 5;i++)
{
Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
TriangleNormal(v[0], v[1], v[2], normal);
if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
{
Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
{
v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
- && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
+ && TriangleBBoxOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
{
Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
void R_Shadow_ClearStencil(void)
{
GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128);
- r_refdef.stats.lights_clears++;
+ r_refdef.stats[r_stat_lights_clears]++;
}
void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
GL_ColorMask(0, 0, 0, 0);
GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
GL_CullFace(GL_NONE);
- R_SetupShader_DepthOrShadow(false);
+ R_SetupShader_DepthOrShadow(false, false, false); // FIXME test if we have a skeletal model?
r_shadow_rendermode = mode;
switch(mode)
{
switch (r_shadow_shadowmode)
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
- if (r_shadow_shadowmap2dtexture) return;
- r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler, false);
- r_shadow_shadowmap2dcolortexture = NULL;
- switch(vid.renderpath)
+ if (r_shadow_shadowmap2ddepthtexture) return;
+ if (r_fb.usedepthtextures)
{
-#ifdef SUPPORTD3D
- case RENDERPATH_D3D9:
- r_shadow_shadowmap2dcolortexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_BGRA, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
- r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- break;
-#endif
- default:
- r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL);
- break;
+ r_shadow_shadowmap2ddepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP24_COMP : TEXTYPE_SHADOWMAP24_RAW) : (r_shadow_shadowmapsampler ? TEXTYPE_SHADOWMAP16_COMP : TEXTYPE_SHADOWMAP16_RAW), r_shadow_shadowmapsampler);
+ r_shadow_shadowmap2ddepthbuffer = NULL;
+ r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ }
+ else
+ {
+ r_shadow_shadowmap2ddepthtexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
+ r_shadow_shadowmap2ddepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits >= 24 ? TEXTYPE_DEPTHBUFFER24 : TEXTYPE_DEPTHBUFFER16);
+ r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
}
break;
default:
return;
}
-
-#ifndef USE_GLES2
- // render depth into the fbo, do not render color at all
- // validate the fbo now
- if (qglDrawBuffer)
- {
- int status;
- qglDrawBuffer(GL_NONE);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
- {
- Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- }
- }
-#endif
}
static void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
- if (!r_shadow_shadowmap2dtexture)
+ if (!r_shadow_shadowmap2ddepthtexture)
R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
- if (r_shadow_shadowmap2dtexture) fbo2d = 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);
+ fbo2d = r_shadow_fbo2d;
+ r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
R_Mesh_ResetTextureState();
R_Shadow_RenderMode_Reset();
- R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
+ else
+ R_Mesh_SetRenderTargets(fbo2d, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
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;
+ if (r_shadow_shadowmap2ddepthbuffer)
+ {
+ // completely different meaning than in depthtexture approach
+ r_shadow_shadowmap_parameters[1] = 0;
+ r_shadow_shadowmap_parameters[3] = -bias;
+ }
+ Vector4Set(clearcolor, 1,1,1,1);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ GL_ColorMask(1,1,1,1);
+ else
+ GL_ColorMask(0,0,0,0);
switch(vid.renderpath)
{
case RENDERPATH_GL11:
int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
GL_Scissor(x1, y1, x2 - x1, y2 - y1);
- GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
+ if (clear)
+ {
+ if (r_shadow_shadowmap2ddepthbuffer)
+ GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
+ else
+ GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
+ }
}
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
break;
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
- Vector4Set(clearcolor, 1,1,1,1);
- // completely different meaning than in OpenGL path
- r_shadow_shadowmap_parameters[1] = 0;
- r_shadow_shadowmap_parameters[3] = -bias;
// we invert the cull mode because we flip the projection matrix
// NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
GL_CullFace(r_refdef.view.cullface_front);
// D3D considers it an error to use a scissor larger than the viewport... clear just this view
GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
- if (r_shadow_shadowmapsampler)
- {
- GL_ColorMask(0,0,0,0);
- if (clear)
- GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
- }
- else
+ if (clear)
{
- GL_ColorMask(1,1,1,1);
- if (clear)
+ if (r_shadow_shadowmap2ddepthbuffer)
GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
+ else
+ GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
}
break;
}
// stencil is 128 (values other than this mean shadow)
R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
if (rsurface.rtlight->specularscale > 0 && r_shadow_gloss.integer > 0)
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
else
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
r_shadow_usingshadowmap2d = shadowmapping;
GL_DepthTest(true);
GL_DepthFunc(GL_GREATER);
GL_CullFace(r_refdef.view.cullface_back);
- R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(8, vertex3f, NULL, 0);
R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
}
if (enable && r_shadow_bouncegrid_static.integer)
{
enable = false;
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
for (lightindex = 0;lightindex < range;lightindex++)
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
// clear variables that produce warnings otherwise
memset(splatcolor, 0, sizeof(splatcolor));
// iterate world rtlights
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
range1 = settings.staticmode ? 0 : r_refdef.scene.numlights;
range2 = range + range1;
photoncount = 0;
w = r_shadow_lightintensityscale.value * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale);
if (w * VectorLength2(rtlight->color) == 0.0f)
continue;
- w *= (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
+ w *= ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1);
VectorScale(rtlight->color, w, rtlight->photoncolor);
//if (!VectorLength2(rtlight->photoncolor))
// continue;
radius = rtlight->radius * settings.lightradiusscale;
s = settings.particleintensity / shootparticles;
VectorScale(rtlight->photoncolor, s, baseshotcolor);
- r_refdef.stats.bouncegrid_lights++;
- r_refdef.stats.bouncegrid_particles += shootparticles;
+ r_refdef.stats[r_stat_bouncegrid_lights]++;
+ r_refdef.stats[r_stat_bouncegrid_particles] += shootparticles;
for (shotparticles = 0;shotparticles < shootparticles;shotparticles++)
{
if (settings.stablerandom > 0)
VectorMA(clipstart, radius, clipend, clipend);
for (bouncecount = 0;;bouncecount++)
{
- r_refdef.stats.bouncegrid_traces++;
+ r_refdef.stats[r_stat_bouncegrid_traces]++;
//r_refdef.scene.worldmodel->TraceLineAgainstSurfaces(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace, clipstart, clipend, hitsupercontentsmask);
//r_refdef.scene.worldmodel->TraceLine(r_refdef.scene.worldmodel, NULL, NULL, &cliptrace2, clipstart, clipend, hitsupercontentsmask);
if (settings.staticmode)
{
// static mode fires a LOT of rays but none of them are identical, so they are not cached
- cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, true, false, NULL, true, true);
+ cliptrace = CL_TraceLine(clipstart, clipend, settings.staticmode ? MOVE_WORLDONLY : (settings.hitmodels ? MOVE_HITMODEL : MOVE_NOMONSTERS), NULL, hitsupercontentsmask, collision_extendmovelength.value, true, false, NULL, true, true);
}
else
{
VectorMA(clipstart, 0.5f, stepdelta, steppos);
for (step = 0;step < numsteps;step++)
{
- r_refdef.stats.bouncegrid_splats++;
+ r_refdef.stats[r_stat_bouncegrid_splats]++;
// figure out which texture pixel this is in
texlerp[1][0] = ((steppos[0] - mins[0]) * ispacing[0]) - 0.5f;
texlerp[1][1] = ((steppos[1] - mins[1]) * ispacing[1]) - 0.5f;
}
if (cliptrace.fraction >= 1.0f)
break;
- r_refdef.stats.bouncegrid_hits++;
+ r_refdef.stats[r_stat_bouncegrid_hits]++;
if (bouncecount >= maxbounce)
break;
// scale down shot color by bounce intensity and texture color (or 50% if no texture reported)
VectorMultiply(shotcolor, surfcolor, shotcolor);
if (VectorLength2(baseshotcolor) == 0.0f)
break;
- r_refdef.stats.bouncegrid_bounces++;
+ r_refdef.stats[r_stat_bouncegrid_bounces]++;
if (settings.bounceanglediffuse)
{
// random direction, primarily along plane normal
|| 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)
- r_refdef.stats.lights_scissored++;
+ r_refdef.stats[r_stat_lights_scissored]++;
return false;
}
lighttris++;
shadowtris = 0;
- if (rtlight->static_numlighttrispvsbytes)
+ if (rtlight->static_numshadowtrispvsbytes)
for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
shadowtris++;
{
if (!mesh->sidetotals[r_shadow_shadowmapside])
continue;
- r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
- if (mesh->vertex3fbuffer)
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
- else
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
+ r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside];
+ R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
}
CHECKGLERROR
mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
for (;mesh;mesh = mesh->next)
{
- r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
- if (mesh->vertex3fbuffer)
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vertex3fbuffer);
- else
- R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer);
+ r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->numtriangles;
+ R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f);
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
{
// increment stencil if frontface is infront of depthbuffer
static entity_render_t *shadowentities[MAX_EDICTS];
static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS];
qboolean nolight;
+ qboolean castshadows;
rtlight->draw = false;
+ rtlight->cached_numlightentities = 0;
+ rtlight->cached_numlightentities_noselfshadow = 0;
+ rtlight->cached_numshadowentities = 0;
+ rtlight->cached_numshadowentities_noselfshadow = 0;
+ rtlight->cached_numsurfaces = 0;
+ rtlight->cached_lightentities = NULL;
+ rtlight->cached_lightentities_noselfshadow = NULL;
+ rtlight->cached_shadowentities = NULL;
+ rtlight->cached_shadowentities_noselfshadow = NULL;
+ rtlight->cached_shadowtrispvs = NULL;
+ rtlight->cached_lighttrispvs = NULL;
+ rtlight->cached_surfacelist = NULL;
// skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights)
// skip lights that are basically invisible (color 0 0 0)
rtlight->currentcubemap = rtlight->cubemapname[0] ? R_GetCubemap(rtlight->cubemapname) : r_texture_whitecube;
// look up the light style value at this time
- f = (rtlight->style >= 0 ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+ f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.rtlightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
VectorScale(rtlight->color, f, rtlight->currentcolor);
/*
if (rtlight->selected)
R_Shadow_ComputeShadowCasterCullingPlanes(rtlight);
+ // don't allow lights to be drawn if using r_shadow_bouncegrid 2, except if we're using static bouncegrid where dynamic lights still need to draw
+ if (r_shadow_bouncegrid.integer == 2 && (rtlight->isstatic || !r_shadow_bouncegrid_static.integer))
+ return;
+
if (rtlight->compiled && r_shadow_realtime_world_compile.integer)
{
// compiled light, world available and can receive realtime lighting
return;
// count this light in the r_speeds
- r_refdef.stats.lights++;
+ r_refdef.stats[r_stat_lights]++;
// flag it as worth drawing later
rtlight->draw = true;
+ // if we have shadows disabled, don't count the shadow entities, this way we don't do the R_AnimCache_GetEntity on each one
+ castshadows = numsurfaces + numshadowentities + numshadowentities_noselfshadow > 0 && rtlight->shadow && (rtlight->isstatic ? r_refdef.scene.rtworldshadows : r_refdef.scene.rtdlightshadows);
+ if (!castshadows)
+ numshadowentities = numshadowentities_noselfshadow = 0;
+
// cache all the animated entities that cast a shadow but are not visible
for (i = 0;i < numshadowentities;i++)
- if (!shadowentities[i]->animcache_vertex3f)
- R_AnimCache_GetEntity(shadowentities[i], false, false);
+ R_AnimCache_GetEntity(shadowentities[i], false, false);
for (i = 0;i < numshadowentities_noselfshadow;i++)
- if (!shadowentities_noselfshadow[i]->animcache_vertex3f)
- R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
+ R_AnimCache_GetEntity(shadowentities_noselfshadow[i], false, false);
// allocate some temporary memory for rendering this light later in the frame
// reusable buffers need to be copied, static data can be used as-is
R_Mesh_DestroyFramebufferObject(r_shadow_prepasslightingdiffusefbo);
r_shadow_prepasslightingdiffusefbo = 0;
- if (r_shadow_prepassgeometrydepthtexture)
- R_FreeTexture(r_shadow_prepassgeometrydepthtexture);
- r_shadow_prepassgeometrydepthtexture = NULL;
-
- if (r_shadow_prepassgeometrydepthcolortexture)
- R_FreeTexture(r_shadow_prepassgeometrydepthcolortexture);
- r_shadow_prepassgeometrydepthcolortexture = NULL;
+ if (r_shadow_prepassgeometrydepthbuffer)
+ R_FreeTexture(r_shadow_prepassgeometrydepthbuffer);
+ r_shadow_prepassgeometrydepthbuffer = NULL;
if (r_shadow_prepassgeometrynormalmaptexture)
R_FreeTexture(r_shadow_prepassgeometrynormalmaptexture);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(1,1,1,1);
GL_DepthTest(true);
- R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
Vector4Set(clearcolor, 0.5f,0.5f,0.5f,1.0f);
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
if (r_timereport_active)
GL_ColorMask(1,1,1,1);
GL_Color(1,1,1,1);
GL_DepthTest(true);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
Vector4Set(clearcolor, 0, 0, 0, 0);
GL_Clear(GL_COLOR_BUFFER_BIT, clearcolor, 1.0f, 0);
if (r_timereport_active)
dlight_t *light;
size_t range;
float f;
- GLenum status;
if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4) ||
(r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer || r_shadow_deferred.integer) ||
r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0 && vid.renderpath == RENDERPATH_GL20) ||
r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
+ r_shadow_shadowmapshadowsampler != (vid.support.arb_shadow && r_shadow_shadowmapping_useshadowsampler.integer) ||
r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
- r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
+ r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16) ||
+ r_shadow_shadowmapdepthtexture != r_fb.usedepthtextures)
R_Shadow_FreeShadowMaps();
r_shadow_fb_fbo = fbo;
r_shadow_usingdeferredprepass = true;
r_shadow_prepass_width = vid.width;
r_shadow_prepass_height = vid.height;
- r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false, false);
- switch (vid.renderpath)
- {
- case RENDERPATH_D3D9:
- r_shadow_prepassgeometrydepthcolortexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrydepthcolormap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- break;
- default:
- break;
- }
- r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
- r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepassgeometrydepthbuffer = R_LoadTextureRenderBuffer(r_shadow_texturepool, "prepassgeometrydepthbuffer", vid.width, vid.height, TEXTYPE_DEPTHBUFFER24);
+ r_shadow_prepassgeometrynormalmaptexture = R_LoadTexture2D(r_shadow_texturepool, "prepassgeometrynormalmap", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER32F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingdiffusetexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingdiffuse", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
+ r_shadow_prepasslightingspeculartexture = R_LoadTexture2D(r_shadow_texturepool, "prepasslightingspecular", vid.width, vid.height, NULL, TEXTYPE_COLORBUFFER16F, TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCENEAREST, -1, NULL);
// set up the geometry pass fbo (depth + normalmap)
- r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepassgeometrynormalmaptexture, r_shadow_prepassgeometrydepthcolortexture, NULL, NULL);
- // render depth into one texture and normalmap into the other
- if (qglDrawBuffersARB)
- {
- qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
+ r_shadow_prepassgeometryfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepassgeometryfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepassgeometrynormalmaptexture, NULL, NULL, NULL);
+ // render depth into a renderbuffer and other important properties into the normalmap texture
// set up the lighting pass fbo (diffuse + specular)
- r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ r_shadow_prepasslightingdiffusespecularfbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusespecularfbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
// render diffuse into one texture and specular into another,
// with depth and normalmap bound as textures,
// with depth bound as attachment as well
- if (qglDrawBuffersARB)
- {
- qglDrawBuffersARB(2, r_shadow_prepasslightingdrawbuffers);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
// set up the lighting pass fbo (diffuse)
- r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
- R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ r_shadow_prepasslightingdiffusefbo = R_Mesh_CreateFramebufferObject(r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
+ R_Mesh_SetRenderTargets(r_shadow_prepasslightingdiffusefbo, r_shadow_prepassgeometrydepthbuffer, r_shadow_prepasslightingdiffusetexture, NULL, NULL, NULL);
// render diffuse into one texture,
// with depth and normalmap bound as textures,
// with depth bound as attachment as well
- if (qglDrawBuffersARB)
- {
- qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
- qglReadBuffer(GL_NONE);CHECKGLERROR
- status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- Con_Printf("R_PrepareRTLights: glCheckFramebufferStatusEXT returned %i\n", status);
- Cvar_SetValueQuick(&r_shadow_deferred, 0);
- r_shadow_usingdeferredprepass = false;
- }
- }
}
#endif
break;
R_Shadow_EnlargeLeafSurfaceTrisBuffer(r_refdef.scene.worldmodel->brush.num_leafs, r_refdef.scene.worldmodel->num_surfaces, r_refdef.scene.worldmodel->brush.shadowmesh ? r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles : r_refdef.scene.worldmodel->surfmesh.num_triangles, r_refdef.scene.worldmodel->surfmesh.num_triangles);
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- if (r_shadow_bouncegrid.integer != 2)
+ if (r_shadow_debuglight.integer >= 0)
{
- if (r_shadow_debuglight.integer >= 0)
+ lightindex = r_shadow_debuglight.integer;
+ light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+ if (light)
+ R_Shadow_PrepareLight(&light->rtlight);
+ }
+ else
+ {
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
- lightindex = r_shadow_debuglight.integer;
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
- if (light)
+ if (light && (light->flags & flag))
R_Shadow_PrepareLight(&light->rtlight);
}
- else
- {
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
- for (lightindex = 0;lightindex < range;lightindex++)
- {
- light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
- if (light && (light->flags & flag))
- R_Shadow_PrepareLight(&light->rtlight);
- }
- }
}
if (r_refdef.scene.rtdlight)
{
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;
+ f = ((rtlight->style >= 0 && rtlight->style < MAX_LIGHTSTYLES) ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
VectorScale(rtlight->color, f, rtlight->currentcolor);
}
}
R_Shadow_RenderMode_Begin();
- if (r_shadow_bouncegrid.integer != 2)
+ flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
+ if (r_shadow_debuglight.integer >= 0)
{
- flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- if (r_shadow_debuglight.integer >= 0)
+ lightindex = r_shadow_debuglight.integer;
+ light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+ if (light)
+ R_Shadow_DrawLight(&light->rtlight);
+ }
+ else
+ {
+ range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
+ for (lightindex = 0;lightindex < range;lightindex++)
{
- lightindex = r_shadow_debuglight.integer;
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
- if (light)
+ if (light && (light->flags & flag))
R_Shadow_DrawLight(&light->rtlight);
}
- else
- {
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
- for (lightindex = 0;lightindex < range;lightindex++)
- {
- light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
- if (light && (light->flags & flag))
- R_Shadow_DrawLight(&light->rtlight);
- }
- }
}
if (r_refdef.scene.rtdlight)
for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
R_Shadow_RenderMode_End();
}
+#define MAX_MODELSHADOWS 1024
+static int r_shadow_nummodelshadows;
+static entity_render_t *r_shadow_modelshadows[MAX_MODELSHADOWS];
+
void R_Shadow_PrepareModelShadows(void)
{
int i;
float scale, size, radius, dot1, dot2;
+ prvm_vec3_t prvmshadowdir, prvmshadowfocus;
vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs;
entity_render_t *ent;
+ r_shadow_nummodelshadows = 0;
if (!r_refdef.scene.numentities)
return;
break;
// fall through
case R_SHADOW_SHADOWMODE_STENCIL:
+ if (!vid.stencil)
+ return;
for (i = 0;i < r_refdef.scene.numentities;i++)
{
ent = r_refdef.scene.entities[i];
- if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ if (ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ {
+ if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
+ break;
+ r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
R_AnimCache_GetEntity(ent, false, false);
+ }
}
return;
default:
scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value;
radius = 0.5f * size / scale;
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
dot1 = DotProduct(r_refdef.view.forward, shadowdir);
dot2 = DotProduct(r_refdef.view.up, shadowdir);
VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
VectorNormalize(shadowforward);
CrossProduct(shadowdir, shadowforward, shadowright);
- Math_atov(r_shadows_focus.string, shadowfocus);
+ Math_atov(r_shadows_focus.string, prvmshadowfocus);
+ VectorCopy(prvmshadowfocus, shadowfocus);
VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs))
continue;
// cast shadows from anything of the map (submodels are optional)
- if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ {
+ if (r_shadow_nummodelshadows >= MAX_MODELSHADOWS)
+ break;
+ r_shadow_modelshadows[r_shadow_nummodelshadows++] = ent;
R_AnimCache_GetEntity(ent, false, false);
+ }
}
}
vec3_t relativelightdirection, relativeforward, relativeright;
vec3_t relativeshadowmins, relativeshadowmaxs;
vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus;
+ prvm_vec3_t prvmshadowdir, prvmshadowfocus;
float m[12];
matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix;
r_viewport_t viewport;
GLuint shadowfbo = 0;
float clearcolor[4];
- if (!r_refdef.scene.numentities)
+ if (!r_shadow_nummodelshadows)
return;
switch (r_shadow_shadowmode)
switch (r_shadow_shadowmode)
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
- if (!r_shadow_shadowmap2dtexture)
+ if (!r_shadow_shadowmap2ddepthtexture)
R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
shadowfbo = 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_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2ddepthtexture);
+ r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2ddepthtexture);
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
break;
default:
radius = 0.5f / scale;
nearclip = -r_shadows_throwdistance.value;
farclip = r_shadows_throwdistance.value;
- bias = r_shadow_shadowmapping_bias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
+ bias = (r_shadows_shadowmapbias.value < 0) ? r_shadow_shadowmapping_bias.value : r_shadows_shadowmapbias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size);
r_shadow_shadowmap_parameters[0] = size;
r_shadow_shadowmap_parameters[1] = size;
r_shadow_shadowmap_parameters[2] = 1.0;
r_shadow_shadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
- Math_atov(r_shadows_focus.string, shadowfocus);
+ Math_atov(r_shadows_focus.string, prvmshadowfocus);
+ VectorCopy(prvmshadowfocus, shadowfocus);
VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin);
VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin);
VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin);
VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin);
- R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
- R_SetupShader_DepthOrShadow(true);
+ if (r_shadow_shadowmap2ddepthbuffer)
+ R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthbuffer, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL);
+ else
+ R_Mesh_SetRenderTargets(shadowfbo, r_shadow_shadowmap2ddepthtexture, NULL, NULL, NULL, NULL);
+ R_SetupShader_DepthOrShadow(true, r_shadow_shadowmap2ddepthbuffer != NULL, false); // FIXME test if we have a skeletal model?
GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
Vector4Set(clearcolor, 1,1,1,1);
// in D3D9 we have to render to a color texture shadowmap
// in GL we render directly to a depth texture only
- if (r_shadow_shadowmap2dtexture)
+ if (r_shadow_shadowmap2ddepthbuffer)
GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
else
GL_Clear(GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
// outside the usable area
GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
-#if 0
- // debugging
- R_Mesh_SetRenderTargets(r_shadow_fb_fbo, r_shadow_fb_depthtexture, r_shadow_fb_colortexture, NULL, NULL, NULL);
- R_SetupShader_ShowDepth(true);
- GL_ColorMask(1,1,1,1);
- GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearcolor, 1.0f, 0);
-#endif
-
- for (i = 0;i < r_refdef.scene.numentities;i++)
- {
- ent = r_refdef.scene.entities[i];
-
- // cast shadows from anything of the map (submodels are optional)
- if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
- {
- relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
- Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
- relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
- relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
- relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
- relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
- relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
- relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
- RSurf_ActiveModelEntity(ent, false, false, false);
- ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
- rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
- }
+ for (i = 0;i < r_shadow_nummodelshadows;i++)
+ {
+ ent = r_shadow_modelshadows[i];
+ relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+ Matrix4x4_Transform(&ent->inversematrix, shadoworigin, relativelightorigin);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright);
+ relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+ relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+ relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+ relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0]));
+ relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
+ relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
}
#if 0
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
-#ifdef OPENGL_ORIENTATION
+#ifdef MATRIX4x4_OPENGLORIENTATION
r_shadow_shadowmapmatrix.m[0][0] *= -1.0f;
r_shadow_shadowmapmatrix.m[0][1] *= -1.0f;
r_shadow_shadowmapmatrix.m[0][2] *= -1.0f;
vec3_t relativelightdirection;
vec3_t relativeshadowmins, relativeshadowmaxs;
vec3_t tmp, shadowdir;
+ prvm_vec3_t prvmshadowdir;
- if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
+ if (!r_shadow_nummodelshadows || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1))
return;
r_shadow_fb_fbo = fbo;
// get shadow dir
if (r_shadows.integer == 2)
{
- Math_atov(r_shadows_throwdirection.string, shadowdir);
+ Math_atov(r_shadows_throwdirection.string, prvmshadowdir);
+ VectorCopy(prvmshadowdir, shadowdir);
VectorNormalize(shadowdir);
}
R_Shadow_ClearStencil();
- for (i = 0;i < r_refdef.scene.numentities;i++)
+ for (i = 0;i < r_shadow_nummodelshadows;i++)
{
- ent = r_refdef.scene.entities[i];
+ ent = r_shadow_modelshadows[i];
// 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 in same direction
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+ else
{
- 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 in same direction
- Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
- else
+ if(ent->entitynumber != 0)
{
- if(ent->entitynumber != 0)
+ if(ent->entitynumber >= MAX_EDICTS) // csqc entity
{
- if(ent->entitynumber >= MAX_EDICTS) // csqc entity
+ // FIXME handle this
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ }
+ else
+ {
+ // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
+ int entnum, entnum2, recursion;
+ entnum = entnum2 = ent->entitynumber;
+ for(recursion = 32; recursion > 0; --recursion)
{
- // FIXME handle this
- VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ entnum2 = cl.entities[entnum].state_current.tagentity;
+ if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
+ entnum = entnum2;
+ else
+ break;
}
- else
+ if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
{
- // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities)
- int entnum, entnum2, recursion;
- entnum = entnum2 = ent->entitynumber;
- for(recursion = 32; recursion > 0; --recursion)
- {
- entnum2 = cl.entities[entnum].state_current.tagentity;
- if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2])
- entnum = entnum2;
- else
- break;
- }
- if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain
- {
- VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
- // transform into modelspace of OUR entity
- Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
- Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
- }
- else
- VectorNegate(ent->modellight_lightdir, relativelightdirection);
+ VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection);
+ // transform into modelspace of OUR entity
+ Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp);
+ Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection);
}
+ else
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
}
- else
- VectorNegate(ent->modellight_lightdir, relativelightdirection);
}
-
- VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
- RSurf_ActiveModelEntity(ent, false, false, false);
- 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
+ else
+ VectorNegate(ent->modellight_lightdir, relativelightdirection);
}
+
+ VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ 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
}
// not really the right mode, but this will disable any silly stencil features
{
float zdist;
vec3_t centerorigin;
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
float vertex3f[12];
+#endif
// if it's too close, skip it
if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
return;
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
CHECKGLERROR
// NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
GL_DepthFunc(GL_ALWAYS);
R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
- R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
GL_DepthFunc(GL_LEQUAL);
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
- R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL);
+ R_Mesh_PrepareVertices_Vertex3f(4, vertex3f, NULL, 0);
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
{
vec3_t color;
+ unsigned int occlude = 0;
GLint allpixels = 0, visiblepixels = 0;
+
// now we have to check the query result
if (rtlight->corona_queryindex_visiblepixels)
{
case RENDERPATH_GL20:
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
CHECKGLERROR
- qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
- qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
+ // See if we can use the GPU-side method to prevent implicit sync
+ if (vid.support.arb_query_buffer_object) {
+#define BUFFER_OFFSET(i) ((void*)NULL + (i))
+ if (!r_shadow_occlusion_buf) {
+ qglGenBuffersARB(1, &r_shadow_occlusion_buf);
+ qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
+ qglBufferDataARB(GL_QUERY_BUFFER_ARB, 8, NULL, GL_DYNAMIC_COPY);
+ } else {
+ qglBindBufferARB(GL_QUERY_BUFFER_ARB, r_shadow_occlusion_buf);
+ }
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(0));
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, BUFFER_OFFSET(4));
+ qglBindBufferBase(GL_UNIFORM_BUFFER, 0, r_shadow_occlusion_buf);
+ occlude = MATERIALFLAG_OCCLUDE;
+ } else {
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels);
+ qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels);
+ if (visiblepixels < 1 || allpixels < 1)
+ return;
+ rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
+ }
+ cscale *= rtlight->corona_visibility;
CHECKGLERROR
-#endif
break;
+#else
+ return;
+#endif
case RENDERPATH_D3D9:
Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_D3D10:
Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
+ return;
case RENDERPATH_SOFT:
//Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
- break;
- }
- //Con_Printf("%i of %i pixels\n", (int)visiblepixels, (int)allpixels);
- if (visiblepixels < 1 || allpixels < 1)
return;
- rtlight->corona_visibility *= bound(0, (float)visiblepixels / (float)allpixels, 1);
- cscale *= rtlight->corona_visibility;
+ default:
+ return;
+ }
}
else
{
// FIXME: these traces should scan all render entities instead of cl.world
- if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
return;
}
VectorScale(rtlight->currentcolor, cscale, color);
}
R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, RENDER_NODEPTHTEST, 0, color[0], color[1], color[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
- R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false, false);
+ R_DrawCustomSurface(r_shadow_lightcorona, &identitymatrix, MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE | MATERIALFLAG_NODEPTHTEST | occlude, 0, 4, 0, 2, false, false);
if(negated)
GL_BlendEquationSubtract(false);
}
case RENDERPATH_GLES1:
case RENDERPATH_GLES2:
usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer;
-#ifdef GL_SAMPLES_PASSED_ARB
+#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
if (usequery)
{
GL_ColorMask(0,0,0,0);
- if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
+ if (r_maxqueries < ((unsigned int)range + r_refdef.scene.numlights) * 2)
if (r_maxqueries < MAX_OCCLUSION_QUERIES)
{
i = r_maxqueries;
- r_maxqueries = (range + r_refdef.scene.numlights) * 4;
+ r_maxqueries = ((unsigned int)range + r_refdef.scene.numlights) * 4;
r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
CHECKGLERROR
qglGenQueriesARB(r_maxqueries - i, r_queries + i);
static void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, vec3_t color, vec_t radius, vec_t corona, int style, int shadowenable, const char *cubemapname, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
{
matrix4x4_t matrix;
+
+ // note that style is no longer validated here, -1 is used for unstyled lights and >= MAX_LIGHTSTYLES is accepted for sake of editing rtlights files that might be out of bounds but perfectly formatted
+
// validate parameters
- if (style < 0 || style >= MAX_LIGHTSTYLES)
- {
- Con_Printf("R_Shadow_NewWorldLight: invalid light style number %i, must be >= 0 and < %i\n", light->style, MAX_LIGHTSTYLES);
- style = 0;
- }
if (!cubemapname)
cubemapname = "";
{
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (light)
- R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight);
}
if (!r_editlights_lockcursor)
- R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL);
}
int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color)
unsigned int range;
dlight_t *light;
rtlight_t *rtlight;
- range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ range = (unsigned int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
if (lightindex >= range)
return -1;
light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
if (rating >= 0.95)
{
rating /= (1 + 0.0625f * sqrt(DotProduct(temp, temp)));
- if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1.0f)
+ if (bestrating < rating && CL_TraceLine(light->origin, r_refdef.view.origin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1.0f)
{
bestrating = rating;
best = light;
n = 0;
while (*s)
{
- t = s;
/*
+ t = s;
shadow = true;
for (;COM_Parse(t, true) && strcmp(
if (COM_Parse(t, true))
vec3_t dest, endpos;
trace_t trace;
VectorMA(r_refdef.view.origin, r_editlights_cursordistance.value, r_refdef.view.forward, dest);
- trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true);
+ trace = CL_TraceLine(r_refdef.view.origin, dest, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true);
if (trace.fraction < 1)
{
dist = trace.fraction * r_editlights_cursordistance.value;
int lightnumber, lightcount;
size_t lightindex, range;
dlight_t *light;
- float x, y;
char temp[256];
+ float x, y;
+
if (!r_editlights.integer)
return;
+
+ // update cvars so QC can query them
+ if (r_shadow_selectedlight)
+ {
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
+ Cvar_SetQuick(&r_editlights_current_origin, temp);
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
+ Cvar_SetQuick(&r_editlights_current_angles, temp);
+ dpsnprintf(temp, sizeof(temp), "%f %f %f", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
+ Cvar_SetQuick(&r_editlights_current_color, temp);
+ Cvar_SetValueQuick(&r_editlights_current_radius, r_shadow_selectedlight->radius);
+ Cvar_SetValueQuick(&r_editlights_current_corona, r_shadow_selectedlight->corona);
+ Cvar_SetValueQuick(&r_editlights_current_coronasize, r_shadow_selectedlight->coronasizescale);
+ Cvar_SetValueQuick(&r_editlights_current_style, r_shadow_selectedlight->style);
+ Cvar_SetValueQuick(&r_editlights_current_shadows, r_shadow_selectedlight->shadow);
+ Cvar_SetQuick(&r_editlights_current_cubemap, r_shadow_selectedlight->cubemapname);
+ Cvar_SetValueQuick(&r_editlights_current_ambient, r_shadow_selectedlight->ambientscale);
+ Cvar_SetValueQuick(&r_editlights_current_diffuse, r_shadow_selectedlight->diffusescale);
+ Cvar_SetValueQuick(&r_editlights_current_specular, r_shadow_selectedlight->specularscale);
+ Cvar_SetValueQuick(&r_editlights_current_normalmode, (r_shadow_selectedlight->flags & LIGHTFLAG_NORMALMODE) ? 1 : 0);
+ Cvar_SetValueQuick(&r_editlights_current_realtimemode, (r_shadow_selectedlight->flags & LIGHTFLAG_REALTIMEMODE) ? 1 : 0);
+ }
+
+ // draw properties on screen
+ if (!r_editlights_drawproperties.integer)
+ return;
x = vid_conwidth.value - 240;
y = 5;
DrawQ_Pic(x-5, y-5, NULL, 250, 155, 0, 0, 0, 0.75, 0);
if (!light)
continue;
if (light == r_shadow_selectedlight)
- lightnumber = lightindex;
+ lightnumber = (int)lightindex;
lightcount++;
}
dpsnprintf(temp, sizeof(temp), "Cursor origin: %.0f %.0f %.0f", r_editlights_cursorlocation[0], r_editlights_cursorlocation[1], r_editlights_cursorlocation[2]); DrawQ_String(x, y, temp, 0, 8, 8, 1, 1, 1, 1, 0, NULL, false, FONT_DEFAULT);y += 8;
"sizescale scale : multiply radius (size) of light (1 does nothing)\n"
"originscale x y z : multiply origin of light (1 1 1 does nothing)\n"
"style style : set lightstyle of light (flickering patterns, switches, etc)\n"
-"cubemap basename : set filter cubemap of light (not yet supported)\n"
+"cubemap basename : set filter cubemap of light\n"
"shadows 1/0 : turn on/off shadows\n"
"corona n : set corona intensity\n"
"coronasize n : set corona size (0-1)\n"
Cvar_RegisterVariable(&r_editlights_cursorpushoff);
Cvar_RegisterVariable(&r_editlights_cursorgrid);
Cvar_RegisterVariable(&r_editlights_quakelightsizescale);
+ Cvar_RegisterVariable(&r_editlights_drawproperties);
+ Cvar_RegisterVariable(&r_editlights_current_origin);
+ Cvar_RegisterVariable(&r_editlights_current_angles);
+ Cvar_RegisterVariable(&r_editlights_current_color);
+ Cvar_RegisterVariable(&r_editlights_current_radius);
+ Cvar_RegisterVariable(&r_editlights_current_corona);
+ Cvar_RegisterVariable(&r_editlights_current_coronasize);
+ Cvar_RegisterVariable(&r_editlights_current_style);
+ Cvar_RegisterVariable(&r_editlights_current_shadows);
+ Cvar_RegisterVariable(&r_editlights_current_cubemap);
+ Cvar_RegisterVariable(&r_editlights_current_ambient);
+ Cvar_RegisterVariable(&r_editlights_current_diffuse);
+ Cvar_RegisterVariable(&r_editlights_current_specular);
+ Cvar_RegisterVariable(&r_editlights_current_normalmode);
+ Cvar_RegisterVariable(&r_editlights_current_realtimemode);
Cmd_AddCommand("r_editlights_help", R_Shadow_EditLights_Help_f, "prints documentation on console commands and variables in rtlight editing system");
Cmd_AddCommand("r_editlights_clear", R_Shadow_EditLights_Clear_f, "removes all world lights (let there be darkness!)");
Cmd_AddCommand("r_editlights_reload", R_Shadow_EditLights_Reload_f, "reloads rtlights file (or imports from .lights file or .ent file or the map itself)");
=============================================================================
*/
-void R_LightPoint(vec3_t color, const vec3_t p, const int flags)
+void R_LightPoint(float *color, const vec3_t p, const int flags)
{
int i, numlights, flag;
float f, relativepoint[3], dist, dist2, lightradius2;
if (flags & LP_RTWORLD)
{
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
for (i = 0; i < numlights; i++)
{
dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
if (f <= 0)
continue;
// todo: add to both ambient and diffuse
- if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1)
+ if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
VectorMA(color, f, light->currentcolor, color);
}
}
if (f <= 0)
continue;
// todo: add to both ambient and diffuse
- if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction == 1)
+ if (!light->shadow || CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction == 1)
VectorMA(color, f, light->color, color);
}
}
if (flags & LP_RTWORLD)
{
flag = r_refdef.scene.rtworld ? LIGHTFLAG_REALTIMEMODE : LIGHTFLAG_NORMALMODE;
- numlights = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
+ numlights = (int)Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray);
for (i = 0; i < numlights; i++)
{
dlight = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, i);
intensity = min(1.0f, (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;
intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist) * r_shadow_lightintensityscale.value;
if (intensity <= 0.0f)
continue;
- if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false, true).fraction < 1)
+ if (light->shadow && CL_TraceLine(p, light->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, collision_extendmovelength.value, true, false, NULL, false, true).fraction < 1)
continue;
// scale down intensity to add to both ambient and diffuse
//intensity *= 0.5f;