#define SHADOWSTAGE_NONE 0
#define SHADOWSTAGE_STENCIL 1
#define SHADOWSTAGE_LIGHT 2
-#define SHADOWSTAGE_ERASESTENCIL 3
+#define SHADOWSTAGE_STENCILTWOSIDE 3
int r_shadowstage = SHADOWSTAGE_NONE;
int r_shadow_reloadlights = false;
cvar_t r_shadow_showtris = {0, "r_shadow_showtris", "0"};
cvar_t r_shadow_staticworldlights = {0, "r_shadow_staticworldlights", "1"};
cvar_t r_shadow_cull = {0, "r_shadow_cull", "1"};
+cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1"};
int c_rt_lights, c_rt_clears, c_rt_scissored;
int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris;
Cvar_RegisterVariable(&r_shadow_showtris);
Cvar_RegisterVariable(&r_shadow_staticworldlights);
Cvar_RegisterVariable(&r_shadow_cull);
+ Cvar_RegisterVariable(&gl_ext_stenciltwoside);
if (gamemode == GAME_TENEBRAE)
{
Cvar_SetValue("r_shadow_gloss", 2);
if (r_shadow_texture3d.integer && !gl_texture3d)
Cvar_SetValueQuick(&r_shadow_texture3d, 0);
+ if (gl_ext_stenciltwoside.integer && !gl_support_stenciltwoside)
+ Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
if (!r_shadow_attenuation2dtexture
|| (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
qglDepthFunc(GL_LESS);
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
qglEnable(GL_STENCIL_TEST);
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- qglStencilFunc(GL_ALWAYS, 128, 0xFF);
- r_shadowstage = SHADOWSTAGE_STENCIL;
+ qglStencilFunc(GL_ALWAYS, 128, ~0);
+ if (gl_ext_stenciltwoside.integer)
+ {
+ r_shadowstage = SHADOWSTAGE_STENCILTWOSIDE;
+ qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+ qglActiveStencilFaceEXT(GL_FRONT); // quake is backwards, this is back faces
+ qglStencilMask(~0);
+ qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+ qglActiveStencilFaceEXT(GL_BACK); // quake is backwards, this is front faces
+ qglStencilMask(~0);
+ qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+ }
+ else
+ {
+ r_shadowstage = SHADOWSTAGE_STENCIL;
+ qglStencilMask(~0);
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ }
GL_Clear(GL_STENCIL_BUFFER_BIT);
c_rt_clears++;
// LordHavoc note: many shadow volumes reside entirely inside the world
qglDepthFunc(GL_EQUAL);
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
qglDisable(GL_STENCIL_TEST);
+ if (gl_support_stenciltwoside)
+ qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+ qglStencilMask(~0);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, 128, 0xFF);
r_shadowstage = SHADOWSTAGE_LIGHT;
qglDepthFunc(GL_EQUAL);
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
qglEnable(GL_STENCIL_TEST);
+ if (gl_support_stenciltwoside)
+ qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+ qglStencilMask(~0);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// only draw light where this geometry was already rendered AND the
// stencil is 128 (values other than this mean shadow)
qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
qglDisable(GL_STENCIL_TEST);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ if (gl_support_stenciltwoside)
+ qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
+ qglStencilMask(~0);
qglStencilFunc(GL_ALWAYS, 128, 0xFF);
r_shadowstage = SHADOWSTAGE_NONE;
}
for (j = 0;j < 3;j++)
for (i = 0;i < 6;i++)
Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
- Con_Printf(" and was unable to find any of them.\n");
+ Con_Print(" and was unable to find any of them.\n");
}
return cubemaptexture;
}
if (radius < 15 || DotProduct(color, color) < 0.03)
{
- Con_Printf("R_Shadow_NewWorldLight: refusing to create a light too small/dim\n");
+ Con_Print("R_Shadow_NewWorldLight: refusing to create a light too small/dim\n");
return;
}
float origin[3], radius, color[3], angles[3], corona;
if (cl.worldmodel == NULL)
{
- Con_Printf("No map loaded.\n");
+ Con_Print("No map loaded.\n");
return;
}
FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
n = 0;
while (*s)
{
+ t = s;
+ /*
+ shadow = true;
+ for (;COM_Parse(t, true) && strcmp(
+ if (COM_Parse(t, true))
+ {
+ if (com_token[0] == '!')
+ {
+ shadow = false;
+ origin[0] = atof(com_token+1);
+ }
+ else
+ origin[0] = atof(com_token);
+ if (Com_Parse(t
+ }
+ */
t = s;
while (*s && *s != '\n')
s++;
return;
if (cl.worldmodel == NULL)
{
- Con_Printf("No map loaded.\n");
+ Con_Print("No map loaded.\n");
return;
}
FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
buf = NULL;
for (light = r_shadow_worldlightchain;light;light = light->next)
{
- sprintf(line, "%s%f %f %f %f %f %f %f %d %s %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname ? light->cubemapname : "\"\"", light->corona, light->angles[0], light->angles[1], light->angles[2]);
+ sprintf(line, "%s%f %f %f %f %f %f %f %d %s %f %f %f %f\n", light->shadow ? "" : "!", light->origin[0], light->origin[1], light->origin[2], light->radius / r_editlights_rtlightssizescale.value, light->color[0] / r_editlights_rtlightscolorscale.value, light->color[1] / r_editlights_rtlightscolorscale.value, light->color[2] / r_editlights_rtlightscolorscale.value, light->style, light->cubemapname[0] ? light->cubemapname : "\"\"", light->corona, light->angles[0], light->angles[1], light->angles[2]);
if (bufchars + (int) strlen(line) > bufmaxchars)
{
bufmaxchars = bufchars + strlen(line) + 2048;
float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
if (cl.worldmodel == NULL)
{
- Con_Printf("No map loaded.\n");
+ Con_Print("No map loaded.\n");
return;
}
FS_StripExtension (cl.worldmodel->name, name, sizeof (name));
if (cl.worldmodel == NULL)
{
- Con_Printf("No map loaded.\n");
+ Con_Print("No map loaded.\n");
return;
}
data = cl.worldmodel->brush.entities;
vec3_t color;
if (!r_editlights.integer)
{
- Con_Printf("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
+ Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
return;
}
if (Cmd_Argc() != 1)
{
- Con_Printf("r_editlights_spawn does not take parameters\n");
+ Con_Print("r_editlights_spawn does not take parameters\n");
return;
}
color[0] = color[1] = color[2] = 1;
char cubemapname[1024];
if (!r_editlights.integer)
{
- Con_Printf("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
+ Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
return;
}
if (!r_shadow_selectedlight)
{
- Con_Printf("No selected light.\n");
+ Con_Print("No selected light.\n");
return;
}
VectorCopy(r_shadow_selectedlight->origin, origin);
}
else
{
- Con_Printf("usage: r_editlights_edit [property] [value]\n");
- Con_Printf("Selected light's properties:\n");
+ Con_Print("usage: r_editlights_edit [property] [value]\n");
+ Con_Print("Selected light's properties:\n");
Con_Printf("Origin : %f %f %f\n", r_shadow_selectedlight->origin[0], r_shadow_selectedlight->origin[1], r_shadow_selectedlight->origin[2]);
Con_Printf("Angles : %f %f %f\n", r_shadow_selectedlight->angles[0], r_shadow_selectedlight->angles[1], r_shadow_selectedlight->angles[2]);
Con_Printf("Color : %f %f %f\n", r_shadow_selectedlight->color[0], r_shadow_selectedlight->color[1], r_shadow_selectedlight->color[2]);
{
if (!r_editlights.integer)
{
- Con_Printf("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
+ Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
return;
}
if (!r_shadow_selectedlight)
{
- Con_Printf("No selected light.\n");
+ Con_Print("No selected light.\n");
return;
}
R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, r_shadow_selectedlight->corona, r_shadow_selectedlight->style, !r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname);
{
if (!r_editlights.integer)
{
- Con_Printf("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
+ Con_Print("Cannot spawn light when not in editing mode. Set r_editlights to 1.\n");
return;
}
if (!r_shadow_selectedlight)
{
- Con_Printf("No selected light.\n");
+ Con_Print("No selected light.\n");
return;
}
R_Shadow_NewWorldLight(r_shadow_selectedlight->origin, r_shadow_selectedlight->angles, r_shadow_selectedlight->color, r_shadow_selectedlight->radius, !r_shadow_selectedlight->corona, r_shadow_selectedlight->style, r_shadow_selectedlight->shadow, r_shadow_selectedlight->cubemapname);
{
if (!r_editlights.integer)
{
- Con_Printf("Cannot remove light when not in editing mode. Set r_editlights to 1.\n");
+ Con_Print("Cannot remove light when not in editing mode. Set r_editlights to 1.\n");
return;
}
if (!r_shadow_selectedlight)
{
- Con_Printf("No selected light.\n");
+ Con_Print("No selected light.\n");
return;
}
R_Shadow_FreeWorldLight(r_shadow_selectedlight);
void R_Shadow_EditLights_Help_f(void)
{
- Con_Printf(
+ Con_Print(
"Documentation on r_editlights system:\n"
"Settings:\n"
"r_editlights : enable/disable editing mode\n"