X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=8a82f06411c73ad8e78c3f84dfbf5f9a9c68680b;hb=2b9253f2a56c8e33c7ac33c794c1f03acc91048c;hp=6460c4016baffad604dbba0ffc8b944d8073c8f4;hpb=ae785d6dc771b68ca55286b1dc4eecc508136183;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index 6460c401..8a82f064 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -194,7 +194,7 @@ cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"}; 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"}; @@ -346,7 +346,7 @@ const char *builtinshader_light_frag = " //\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" @@ -354,20 +354,16 @@ const char *builtinshader_light_frag = "#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" @@ -375,9 +371,14 @@ const char *builtinshader_light_frag = "\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" @@ -457,6 +458,11 @@ void r_shadow_start(void) 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 @@ -941,10 +947,10 @@ static void R_Shadow_MakeTextures(void) #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; @@ -1622,35 +1628,41 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements 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); @@ -1659,6 +1671,10 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements 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) { @@ -2711,7 +2727,7 @@ void R_DrawRTLight(rtlight_t *rtlight, int visiblevolumes) if (numclusters) { for (i = 0;i < numclusters;i++) - if (CHECKPVSBIT(r_pvsbits, clusterlist[i])) + if (r_worldleafvisible[clusterlist[i]]) break; if (i == numclusters) return; @@ -2935,7 +2951,7 @@ rtexture_t *R_Shadow_LoadCubemap(const char *basename) 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))) { @@ -3028,7 +3044,7 @@ void R_Shadow_UpdateWorldLight(dlight_t *light, vec3_t origin, vec3_t angles, ve 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; @@ -3130,7 +3146,7 @@ void R_Shadow_SelectLightInView(void) 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) { @@ -3163,11 +3179,11 @@ void R_Shadow_LoadWorldLights(void) } */ 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 == '!') @@ -3175,7 +3191,9 @@ void R_Shadow_LoadWorldLights(void) 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) @@ -3198,7 +3216,6 @@ void R_Shadow_LoadWorldLights(void) 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); @@ -3207,7 +3224,10 @@ void R_Shadow_LoadWorldLights(void) 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) @@ -3269,7 +3289,7 @@ void R_Shadow_SaveWorldLights(void) 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) { @@ -3286,13 +3306,14 @@ void R_Shadow_LoadLightsFile(void) 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); @@ -3302,7 +3323,10 @@ void R_Shadow_LoadLightsFile(void) 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)