cvar_t r_shadow_glsl = {0, "r_shadow_glsl", "1"};
cvar_t r_shadow_glsl_offsetmapping = {0, "r_shadow_glsl_offsetmapping", "1"};
cvar_t r_shadow_glsl_offsetmapping_scale = {0, "r_shadow_glsl_offsetmapping_scale", "0.04"};
-cvar_t r_shadow_glsl_offsetmapping_bias = {0, "r_shadow_glsl_offsetmapping_bias", "-0.02"};
+cvar_t r_shadow_glsl_offsetmapping_bias = {0, "r_shadow_glsl_offsetmapping_bias", "-0.04"};
cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1"};
cvar_t r_editlights = {0, "r_editlights", "0"};
cvar_t r_editlights_cursordistance = {0, "r_editlights_distance", "1024"};
" //\n"
" // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
" // provide significant illumination, large = slow = pain.\n"
-" float colorscale = clamp(1.0 - dot(CubeVector, CubeVector), 0.0, 1.0);\n"
+" float colorscale = max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
"\n"
"#ifdef USEFOG\n"
" // apply fog\n"
"#endif\n"
"\n"
"#ifdef USEOFFSETMAPPING\n"
-" vec2 OffsetVector = normalize(EyeVector).xy * vec2(-1, 1);\n"
-" TexCoord += OffsetVector * (texture2D(Texture_Normal, TexCoord).w * OffsetMapping_Scale + OffsetMapping_Bias);\n"
-" TexCoord += OffsetVector * (texture2D(Texture_Normal, TexCoord).w * OffsetMapping_Scale + OffsetMapping_Bias);\n"
-" TexCoord += OffsetVector * (texture2D(Texture_Normal, TexCoord).w * OffsetMapping_Scale + OffsetMapping_Bias);\n"
-" TexCoord += OffsetVector * (texture2D(Texture_Normal, TexCoord).w * OffsetMapping_Scale + OffsetMapping_Bias);\n"
-"#endif\n"
-"\n"
-"#ifdef USECUBEFILTER\n"
-" // apply light cubemap filter\n"
-" LightColor *= vec3(textureCube(Texture_Cube, CubeVector));\n"
+" // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
+" vec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
+" vec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
+" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
+" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
+"#define TexCoord TexCoordOffset\n"
"#endif\n"
"\n"
" // get the texels - with a blendmap we'd need to blend multiple here\n"
-" vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) * 2.0 - 1.0;\n"
+" vec3 surfacenormal = -1.0 + 2.0 * vec3(texture2D(Texture_Normal, TexCoord));\n"
" vec3 colortexel = vec3(texture2D(Texture_Color, TexCoord));\n"
"#ifdef USESPECULAR\n"
" vec3 glosstexel = vec3(texture2D(Texture_Gloss, TexCoord));\n"
"\n"
" // calculate shading\n"
" vec3 diffusenormal = normalize(LightVector);\n"
-" vec3 color = colortexel * (AmbientScale + DiffuseScale * clamp(dot(surfacenormal, diffusenormal), 0.0, 1.0));\n"
+" vec3 color = colortexel * (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
"#ifdef USESPECULAR\n"
-" color += glosstexel * (SpecularScale * pow(clamp(dot(surfacenormal, normalize(diffusenormal + normalize(EyeVector))), 0.0, 1.0), SpecularPower));\n"
+" color += glosstexel * (SpecularScale * pow(max(dot(surfacenormal, normalize(diffusenormal + normalize(EyeVector))), 0.0), SpecularPower));\n"
+"#endif\n"
+"\n"
+"#ifdef USECUBEFILTER\n"
+" // apply light cubemap filter\n"
+" color *= vec3(textureCube(Texture_Cube, CubeVector));\n"
"#endif\n"
"\n"
" // calculate fragment color\n"
vertstrings_list[vertstrings_count++] = vertstring ? vertstring : builtinshader_light_vert;
fragstrings_list[fragstrings_count++] = fragstring ? fragstring : builtinshader_light_frag;
r_shadow_program_light[i] = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
+ if (!r_shadow_program_light[i])
+ {
+ Con_Printf("permutation %s %s %s %s failed for shader %s, some features may not work properly!\n", i & 1 ? "specular" : "", i & 2 ? "fog" : "", i & 4 ? "cubefilter" : "", i & 8 ? "offsetmapping" : "", "glsl/light");
+ continue;
+ }
qglUseProgramObjectARB(r_shadow_program_light[i]);
qglUniform1iARB(qglGetUniformLocationARB(r_shadow_program_light[i], "Texture_Normal"), 0);CHECKGLERROR
qglUniform1iARB(qglGetUniformLocationARB(r_shadow_program_light[i], "Texture_Color"), 1);CHECKGLERROR
qglUniform1iARB(qglGetUniformLocationARB(r_shadow_program_light[i], "Texture_FogMask"), 4);CHECKGLERROR
}
}
+ qglUseProgramObjectARB(0);
if (fragstring)
Mem_Free(fragstring);
if (vertstring)
#define ATTEN2DSIZE 64
#define ATTEN3DSIZE 32
data = Mem_Alloc(tempmempool, max(6*NORMSIZE*NORMSIZE*4, max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE*4, ATTEN2DSIZE*ATTEN2DSIZE*4)));
- data[0] = 128;
- data[1] = 128;
- data[2] = 255;
- data[3] = 255;
+ data[0] = 128; // normal X
+ data[1] = 128; // normal Y
+ data[2] = 255; // normal Z
+ data[3] = 128; // height
r_shadow_blankbumptexture = R_LoadTexture2D(r_shadow_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
data[0] = 255;
data[1] = 255;
GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 0);
CHECKGLERROR
perm = 0;
- if (specularscale)
+ // only add a feature to the permutation if that permutation exists
+ // (otherwise it might end up not using a shader at all, which looks
+ // worse than using less features)
+ if (specularscale && r_shadow_program_light[perm | SHADERPERMUTATION_SPECULAR])
perm |= SHADERPERMUTATION_SPECULAR;
- //if (fog)
+ //if (fog && r_shadow_program_light[perm | SHADERPERMUTATION_FOG])
// perm |= SHADERPERMUTATION_FOG;
- if (lightcubemap)
+ if (lightcubemap && r_shadow_program_light[perm | SHADERPERMUTATION_CUBEFILTER])
perm |= SHADERPERMUTATION_CUBEFILTER;
- if (r_shadow_glsl_offsetmapping.integer)
+ if (r_shadow_glsl_offsetmapping.integer && r_shadow_program_light[perm | SHADERPERMUTATION_OFFSETMAPPING])
perm |= SHADERPERMUTATION_OFFSETMAPPING;
prog = r_shadow_program_light[perm];
- qglUseProgramObjectARB(r_shadow_program_light[perm]);
+ qglUseProgramObjectARB(prog);CHECKGLERROR
// TODO: support fog (after renderer is converted to texture fog)
if (perm & SHADERPERMUTATION_FOG)
- qglUniform1fARB(qglGetUniformLocationARB(prog, "FogRangeRecip"), 0);
- qglUniform1fARB(qglGetUniformLocationARB(prog, "AmbientScale"), ambientscale);
- qglUniform1fARB(qglGetUniformLocationARB(prog, "DiffuseScale"), diffusescale);
+ {
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "FogRangeRecip"), 0);CHECKGLERROR
+ }
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "AmbientScale"), ambientscale);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "DiffuseScale"), diffusescale);CHECKGLERROR
if (perm & SHADERPERMUTATION_SPECULAR)
{
- qglUniform1fARB(qglGetUniformLocationARB(prog, "SpecularPower"), 8);
- qglUniform1fARB(qglGetUniformLocationARB(prog, "SpecularScale"), specularscale);
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "SpecularPower"), 8);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "SpecularScale"), specularscale);CHECKGLERROR
}
- qglUniform3fARB(qglGetUniformLocationARB(prog, "LightColor"), lightcolor[0], lightcolor[1], lightcolor[2]);
- qglUniform3fARB(qglGetUniformLocationARB(prog, "LightPosition"), relativelightorigin[0], relativelightorigin[1], relativelightorigin[2]);
+ qglUniform3fARB(qglGetUniformLocationARB(prog, "LightColor"), lightcolor[0], lightcolor[1], lightcolor[2]);CHECKGLERROR
+ qglUniform3fARB(qglGetUniformLocationARB(prog, "LightPosition"), relativelightorigin[0], relativelightorigin[1], relativelightorigin[2]);CHECKGLERROR
if (perm & (SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_FOG | SHADERPERMUTATION_OFFSETMAPPING))
- qglUniform3fARB(qglGetUniformLocationARB(prog, "EyePosition"), relativeeyeorigin[0], relativeeyeorigin[1], relativeeyeorigin[2]);
+ {
+ qglUniform3fARB(qglGetUniformLocationARB(prog, "EyePosition"), relativeeyeorigin[0], relativeeyeorigin[1], relativeeyeorigin[2]);CHECKGLERROR
+ }
if (perm & SHADERPERMUTATION_OFFSETMAPPING)
{
- // these are * 0.25 because the offsetmapping shader does the process 4 times
- qglUniform1fARB(qglGetUniformLocationARB(prog, "OffsetMapping_Scale"), r_shadow_glsl_offsetmapping_scale.value * 0.25);
- qglUniform1fARB(qglGetUniformLocationARB(prog, "OffsetMapping_Bias"), r_shadow_glsl_offsetmapping_bias.value * 0.25);
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "OffsetMapping_Scale"), r_shadow_glsl_offsetmapping_scale.value);CHECKGLERROR
+ qglUniform1fARB(qglGetUniformLocationARB(prog, "OffsetMapping_Bias"), r_shadow_glsl_offsetmapping_bias.value);CHECKGLERROR
}
CHECKGLERROR
GL_LockArrays(0, numverts);
c_rt_lighttris += numtriangles;
GL_LockArrays(0, 0);
qglUseProgramObjectARB(0);
+ // HACK HACK HACK: work around for stupid NVIDIA bug that causes GL_OUT_OF_MEMORY and/or software rendering
+ qglBegin(GL_TRIANGLES);
+ qglEnd();
+ CHECKGLERROR
}
else if (gl_dot3arb && gl_texturecubemap && gl_combine.integer && gl_stencil)
{
for (i = 0;i < 6;i++)
{
// generate an image name based on the base and and suffix
- snprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
+ dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
// load it
if ((image_rgba = loadimagepixels(name, false, cubemapsize, cubemapsize)))
{
light->corona = corona;
if (!cubemapname)
cubemapname = "";
- strlcpy(light->cubemapname, cubemapname, strlen(light->cubemapname));
+ strlcpy(light->cubemapname, cubemapname, sizeof(light->cubemapname));
light->coronasizescale = coronasizescale;
light->ambientscale = ambientscale;
light->diffusescale = diffusescale;
void R_Shadow_LoadWorldLights(void)
{
int n, a, style, shadow, flags;
- char name[MAX_QPATH], cubemapname[MAX_QPATH], *lightsstring, *s, *t;
+ char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
if (r_refdef.worldmodel == NULL)
{
}
*/
t = s;
- while (*s && *s != '\n')
+ while (*s && *s != '\n' && *s != '\r')
s++;
if (!*s)
break;
- *s = 0;
+ tempchar = *s;
shadow = true;
// check for modifier flags
if (*t == '!')
shadow = false;
t++;
}
+ *s = 0;
a = sscanf(t, "%f %f %f %f %f %f %f %d %s %f %f %f %f %f %f %f %f %i", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname, &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
+ *s = tempchar;
if (a < 18)
flags = LIGHTFLAG_REALTIMEMODE;
if (a < 17)
cubemapname[strlen(cubemapname)-1] = 0;
strcpy(cubemapname, cubemapname + 1);
}
- *s = '\n';
if (a < 8)
{
Con_Printf("found %d parameters on line %i, should be 8 or more parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style \"cubemapname\" corona angles[0] angles[1] angles[2] coronasizescale ambientscale diffusescale specularscale flags)\n", a, n + 1);
VectorScale(color, r_editlights_rtlightscolorscale.value, color);
radius *= r_editlights_rtlightssizescale.value;
R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
- s++;
+ if (*s == '\r')
+ s++;
+ if (*s == '\n')
+ s++;
n++;
}
if (*s)
void R_Shadow_LoadLightsFile(void)
{
int n, a, style;
- char name[MAX_QPATH], *lightsstring, *s, *t;
+ char tempchar, *lightsstring, *s, *t, name[MAX_QPATH];
float origin[3], radius, color[3], subtract, spotdir[3], spotcone, falloff, distbias;
if (r_refdef.worldmodel == NULL)
{
while (*s)
{
t = s;
- while (*s && *s != '\n')
+ while (*s && *s != '\n' && *s != '\r')
s++;
if (!*s)
break;
+ tempchar = *s;
*s = 0;
a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &origin[0], &origin[1], &origin[2], &falloff, &color[0], &color[1], &color[2], &subtract, &spotdir[0], &spotdir[1], &spotdir[2], &spotcone, &distbias, &style);
- *s = '\n';
+ *s = tempchar;
if (a < 14)
{
Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
radius = bound(15, radius, 4096);
VectorScale(color, (2.0f / (8388608.0f)), color);
R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, vec3_origin, color, radius, 0, style, true, NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
- s++;
+ if (*s == '\r')
+ s++;
+ if (*s == '\n')
+ s++;
n++;
}
if (*s)