diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index a8cf184f2..b4105decf 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -235,90 +235,3 @@ inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLi float3 final = max(0.0f, diffuse + spec * surface.ao * surface.F); return final; } - -//Probe IBL stuff -struct ProbeData -{ - float3 wsPosition; - float radius; - float3 boxMin; - float3 boxMax; - float attenuation; - float4x4 worldToLocal; - uint probeIdx; - uint type; //box = 0, sphere = 1 - float contribution; - float3 refPosition; - float3 pad; -}; - -// Box Projected IBL Lighting -// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/ -// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ -float3 boxProject(Surface surface, ProbeData probe) //float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax -{ - //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz; - //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz; - - float3 nrdir = surface.R; - float3 offset = surface.P; - float3 plane1vec = (probe.boxMax - offset) / nrdir; - float3 plane2vec = (probe.boxMin - offset) / nrdir; - - float3 furthestPlane = max(plane1vec, plane2vec); - float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); - float3 posonbox = offset + nrdir * dist; - - return posonbox - probe.refPosition; -} - -float defineSphereSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay) -{ - float3 L = probe.wsPosition.xyz - surface.P; - return 1.0 - length(L) / probe.radius; -} - -float defineBoxSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay) -{ - /*float3 lsPos = mul(probe.worldToLocal, float4(surface.P, 1.0)).xyz; - float3 lsDir = mul(probe.worldToLocal, float4(wsEyeRay, 0)).xyz; - - float3 lsInvDir = rcp(lsDir); - - float3 intersectsMax = lsInvDir - lsPos * lsInvDir; - float3 intersectsMin = -lsInvDir - lsPos * lsInvDir; - - float3 positiveIntersections = max(intersectsMax, intersectsMin); - float intersectDist = min(positiveIntersections.x, min(positiveIntersections.y, positiveIntersections.z)); - - float3 wsIntersectPosition = surface.P + intersectDist * wsEyeRay; - float3 lookupDir = wsIntersectPosition - probe.wsPosition; - - //replace this mess with a second pair of minmaxes - float atten = probe.radius - probe.radius*probe.attenuation / 2; - float rad = probe.radius * 2; - float3 atten3 = float3(atten, atten, atten); // atten as a % of box - float3 reducedExtents = float3(rad, rad, rad) - atten3; - - float distToBox = getDistBoxToPoint(lsPos*probe.boxExtents, float3(rad, rad, rad)); - - float normalizedDistance = distToBox / length(rad); - - float t = saturate(3.3333 - 3.3333 * normalizedDistance); - contribution = t * t * (3.0 - 2.0 * t); - - return lookupDir;*/ - - float3 surfPosLS = mul(probe.worldToLocal, float4(surface.P, 1.0)).xyz; - - float3 boxMinLS = probe.wsPosition.xyz - (float3(1, 1, 1)*probe.radius); - float3 boxMaxLS = probe.wsPosition.xyz + (float3(1, 1, 1)*probe.radius); - - float boxOuterRange = length(boxMaxLS - boxMinLS); - float boxInnerRange = boxOuterRange / probe.attenuation; - - float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z)); - localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange); - - return max(localDir.x, max(localDir.y, localDir.z)) * -1; -} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl index 9fcbb4bfa..2cfdb5f67 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -32,56 +32,90 @@ uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten uniform float4 probeContribColors[MAX_PROBES]; #endif -// Box Projected IBL Lighting -// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/ -// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ -/*float3 boxProject(float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax) -{ - float3 positionLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz; - //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz; - //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz; - - float3 nrdir = reflectDir; - float3 offset = wsPosition; - float3 plane1vec = (boxMax - offset) / nrdir; - float3 plane2vec = (boxMin - offset) / nrdir; - - float3 furthestPlane = max(plane1vec, plane2vec); - float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); - float3 posonbox = offset + nrdir * dist; - - return posonbox - boxWSPos; -}*/ - - -float3 iblBoxDiffuse( Surface surface, ProbeData probe) +//Probe IBL stuff +struct ProbeData { - float3 dir = boxProject(surface, probe); + float3 wsPosition; + float radius; + float3 boxMin; + float3 boxMax; + float attenuation; + float4x4 worldToLocal; + uint probeIdx; + uint type; //box = 0, sphere = 1 + float contribution; + float3 refPosition; + float3 pad; + + inline void defineSphereSpaceInfluence(Surface surface, float3 wsEyeRay) + { + float3 L = wsPosition.xyz - surface.P; + contribution = 1.0 - length(L) / radius; + } - float lod = surface.roughness*cubeMips; - float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probe.probeIdx, lod).xyz; + inline void defineBoxSpaceInfluence(Surface surface, float3 wsEyeRay) + { + float3 surfPosLS = mul(worldToLocal, float4(surface.P, 1.0)).xyz; - return color; -} + float3 boxMinLS = wsPosition.xyz - (float3(1, 1, 1)*radius); + float3 boxMaxLS = wsPosition.xyz + (float3(1, 1, 1)*radius); -float3 iblBoxSpecular(Surface surface, ProbeData probe) -{ - // BRDF - float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV,0.0,0.0)).xy; + float boxOuterRange = length(boxMaxLS - boxMinLS); + float boxInnerRange = boxOuterRange / attenuation; - float3 dir = boxProject(surface, probe); + float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z)); + localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange); - // Radiance (Specular) -#if DEBUGVIZ_SPECCUBEMAP == 0 - float lod = surface.roughness*cubeMips; -#elif DEBUGVIZ_SPECCUBEMAP == 1 - float lod = 0; -#endif + contribution = max(localDir.x, max(localDir.y, localDir.z)) * -1; + } + + // Box Projected IBL Lighting + // Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/ + // and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ + inline float3 boxProject(Surface surface) //float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax + { + float3 nrdir = surface.R; + float3 offset = surface.P; + float3 plane1vec = (boxMax - offset) / nrdir; + float3 plane2vec = (boxMin - offset) / nrdir; - float3 color = TORQUE_TEXCUBEARRAYLOD(cubeMapAR, dir, probe.probeIdx, lod).xyz * (brdf.x + brdf.y); + float3 furthestPlane = max(plane1vec, plane2vec); + float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); + float3 posonbox = offset + nrdir * dist; + + return posonbox - refPosition; + } + + float3 iblBoxDiffuse( Surface surface) + { + float3 dir = boxProject(surface); + + float lod = surface.roughness*cubeMips; + float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probeIdx, lod).xyz; + + return color; + } + + float3 iblBoxSpecular(Surface surface) + { + // BRDF + float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV,0.0,0.0)).xy; + + float3 dir = boxProject(surface); + + // Radiance (Specular) + #if DEBUGVIZ_SPECCUBEMAP == 0 + float lod = surface.roughness*cubeMips; + #elif DEBUGVIZ_SPECCUBEMAP == 1 + float lod = 0; + #endif + + float3 color = TORQUE_TEXCUBEARRAYLOD(cubeMapAR, dir, probeIdx, lod).xyz * (brdf.x + brdf.y); + + return color; + } +}; - return color; -} float4 main( PFXVertToPix IN ) : SV_TARGET { @@ -99,7 +133,6 @@ float4 main( PFXVertToPix IN ) : SV_TARGET } int i = 0; - float blendVal[MAX_PROBES]; float blendFactor[MAX_PROBES]; float blendSum = 0; float blendFacSum = 0; @@ -124,16 +157,16 @@ float4 main( PFXVertToPix IN ) : SV_TARGET if (probes[i].type == 0) //box { - blendVal[i] = defineBoxSpaceInfluence(surface, probes[i], IN.wsEyeRay); + probes[i].defineBoxSpaceInfluence(surface, IN.wsEyeRay); } else { - blendVal[i] = defineSphereSpaceInfluence(surface, probes[i], IN.wsEyeRay); + probes[i].defineSphereSpaceInfluence(surface,IN.wsEyeRay); } - blendVal[i] = saturate(blendVal[i]); - blendSum += blendVal[i]; - invBlendSum += (1.0f - blendVal[i]); + probes[i].contribution = saturate(probes[i].contribution); + blendSum += probes[i].contribution; + invBlendSum += (1.0f - probes[i].contribution); } // Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary. @@ -145,14 +178,14 @@ float4 main( PFXVertToPix IN ) : SV_TARGET { if (numProbes>1) { - blendFactor[i] = ((1.0f - blendVal[i] / blendSum)) / (numProbes - 1); - blendFactor[i] *= ((1.0f - blendVal[i]) / invBlendSum); + blendFactor[i] = ((1.0f - probes[i].contribution / blendSum)) / (numProbes - 1); + blendFactor[i] *= ((1.0f - probes[i].contribution) / invBlendSum); blendFacSum += blendFactor[i]; } else { - blendFactor[i] = blendVal[i]; - blendFacSum = blendVal[i]; + blendFactor[i] = probes[i].contribution; + blendFacSum = probes[i].contribution; } } @@ -199,12 +232,12 @@ float4 main( PFXVertToPix IN ) : SV_TARGET kD *= 1.0 - surface.metalness; for (i = 0; i < numProbes; ++i) { - if (blendVal[i] == 0) + if (probes[i].contribution == 0) continue; - irradiance += blendFactor[i]*iblBoxDiffuse(surface, probes[i]); + irradiance += blendFactor[i]*probes[i].iblBoxDiffuse(surface); - specular += blendFactor[i]*F*iblBoxSpecular(surface, probes[i]); + specular += blendFactor[i]*F*probes[i].iblBoxSpecular(surface); } //final diffuse color @@ -217,7 +250,7 @@ float4 main( PFXVertToPix IN ) : SV_TARGET float3 cubeColor = float3(0, 0, 0); for (i = 0; i < numProbes; ++i) { - cubeColor += blendFactor[i] * iblBoxSpecular(surface, probes[i]); + cubeColor += blendFactor[i] * probes[i].iblBoxSpecular(surface); } return float4(cubeColor, 1); @@ -225,7 +258,7 @@ float4 main( PFXVertToPix IN ) : SV_TARGET float3 cubeColor = float3(0, 0, 0); for (i = 0; i < numProbes; ++i) { - cubeColor += blendFactor[i] * iblBoxDiffuse(surface, probes[i]); + cubeColor += blendFactor[i] * probes[i].iblBoxDiffuse(surface); } return float4(cubeColor, 1);