From f0924c8dcd5442cb1690eca2f1a7044b55362336 Mon Sep 17 00:00:00 2001 From: Tim Barnes Date: Wed, 14 Nov 2018 20:58:47 +1000 Subject: [PATCH] point light WIP & moved lighting position/direction to WS --- .../advanced/advancedLightBinManager.cpp | 17 +-- .../advanced/advancedLightBinManager.h | 2 +- .../Full/game/shaders/common/lighting.hlsl | 33 ++++- .../common/lighting/advanced/pointLightP.hlsl | 139 ++++++++---------- .../lighting/advanced/vectorLightP.hlsl | 5 +- .../Full/game/shaders/common/torque.hlsl | 2 - 6 files changed, 96 insertions(+), 102 deletions(-) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index cc3267b41..17a923f50 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -337,7 +337,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) // Set up SG data setupSGData( sgData, state, sunLight ); - vectorMatInfo->setLightParameters( sunLight, state, worldToCameraXfm ); + vectorMatInfo->setLightParameters( sunLight, state ); // Set light holds the active shadow map. mShadowManager->setLightShadowMapForLight( sunLight ); @@ -375,7 +375,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state ) GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Light, ColorI::RED ); setupSGData( sgData, state, curLightInfo ); - curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm ); + curLightMat->setLightParameters( curLightInfo, state ); mShadowManager->setLightShadowMap( curEntry.shadowMap ); mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap ); @@ -703,7 +703,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setViewParameters( const F32 _ matParams->setSafe( zNearFarInvNearFar, Point4F( _zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar ) ); } -void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const LightInfo *lightInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly ) +void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const LightInfo *lightInfo, const SceneRenderState* renderState ) { MaterialParameters *matParams = matInstance->getMaterialParameters(); @@ -728,9 +728,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light { case LightInfo::Vector: { - VectorF lightDir = lightInfo->getDirection(); - worldViewOnly.mulV(lightDir); - lightDir.normalize(); + const VectorF lightDir = lightInfo->getDirection(); matParams->setSafe( lightDirection, lightDir ); // Set small number for alpha since it represents existing specular in @@ -769,8 +767,6 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light matParams->setSafe( lightSpotParams, spotParams ); VectorF lightDir = lightInfo->getDirection(); - worldViewOnly.mulV(lightDir); - lightDir.normalize(); matParams->setSafe( lightDirection, lightDir ); } // Fall through @@ -779,10 +775,7 @@ void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const Light { const F32 radius = lightInfo->getRange().x; matParams->setSafe( lightRange, radius ); - - Point3F lightPos; - worldViewOnly.mulP(lightInfo->getPosition(), &lightPos); - matParams->setSafe( lightPosition, lightPos ); + matParams->setSafe( lightPosition, lightInfo->getPosition()); // Get the attenuation falloff ratio and normalize it. Point3F attenRatio = lightInfo->getExtended()->attenuationRatio; diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.h b/Engine/source/lighting/advanced/advancedLightBinManager.h index fe2515382..85e40c2cb 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.h +++ b/Engine/source/lighting/advanced/advancedLightBinManager.h @@ -184,7 +184,7 @@ protected: const PlaneF &farPlane, const PlaneF &_vsFarPlane ); - void setLightParameters( const LightInfo *light, const SceneRenderState* renderState, const MatrixF &worldViewOnly ); + void setLightParameters( const LightInfo *light, const SceneRenderState* renderState ); }; protected: diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index 89f880698..786ac90ed 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -104,7 +104,7 @@ struct Surface NdotV = abs(dot(N, V)) + 1e-5f; // avoid artifact albedo = baseColor.rgb * (1.0 - metalness); - f0 = lerp(float3_splat(0.04), baseColor.rgb, metalness); + f0 = lerp(0.04.xxx, baseColor.rgb, metalness); R = -reflect(V, N); float f90 = saturate(50.0 * dot(f0, 0.33)); @@ -114,7 +114,7 @@ struct Surface inline Surface CreateSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TORQUE_SAMPLER2D(gbufferTex2), in float2 uv, in float3 wsEyePos, in float3 wsEyeRay, in float4x4 invView) { - Surface surface; + Surface surface = (Surface)0; float4 gbuffer1 = TORQUE_TEX2DLOD(gbufferTex1, float4(uv,0,0)); float4 gbuffer2 = TORQUE_TEX2DLOD(gbufferTex2, float4(uv,0,0)); @@ -125,7 +125,7 @@ inline Surface CreateSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TOR surface.V = normalize(wsEyePos - surface.P); surface.baseColor = gbuffer1; const float minRoughness=1e-4; - surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //torque uses smoothness so we convert to roughness. Should really clamp during gbuffer pass though + surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness. surface.roughness_brdf = surface.roughness * surface.roughness; surface.metalness = gbuffer2.a; surface.ao = gbuffer2.g; @@ -146,8 +146,7 @@ struct SurfaceToLight inline SurfaceToLight CreateSurfaceToLight(in Surface surface, in float3 L) { - SurfaceToLight surfaceToLight; - + SurfaceToLight surfaceToLight = (SurfaceToLight)0; surfaceToLight.L = normalize(L); surfaceToLight.H = normalize(surface.V + surfaceToLight.L); surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N)); @@ -169,7 +168,7 @@ float3 BRDF_GetSpecular(in Surface surface, in SurfaceToLight surfaceToLight) float BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight) { - //getting some banding with disney method, using lambert instead - todo do some futher testing + //getting some banding with disney method, using lambert instead - todo futher testing float Fd = 1.0 / M_PI_F;//Fr_DisneyDiffuse(surface.NdotV, surfaceToLight.NdotL, surfaceToLight.HdotV, surface.roughness) / M_PI_F; return Fd; } @@ -182,7 +181,7 @@ struct LightResult inline LightResult GetDirectionalLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow) { - LightResult result; + LightResult result = (LightResult)0; float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity; result.diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor; result.spec = BRDF_GetSpecular(surface,surfaceToLight) * factor; @@ -192,3 +191,23 @@ inline LightResult GetDirectionalLight(in Surface surface, in SurfaceToLight sur return result; } + +inline LightResult GetPointLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity,float distToLight, float radius, float shadow) +{ + LightResult result = (LightResult)0; + + // Distance attenuation from Epic Games' paper + float distanceByRadius = 1.0f - pow((distToLight / radius), 4); + float clamped = pow(clamp(distanceByRadius, 0.0f, 1.0f), 2.0f); + float attenuation = clamped / (sqr(distToLight) + 1.0f); + + float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation; + + result.diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor; + result.spec = BRDF_GetSpecular(surface,surfaceToLight) * factor; + + result.diffuse = max(0.0f, result.diffuse); + result.spec = max(0.0f, result.spec); + + return result; +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl index a9d4e287b..fc650de18 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl @@ -131,9 +131,9 @@ uniform float4 lightParams; uniform float lightRange; uniform float shadowSoftness; -uniform float2 lightAttenuation; - +uniform float4x4 worldToCamera; uniform float3x3 viewToLightProj; +uniform float3x3 worldToLightProj; uniform float3x3 dynamicViewToLightProj; uniform float3 eyePosWorld; @@ -152,25 +152,14 @@ LightTargetOutput main( ConvexConnectP IN ) if (normDepth.w>0.9999) return Output; - // Eye ray - Eye -> Pixel - float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); - float3 viewSpacePos = eyeRay * normDepth.w; - - // Build light vec, get length, clip pixel if needed - float3 lightVec = lightPosition - viewSpacePos; - float lenLightV = length(lightVec); - clip(lightRange - lenLightV); + //eye ray WS/VS + float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane ); + float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz; - // Get the attenuated falloff. - float atten = attenuate(lightColor, lightAttenuation, lenLightV); - clip(atten - 1e-6); - - // Normalize lightVec - lightVec /= lenLightV; - //create surface Surface surface = CreateSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer), - uvScene, eyePosWorld, eyeRay, cameraToWorld); + uvScene, eyePosWorld, wsEyeRay, cameraToWorld); + //early out if emissive if (getFlag(surface.matFlag, 0)) { @@ -178,80 +167,76 @@ LightTargetOutput main( ConvexConnectP IN ) Output.spec = surface.baseColor; return Output; } - - // If we can do dynamic branching then avoid wasting - // fillrate on pixels that are backfacing to the light. - float nDotL = dot( lightVec, normDepth.xyz ); - //DB_CLIP( nDotL < 0 ); + //create surface to light - float3 wsLightDir = mul(cameraToWorld, float4(lightVec,0)).xyz; - SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, wsLightDir);//lightPosition - viewSpacePos); + float3 L = lightPosition - surface.P; + float dist = length(L); + LightResult result = (LightResult)0; + [branch] + if (dist < lightRange) + { + float distToLight = dist / lightRange; + SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, L); -#ifdef NO_SHADOW + #ifdef NO_SHADOW + float shadowed = 1.0; + #else - float shadowed = 1.0; + #ifdef SHADOW_CUBE -#else + // TODO: We need to fix shadow cube to handle soft shadows! + float occ = TORQUE_TEXCUBE( shadowMap, mul( worldToLightProj, -surfaceToLight.L ) ).r; + float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) ); - // Get a linear depth from the light source. - float distToLight = lenLightV / lightRange; + #else + // Static + float2 shadowCoord = decodeShadowCoord( mul( worldToLightProj, -surfaceToLight.L ) ).xy; + float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + surfaceToLight.NdotL, + lightParams.y); -#ifdef SHADOW_CUBE + // Dynamic + float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), + ssPos.xy, + shadowCoord, + shadowSoftness, + distToLight, + surfaceToLight.NdotL, + lightParams.y); - // TODO: We need to fix shadow cube to handle soft shadows! - float occ = TORQUE_TEXCUBE(shadowMap, mul(viewToLightProj, -lightVec)).r; - float shadowed = saturate(exp(lightParams.y * (occ - distToLight))); + float shadowed = min(static_shadowed, dynamic_shadowed); -#else + #endif + + #endif // !NO_SHADOW + + float3 lightcol = lightColor.rgb; + /*#ifdef USE_COOKIE_TEX - // Static - float2 shadowCoord = decodeShadowCoord(mul(viewToLightProj, -lightVec)).xy; - float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), - ssPos.xy, - shadowCoord, - shadowSoftness, - distToLight, - surfaceToLight.NdotL, - lightParams.y); + // Lookup the cookie sample. + float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(viewToLightProj, -surfaceToLight.L)); - // Dynamic - float2 dynamicShadowCoord = decodeShadowCoord(mul(dynamicViewToLightProj, -lightVec)).xy; - float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), - ssPos.xy, - dynamicShadowCoord, - shadowSoftness, - distToLight, - surfaceToLight.NdotL, - lightParams.y); + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; - float shadowed = min(static_shadowed, dynamic_shadowed); + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max(cookie.r, max(cookie.g, cookie.b)); -#endif + #endif*/ -#endif // !NO_SHADOW - - float3 lightcol = lightColor.rgb; -#ifdef USE_COOKIE_TEX - - // Lookup the cookie sample. - float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(viewToLightProj, -lightVec)); - - // Multiply the light with the cookie tex. - lightcol *= cookie.rgb; - - // Use a maximum channel luminance to attenuate - // the lighting else we get specular in the dark - // regions of the cookie texture. - atten *= max(cookie.r, max(cookie.g, cookie.b)); - -#endif - - //get directional light contribution - LightResult result = GetDirectionalLight(surface, surfaceToLight, lightColor.rgb, lightBrightness, shadowed); + //get point light contribution + result = GetPointLight(surface, surfaceToLight, lightcol, lightBrightness, dist, lightRange, shadowed); + } //output - Output.diffuse = float4(result.diffuse*atten, 0); - Output.spec = float4(result.spec*atten, 0); + Output.diffuse = float4(result.diffuse, 0); + Output.spec = float4(result.spec, 0); return Output; } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl index 9c9f3aa2b..065bb2c19 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl @@ -203,9 +203,8 @@ LightTargetOutput main(FarFrustumQuadConnectP IN) return Output; } - //create surface to light - float3 wsLightDir = mul(cameraToWorld, float4(lightDirection,0)).xyz; - SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, -wsLightDir); + //create surface to light + SurfaceToLight surfaceToLight = CreateSurfaceToLight(surface, -lightDirection); //light color might be changed by PSSM_DEBUG_RENDER float3 lightingColor = lightColor.rgb; diff --git a/Templates/Full/game/shaders/common/torque.hlsl b/Templates/Full/game/shaders/common/torque.hlsl index 2661cc1a4..f4555ec78 100644 --- a/Templates/Full/game/shaders/common/torque.hlsl +++ b/Templates/Full/game/shaders/common/torque.hlsl @@ -346,6 +346,4 @@ float3 getCubeDir(int face, float2 uv) } #define sqr(a) ((a)*(a)) -#define float4_splat(a) float4(a,a,a,a) -#define float3_splat(a) float3(a,a,a) #endif // _TORQUE_HLSL_