R_SHADOW_RENDERMODE_LIGHT_GLSL,
R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
R_SHADOW_RENDERMODE_VISIBLELIGHTING,
- R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
R_SHADOW_RENDERMODE_SHADOWMAP2D,
+ R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
}
r_shadow_rendermode_t;
+typedef enum r_shadow_shadowmode_e
+{
+ R_SHADOW_SHADOWMODE_STENCIL,
+ R_SHADOW_SHADOWMODE_SHADOWMAP2D,
+ R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
+ R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
+}
+r_shadow_shadowmode_t;
+
r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
int r_shadow_shadowmapside;
float r_shadow_shadowmap_texturescale[2];
float r_shadow_shadowmap_parameters[4];
+#if 0
int r_shadow_drawbuffer;
int r_shadow_readbuffer;
-int r_shadow_cullface;
+#endif
+int r_shadow_cullface_front, r_shadow_cullface_back;
GLuint r_shadow_fborectangle;
-GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS][6];
+GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
GLuint r_shadow_fbo2d;
-int r_shadow_shadowmode;
+r_shadow_shadowmode_t r_shadow_shadowmode;
int r_shadow_shadowmapfilterquality;
int r_shadow_shadowmaptexturetype;
-int r_shadow_shadowmapprecision;
+int r_shadow_shadowmapdepthbits;
int r_shadow_shadowmapmaxsize;
qboolean r_shadow_shadowmapvsdct;
qboolean r_shadow_shadowmapsampler;
rtexture_t *r_shadow_attenuationgradienttexture;
rtexture_t *r_shadow_attenuation2dtexture;
rtexture_t *r_shadow_attenuation3dtexture;
-rtexture_t *r_shadow_lightcorona;
+skinframe_t *r_shadow_lightcorona;
rtexture_t *r_shadow_shadowmaprectangletexture;
rtexture_t *r_shadow_shadowmap2dtexture;
rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
+cvar_t r_shadow_dot3 = {CVAR_SAVE, "r_shadow_dot3", "0", "enables use of (slow) per pixel lighting on GL1.3 hardware"};
cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "1", "enables portal-based culling optimization during compilation"};
cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
-cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "0", "shadowmap texture types: 0 = auto-select, 1 = 2D, 2 = rectangle, 3 = cubemap"};
+cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
-cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "24", "requested minimum shadowmap texture precision"};
+cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
-cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
-cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
+cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
+//cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
+//cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
+cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
+cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
cvar_t r_shadow_culltriangles = {0, "r_shadow_culltriangles", "1", "performs more expensive tests to remove unnecessary triangles of lit surfaces"};
cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
}
cubemapinfo_t;
-#define MAX_CUBEMAPS 256
static int numcubemaps;
static cubemapinfo_t cubemaps[MAX_CUBEMAPS];
void R_Shadow_ValidateCvars(void);
static void R_Shadow_MakeTextures(void);
-// VorteX: custom editor light sprites
#define EDLIGHTSPRSIZE 8
-cachepic_t *r_editlights_sprcursor;
-cachepic_t *r_editlights_sprlight;
-cachepic_t *r_editlights_sprnoshadowlight;
-cachepic_t *r_editlights_sprcubemaplight;
-cachepic_t *r_editlights_sprcubemapnoshadowlight;
-cachepic_t *r_editlights_sprselection;
+skinframe_t *r_editlights_sprcursor;
+skinframe_t *r_editlights_sprlight;
+skinframe_t *r_editlights_sprnoshadowlight;
+skinframe_t *r_editlights_sprcubemaplight;
+skinframe_t *r_editlights_sprcubemapnoshadowlight;
+skinframe_t *r_editlights_sprselection;
+extern cvar_t gl_max_size;
void R_Shadow_SetShadowMode(void)
{
- r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, 2048);
+ r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4);
r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
- r_shadow_shadowmapprecision = r_shadow_shadowmapping_precision.integer;
+ r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
r_shadow_shadowmaplod = -1;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
- r_shadow_shadowmode = 0;
- if(r_shadow_shadowmapping.integer)
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
+ if(r_shadow_shadowmapping.integer && r_glsl.integer && gl_support_fragment_shader && gl_support_ext_framebuffer_object)
{
if(r_shadow_shadowmapfilterquality < 0)
{
break;
}
}
- r_shadow_shadowmode = r_shadow_shadowmaptexturetype;
- if(r_shadow_shadowmode <= 0)
- {
+ switch (r_shadow_shadowmaptexturetype)
+ {
+ case 0:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
+ break;
+ case 1:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
+ break;
+ case 2:
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
+ break;
+ default:
if((gl_support_amd_texture_texture4 || gl_support_arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
- r_shadow_shadowmode = 1;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
else if(gl_texturerectangle)
- r_shadow_shadowmode = 2;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
else
- r_shadow_shadowmode = 1;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
+ break;
}
}
}
r_shadow_fbo2d = 0;
CHECKGLERROR
for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
- if (r_shadow_fbocubeside[i][0])
- qglDeleteFramebuffersEXT(6, r_shadow_fbocubeside[i]);
+ if (r_shadow_fbocubeside[i])
+ qglDeleteFramebuffersEXT(1, &r_shadow_fbocubeside[i]);
memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
CHECKGLERROR
r_shadow_attenuationgradienttexture = NULL;
r_shadow_attenuation2dtexture = NULL;
r_shadow_attenuation3dtexture = NULL;
- r_shadow_shadowmode = 0;
+ r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
r_shadow_shadowmaprectangletexture = NULL;
r_shadow_shadowmap2dtexture = NULL;
memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
r_shadow_shadowmapmaxsize = 0;
r_shadow_shadowmapsize = 0;
r_shadow_shadowmaplod = 0;
- r_shadow_shadowmapfilterquality = 0;
- r_shadow_shadowmaptexturetype = 0;
- r_shadow_shadowmapprecision = 0;
+ r_shadow_shadowmapfilterquality = -1;
+ r_shadow_shadowmaptexturetype = -1;
+ r_shadow_shadowmapdepthbits = 0;
r_shadow_shadowmapvsdct = false;
r_shadow_shadowmapsampler = false;
r_shadow_shadowmappcf = 0;
void r_shadow_newmap(void)
{
+ if (r_shadow_lightcorona) R_SkinFrame_MarkUsed(r_shadow_lightcorona);
+ if (r_editlights_sprcursor) R_SkinFrame_MarkUsed(r_editlights_sprcursor);
+ if (r_editlights_sprlight) R_SkinFrame_MarkUsed(r_editlights_sprlight);
+ if (r_editlights_sprnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
+ if (r_editlights_sprcubemaplight) R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
+ if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
+ if (r_editlights_sprselection) R_SkinFrame_MarkUsed(r_editlights_sprselection);
if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname)))
R_Shadow_EditLights_Reload_f();
}
{
Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+ Cvar_RegisterVariable(&r_shadow_dot3);
Cvar_RegisterVariable(&r_shadow_usenormalmap);
Cvar_RegisterVariable(&r_shadow_debuglight);
Cvar_RegisterVariable(&r_shadow_gloss);
Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
- Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
- Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
+// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
+// Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
+ Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
Cvar_RegisterVariable(&r_shadow_culltriangles);
Cvar_RegisterVariable(&r_shadow_polygonfactor);
Cvar_RegisterVariable(&r_shadow_polygonoffset);
pixels[y][x][3] = 255;
}
}
- r_shadow_lightcorona = R_LoadTexture2D(r_shadow_texturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR, NULL);
+ r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_PRECACHE | TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
}
static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
int x, y, z;
float intensity, dist;
unsigned int *data;
+ R_Shadow_FreeShadowMaps();
R_FreeTexturePool(&r_shadow_texturepool);
r_shadow_texturepool = R_AllocTexturePool();
r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
R_Shadow_MakeTextures_MakeCorona();
// Editor light sprites
- r_editlights_sprcursor = Draw_CachePic ("gfx/editlights/cursor");
- r_editlights_sprlight = Draw_CachePic ("gfx/editlights/light");
- r_editlights_sprnoshadowlight = Draw_CachePic ("gfx/editlights/noshadow");
- r_editlights_sprcubemaplight = Draw_CachePic ("gfx/editlights/cubemaplight");
- r_editlights_sprcubemapnoshadowlight = Draw_CachePic ("gfx/editlights/cubemapnoshadowlight");
- r_editlights_sprselection = Draw_CachePic ("gfx/editlights/selection");
+ r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+ "................"
+ ".3............3."
+ "..5...2332...5.."
+ "...7.3....3.7..."
+ "....7......7...."
+ "...3.7....7.3..."
+ "..2...7..7...2.."
+ "..3..........3.."
+ "..3..........3.."
+ "..2...7..7...2.."
+ "...3.7....7.3..."
+ "....7......7...."
+ "...7.3....3.7..."
+ "..5...2332...5.."
+ ".3............3."
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+ r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+ "................"
+ "................"
+ "......1111......"
+ "....11233211...."
+ "...1234554321..."
+ "...1356776531..."
+ "..124677776421.."
+ "..135777777531.."
+ "..135777777531.."
+ "..124677776421.."
+ "...1356776531..."
+ "...1234554321..."
+ "....11233211...."
+ "......1111......"
+ "................"
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+ r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+ "................"
+ "................"
+ "......1111......"
+ "....11233211...."
+ "...1234554321..."
+ "...1356226531..."
+ "..12462..26421.."
+ "..1352....2531.."
+ "..1352....2531.."
+ "..12462..26421.."
+ "...1356226531..."
+ "...1234554321..."
+ "....11233211...."
+ "......1111......"
+ "................"
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+ r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+ "................"
+ "................"
+ "......2772......"
+ "....27755772...."
+ "..277533335772.."
+ "..753333333357.."
+ "..777533335777.."
+ "..735775577537.."
+ "..733357753337.."
+ "..733337733337.."
+ "..753337733357.."
+ "..277537735772.."
+ "....27777772...."
+ "......2772......"
+ "................"
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+ r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
+ "................"
+ "................"
+ "......2772......"
+ "....27722772...."
+ "..2772....2772.."
+ "..72........27.."
+ "..7772....2777.."
+ "..7.27722772.7.."
+ "..7...2772...7.."
+ "..7....77....7.."
+ "..72...77...27.."
+ "..2772.77.2772.."
+ "....27777772...."
+ "......2772......"
+ "................"
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
+ r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_PRECACHE | TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
+ "................"
+ ".777752..257777."
+ ".742........247."
+ ".72..........27."
+ ".7............7."
+ ".5............5."
+ ".2............2."
+ "................"
+ "................"
+ ".2............2."
+ ".5............5."
+ ".7............7."
+ ".72..........27."
+ ".742........247."
+ ".777752..257777."
+ "................"
+ , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
}
void R_Shadow_ValidateCvars(void)
void R_Shadow_RenderMode_Begin(void)
{
+#if 0
GLint drawbuffer;
GLint readbuffer;
+#endif
R_Shadow_ValidateCvars();
if (!r_shadow_attenuation2dtexture
if (r_glsl.integer && gl_support_fragment_shader)
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
- else if (gl_dot3arb && gl_texturecubemap && r_textureunits.integer >= 2 && gl_combine.integer && gl_stencil)
+ else if (gl_dot3arb && gl_texturecubemap && r_shadow_dot3.integer && gl_stencil)
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_DOT3;
else
r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
CHECKGLERROR
+#if 0
qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
r_shadow_drawbuffer = drawbuffer;
r_shadow_readbuffer = readbuffer;
- r_shadow_cullface = r_refdef.view.cullface_back;
+#endif
+ r_shadow_cullface_front = r_refdef.view.cullface_front;
+ r_shadow_cullface_back = r_refdef.view.cullface_back;
}
void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
{
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
}
+#if 0
qglDrawBuffer(r_shadow_drawbuffer);CHECKGLERROR
qglReadBuffer(r_shadow_readbuffer);CHECKGLERROR
+#endif
R_SetViewport(&r_refdef.view.viewport);
GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
R_Mesh_ColorPointer(NULL, 0, 0);
qglStencilMask(~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
- r_refdef.view.cullface_back = r_shadow_cullface;
+ r_refdef.view.cullface_front = r_shadow_cullface_front;
+ r_refdef.view.cullface_back = r_shadow_cullface_back;
GL_CullFace(r_refdef.view.cullface_back);
GL_Color(1, 1, 1, 1);
GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
void R_Shadow_RenderMode_ShadowMap(int side, qboolean clear, int size)
{
- int i;
int status;
int maxsize;
float nearclip, farclip, bias;
r_viewport_t viewport;
+ GLuint fbo = 0;
CHECKGLERROR
maxsize = r_shadow_shadowmapmaxsize;
nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
r_shadow_shadowmapside = side;
r_shadow_shadowmapsize = size;
- if (r_shadow_shadowmode == 1)
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
{
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
+
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
{
#if 1
int w = maxsize*2, h = gl_support_arb_texture_non_power_of_two ? maxsize*3 : maxsize*4;
- r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+ r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", w, h, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
qglGenFramebuffersEXT(1, &r_shadow_fbo2d);CHECKGLERROR
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, R_GetTexture(r_shadow_shadowmap2dtexture), 0);CHECKGLERROR
-#endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmap2dtexture)
- {
- // render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbo2d);CHECKGLERROR
+ // render depth into the fbo, do not render color at all
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+#endif
}
- R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ CHECKGLERROR
+ if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
- r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
}
- else if (r_shadow_shadowmode == 2)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
{
+ r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
+ r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
+ R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
+
// complex unrolled cube approach (more flexible)
if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
R_Shadow_MakeVSDCT();
if (!r_shadow_shadowmaprectangletexture)
{
#if 1
- r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
+ r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", maxsize*2, maxsize*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
qglGenFramebuffersEXT(1, &r_shadow_fborectangle);CHECKGLERROR
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, R_GetTexture(r_shadow_shadowmaprectangletexture), 0);CHECKGLERROR
-#endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmaprectangletexture)
- {
// render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fborectangle);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+#endif
}
- R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
+ CHECKGLERROR
+ if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
r_shadow_shadowmap_texturescale[0] = 1.0f;
r_shadow_shadowmap_texturescale[1] = 1.0f;
- r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
- r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
}
- else if (r_shadow_shadowmode == 3)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
{
+ r_shadow_shadowmap_parameters[0] = 1.0f;
+ r_shadow_shadowmap_parameters[1] = 1.0f;
+ R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
+
// simple cube approach
if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
{
#if 1
- r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapprecision, r_shadow_shadowmapsampler);
- qglGenFramebuffersEXT(6, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
- for (i = 0;i < 6;i++)
- {
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][i]);CHECKGLERROR
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
- }
- #endif
- }
- CHECKGLERROR
- R_Shadow_RenderMode_Reset();
- if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
- {
+ r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+ qglGenFramebuffersEXT(1, &r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod]);CHECKGLERROR
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
// render depth into the fbo, do not render color at all
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r_shadow_fbocubeside[r_shadow_shadowmaplod][side]);CHECKGLERROR
qglDrawBuffer(GL_NONE);CHECKGLERROR
qglReadBuffer(GL_NONE);CHECKGLERROR
status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT && r_shadow_shadowmapping.integer)
{
Con_Printf("R_Shadow_RenderMode_ShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
}
- R_SetupDepthOrShadowShader();
- }
- else
- {
- R_SetupShowDepthShader();
- qglClearColor(1,1,1,1);CHECKGLERROR
+ #endif
}
- R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
- r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureWidth(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
- r_shadow_shadowmap_parameters[0] = 1.0f;
- r_shadow_shadowmap_parameters[1] = 1.0f;
+ CHECKGLERROR
+ if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
+ r_shadow_shadowmap_texturescale[0] = 0.0f;
+ r_shadow_shadowmap_texturescale[1] = 0.0f;
r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
}
- CHECKGLERROR
- R_SetViewport(&viewport);
- GL_PolygonOffset(0, 0);
- if(r_shadow_shadowmode >= 1 && r_shadow_shadowmode <= 2)
+
+ R_Shadow_RenderMode_Reset();
+ if (fbo)
{
- static qboolean cullfront[6] = { false, true, false, true, true, false };
- if(cullfront[side]) r_refdef.view.cullface_back = r_refdef.view.cullface_front;
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
+ R_SetupDepthOrShadowShader();
}
- GL_CullFace(r_refdef.view.cullface_back);
- GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+ else
+ {
+ R_SetupShowDepthShader();
+ qglClearColor(1,1,1,1);CHECKGLERROR
+ }
+ CHECKGLERROR
+ GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
GL_DepthMask(true);
GL_DepthTest(true);
- qglClearDepth(1);CHECKGLERROR
+ qglClearDepth(1);
CHECKGLERROR
+
+init_done:
+ R_SetViewport(&viewport);
+ GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
+ if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D || r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE)
+ {
+ int flipped = (side&1)^(side>>2);
+ r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
+ r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
+ GL_CullFace(r_refdef.view.cullface_back);
+ }
+ else if(r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE)
+ {
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
+ }
if (clear)
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
CHECKGLERROR
void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
{
+ if (transparent)
+ {
+ r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
+ r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
+ r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
+ r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
+ }
CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
CHECKGLERROR
if (shadowmapping)
{
- if (r_shadow_shadowmode == 1)
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D)
{
r_shadow_usingshadowmap2d = true;
R_Mesh_TexBind(GL20TU_SHADOWMAP2D, R_GetTexture(r_shadow_shadowmap2dtexture));
CHECKGLERROR
}
- else if (r_shadow_shadowmode == 2)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE)
{
r_shadow_usingshadowmaprect = true;
R_Mesh_TexBindRectangle(GL20TU_SHADOWMAPRECT, R_GetTexture(r_shadow_shadowmaprectangletexture));
CHECKGLERROR
}
- else if (r_shadow_shadowmode == 3)
+ else if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
{
r_shadow_usingshadowmapcube = true;
R_Mesh_TexBindCubeMap(GL20TU_SHADOWMAPCUBE, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
}
else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_VERTEX)
R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ //GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
CHECKGLERROR
}
static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor)
{
- float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
- float *normal3f = rsurface.normal3f + 3 * firstvertex;
+ const float *vertex3f = rsurface.vertex3f + 3 * firstvertex;
+ const float *normal3f = rsurface.normal3f + 3 * firstvertex;
float *color4f = rsurface.array_color4f + 4 * firstvertex;
float dist, dot, distintensity, shadeintensity, v[3], n[3];
if (r_textureunits.integer >= 3)
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
color4f[3] = 1;
{
float f;
Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
color4f[3] = 1;
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
if (r_refdef.fogenabled)
{
float f;
- f = FogPoint_Model(vertex3f);
+ f = RSurf_FogVertex(vertex3f);
VectorScale(color4f, f, color4f);
}
}
{
VectorSubtract(rsurface.entitylightorigin, vertex3f, lightdir);
VectorNormalize(lightdir);
- VectorSubtract(rsurface.modelorg, vertex3f, eyedir);
+ VectorSubtract(rsurface.localvieworigin, vertex3f, eyedir);
VectorNormalize(eyedir);
VectorAdd(lightdir, eyedir, halfdir);
// the cubemap normalizes this for us
m.pointer_texcoord_bufferoffset[1] = rsurface.vertex3f_bufferoffset;
if (r_textureunits.integer >= 3)
{
- // Voodoo4 or Kyro (or Geforce3/Radeon with gl_combine off)
+ // Voodoo4 or Kyro (or Geforce3/Radeon with r_shadow_dot3 off)
m.tex[2] = R_GetTexture(r_shadow_attenuation2dtexture);
m.texmatrix[2] = rsurface.entitytoattenuationz;
m.pointer_texcoord3f[2] = rsurface.vertex3f;
void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject)
{
float ambientscale, diffusescale, specularscale;
+ qboolean negated;
vec3_t lightcolorbase, lightcolorpants, lightcolorshirt;
rtexture_t *nmap;
// calculate colors to render this texture with
}
if ((ambientscale + diffusescale) * VectorLength2(lightcolorbase) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
return;
+ negated = (lightcolorbase[0] + lightcolorbase[1] + lightcolorbase[2] < 0) && gl_support_ext_blend_subtract;
+ if(negated)
+ {
+ VectorNegate(lightcolorbase, lightcolorbase);
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ }
RSurf_SetupDepthAndCulling();
nmap = rsurface.texture->currentskinframe->nmap;
if (gl_lightmaps.integer)
break;
}
}
+ if(negated)
+ qglBlendEquationEXT(GL_FUNC_ADD_EXT);
}
void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
// compile the light
rtlight->compiled = true;
- rtlight->shadowmode = rtlight->shadow ? r_shadow_shadowmode : -1;
+ rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
rtlight->static_numleafs = 0;
rtlight->static_numleafpvsbytes = 0;
rtlight->static_leaflist = NULL;
memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
if (rtlight->static_numlighttrispvsbytes)
memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
- if (rtlight->shadowmode <= 0)
- {
- if (model->CompileShadowVolume && rtlight->shadow)
- model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
- }
- else
+ switch (rtlight->shadowmode)
{
+ case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+ case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+ case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
if (model->CompileShadowMap && rtlight->shadow)
model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
+ break;
+ default:
+ if (model->CompileShadowVolume && rtlight->shadow)
+ model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
+ break;
}
// now we're done compiling the rtlight
r_shadow_compilingrtlight = NULL;
// all at once at the start of a level, not when it stalls gameplay.
// (especially important to benchmarks)
// compile light
- if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
+ if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer)
{
if (rtlight->compiled)
R_RTLight_Uncompile(rtlight);
nearestpoint[1] = bound(rtlight->cullmins[1], r_refdef.view.origin[1], rtlight->cullmaxs[1]);
nearestpoint[2] = bound(rtlight->cullmins[2], r_refdef.view.origin[2], rtlight->cullmaxs[2]);
distance = VectorDistance(nearestpoint, r_refdef.view.origin);
- lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
- lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapping_maxsize.integer);
- if (castshadows && r_shadow_shadowmode >= 1 && r_shadow_shadowmode <= 3 && r_glsl.integer && gl_support_fragment_shader)
+ lodlinear = (rtlight->radius * r_shadow_shadowmapping_precision.value) / sqrt(max(1.0f, distance/rtlight->radius));
+ //lodlinear = (int)(r_shadow_shadowmapping_lod_bias.value + r_shadow_shadowmapping_lod_scale.value * rtlight->radius / max(1.0f, distance));
+ lodlinear = bound(r_shadow_shadowmapping_minsize.integer, lodlinear, r_shadow_shadowmapmaxsize);
+
+ if (castshadows && (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAP2D || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE || r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE))
{
float borderbias;
int side;
r_shadow_shadowmaplod = 0;
for (i = 1;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
- if ((r_shadow_shadowmapping_maxsize.integer >> i) > lodlinear)
+ if ((r_shadow_shadowmapmaxsize >> i) > lodlinear)
r_shadow_shadowmaplod = i;
- size = r_shadow_shadowmode == 3 ? r_shadow_shadowmapping_maxsize.integer >> r_shadow_shadowmaplod : lodlinear;
- size = bound(1, size, 2048);
+ if (r_shadow_shadowmode == R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE)
+ size = max(1, r_shadow_shadowmapmaxsize >> r_shadow_shadowmaplod);
+ else
+ size = bound(r_shadow_shadowmapborder, lodlinear, r_shadow_shadowmapmaxsize);
+
borderbias = r_shadow_shadowmapborder / (float)(size - r_shadow_shadowmapborder);
if (numsurfaces)
for (side = 0;side < 6;side++) if ((receivermask & castermask) & (1 << side))
{
R_Shadow_RenderMode_ShadowMap(side, false, size);
- for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides[shadowentities_noselfshadow - i] && (1 << side))
+ for (i = 0;i < numshadowentities_noselfshadow;i++) if (entitysides[shadowentities_noselfshadow - i] & (1 << side))
R_Shadow_DrawEntityShadow(shadowentities[shadowentities_noselfshadow - i]);
}
}
size_t lightindex;
dlight_t *light;
size_t range;
+ float f;
- if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, 2048) ||
- (r_shadow_shadowmode != 0) != (r_shadow_shadowmapping.integer != 0) ||
+ if (r_shadow_shadowmapmaxsize != bound(1, r_shadow_shadowmapping_maxsize.integer, gl_max_size.integer / 4) ||
+ (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) != (r_shadow_shadowmapping.integer && r_glsl.integer && gl_support_fragment_shader && gl_support_ext_framebuffer_object) ||
r_shadow_shadowmapvsdct != (r_shadow_shadowmapping_vsdct.integer != 0) ||
r_shadow_shadowmaptexturetype != r_shadow_shadowmapping_texturetype.integer ||
r_shadow_shadowmapfilterquality != r_shadow_shadowmapping_filterquality.integer ||
- r_shadow_shadowmapprecision != r_shadow_shadowmapping_precision.integer ||
+ r_shadow_shadowmapdepthbits != r_shadow_shadowmapping_depthbits.integer ||
r_shadow_shadowmapborder != bound(0, r_shadow_shadowmapping_bordersize.integer, 16))
R_Shadow_FreeShadowMaps();
}
}
if (r_refdef.scene.rtdlight)
+ {
for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
R_DrawRTLight(r_refdef.scene.lights[lnum], visible);
+ }
+ else if(gl_flashblend.integer)
+ {
+ for (lnum = 0;lnum < r_refdef.scene.numlights;lnum++)
+ {
+ rtlight_t *rtlight = r_refdef.scene.lights[lnum];
+ f = (rtlight->style >= 0 ? r_refdef.scene.lightstylevalue[rtlight->style] : 1) * r_shadow_lightintensityscale.value;
+ VectorScale(rtlight->color, f, rtlight->currentcolor);
+ }
+ }
R_Shadow_RenderMode_End();
}
qglStencilFunc(GL_NOTEQUAL, 128, ~0);CHECKGLERROR
// apply the blend to the shadowed areas
- R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
// restore the viewport
R_SetViewport(&r_refdef.view.viewport);
{
float zdist;
vec3_t centerorigin;
+ float vertex3f[12];
// if it's too close, skip it
- if (VectorLength(rtlight->color) < (1.0f / 256.0f))
+ if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f))
return;
zdist = (DotProduct(rtlight->shadoworigin, r_refdef.view.forward) - DotProduct(r_refdef.view.origin, r_refdef.view.forward));
if (zdist < 32)
{
rtlight->corona_queryindex_allpixels = r_queries[r_numqueries++];
rtlight->corona_queryindex_visiblepixels = r_queries[r_numqueries++];
+ // we count potential samples in the middle of the screen, we count actual samples at the light location, this allows counting potential samples of off-screen lights
VectorMA(r_refdef.view.origin, zdist, r_refdef.view.forward, centerorigin);
CHECKGLERROR
- // NOTE: we can't disable depth testing using R_DrawSprite's depthdisable argument, which calls GL_DepthTest, as that's broken in the ATI drivers
+ // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use qglDepthFunc instead
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels);
qglDepthFunc(GL_ALWAYS);
- R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
+ R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
+ R_Mesh_VertexPointer(vertex3f, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
qglDepthFunc(GL_LEQUAL);
qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels);
- R_DrawSprite(GL_ONE, GL_ZERO, r_shadow_lightcorona, NULL, false, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, 1, 1, 1, 1);
+ R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale);
+ R_Mesh_VertexPointer(vertex3f, 0, 0);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
CHECKGLERROR
}
rtlight->corona_visibility = bound(0, (zdist - 32) / 32, 1);
}
+static float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
+
void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale)
{
vec3_t color;
if (CL_TraceLine(r_refdef.view.origin, rtlight->shadoworigin, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, true, false, NULL, false).fraction < 1)
return;
}
- VectorScale(rtlight->color, cscale, color);
+ VectorScale(rtlight->currentcolor, cscale, color);
if (VectorLength(color) > (1.0f / 256.0f))
- R_DrawSprite(GL_ONE, GL_ONE, r_shadow_lightcorona, NULL, true, false, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale, color[0], color[1], color[2], 1);
+ {
+ float vertex3f[12];
+ qboolean negated = (color[0] + color[1] + color[2] < 0) && gl_support_ext_blend_subtract;
+ if(negated)
+ {
+ VectorNegate(color, color);
+ qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
+ }
+ R_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);
+ if(negated)
+ qglBlendEquationEXT(GL_FUNC_ADD_EXT);
+ }
}
void R_DrawCoronas(void)
{
GL_ColorMask(0,0,0,0);
if (r_maxqueries < (range + r_refdef.scene.numlights) * 2)
- if (r_maxqueries < R_MAX_OCCLUSION_QUERIES)
+ if (r_maxqueries < MAX_OCCLUSION_QUERIES)
{
i = r_maxqueries;
r_maxqueries = (range + r_refdef.scene.numlights) * 4;
- r_maxqueries = min(r_maxqueries, R_MAX_OCCLUSION_QUERIES);
+ r_maxqueries = min(r_maxqueries, MAX_OCCLUSION_QUERIES);
CHECKGLERROR
qglGenQueriesARB(r_maxqueries - i, r_queries + i);
CHECKGLERROR
}
+ RSurf_ActiveWorldEntity();
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_CullFace(GL_NONE);
+ GL_DepthMask(false);
+ GL_DepthRange(0, 1);
+ GL_PolygonOffset(0, 0);
+ GL_DepthTest(true);
+ R_Mesh_ColorPointer(NULL, 0, 0);
+ R_Mesh_ResetTextureState();
+ R_SetupGenericShader(false);
}
for (lightindex = 0;lightindex < range;lightindex++)
{
light->angles[0] = angles[0] - 360 * floor(angles[0] / 360);
light->angles[1] = angles[1] - 360 * floor(angles[1] / 360);
light->angles[2] = angles[2] - 360 * floor(angles[2] / 360);
+ /*
light->color[0] = max(color[0], 0);
light->color[1] = max(color[1], 0);
light->color[2] = max(color[2], 0);
+ */
+ light->color[0] = color[0];
+ light->color[1] = color[1];
+ light->color[2] = color[2];
light->radius = max(radius, 0);
light->style = style;
light->shadow = shadowenable;
void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
// this is never batched (there can be only one)
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprcursor->tex, r_editlights_sprcursor->tex, false, false, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE, 1, 1, 1, 1);
+ float vertex3f[12];
+ R_CalcSprite_Vertex3f(vertex3f, r_editlights_cursorlocation, r_refdef.view.right, r_refdef.view.up, EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, -EDLIGHTSPRSIZE, EDLIGHTSPRSIZE);
+ RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+ R_DrawCustomSurface(r_editlights_sprcursor, &identitymatrix, MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
}
void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
float intensity;
float s;
vec3_t spritecolor;
- cachepic_t *pic;
+ skinframe_t *skinframe;
+ float vertex3f[12];
// this is never batched (due to the ent parameter changing every time)
// so numsurfaces == 1 and surfacelist[0] == lightnumber
const dlight_t *light = (dlight_t *)ent;
s = EDLIGHTSPRSIZE;
+
+ R_CalcSprite_Vertex3f(vertex3f, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s);
+
intensity = 0.5f;
VectorScale(light->color, intensity, spritecolor);
if (VectorLength(spritecolor) < 0.1732f)
// draw light sprite
if (light->cubemapname[0] && !light->shadow)
- pic = r_editlights_sprcubemapnoshadowlight;
+ skinframe = r_editlights_sprcubemapnoshadowlight;
else if (light->cubemapname[0])
- pic = r_editlights_sprcubemaplight;
+ skinframe = r_editlights_sprcubemaplight;
else if (!light->shadow)
- pic = r_editlights_sprnoshadowlight;
+ skinframe = r_editlights_sprnoshadowlight;
else
- pic = r_editlights_sprlight;
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, pic->tex, pic->tex, false, false, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s, spritecolor[0], spritecolor[1], spritecolor[2], 1);
+ skinframe = r_editlights_sprlight;
+
+ RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, spritecolor[0], spritecolor[1], spritecolor[2], 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+ R_DrawCustomSurface(skinframe, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+
// draw selection sprite if light is selected
if (light->selected)
- R_DrawSprite(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, r_editlights_sprselection->tex, r_editlights_sprselection->tex, false, false, light->origin, r_refdef.view.right, r_refdef.view.up, s, -s, -s, s, 1, 1, 1, 1);
- // VorteX todo: add normalmode/realtime mode light overlay sprites?
+ {
+ RSurf_ActiveCustomEntity(&identitymatrix, &identitymatrix, 0, 0, 1, 1, 1, 1, 4, vertex3f, spritetexcoord2f, NULL, NULL, NULL, NULL, 2, polygonelement3i, polygonelement3s, false, false);
+ R_DrawCustomSurface(r_editlights_sprselection, &identitymatrix, MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_NOCULLFACE, 0, 4, 0, 2, false);
+ // VorteX todo: add normalmode/realtime mode light overlay sprites?
+ }
}
void R_Shadow_DrawLightSprites(void)
R_MeshQueue_AddTransparent(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);
+ if (lightindex >= range)
+ return -1;
+ light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
+ if (!light)
+ return 0;
+ rtlight = &light->rtlight;
+ //if (!(rtlight->flags & flag))
+ // return 0;
+ VectorCopy(rtlight->shadoworigin, origin);
+ *radius = rtlight->radius;
+ VectorCopy(rtlight->color, color);
+ return 1;
+}
+
void R_Shadow_SelectLightInView(void)
{
float bestrating, rating, temp[3];