From c025760422b2104c959a2cdf5ec43c4f31847155 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 7 Apr 2019 23:57:05 -0500 Subject: [PATCH] Majority of forward work. Some state/register count issues and further testing required. Also requires proper binding of forward probe values, as well as scoring probes for forward selection. --- .../source/renderInstance/renderProbeMgr.cpp | 129 +++++++-------- Engine/source/renderInstance/renderProbeMgr.h | 2 +- .../shaderGen/HLSL/shaderFeatureHLSL.cpp | 150 +++++++++++++----- Engine/source/shaderGen/shaderGenVars.cpp | 2 +- .../Full/game/shaders/common/lighting.hlsl | 150 +++++++++++++++++- .../advanced/reflectionProbeArrayP.hlsl | 55 ++++--- 6 files changed, 344 insertions(+), 144 deletions(-) diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 8816ff47e..0f884bf98 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -164,7 +164,7 @@ void ProbeShaderConstants::init(GFXShader* shader) mProbeIrradianceCubemapSC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR); mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount); - mSkylightPrefilterMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap); + mSkylightSpecularMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap); mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap); mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight); @@ -568,29 +568,29 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, { PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes); - static AlignedArray probePositions(4, sizeof(Point3F)); - static AlignedArray probeRadius(4, sizeof(F32)); - static AlignedArray probeBoxMins(4, sizeof(Point3F)); - static AlignedArray probeBoxMaxs(4, sizeof(Point3F)); - static AlignedArray probeLocalPositions(4, sizeof(Point3F)); - static AlignedArray probeIsSphere(4, sizeof(F32)); + const U32 MAX_FORWARD_PROBES = 4; + + static AlignedArray probePositionArray(MAX_FORWARD_PROBES, sizeof(Point4F)); + static AlignedArray probeBoxMinArray(MAX_FORWARD_PROBES, sizeof(Point4F)); + static AlignedArray probeBoxMaxArray(MAX_FORWARD_PROBES, sizeof(Point4F)); + static AlignedArray probeRefPositionArray(MAX_FORWARD_PROBES, sizeof(Point4F)); + static AlignedArray probeConfigArray(MAX_FORWARD_PROBES, sizeof(Point4F)); + + Vector probeWorldToObjArray; + probeWorldToObjArray.setSize(MAX_FORWARD_PROBES); //static AlignedArray probeCubemap(4, sizeof(CubemapData)); //F32 range; // Need to clear the buffers so that we don't leak // lights from previous passes or have NaNs. - dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize()); - dMemset(probeRadius.getBuffer(), 0, probeRadius.getBufferSize()); - dMemset(probeBoxMins.getBuffer(), 0, probeBoxMins.getBufferSize()); - dMemset(probeBoxMaxs.getBuffer(), 0, probeBoxMaxs.getBufferSize()); - dMemset(probeLocalPositions.getBuffer(), 0, probeLocalPositions.getBufferSize()); - dMemset(probeIsSphere.getBuffer(), 0, probeRadius.getBufferSize()); - //dMemset(probeCubemap.getBuffer(), 0, probeCubemap.getBufferSize()); + dMemset(probePositionArray.getBuffer(), 0, probePositionArray.getBufferSize()); + dMemset(probeBoxMinArray.getBuffer(), 0, probeBoxMinArray.getBufferSize()); + dMemset(probeBoxMaxArray.getBuffer(), 0, probeBoxMaxArray.getBufferSize()); + dMemset(probeRefPositionArray.getBuffer(), 0, probeRefPositionArray.getBufferSize()); + dMemset(probeConfigArray.getBuffer(), 0, probeConfigArray.getBufferSize()); matSet.restoreSceneViewProjection(); - //const MatrixF &worldToCameraXfm = matSet.getWorldToCamera(); - // Gather the data for the first 4 probes. /*const ProbeRenderInst *probe; for (U32 i = 0; i < 4; i++) @@ -649,26 +649,21 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, mEffectiveProbeCount = 0; mMipCount = 0; - if (probePositionsData.size() != MAXPROBECOUNT) + /*if (probePositionArray.size() != MAX_FORWARD_PROBES) { - probePositionsData.setSize(MAXPROBECOUNT); - probeRefPositionsData.setSize(MAXPROBECOUNT); - probeWorldToObjData.setSize(MAXPROBECOUNT); - probeBBMinData.setSize(MAXPROBECOUNT); - probeBBMaxData.setSize(MAXPROBECOUNT); - probeConfigData.setSize(MAXPROBECOUNT); - } + probePositionArray.setSize(MAX_FORWARD_PROBES); + probeBoxMinArray.setSize(MAX_FORWARD_PROBES); + probeBoxMaxArray.setSize(MAX_FORWARD_PROBES); + probeBoxMaxArray.setSize(MAX_FORWARD_PROBES); + probeRefPositionArray.setSize(MAX_FORWARD_PROBES); + probeConfigArray.setSize(MAX_FORWARD_PROBES); - probePositionsData.fill(Point4F::Zero); - probeRefPositionsData.fill(Point4F::Zero); - probeWorldToObjData.fill(MatrixF::Identity); - probeBBMinData.fill(Point4F::Zero); - probeBBMaxData.fill(Point4F::Zero); - probeConfigData.fill(Point4F::Zero); + probeWorldToObjArray.setSize(MAX_FORWARD_PROBES); + }*/ - cubeMaps.clear(); - irradMaps.clear(); - Vector cubemapIdxes; + //cubeMaps.clear(); + //irradMaps.clear(); + //Vector cubemapIdxes; U32 effectiveProbeCount = 0; bool hasSkylight = false; @@ -683,41 +678,51 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, if (curEntry.mIsSkylight) { - GFX->setCubeTexture(probeShaderConsts->mSkylightPrefilterMap->getSamplerRegister(), curEntry.mPrefilterCubemap); - GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap); + if (curEntry.mPrefilterCubemap.isValid() && curEntry.mPrefilterCubemap.isValid()) + { + U32 specSample = probeShaderConsts->mSkylightSpecularMap->getSamplerRegister(); + U32 irradSample = probeShaderConsts->mSkylightIrradMap->getSamplerRegister(); - shaderConsts->setSafe(probeShaderConsts->mHasSkylight, true); - hasSkylight = true; - continue; + GFX->setCubeTexture(probeShaderConsts->mSkylightSpecularMap->getSamplerRegister(), curEntry.mPrefilterCubemap); + GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap); + + shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 1.0f); + hasSkylight = true; + continue; + } + } + else + { + /*probePositions[effectiveProbeCount] = curEntry.getPosition(); + probeRefPositions[effectiveProbeCount] = curEntry.mProbeRefOffset; + probeWorldToObj[effectiveProbeCount] = curEntry.getTransform(); + probeBBMin[effectiveProbeCount] = curEntry.mBounds.minExtents; + probeBBMax[effectiveProbeCount] = curEntry.mBounds.maxExtents; + probeConfig[effectiveProbeCount] = Point4F(curEntry.mProbeShapeType, + curEntry.mRadius, + curEntry.mAtten, + curEntry.mCubemapIndex);*/ } - - //Setup - /*Point3F probePos = curEntry.getPosition(); - Point3F refPos = curEntry.getPosition() + curEntry.mProbeRefOffset; - probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z, 0); - probeRefPositionsData[mEffectiveProbeCount] = Point4F(refPos.x, refPos.y, refPos.z, 0); - - probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform(); - Point3F bbMin = refPos - curEntry.mProbeRefScale / 2 * curEntry.getTransform().getScale(); - Point3F bbMax = refPos + curEntry.mProbeRefScale / 2 * curEntry.getTransform().getScale(); - probeBBMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0); - probeBBMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0); - - probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType, - curEntry.mRadius, - curEntry.mAtten, - curEntry.mCubemapIndex); - - cubeMaps.push_back(curEntry.mPrefilterCubemap); - irradMaps.push_back(curEntry.mIrradianceCubemap); - - cubemapIdxes.push_back(i);*/ effectiveProbeCount++; } + shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (float)effectiveProbeCount); + + shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionArray); + shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionArray); + + shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeWorldToObjArray.address(), effectiveProbeCount, GFXSCT_Float4x4); + + shaderConsts->setSafe(probeShaderConsts->mProbeBoxMinSC, probeBoxMinArray); + shaderConsts->setSafe(probeShaderConsts->mProbeBoxMaxSC, probeBoxMaxArray); + shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigArray); + + GFX->setCubeArrayTexture(probeShaderConsts->mProbeSpecularCubemapSC->getSamplerRegister(), mPrefilterArray); + GFX->setCubeArrayTexture(probeShaderConsts->mProbeIrradianceCubemapSC->getSamplerRegister(), mIrradianceArray); + if (!hasSkylight) - shaderConsts->setSafe(probeShaderConsts->mHasSkylight, false); + shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 0.0f); } /*else { @@ -863,8 +868,6 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe) { GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE); - bool serverObj = probe->isServerObject(); - Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!"); U32 startMSTime = Platform::getRealMilliseconds(); diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index 0a2b32d84..a9039fbbe 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -145,7 +145,7 @@ struct ProbeShaderConstants GFXShaderConstHandle *mProbeIrradianceCubemapSC; GFXShaderConstHandle *mProbeCountSC; - GFXShaderConstHandle *mSkylightPrefilterMap; + GFXShaderConstHandle *mSkylightSpecularMap; GFXShaderConstHandle *mSkylightIrradMap; GFXShaderConstHandle *mHasSkylight; diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 745d9e516..4dbce82c9 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -2966,7 +2966,7 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList MultiLine *meta = new MultiLine; // Look for a wsNormal or grab it from the connector. - Var *wsNormal = (Var*)LangElement::find("wsNormal"); + /*Var *wsNormal = (Var*)LangElement::find("wsNormal"); if (!wsNormal) { wsNormal = connectComp->getElement(RT_TEXCOORD); @@ -2983,63 +2983,69 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList // on older Geforce cards. // meta->addStatement(new GenOp(" @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal)); - } + }*/ // Now the wsPosition and wsView. Var *wsPosition = getInWsPosition(componentList); Var *wsView = getWsView(wsPosition, meta); - Var *metalness = (Var*)LangElement::find("metalness"); - Var *smoothness = (Var*)LangElement::find("smoothness"); - if (!fd.features[MFT_SpecularMap]) - { - if (!metalness) - { - metalness = new Var("metalness", "float"); - metalness->uniform = true; - metalness->constSortPos = cspPotentialPrimitive; - } - if (!smoothness) - { - smoothness = new Var("smoothness", "float"); - smoothness->uniform = true; - smoothness->constSortPos = cspPotentialPrimitive; - } - } - Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); //Reflection Probe WIP - Var *inProbePos = new Var("inProbePosArray", "float4"); - inProbePos->arraySize = 4; - inProbePos->uniform = true; - inProbePos->constSortPos = cspPotentialPrimitive; + U32 MAX_FORWARD_PROBES = 4; - Var *inProbeRadius = new Var("inRefPosArray", "float4"); - inProbeRadius->arraySize = 4; - inProbeRadius->uniform = true; - inProbeRadius->constSortPos = cspPotentialPrimitive; + Var *numProbes = new Var("numProbes", "float"); + numProbes->uniform = true; + numProbes->constSortPos = cspPotentialPrimitive; - Var *inProbeBoxMin = new Var("inProbeBoxMin", "float4"); - inProbeBoxMin->arraySize = 4; - inProbeBoxMin->uniform = true; - inProbeBoxMin->constSortPos = cspPotentialPrimitive; + Var *cubeMips = new Var("cubeMips", "float"); + cubeMips->uniform = true; + cubeMips->constSortPos = cspPotentialPrimitive; - Var *inProbeBoxMax = new Var("inProbeBoxMax", "float4"); - inProbeBoxMax->arraySize = 4; - inProbeBoxMax->uniform = true; - inProbeBoxMax->constSortPos = cspPotentialPrimitive; + Var *hasSkylight = new Var("hasSkylight", "float"); + hasSkylight->uniform = true; + hasSkylight->constSortPos = cspPotentialPrimitive; - Var *inProbeIsSphere = new Var("probeConfigData", "float4"); - inProbeIsSphere->arraySize = 4; - inProbeIsSphere->uniform = true; - inProbeIsSphere->constSortPos = cspPotentialPrimitive; + Var *inProbePosArray = new Var("inProbePosArray", "float4"); + inProbePosArray->arraySize = MAX_FORWARD_PROBES; + inProbePosArray->uniform = true; + inProbePosArray->constSortPos = cspPotentialPrimitive; + + Var *inRefPosArray = new Var("inRefPosArray", "float4"); + inRefPosArray->arraySize = MAX_FORWARD_PROBES; + inRefPosArray->uniform = true; + inRefPosArray->constSortPos = cspPotentialPrimitive; + + Var *bbMinArray = new Var("inProbeBoxMin", "float4"); + bbMinArray->arraySize = MAX_FORWARD_PROBES; + bbMinArray->uniform = true; + bbMinArray->constSortPos = cspPotentialPrimitive; + + Var *bbMaxArray = new Var("inProbeBoxMax", "float4"); + bbMaxArray->arraySize = MAX_FORWARD_PROBES; + bbMaxArray->uniform = true; + bbMaxArray->constSortPos = cspPotentialPrimitive; + + Var *probeConfigData = new Var("probeConfigData", "float4"); + probeConfigData->arraySize = MAX_FORWARD_PROBES; + probeConfigData->uniform = true; + probeConfigData->constSortPos = cspPotentialPrimitive; Var *worldToObjArray = new Var("worldToObjArray", "float4x4"); - worldToObjArray->arraySize = 4; + worldToObjArray->arraySize = MAX_FORWARD_PROBES; worldToObjArray->uniform = true; worldToObjArray->constSortPos = cspPotentialPrimitive; + Var *BRDFTexture = new Var("BRDFTexture", "SamplerState"); + BRDFTexture->uniform = true; + BRDFTexture->sampler = true; + BRDFTexture->constNum = Var::getTexUnitNum(); // used as texture unit num here + + Var *BRDFTextureTex = new Var("BRDFTextureTex", "Texture2D"); + BRDFTextureTex->uniform = true; + BRDFTextureTex->texture = true; + BRDFTextureTex->constNum = BRDFTexture->constNum; + Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState"); specularCubemapAR->uniform = true; specularCubemapAR->sampler = true; @@ -3058,7 +3064,27 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList Var *irradianceCubemapARTex = new Var("irradianceCubemapARTex", "TextureCubeArray"); irradianceCubemapARTex->uniform = true; irradianceCubemapARTex->texture = true; - irradianceCubemapARTex->constNum = specularCubemapAR->constNum; + irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum; + + Var *skylightSpecularMap = new Var("skylightSpecularMap", "SamplerState"); + skylightSpecularMap->uniform = true; + skylightSpecularMap->sampler = true; + skylightSpecularMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + Var *skylightSpecularMapTex = new Var("skylightSpecularMapTex", "TextureCube"); + skylightSpecularMapTex->uniform = true; + skylightSpecularMapTex->texture = true; + skylightSpecularMapTex->constNum = skylightSpecularMap->constNum; + + Var *skylightIrradMap = new Var("skylightIrradMap", "SamplerState"); + skylightIrradMap->uniform = true; + skylightIrradMap->sampler = true; + skylightIrradMap->constNum = Var::getTexUnitNum(); // used as texture unit num here + + Var *skylightIrradMapTex = new Var("skylightIrradMapTex", "TextureCube"); + skylightIrradMapTex->uniform = true; + skylightIrradMapTex->texture = true; + skylightIrradMapTex->constNum = skylightIrradMap->constNum; /*Var *probeVec = new Var("probeVec", "float3"); meta->addStatement(new GenOp(" @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition)); @@ -3137,7 +3163,45 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList meta->addStatement(new GenOp(" @.rgb = simpleFresnel(@.rgb, @, 0, @, @, @));\r\n", albedo, albedo, probeColor, angle, FRESNEL_BIAS, FRESNEL_POWER)); }*/ - meta->addStatement(new GenOp(" @.rgb = float3(1,1,1);\r\n", albedo)); + Var *inTex = getInTexCoord("texCoord", "float2", componentList); + if (!inTex) + return; + + Var *diffuseColor = (Var*)LangElement::find("diffuseColor"); + if (!diffuseColor) + return; + + Var *specularColor = (Var*)LangElement::find("specularColor"); + if (!specularColor) + return; + + Var *bumpNormal = (Var*)LangElement::find("bumpNormal"); + if (!bumpNormal) + return; + + Var *wsEyePos = (Var*)LangElement::find("eyePosWorld"); + + Var *worldToCamera = (Var*)LangElement::find("worldToCamera"); + if (!worldToCamera) + { + worldToCamera = new Var; + worldToCamera->setType("float4x4"); + worldToCamera->setName("worldToCamera"); + worldToCamera->uniform = true; + worldToCamera->constSortPos = cspPass; + } + + //Reflection vec + Var *surface = new Var("surface", "Surface"); + meta->addStatement(new GenOp(" @ = createForwardSurface(@,@,@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, bumpNormal, specularColor, + inTex, wsPosition, wsEyePos, wsView, worldToCamera)); + + meta->addStatement(new GenOp(" @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t@,@,@,@,@,\r\n\t\t@,@,@,@,@,@).rgb;\r\n", albedo, + surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, bbMinArray, bbMaxArray, inRefPosArray, + hasSkylight, skylightIrradMap, skylightIrradMapTex, skylightSpecularMap, skylightSpecularMapTex, + BRDFTexture, BRDFTextureTex, irradianceCubemapAR, irradianceCubemapARTex, specularCubemapAR, specularCubemapARTex)); + + //meta->addStatement(new GenOp(" @.rgb = @.roughness.xxx;\r\n", albedo, surface)); output = meta; } diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index 4b3ae3ef2..fac29f184 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/Engine/source/shaderGen/shaderGenVars.cpp @@ -81,7 +81,7 @@ const String ShaderGenVars::irradianceCubemapAR("$irradianceCubemapAR"); const String ShaderGenVars::probeCount("$numProbes"); //Skylight -const String ShaderGenVars::skylightPrefilterMap("$skylightPrefilterMap"); +const String ShaderGenVars::skylightPrefilterMap("$skylightSpecularMap"); const String ShaderGenVars::skylightIrradMap("$skylightIrradMap"); const String ShaderGenVars::hasSkylight("$hasSkylight"); diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index debbc7f1f..f4ae2f405 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -45,6 +45,9 @@ uniform float4 albedo; #endif // !TORQUE_SHADERGEN +#define MAX_PROBES 50 +#define MAX_FORWARD_PROBES 4 + inline float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane ) { float denum = dot( plane.xyz, direction.xyz ); @@ -145,6 +148,26 @@ inline Surface createSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TOR return surface; } +inline Surface createForwardSurface(float4 baseColor, float4 normal, float4 pbrProperties, in float2 uv, in float3 wsPosition, in float3 wsEyePos, in float3 wsEyeRay, in float4x4 invView) +{ + Surface surface = (Surface)0; + + surface.depth = 0; + surface.P = wsPosition; + surface.N = mul(invView, float4(normal.xyz,0)).xyz; //TODO move t3d to use WS normals + surface.V = normalize(wsEyePos - surface.P); + surface.baseColor = baseColor; + const float minRoughness=1e-4; + surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness. + surface.roughness_brdf = surface.roughness * surface.roughness; + surface.metalness = pbrProperties.a; + surface.ao = pbrProperties.g; + surface.matFlag = pbrProperties.r; + + surface.Update(); + return surface; +} + struct SurfaceToLight { float3 L; // surface to light vector @@ -237,9 +260,9 @@ inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLi } //Probe IBL stuff -float defineSphereSpaceInfluence(Surface surface, float3 wsProbePosition, float radius) +float defineSphereSpaceInfluence(float3 wsPosition, float3 wsProbePosition, float radius) { - float3 L = wsProbePosition.xyz - surface.P; + float3 L = wsProbePosition.xyz - wsPosition; float contribution = 1.0 - length(L) / radius; return contribution; } @@ -250,9 +273,9 @@ float getDistBoxToPoint(float3 pt, float3 extents) return max(max(d.x, d.y), d.z); } -float defineBoxSpaceInfluence(Surface surface, float4x4 worldToObj, float attenuation) +float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation) { - float3 surfPosLS = mul(worldToObj, float4(surface.P, 1.0)).xyz; + float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz; float atten = 1.0 - attenuation; float baseVal = 0.25; float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal)); @@ -262,17 +285,128 @@ float defineBoxSpaceInfluence(Surface surface, float4x4 worldToObj, float attenu // 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, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition) +float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition) { - float3 RayLS = mul(worldToObj, float4(surface.R, 0.0)).xyz; - float3 PositionLS = mul(worldToObj, float4(surface.P, 1.0)).xyz; + float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz; + float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz; float3 unit = bbMax.xyz - bbMin.xyz; float3 plane1vec = (unit / 2 - PositionLS) / RayLS; float3 plane2vec = (-unit / 2 - PositionLS) / RayLS; float3 furthestPlane = max(plane1vec, plane2vec); float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); - float3 posonbox = surface.P + surface.R * dist; + float3 posonbox = wsPosition + wsReflectVec * dist; return posonbox - refPosition.xyz; } + +float4 computeForwardProbes(Surface surface, + float cubeMips, float numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], + float4 inProbePosArray[MAX_FORWARD_PROBES], float4 bbMinArray[MAX_FORWARD_PROBES], float4 bbMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES], + float hasSkylight, SamplerState skylightIrradMap, TextureCube skylightIrradMapTex, SamplerState skylightSpecularMap, TextureCube skylightSpecularMapTex, + SamplerState BRDFTexture, Texture2D BRDFTextureTex, SamplerState irradianceCubemapAR, TextureCubeArray irradianceCubemapARTex, + SamplerState specularCubemapAR, TextureCubeArray specularCubemapARTex) +{ + int i = 0; + float blendFactor[MAX_FORWARD_PROBES]; + float blendSum = 0; + float blendFacSum = 0; + float invBlendSum = 0; + float probehits = 0; + //Set up our struct data + float contribution[MAX_FORWARD_PROBES]; + for (i = 0; i < numProbes; ++i) + { + contribution[i] = 0; + + if (probeConfigData[i].r == 0) //box + { + contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); + if (contribution[i] > 0.0) + probehits++; + } + else if (probeConfigData[i].r == 1) //sphere + { + contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); + if (contribution[i] > 0.0) + probehits++; + } + + contribution[i] = max(contribution[i], 0); + + blendSum += contribution[i]; + invBlendSum += (1.0f - contribution[i]); + } + + if (probehits > 1.0) + { + for (i = 0; i < numProbes; i++) + { + blendFactor[i] = ((contribution[i] / blendSum)) / probehits; + blendFactor[i] *= ((contribution[i]) / invBlendSum); + blendFactor[i] = saturate(blendFactor[i]); + blendFacSum += blendFactor[i]; + } + + // Normalize blendVal + if (blendFacSum == 0.0f) // Possible with custom weight + { + blendFacSum = 1.0f; + } + + float invBlendSumWeighted = 1.0f / blendFacSum; + for (i = 0; i < numProbes; ++i) + { + blendFactor[i] *= invBlendSumWeighted; + contribution[i] *= blendFactor[i]; + //alpha -= contribution[i]; + } + } + //else + // alpha -= blendSum; + + float3 irradiance = float3(0, 0, 0); + float3 specular = float3(0, 0, 0); + + // Radiance (Specular) + float lod = surface.roughness*cubeMips; + + float alpha = 1; + for (i = 0; i < numProbes; ++i) + { + float contrib = contribution[i]; + if (contrib != 0) + { + int cubemapIdx = probeConfigData[i].a; + float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz); + + irradiance += irradianceCubemapARTex.SampleLevel(irradianceCubemapAR,float4(dir,cubemapIdx),0).xyz * contrib; + specular += specularCubemapARTex.SampleLevel(specularCubemapAR,float4(dir,cubemapIdx),lod).xyz * contrib; + alpha -= contrib; + } + } + + if (hasSkylight && alpha > 0.001) + { + irradiance += skylightIrradMapTex.SampleLevel(skylightIrradMap,surface.R,0).xyz * alpha; + specular += skylightSpecularMapTex.SampleLevel(skylightSpecularMap,surface.R,lod).xyz * alpha; + } + + float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); + + //energy conservation + float3 kD = 1.0.xxx - F; + kD *= 1.0 - surface.metalness; + + //apply brdf + //Do it once to save on texture samples + float2 brdf = BRDFTextureTex.SampleLevel(BRDFTexture,float2(surface.roughness, surface.NdotV),0).xy; + specular *= brdf.x * F + brdf.y; + + //final diffuse color + float3 diffuse = kD * irradiance * surface.baseColor.rgb; + float4 finalColor = float4(diffuse + specular * surface.ao, 1.0); + + finalColor = float4(irradiance.rgb,1); + return finalColor; +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl index 325f13095..32dac412c 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -15,7 +15,6 @@ uniform float3 eyePosWorld; //cubemap arrays require all the same size. so shared mips# value uniform float cubeMips; -#define MAX_PROBES 50 uniform float numProbes; TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4); @@ -32,7 +31,7 @@ uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten uniform float4 probeContribColors[MAX_PROBES]; #endif -TORQUE_UNIFORM_SAMPLERCUBE(skylightPrefilterMap, 6); +TORQUE_UNIFORM_SAMPLERCUBE(skylightSpecularMap, 6); TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7); uniform float hasSkylight; @@ -70,13 +69,13 @@ float4 main(PFXVertToPix IN) : SV_TARGET if (probeConfigData[i].r == 0) //box { - contribution[i] = defineBoxSpaceInfluence(surface, worldToObjArray[i], probeConfigData[i].b); + contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b); if (contribution[i]>0.0) probehits++; } else if (probeConfigData[i].r == 1) //sphere { - contribution[i] = defineSphereSpaceInfluence(surface, inProbePosArray[i].xyz, probeConfigData[i].g); + contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g); if (contribution[i]>0.0) probehits++; } @@ -93,33 +92,33 @@ float4 main(PFXVertToPix IN) : SV_TARGET // and respect constraint A. if (probehits>1.0) - { - for (i = 0; i < numProbes; i++) - { - blendFactor[i] = ((contribution[i] / blendSum)) / probehits; - blendFactor[i] *= ((contribution[i]) / invBlendSum); - blendFactor[i] = saturate(blendFactor[i]); - blendFacSum += blendFactor[i]; - } + { + for (i = 0; i < numProbes; i++) + { + blendFactor[i] = ((contribution[i] / blendSum)) / probehits; + blendFactor[i] *= ((contribution[i]) / invBlendSum); + blendFactor[i] = saturate(blendFactor[i]); + blendFacSum += blendFactor[i]; + } // Normalize blendVal #if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior - if (blendFacSum == 0.0f) // Possible with custom weight - { - blendFacSum = 1.0f; - } + if (blendFacSum == 0.0f) // Possible with custom weight + { + blendFacSum = 1.0f; + } #endif - float invBlendSumWeighted = 1.0f / blendFacSum; - for (i = 0; i < numProbes; ++i) - { - blendFactor[i] *= invBlendSumWeighted; - contribution[i] *= blendFactor[i]; - alpha -= contribution[i]; - } - } - else - alpha -= blendSum; + float invBlendSumWeighted = 1.0f / blendFacSum; + for (i = 0; i < numProbes; ++i) + { + blendFactor[i] *= invBlendSumWeighted; + contribution[i] *= blendFactor[i]; + alpha -= contribution[i]; + } + } + else + alpha -= blendSum; #if DEBUGVIZ_ATTENUATION == 1 float contribAlpha = 1; @@ -164,7 +163,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET if (contrib != 0) { int cubemapIdx = probeConfigData[i].a; - float3 dir = boxProject(surface, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz); + float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz); irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib; specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib; @@ -175,7 +174,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET if (hasSkylight && alpha > 0.001) { irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha; - specular += TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz * alpha; + specular += TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz * alpha; } #if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0