diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index fd8cd6dc4..c857933dd 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -790,7 +790,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light MaterialParameters *matParams = matInstance->getMaterialParameters(); matParams->setSafe( lightColor, lightInfo->getColor() ); - matParams->setSafe(lightBrightness, lightInfo->getBrightness() * lightInfo->getFadeAmount()); + F32 luxTargMultiplier = 1; switch( lightInfo->getType() ) { @@ -804,10 +804,10 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light case LightInfo::Spot: { const F32 outerCone = lightInfo->getOuterConeAngle(); - const F32 innerCone = getMin(lightInfo->getInnerConeAngle(), outerCone); + const F32 innerCone = getMin(lightInfo->getInnerConeAngle(), outerCone-0.0001f); const F32 outerCos = mCos(mDegToRad(outerCone / 2.0f)); const F32 innerCos = mCos(mDegToRad(innerCone / 2.0f)); - Point2F spotParams(outerCos,innerCos - outerCos); + Point2F spotParams(outerCos,mMax(innerCos - outerCos,0.001f)); matParams->setSafe( lightSpotParams, spotParams ); matParams->setSafe( lightDirection, lightInfo->getDirection()); @@ -817,6 +817,9 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light const F32 invSqrRadius = 1.0f / mSquared(radius); matParams->setSafe(lightRange, radius); matParams->setSafe(lightInvSqrRange, invSqrRadius); + + F32 concentration = 360.0f/ outerCone; + luxTargMultiplier = radius * concentration; } break; @@ -828,6 +831,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light const F32 invSqrRadius = 1.0f / (radius * radius); matParams->setSafe( lightRange, radius); matParams->setSafe( lightInvSqrRange, invSqrRadius); + luxTargMultiplier =radius; } break; @@ -835,6 +839,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light AssertFatal( false, "Bad light type!" ); break; } + matParams->setSafe(lightBrightness, lightInfo->getBrightness()* lightInfo->getFadeAmount() * luxTargMultiplier); } bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgData ) diff --git a/Engine/source/lighting/lightManager.cpp b/Engine/source/lighting/lightManager.cpp index d0652a62f..ac331ba4d 100644 --- a/Engine/source/lighting/lightManager.cpp +++ b/Engine/source/lighting/lightManager.cpp @@ -333,7 +333,7 @@ void LightManager::_update4LightConsts( const SceneData &sgData, static AlignedArray lightSpotDirs(MAX_FORWARD_LIGHTS, sizeof(Point4F)); static AlignedArray lightColors(MAX_FORWARD_LIGHTS, sizeof(Point4F)); static AlignedArray lightConfigData(MAX_FORWARD_LIGHTS, sizeof(Point4F)); //type, brightness, range, invSqrRange : rgba - static AlignedArray lightSpotParams(MAX_FORWARD_LIGHTS, sizeof(Point2F)); + static AlignedArray lightSpotParams(MAX_FORWARD_LIGHTS, sizeof(Point4F)); dMemset(lightPositions.getBuffer(), 0, lightPositions.getBufferSize()); dMemset(lightSpotDirs.getBuffer(), 0, lightSpotDirs.getBufferSize()); @@ -352,11 +352,12 @@ void LightManager::_update4LightConsts( const SceneData &sgData, vectorLightDirection = Point4F::Zero; vectorLightColor = Point4F::Zero; vectorLightAmbientColor = Point4F::Zero; - + F32 luxTargMultiplier[MAX_FORWARD_LIGHTS]; // Gather the data for the first 4 lights. const LightInfo* light; for (U32 i = 0; i < MAX_FORWARD_LIGHTS; i++) { + luxTargMultiplier[i] = 1.0; light = sgData.lights[i]; if (!light) break; @@ -371,48 +372,52 @@ void LightManager::_update4LightConsts( const SceneData &sgData, vectorLightColor = Point4F(light->getColor()); vectorLightAmbientColor = Point4F(light->getAmbient()); hasVectorLight = 1; - continue; } - - // The light positions and spot directions are - // in SoA order to make optimal use of the GPU. - const Point3F& lightPos = light->getPosition(); - lightPositions[i].x = lightPos.x; - lightPositions[i].y = lightPos.y; - lightPositions[i].z = lightPos.z; - lightPositions[i].w = 0; - - const VectorF& lightDir = light->getDirection(); - lightSpotDirs[i].x = lightDir.x; - lightSpotDirs[i].y = lightDir.y; - lightSpotDirs[i].z = lightDir.z; - lightSpotDirs[i].w = 0; - - lightColors[i] = Point4F(light->getColor()); - - if (light->getType() == LightInfo::Point) + else { - lightConfigData[i].x = 0; + // The light positions and spot directions are + // in SoA order to make optimal use of the GPU. + const Point3F& lightPos = light->getPosition(); + lightPositions[i].x = lightPos.x; + lightPositions[i].y = lightPos.y; + lightPositions[i].z = lightPos.z; + lightPositions[i].w = 0; + + lightColors[i] = Point4F(light->getColor()); + + F32 range = light->getRange().x; + lightConfigData[i].z = range; + + if (light->getType() == LightInfo::Point) + { + lightConfigData[i].x = 0; + luxTargMultiplier[i] = range; + } + else if (light->getType() == LightInfo::Spot) + { + const VectorF& lightDir = light->getDirection(); + lightSpotDirs[i].x = lightDir.x; + lightSpotDirs[i].y = lightDir.y; + lightSpotDirs[i].z = lightDir.z; + lightSpotDirs[i].w = 0; + + lightConfigData[i].x = 1; + + const F32 outerCone = light->getOuterConeAngle(); + const F32 innerCone = getMin(light->getInnerConeAngle(), outerCone - 0.0001f); + const F32 outerCos = mCos(mDegToRad(outerCone / 2.0f)); + const F32 innerCos = mCos(mDegToRad(innerCone / 2.0f)); + Point2F spotParams(outerCos, mMax(innerCos - outerCos, 0.001f)); + + lightSpotParams[i].x = spotParams.x; + lightSpotParams[i].y = spotParams.y; + F32 concentration = 360.0f / outerCone; + luxTargMultiplier[i] = range * concentration; + } + + lightConfigData[i].y = light->getBrightness() * luxTargMultiplier[i]; + lightConfigData[i].w = 1.0f / (range * range); } - else if (light->getType() == LightInfo::Spot) - { - lightConfigData[i].x = 1; - - const F32 outerCone = light->getOuterConeAngle(); - const F32 innerCone = getMin(light->getInnerConeAngle(), outerCone); - const F32 outerCos = mCos(mDegToRad(outerCone / 2.0f)); - const F32 innerCos = mCos(mDegToRad(innerCone / 2.0f)); - Point2F spotParams(outerCos, innerCos - outerCos); - - lightSpotParams[i].x = spotParams.x; - lightSpotParams[i].y = spotParams.y; - } - - lightConfigData[i].y = light->getBrightness(); - - F32 range = light->getRange().x; - lightConfigData[i].z = range; - lightConfigData[i].w = 1.0f / (range * range); } shaderConsts->setSafe(lightPositionSC, lightPositions); diff --git a/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp b/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp index cd4724838..4f246bec8 100644 --- a/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/singleLightShadowMap.cpp @@ -71,7 +71,8 @@ void SingleLightShadowMap::_render( RenderPassManager* renderPass, lightMatrix.inverse(); GFX->setWorldMatrix(lightMatrix); - const MatrixF& lightProj = GFX->getProjectionMatrix(); + MatrixF lightProj = GFX->getProjectionMatrix(); + lightProj.reverseProjection(); mWorldToLightProj = lightProj * lightMatrix; // Render the shadowmap! diff --git a/Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl b/Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl index e18d1d0be..e36762e6e 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl @@ -73,4 +73,14 @@ float D_GGX(float NdotH, float alphaRoughnessSq) return alphaRoughnessSq / (M_PI_F * f * f); } +float3 Fr_DisneyDiffuse(float3 F0, float NdotV, float NdotL, float LdotH, float linearRoughness) +{ + float energyBias = lerp (0 , 0.5 , linearRoughness ); + float energyFactor = lerp (1.0 , 1.0 / 1.51 , linearRoughness ); + float fd90 = energyBias + 2.0 * LdotH * LdotH * linearRoughness ; + float3 lightScatter = F_Schlick( F0 , fd90 , NdotL ); + float3 viewScatter = F_Schlick(F0 , fd90 , NdotV ); + + return lightScatter * viewScatter * energyFactor ; +} #endif diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl index dbe4d50ac..9d76de406 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl @@ -67,4 +67,15 @@ float D_GGX(float NdotH, float alphaRoughnessSq) return alphaRoughnessSq / (M_PI_F * f * f); } +vec3 Fr_DisneyDiffuse(vec3 F0, float NdotV, float NdotL, float LdotH, float linearRoughness) +{ + float energyBias = lerp(0 , 0.5 , linearRoughness ); + float energyFactor = lerp(1.0 , 1.0 / 1.51 , linearRoughness ); + float fd90 = energyBias + 2.0 * LdotH * LdotH * linearRoughness ; + vec3 lightScatter = F_Schlick( F0 , fd90 , NdotL ); + vec3 viewScatter = F_Schlick(F0 , fd90 , NdotV ); + + return lightScatter * viewScatter * energyFactor ; +} + #endif diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl index a903c0896..cc66cb500 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl @@ -216,8 +216,8 @@ float getDistanceAtt( vec3 unormalizedLightVector , float invSqrAttRadius ) float getSpotAngleAtt( vec3 normalizedLightVector , vec3 lightDir , vec2 lightSpotParams ) { - float cd = dot ( lightDir , normalizedLightVector ); - float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y ); + float cd = max(dot( lightDir , normalizedLightVector ),0.0); + float attenuation = saturate ( ( cd - lightSpotParams.x/(cd*1.001) ) / lightSpotParams.y ); // smooth the transition return sqr(attenuation); } @@ -225,7 +225,7 @@ float getDistanceAtt( vec3 unormalizedLightVector , float invSqrAttRadius ) vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) { //lambert diffuse - vec3 Fd = surface.albedo.rgb * M_1OVER_PI_F; + vec3 Fd = Fr_DisneyDiffuse(surface.f0, surface.NdotV, surfaceToLight.NdotL, surfaceToLight.NdotH, surface.linearRoughness); //GGX specular vec3 F = F_Schlick(surface.f0, surface.f90, surfaceToLight.HdotV); @@ -236,7 +236,7 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) #if CAPTURING == 1 return saturate(mix(Fd + Fr,surface.f0,surface.metalness)); #else - return saturate(Fd + Fr); + return Fd + Fr; #endif } @@ -254,6 +254,15 @@ vec3 getPunctualLight(Surface surface, SurfaceToLight surfaceToLight, vec3 light return evaluateStandardBRDF(surface,surfaceToLight) * factor; } +vec3 getSpotlight(Surface surface, SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float radius, vec3 lightDir, vec2 lightSpotParams, float shadow) +{ + float attenuation = 1.0f; + attenuation *= getDistanceAtt(surfaceToLight.Lu, radius); + attenuation *= getSpotAngleAtt(-surfaceToLight.L, lightDir, lightSpotParams.xy); + vec3 factor = lightColor * max(surfaceToLight.NdotL* shadow * lightIntensity * attenuation, 0.0f) ; + return evaluateStandardBRDF(surface,surfaceToLight) * factor; +} + float computeSpecOcclusion( float NdotV , float AO , float roughness ) { return saturate (pow( abs(NdotV + AO) , exp2 ( -16.0f * roughness - 1.0f )) - 1.0f + AO ); @@ -270,7 +279,7 @@ vec4 compute4Lights( Surface surface, vec4 inLightConfigData[4], vec4 inLightColor[4], vec4 inLightSpotDir[4], - vec2 lightSpotParams[4], + vec2 inlightSpotParams[4], int hasVectorLight, vec4 vectorLightDirection, vec4 vectorLightingColor, @@ -305,13 +314,10 @@ vec4 compute4Lights( Surface surface, //get punctual light contribution lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); } - else //spot + else if(inLightConfigData[i].x == 1) //spot { - - //get Punctual light contribution - lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); - //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, inLightSpotDir[i].xyz, lightSpotParams[i].xy ); + //get spot light contribution + lighting = getSpotlight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, inLightSpotDir[i].xyz, inlightSpotParams[i], shadowed); } } finalLighting += lighting; diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index 0a0f1b967..9f5659ae1 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -217,16 +217,16 @@ float getDistanceAtt( float3 unormalizedLightVector , float invSqrAttRadius ) float getSpotAngleAtt( float3 normalizedLightVector , float3 lightDir , float2 lightSpotParams ) { - float cd = dot ( lightDir , normalizedLightVector ); - float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y ); + float cd = max(dot ( lightDir , normalizedLightVector ),0.0); + float attenuation = saturate(((cd - lightSpotParams.x/(cd*1.001))/lightSpotParams.y)); // smooth the transition return sqr(attenuation); } float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) { - //lambert diffuse - float3 Fd = surface.albedo.rgb * M_1OVER_PI_F; + //disney diffuse + float3 Fd = Fr_DisneyDiffuse(surface.f0, surface.NdotV, surfaceToLight.NdotL, surfaceToLight.NdotH, surface.linearRoughness); //GGX specular float3 F = F_Schlick(surface.f0, surface.f90, surfaceToLight.HdotV); @@ -237,7 +237,7 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) #if CAPTURING == 1 return saturate(lerp(Fd + Fr,surface.f0,surface.metalness)); #else - return saturate(Fd + Fr); + return Fd + Fr; #endif } @@ -255,6 +255,14 @@ float3 getPunctualLight(Surface surface, SurfaceToLight surfaceToLight, float3 l return evaluateStandardBRDF(surface,surfaceToLight) * factor; } +float3 getSpotlight(Surface surface, SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float radius, float3 lightDir, float2 lightSpotParams, float shadow) +{ + float attenuation = 1.0f; + attenuation *= getDistanceAtt(surfaceToLight.Lu, radius); + attenuation *= getSpotAngleAtt(-surfaceToLight.L, lightDir, lightSpotParams.xy); + float3 factor = lightColor * max(surfaceToLight.NdotL* shadow * lightIntensity * attenuation, 0.0f) ; + return evaluateStandardBRDF(surface,surfaceToLight) * factor; +} float computeSpecOcclusion( float NdotV , float AO , float roughness ) { return saturate (pow( abs(NdotV + AO) , exp2 ( -16.0f * roughness - 1.0f )) - 1.0f + AO ); @@ -271,7 +279,7 @@ float4 compute4Lights( Surface surface, float4 inLightConfigData[4], float4 inLightColor[4], float4 inLightSpotDir[4], - float2 lightSpotParams[4], + float2 inlightSpotParams[4], int hasVectorLight, float4 vectorLightDirection, float4 vectorLightingColor, @@ -296,7 +304,7 @@ float4 compute4Lights( Surface surface, float lightBrightness = inLightConfigData[i].y; float lightInvSqrRange= inLightConfigData[i].a; - float3 lighting = 0.0.xxx; + float3 lighting = float3(0.0,0.0,0.0); [branch] if(dist < lightRange) @@ -307,13 +315,10 @@ float4 compute4Lights( Surface surface, //get punctual light contribution lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); } - else //spot + else if(inLightConfigData[i].x == 1) //spot { - - //get Punctual light contribution - lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed); - //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, inLightSpotDir[i].xyz, lightSpotParams[i].xy ); + //get spot light contribution + lighting = getSpotlight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, inLightSpotDir[i].xyz, inlightSpotParams[i], shadowed); } } finalLighting += lighting; @@ -321,7 +326,7 @@ float4 compute4Lights( Surface surface, //Vector light [branch] - if(hasVectorLight) + if(hasVectorLight == 1) { SurfaceToLight surfaceToVecLight = createSurfaceToLight(surface, -vectorLightDirection.xyz); diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl index 1a7c42822..42654c532 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/gl/spotLightP.glsl @@ -154,10 +154,8 @@ void main() return; #endif - //get Punctual light contribution - lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadow); - //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams ); + //get spot light contribution + lighting = getSpotlight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, lightDirection, lightSpotParams, shadow); } OUT_col = vec4(lighting, 0); diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl index a78ed019b..d4ef36a36 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting/advanced/spotLightP.hlsl @@ -151,10 +151,8 @@ float4 main( ConvexConnectP IN ) : SV_TARGET return final; #endif - //get Punctual light contribution - lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadow); - //get spot angle attenuation - lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams ); + //get spot light contribution + lighting = getSpotlight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, lightDirection, lightSpotParams, shadow); } return float4(lighting, 0);