Added gl_light_math and changed pixelpos + lights to be in eye space

This commit is contained in:
Magnus Norddahl 2016-08-25 06:25:05 +02:00
parent f79c442df5
commit 9525d3690f
10 changed files with 140 additions and 12 deletions

View file

@ -80,6 +80,11 @@ CUSTOM_CVAR (Bool, gl_lights_additive, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG
gl_RecreateAllAttachedLights();
}
CUSTOM_CVAR(Int, gl_light_math, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 2) self = 0;
}
//==========================================================================
//
// Sets up the parameters to render one dynamic light onto one plane
@ -128,10 +133,28 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bo
i = 1;
}
float worldPos[4] = { (float)pos.X, (float)pos.Z, (float)pos.Y, 1.0f };
float eyePos[4];
gl_RenderState.mViewMatrix.multMatrixPoint(worldPos, eyePos);
if (gl_light_math != 0)
{
// Adjust light slightly to make the range better match plain attenuation
radius *= 1.5;
// Move light up because flasks/vials have their light source location at/below the floor.
//
// If the point is exactly on the wall plane it might cause some acne as some pixels could
// be in front and some behind. Move light just a tiny bit to avoid this.
eyePos[0] += 0.01f;
eyePos[1] += 5.01f;
eyePos[2] += 0.01f;
}
float *data = &ldata.arrays[i][ldata.arrays[i].Reserve(8)];
data[0] = pos.X;
data[1] = pos.Z;
data[2] = pos.Y;
data[0] = eyePos[0];
data[1] = eyePos[1];
data[2] = eyePos[2];
data[3] = radius;
data[4] = r;
data[5] = g;

View file

@ -144,6 +144,7 @@ bool FRenderState::ApplyShader()
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
activeShader->muLightMath.Set(gl_light_math);
activeShader->muClipSplit.Set(mClipSplit);
if (mGlowEnabled)

View file

@ -246,6 +246,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
muColormapStart.Init(hShader, "uFixedColormapStart");
muColormapRange.Init(hShader, "uFixedColormapRange");
muLightIndex.Init(hShader, "uLightIndex");
muLightMath.Init(hShader, "uLightMath");
muFogColor.Init(hShader, "uFogColor");
muDynLightColor.Init(hShader, "uDynLightColor");
muObjectColor.Init(hShader, "uObjectColor");

View file

@ -221,6 +221,7 @@ class FShader
FUniform1i muFixedColormap;
FUniform4f muColormapStart;
FUniform4f muColormapRange;
FBufferedUniform1i muLightMath;
FBufferedUniform1i muLightIndex;
FBufferedUniformPE muFogColor;
FBufferedUniform4f muDynLightColor;

View file

@ -29,6 +29,7 @@ EXTERN_CVAR (Float, gl_lights_size);
EXTERN_CVAR (Bool, gl_lights_additive);
EXTERN_CVAR (Bool, gl_light_sprites);
EXTERN_CVAR (Bool, gl_light_particles);
EXTERN_CVAR (Int, gl_light_math);
EXTERN_CVAR(Int, gl_fogmode)
EXTERN_CVAR(Int, gl_lightmode)

View file

@ -2603,6 +2603,7 @@ GLLIGHTMNU_LIGHTPARTICLES = "Lights affect particles";
GLLIGHTMNU_FORCEADDITIVE = "Force additive lighting";
GLLIGHTMNU_LIGHTINTENSITY = "Light intensity";
GLLIGHTMNU_LIGHTSIZE = "Light size";
GLLIGHTMNU_LIGHTMATH = "Light quality";
// OpenGL Preferences
GLPREFMNU_TITLE = "OPENGL PREFERENCES";
@ -2701,3 +2702,6 @@ OPTVAL_UNCHARTED2 = "Uncharted 2";
OPTVAL_HEJLDAWSON = "Hejl Dawson";
OPTVAL_REINHARD = "Reinhard";
OPTVAL_PALETTE = "Palette";
OPTVAL_LOW = "Low";
OPTVAL_MEDIUM = "Medium";
OPTVAL_HIGH = "High";

View file

@ -25,6 +25,13 @@ OptionValue "FilterModes"
4, "$OPTVAL_TRILINEAR"
}
OptionValue "LightMathModes"
{
0, "$OPTVAL_LOW"
1, "$OPTVAL_MEDIUM"
2, "$OPTVAL_HIGH"
}
OptionValue "HWGammaModes"
{
0, "$OPTVAL_ON"
@ -193,6 +200,7 @@ OptionMenu "GLLightOptions"
Option "$GLLIGHTMNU_LIGHTSPRITES", gl_light_sprites, "YesNo"
Option "$GLLIGHTMNU_LIGHTPARTICLES", gl_light_particles, "YesNo"
Option "$GLLIGHTMNU_FORCEADDITIVE", gl_lights_additive, "YesNo"
Option "$GLLIGHTMNU_LIGHTMATH", gl_light_math, "LightMathModes"
Slider "$GLLIGHTMNU_LIGHTINTENSITY", gl_lights_intensity, 0.0, 1.0, 0.1
Slider "$GLLIGHTMNU_LIGHTSIZE", gl_lights_size, 0.0, 2.0, 0.1
}

View file

@ -25,6 +25,88 @@ vec4 Process(vec4 color);
vec4 ProcessTexel();
vec4 ProcessLight(vec4 color);
// Smoothed normal used for the face, in eye space. Should be converted to an 'in' variable in the future.
vec3 pixelnormal;
//===========================================================================
//
// Calculates the face normal vector for the fragment, in eye space
//
//===========================================================================
vec3 calculateFaceNormal()
{
#if __VERSION__ < 450
vec3 dFdxPos = dFdx(pixelpos.xyz);
vec3 dFdyPos = dFdy(pixelpos.xyz);
#else
vec3 dFdxPos = dFdxCoarse(pixelpos.xyz);
vec3 dFdyPos = dFdyCoarse(pixelpos.xyz);
#endif
return normalize(cross(dFdxPos,dFdyPos));
}
//===========================================================================
//
// Standard lambertian diffuse light calculation
//
//===========================================================================
float diffuseContribution(vec3 eyeLightDirection, vec3 eyeNormal)
{
return max(dot(eyeNormal, eyeLightDirection), 0.0f);
}
//===========================================================================
//
// Blinn specular light calculation
//
//===========================================================================
float blinnSpecularContribution(float diffuseContribution, vec3 eyeLightDirection, vec3 eyePosition, vec3 eyeNormal, float glossiness, float specularLevel)
{
if (diffuseContribution > 0.0f)
{
vec3 viewDir = normalize(-eyePosition);
vec3 halfDir = normalize(eyeLightDirection + viewDir);
float specAngle = max(dot(halfDir, eyeNormal), 0.0f);
float phExp = glossiness * 4.0f;
return specularLevel * pow(specAngle, phExp);
}
else
{
return 0.0f;
}
}
//===========================================================================
//
// Calculates the brightness of a dynamic point light
//
//===========================================================================
float pointLightAttenuation(vec4 lightpos)
{
float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
if (uLightMath == 0)
{
return attenuation;
}
else
{
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
float diffuseAmount = diffuseContribution(lightDirection, pixelnormal);
if (uLightMath == 1)
{
return attenuation * diffuseAmount;
}
else
{
float specularAmount = blinnSpecularContribution(diffuseAmount, lightDirection, pixelpos.xyz, pixelnormal, 3.0, 1.2);
return attenuation * (diffuseAmount + specularAmount);
}
}
}
//===========================================================================
//
@ -223,7 +305,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
dynlight.rgb += lightcolor.rgb;
}
//
@ -234,7 +316,7 @@ vec4 getLightColor(float fogdist, float fogfactor)
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
dynlight.rgb -= lightcolor.rgb;
}
}
@ -268,6 +350,13 @@ void main()
{
vec4 frag = ProcessTexel();
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
if (uLightMath != 0) // Remove this if pixelnormal is converted to an 'in' variable
{
pixelnormal = calculateFaceNormal();
}
#endif
#ifndef NO_ALPHATEST
if (frag.a <= uAlphaThreshold) discard;
#endif
@ -292,12 +381,11 @@ void main()
}
else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
fogdist = max(16.0, length(pixelpos.xyz));
}
fogfactor = exp2 (uFogDensity * fogdist);
}
frag *= getLightColor(fogdist, fogfactor);
#if defined NUM_UBO_LIGHTS || defined SHADER_STORAGE_LIGHTS
@ -316,7 +404,7 @@ void main()
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
lightcolor.rgb *= max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w;
lightcolor.rgb *= pointLightAttenuation(lightpos);
addlight.rgb += lightcolor.rgb;
}
frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);
@ -363,7 +451,7 @@ void main()
}
else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
fogdist = max(16.0, length(pixelpos.xyz));
}
fogfactor = exp2 (uFogDensity * fogdist);

View file

@ -43,7 +43,7 @@ void main()
vColor = aColor;
#ifndef SIMPLE
pixelpos.xyz = worldcoord.xyz;
pixelpos.xyz = eyeCoordPos.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
glowdist.x = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z) - worldcoord.y;

View file

@ -44,6 +44,7 @@ uniform int uFogEnabled;
// dynamic lights
uniform int uLightIndex;
uniform int uLightMath; // 0, when using only attenuation, 1 for diffuse light, 2 for blinn specular light
// quad drawer stuff
#ifdef USE_QUAD_DRAWER