in vec4 pixelpos; in vec2 glowdist; #ifdef SHADER_STORAGE_LIGHTS layout(std430, binding = 3) buffer ParameterBuffer { vec4 lights[]; }; #elif defined MAXLIGHTS128 uniform vec4 lights[256]; #else uniform vec4 lights[128]; #endif uniform sampler2D tex; vec4 Process(vec4 color); vec4 ProcessTexel(); vec4 ProcessLight(vec4 color); //=========================================================================== // // Desaturate a color // //=========================================================================== vec4 desaturate(vec4 texel) { if (uDesaturationFactor > 0.0) { float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); return mix (texel, vec4(gray,gray,gray,texel.a), uDesaturationFactor); } else { return texel; } } //=========================================================================== // // This function is common for all (non-special-effect) fragment shaders // //=========================================================================== vec4 getTexel(vec2 st) { vec4 texel = texture2D(tex, st); // // Apply texture modes // switch (uTextureMode) { case 1: texel.rgb = vec3(1.0,1.0,1.0); break; case 2: texel.a = 1.0; break; case 3: texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a); break; } texel *= uObjectColor; return desaturate(texel); } //=========================================================================== // // Doom lighting equation ripped from EDGE. // Big thanks to EDGE developers for making the only port // that actually replicates software renderer's lighting in OpenGL. // Float version. // Basically replace int with float and divide all constants by 31. // //=========================================================================== float R_DoomLightingEquation(float light, float dist) { // Changing this constant gives results very similar to changing r_visibility. // Default is 232, it seems to give exactly the same light bands as software renderer. #define DOOMLIGHTFACTOR 232.0 /* L in the range 0 to 63 */ float L = light * 63.0/31.0; float min_L = clamp(36.0/31.0 - L, 0.0, 1.0); // Fix objects getting totally black when close. if (dist < 0.0001) dist = 0.0001; float scale = 1.0 / dist; float index = (59.0/31.0 - L) - (scale * DOOMLIGHTFACTOR/31.0 - DOOMLIGHTFACTOR/31.0); /* result is colormap index (0 bright .. 31 dark) */ return clamp(index, min_L, 1.0); } //=========================================================================== // // Calculate light // // It is important to note that the light color is not desaturated // due to ZDoom's implementation weirdness. Everything that's added // on top of it, e.g. dynamic lights and glows are, though, because // the objects emitting these lights are also. // // This is making this a bit more complicated than it needs to // because we can't just desaturate the final fragment color. // //=========================================================================== vec4 getLightColor(float fogdist, float fogfactor) { vec4 color = gl_Color; if (uLightLevel >= 0.0) { float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel, gl_FragCoord.z); color.rgb *= newlightlevel; } else if (uFogEnabled > 0.0) { // brightening around the player for light mode 2 if (fogdist < uLightDist) { color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0); } // // apply light diminishing through fog equation // color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor); } // // handle glowing walls // if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a) { color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb; } if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a) { color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb; } color = min(color, 1.0); // // apply brightmaps (or other light manipulation by custom shaders. // color = ProcessLight(color); // // apply dynamic lights (except additive) // vec4 dynlight = uDynLightColor; if (uLightRange.z > uLightRange.x) { // // modulated lights // for(int i=uLightRange.x; i uClipHeightTop) discard; if (pixelpos.y < uClipHeightBottom) discard; #endif vec4 frag = ProcessTexel(); #ifndef NO_DISCARD // alpha testing if (frag.a <= uAlphaThreshold) discard; #endif switch (uFixedColormap) { case 0: { float fogdist = 0.0; float fogfactor = 0.0; // // calculate fog factor // if (uFogEnabled != 0) { if (uFogEnabled == 1 || uFogEnabled == -1) { fogdist = pixelpos.w; } else { fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); } fogfactor = exp2 (uFogDensity * fogdist); } frag *= getLightColor(fogdist, fogfactor); if (uLightRange.w > uLightRange.z) { vec4 addlight = vec4(0.0,0.0,0.0,0.0); // // additive lights - these can be done after the alpha test. // for(int i=uLightRange.z; i