diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 8cda20048..8816ff47e 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -121,12 +121,12 @@ ProbeShaderConstants::ProbeShaderConstants() mShader(NULL), mProbeParamsSC(NULL), mProbePositionSC(NULL), - mProbeRadiusSC(NULL), + mProbeRefPosSC(NULL), mProbeBoxMinSC(NULL), mProbeBoxMaxSC(NULL), - mProbeIsSphereSC(NULL), - mProbeLocalPosSC(NULL), - mProbeCubemapSC(NULL), + mProbeConfigDataSC(NULL), + mProbeSpecularCubemapSC(NULL), + mProbeIrradianceCubemapSC(NULL), mProbeCountSC(NULL) { } @@ -155,14 +155,19 @@ void ProbeShaderConstants::init(GFXShader* shader) //Reflection Probes mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition); - mProbeRadiusSC = shader->getShaderConstHandle(ShaderGenVars::probeRadius); + mProbeRefPosSC = shader->getShaderConstHandle(ShaderGenVars::probeRefPos); mProbeBoxMinSC = shader->getShaderConstHandle(ShaderGenVars::probeBoxMin); mProbeBoxMaxSC = shader->getShaderConstHandle(ShaderGenVars::probeBoxMax); - mProbeIsSphereSC = shader->getShaderConstHandle(ShaderGenVars::probeIsSphere); - mProbeLocalPosSC = shader->getShaderConstHandle(ShaderGenVars::probeLocalPos); - mProbeCubemapSC = shader->getShaderConstHandle(ShaderGenVars::probeCubemap); + mWorldToObjArraySC = shader->getShaderConstHandle(ShaderGenVars::worldToObjArray); + mProbeConfigDataSC = shader->getShaderConstHandle(ShaderGenVars::probeConfigData); + mProbeSpecularCubemapSC = shader->getShaderConstHandle(ShaderGenVars::specularCubemapAR); + mProbeIrradianceCubemapSC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR); mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount); + mSkylightPrefilterMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap); + mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap); + mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight); + mInit = true; } @@ -548,23 +553,18 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, MatrixSet &matSet, - GFXShaderConstHandle *probePositionSC, - GFXShaderConstHandle *probeRadiusSC, - GFXShaderConstHandle *probeBoxMinSC, - GFXShaderConstHandle *probeBoxMaxSC, - GFXShaderConstHandle *probeCubemapSC, - GFXShaderConstHandle *probeIsSphereSC, - GFXShaderConstHandle *probeLocalPosSC, + ProbeShaderConstants *probeShaderConsts, GFXShaderConstBuffer *shaderConsts) { PROFILE_SCOPE(ProbeManager_Update4ProbeConsts); // Skip over gathering lights if we don't have to! - if (probePositionSC->isValid() || - probeRadiusSC->isValid() || - probeBoxMinSC->isValid() || - probeBoxMaxSC->isValid() || - probeCubemapSC->isValid()/* && (!ProbeRenderInst::all.empty())*/) + if (probeShaderConsts->mProbePositionSC->isValid() || + probeShaderConsts->mProbeConfigDataSC->isValid() || + probeShaderConsts->mProbeBoxMinSC->isValid() || + probeShaderConsts->mProbeBoxMaxSC->isValid() || + probeShaderConsts->mProbeSpecularCubemapSC->isValid() || + probeShaderConsts->mProbeIrradianceCubemapSC->isValid()/* && (!ProbeRenderInst::all.empty())*/) { PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes); @@ -606,7 +606,7 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, if (!probe->mIsEnabled) continue; - // The light positions and spot directions are + // The light positions and spot directions are // in SoA order to make optimal use of the GPU. const Point3F &probePos = probe->getPosition(); probePositions[i].x = probePos.x; @@ -643,48 +643,90 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, } }*/ - for (U32 i = 0; i < 4; i++) + //Array rendering + U32 probeCount = ProbeRenderInst::all.size(); + + mEffectiveProbeCount = 0; + mMipCount = 0; + + if (probePositionsData.size() != MAXPROBECOUNT) { - probePositions[i].x = 0; - probePositions[i].y = 0; - probePositions[i].z = 0; - - probeRadius[i] = 0; - - probeBoxMins[i].x = 0; - probeBoxMins[i].y = 0; - probeBoxMins[i].z = 0; - - probeBoxMaxs[i].x = 0; - probeBoxMaxs[i].y = 0; - probeBoxMaxs[i].z = 0; - - probeIsSphere[i] = 0; - - probeLocalPositions[i].x = 0; - probeLocalPositions[i].y = 0; - probeLocalPositions[i].z = 0; - - S32 samplerReg = probeCubemapSC->getSamplerRegister(); - - GFX->setCubeTexture(samplerReg + i, nullptr); + probePositionsData.setSize(MAXPROBECOUNT); + probeRefPositionsData.setSize(MAXPROBECOUNT); + probeWorldToObjData.setSize(MAXPROBECOUNT); + probeBBMinData.setSize(MAXPROBECOUNT); + probeBBMaxData.setSize(MAXPROBECOUNT); + probeConfigData.setSize(MAXPROBECOUNT); } - shaderConsts->setSafe(probePositionSC, probePositions); - shaderConsts->setSafe(probeRadiusSC, probeRadius); - shaderConsts->setSafe(probeBoxMinSC, probeBoxMins); - shaderConsts->setSafe(probeBoxMaxSC, probeBoxMaxs); - shaderConsts->setSafe(probeLocalPosSC, probeLocalPositions); - shaderConsts->setSafe(probeIsSphereSC, probeIsSphere); + probePositionsData.fill(Point4F::Zero); + probeRefPositionsData.fill(Point4F::Zero); + probeWorldToObjData.fill(MatrixF::Identity); + probeBBMinData.fill(Point4F::Zero); + probeBBMaxData.fill(Point4F::Zero); + probeConfigData.fill(Point4F::Zero); + + cubeMaps.clear(); + irradMaps.clear(); + Vector cubemapIdxes; + + U32 effectiveProbeCount = 0; + bool hasSkylight = false; + for (U32 i = 0; i < probeCount; i++) + { + if (effectiveProbeCount >= 4) + break; + + const ProbeRenderInst& curEntry = *ProbeRenderInst::all[i]; + if (!curEntry.mIsEnabled) + continue; + + if (curEntry.mIsSkylight) + { + GFX->setCubeTexture(probeShaderConsts->mSkylightPrefilterMap->getSamplerRegister(), curEntry.mPrefilterCubemap); + GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap); + + shaderConsts->setSafe(probeShaderConsts->mHasSkylight, true); + hasSkylight = true; + continue; + } + + //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++; + } + + if (!hasSkylight) + shaderConsts->setSafe(probeShaderConsts->mHasSkylight, false); } - else + /*else { if (probeCubemapSC->isValid()) { for (U32 i = 0; i < 4; ++i) GFX->setCubeTexture(probeCubemapSC->getSamplerRegister() + i, NULL); } - } + }*/ } void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat, @@ -717,16 +759,7 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat, MatrixSet matSet = state->getRenderPass()->getMatrixSet(); // Update the forward shading light constants. - _update4ProbeConsts(sgData, - matSet, - psc->mProbePositionSC, - psc->mProbeRadiusSC, - psc->mProbeBoxMinSC, - psc->mProbeBoxMaxSC, - psc->mProbeCubemapSC, - psc->mProbeIsSphereSC, - psc->mProbeLocalPosSC, - shaderConsts); + _update4ProbeConsts(sgData, matSet, psc, shaderConsts); } //----------------------------------------------------------------------------- diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index 264e4d05c..0a2b32d84 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -136,14 +136,19 @@ struct ProbeShaderConstants //Reflection Probes GFXShaderConstHandle *mProbePositionSC; - GFXShaderConstHandle *mProbeRadiusSC; + GFXShaderConstHandle *mProbeRefPosSC; GFXShaderConstHandle *mProbeBoxMinSC; GFXShaderConstHandle *mProbeBoxMaxSC; - GFXShaderConstHandle *mProbeIsSphereSC; - GFXShaderConstHandle *mProbeLocalPosSC; - GFXShaderConstHandle *mProbeCubemapSC; + GFXShaderConstHandle *mWorldToObjArraySC; + GFXShaderConstHandle *mProbeConfigDataSC; + GFXShaderConstHandle *mProbeSpecularCubemapSC; + GFXShaderConstHandle *mProbeIrradianceCubemapSC; GFXShaderConstHandle *mProbeCountSC; + GFXShaderConstHandle *mSkylightPrefilterMap; + GFXShaderConstHandle *mSkylightIrradMap; + GFXShaderConstHandle *mHasSkylight; + ProbeShaderConstants(); ~ProbeShaderConstants(); @@ -239,13 +244,7 @@ protected: /// for the stock 4 light forward lighting code. void _update4ProbeConsts(const SceneData &sgData, MatrixSet &matSet, - GFXShaderConstHandle *probePositionSC, - GFXShaderConstHandle *probeRadiusSC, - GFXShaderConstHandle *probeBoxMinSC, - GFXShaderConstHandle *probeBoxMaxSC, - GFXShaderConstHandle *probeCubemapSC, - GFXShaderConstHandle *probeIsSphereSC, - GFXShaderConstHandle *probeLocalPosSC, + ProbeShaderConstants *probeShaderConsts, GFXShaderConstBuffer *shaderConsts); void _setupStaticParameters(); diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index bdad37a4c..745d9e516 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -3010,52 +3010,57 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget)); //Reflection Probe WIP - Var *inProbePos = new Var("inProbePos", "float3"); + Var *inProbePos = new Var("inProbePosArray", "float4"); inProbePos->arraySize = 4; inProbePos->uniform = true; inProbePos->constSortPos = cspPotentialPrimitive; - Var *inProbeRadius = new Var("inProbeRadius", "float"); + Var *inProbeRadius = new Var("inRefPosArray", "float4"); inProbeRadius->arraySize = 4; inProbeRadius->uniform = true; inProbeRadius->constSortPos = cspPotentialPrimitive; - Var *inProbeBoxMin = new Var("inProbeBoxMin", "float3"); + Var *inProbeBoxMin = new Var("inProbeBoxMin", "float4"); inProbeBoxMin->arraySize = 4; inProbeBoxMin->uniform = true; inProbeBoxMin->constSortPos = cspPotentialPrimitive; - Var *inProbeBoxMax = new Var("inProbeBoxMax", "float3"); + Var *inProbeBoxMax = new Var("inProbeBoxMax", "float4"); inProbeBoxMax->arraySize = 4; inProbeBoxMax->uniform = true; inProbeBoxMax->constSortPos = cspPotentialPrimitive; - Var *inProbeIsSphere = new Var("inProbeIsSphere", "float"); + Var *inProbeIsSphere = new Var("probeConfigData", "float4"); inProbeIsSphere->arraySize = 4; inProbeIsSphere->uniform = true; inProbeIsSphere->constSortPos = cspPotentialPrimitive; - Var *inProbeLocalPos = new Var("inProbeLocalPos", "float3"); - inProbeLocalPos->arraySize = 4; - inProbeLocalPos->uniform = true; - inProbeLocalPos->constSortPos = cspPotentialPrimitive; + Var *worldToObjArray = new Var("worldToObjArray", "float4x4"); + worldToObjArray->arraySize = 4; + worldToObjArray->uniform = true; + worldToObjArray->constSortPos = cspPotentialPrimitive; - Var *inProbeCubemap = new Var("inProbeCubemap", "SamplerState"); - //inProbeCubemap->arraySize = 4; - inProbeCubemap->uniform = true; - inProbeCubemap->sampler = true; - inProbeCubemap->constNum = Var::getTexUnitNum(); // used as texture unit num here + Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState"); + specularCubemapAR->uniform = true; + specularCubemapAR->sampler = true; + specularCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here - Var *inProbeCubemapTex = new Var("inProbeCubemapTex", "TextureCube"); - //inProbeCubemapTex->arraySize = 4; - inProbeCubemapTex->uniform = true; - inProbeCubemapTex->texture = true; - inProbeCubemapTex->constNum = inProbeCubemap->constNum; + Var *specularCubemapARTex = new Var("specularCubemapARTex", "TextureCubeArray"); + specularCubemapARTex->uniform = true; + specularCubemapARTex->texture = true; + specularCubemapARTex->constNum = specularCubemapAR->constNum; - //Var *nDotL = new Var("nDotL", "float3"); - //meta->addStatement(new GenOp(" @ = abs(dot(@,@);\r\n", new DecOp(nDotL), wsView, wsNormal)); + Var *irradianceCubemapAR = new Var("irradianceCubemapAR", "SamplerState"); + irradianceCubemapAR->uniform = true; + irradianceCubemapAR->sampler = true; + irradianceCubemapAR->constNum = Var::getTexUnitNum(); // used as texture unit num here - Var *probeVec = new Var("probeVec", "float3"); + Var *irradianceCubemapARTex = new Var("irradianceCubemapARTex", "TextureCubeArray"); + irradianceCubemapARTex->uniform = true; + irradianceCubemapARTex->texture = true; + irradianceCubemapARTex->constNum = specularCubemapAR->constNum; + + /*Var *probeVec = new Var("probeVec", "float3"); meta->addStatement(new GenOp(" @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition)); Var *nDotL = new Var("nDotL", "float"); @@ -3087,7 +3092,7 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList meta->addStatement(new GenOp("/* if (dot( @, @ ) < 0.0f)\r\n", probeVec, wsNormal)); - meta->addStatement(new GenOp(" clip(@); */\r\n", fa)); + meta->addStatement(new GenOp(" clip(@); *//*\r\n", fa)); meta->addStatement(new GenOp(" \r\n")); @@ -3130,7 +3135,9 @@ void ReflectionProbeFeatHLSL::processPix(Vector &componentList else { 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)); output = meta; } diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index 90e08739f..4b3ae3ef2 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/Engine/source/shaderGen/shaderGenVars.cpp @@ -70,15 +70,21 @@ const String ShaderGenVars::smoothness("$smoothness"); const String ShaderGenVars::metalness("$metalness"); //Reflection Probes -const String ShaderGenVars::probePosition("$inProbePos"); -const String ShaderGenVars::probeRadius("$inProbeRadius"); +const String ShaderGenVars::probePosition("$inProbePosArray"); +const String ShaderGenVars::probeRefPos("$inRefPosArray"); const String ShaderGenVars::probeBoxMin("$inProbeBoxMin"); const String ShaderGenVars::probeBoxMax("$inProbeBoxMax"); -const String ShaderGenVars::probeLocalPos("$inProbeLocalPos"); -const String ShaderGenVars::probeIsSphere("$inProbeIsSphere"); -const String ShaderGenVars::probeCubemap("$inProbeCubemap"); +const String ShaderGenVars::worldToObjArray("$worldToObjArray"); +const String ShaderGenVars::probeConfigData("$probeConfigData"); +const String ShaderGenVars::specularCubemapAR("$specularCubemapAR"); +const String ShaderGenVars::irradianceCubemapAR("$irradianceCubemapAR"); const String ShaderGenVars::probeCount("$numProbes"); +//Skylight +const String ShaderGenVars::skylightPrefilterMap("$skylightPrefilterMap"); +const String ShaderGenVars::skylightIrradMap("$skylightIrradMap"); +const String ShaderGenVars::hasSkylight("$hasSkylight"); + // These are ignored by the D3D layers. const String ShaderGenVars::fogMap("$fogMap"); const String ShaderGenVars::dlightMap("$dlightMap"); diff --git a/Engine/source/shaderGen/shaderGenVars.h b/Engine/source/shaderGen/shaderGenVars.h index f35e81aab..fc64b5e3f 100644 --- a/Engine/source/shaderGen/shaderGenVars.h +++ b/Engine/source/shaderGen/shaderGenVars.h @@ -84,13 +84,19 @@ struct ShaderGenVars //Reflection Probes const static String probePosition; - const static String probeRadius; + const static String probeRefPos; const static String probeBoxMin; const static String probeBoxMax; - const static String probeLocalPos; - const static String probeIsSphere; - const static String probeCubemap; + const static String worldToObjArray; + const static String probeConfigData; + const static String specularCubemapAR; + const static String irradianceCubemapAR; const static String probeCount; + + //Skylight + const static String skylightPrefilterMap; + const static String skylightIrradMap; + const static String hasSkylight; // Textures const static String fogMap; diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index 6e6da4cb8..debbc7f1f 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -237,3 +237,42 @@ inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLi } //Probe IBL stuff +float defineSphereSpaceInfluence(Surface surface, float3 wsProbePosition, float radius) +{ + float3 L = wsProbePosition.xyz - surface.P; + float contribution = 1.0 - length(L) / radius; + return contribution; +} + +float getDistBoxToPoint(float3 pt, float3 extents) +{ + float3 d = max(max(-extents - pt, 0), pt - extents); + return max(max(d.x, d.y), d.z); +} + +float defineBoxSpaceInfluence(Surface surface, float4x4 worldToObj, float attenuation) +{ + float3 surfPosLS = mul(worldToObj, float4(surface.P, 1.0)).xyz; + float atten = 1.0 - attenuation; + float baseVal = 0.25; + float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal)); + return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist)); +} + +// 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 RayLS = mul(worldToObj, float4(surface.R, 0.0)).xyz; + float3 PositionLS = mul(worldToObj, float4(surface.P, 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; + + return posonbox - refPosition.xyz; +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl index ed7c330c8..325f13095 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -18,7 +18,7 @@ uniform float cubeMips; #define MAX_PROBES 50 uniform float numProbes; -TORQUE_UNIFORM_SAMPLERCUBEARRAY(cubeMapAR, 4); +TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4); TORQUE_UNIFORM_SAMPLERCUBEARRAY(irradianceCubemapAR, 5); uniform float4 inProbePosArray[MAX_PROBES]; @@ -36,95 +36,6 @@ TORQUE_UNIFORM_SAMPLERCUBE(skylightPrefilterMap, 6); TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7); uniform float hasSkylight; -//Probe IBL stuff -float defineSphereSpaceInfluence(Surface surface, int ID) -{ - float3 L = inProbePosArray[ID].xyz.xyz - surface.P; - float contribution = 1.0 - length(L) / probeConfigData[ID].g; - return contribution; -} - -float getDistBoxToPoint(float3 pt, float3 extents) -{ - float3 d = max(max(-extents - pt, 0), pt - extents); - return max(max(d.x, d.y), d.z); -} - -float defineBoxSpaceInfluence(Surface surface, int ID) -{ - float3 surfPosLS = mul(worldToObjArray[ID], float4(surface.P, 1.0)).xyz; - float atten = 1.0-probeConfigData[ID].b; - float baseVal = 0.25; - float dist = getDistBoxToPoint(surfPosLS,float3(baseVal,baseVal,baseVal)); - return saturate(smoothstep(baseVal+0.0001,atten*baseVal,dist)); -} - -// 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, int ID) -{ - float3 RayLS = mul(worldToObjArray[ID], float4(surface.R, 0.0)).xyz; - float3 PositionLS = mul(worldToObjArray[ID], float4(surface.P, 1.0)).xyz; - - float3 unit = bbMaxArray[ID].xyz - bbMinArray[ID].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; - - return posonbox - inRefPosArray[ID].xyz; -} - -float3 iblBoxDiffuse(Surface surface, int ID) -{ - float3 dir = boxProject(surface, ID); - - float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probeConfigData[ID].a, 0).xyz; - return color; -} - -float3 iblBoxSpecular(Surface surface, int ID) -{ - // BRDF - //float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy; - - float3 dir = boxProject(surface, ID); - - // 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, probeConfigData[ID].a, lod).xyz; - return color; -} - -float3 iblSkylightDiffuse(Surface surface) -{ - float3 color = TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz; - return color; -} - -float3 iblSkylightSpecular(Surface surface) -{ - // BRDF - //float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy; - - // Radiance (Specular) -#if DEBUGVIZ_SPECCUBEMAP == 0 - float lod = surface.roughness*cubeMips; -#elif DEBUGVIZ_SPECCUBEMAP == 1 - float lod = 0; -#endif - - float3 color = TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz; - return color; -} - float4 main(PFXVertToPix IN) : SV_TARGET { //unpack normal and linear depth @@ -159,13 +70,13 @@ float4 main(PFXVertToPix IN) : SV_TARGET if (probeConfigData[i].r == 0) //box { - contribution[i] = defineBoxSpaceInfluence(surface, i); + contribution[i] = defineBoxSpaceInfluence(surface, worldToObjArray[i], probeConfigData[i].b); if (contribution[i]>0.0) probehits++; } else if (probeConfigData[i].r == 1) //sphere { - contribution[i] = defineSphereSpaceInfluence(surface, i); + contribution[i] = defineSphereSpaceInfluence(surface, inProbePosArray[i].xyz, probeConfigData[i].g); if (contribution[i]>0.0) probehits++; } @@ -211,49 +122,68 @@ float4 main(PFXVertToPix IN) : SV_TARGET alpha -= blendSum; #if DEBUGVIZ_ATTENUATION == 1 - float attenVis = 0; - for (i = 0; i < numProbes; ++i) - { - attenVis += contribution[i]; - } + float contribAlpha = 1; + for (i = 0; i < numProbes; ++i) + { + contribAlpha -= contribution[i]; + } - //return float4(attenVis, attenVis, attenVis, 1); - return float4(blendSum, blendSum, blendSum, 1); + return float4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1); #endif #if DEBUGVIZ_CONTRIB == 1 float3 finalContribColor = float3(0, 0, 0); + float contribAlpha = 1; for (i = 0; i < numProbes; ++i) { finalContribColor += contribution[i] *probeContribColors[i].rgb; + contribAlpha -= contribution[i]; } + //Skylight coloration for anything not covered by probes above + finalContribColor += float3(0.3, 0.3, 0.3) * contribAlpha; + return float4(finalContribColor, 1); #endif } -#if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0 - float3 irradiance = float3(0, 0, 0); float3 specular = float3(0, 0, 0); - float contrib = 0; + // Radiance (Specular) +#if DEBUGVIZ_SPECCUBEMAP == 0 + float lod = surface.roughness*cubeMips; +#elif DEBUGVIZ_SPECCUBEMAP == 1 + float lod = 0; +#endif + + alpha = 1; for (i = 0; i < numProbes; ++i) { - if (contribution[i] == 0) - continue; + float contrib = contribution[i]; + if (contrib != 0) + { + int cubemapIdx = probeConfigData[i].a; + float3 dir = boxProject(surface, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz); - irradiance += iblBoxDiffuse(surface, i) * contribution[i]; - specular += iblBoxSpecular(surface, i) * contribution[i]; - contrib +=contribution[i]; + irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib; + specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib; + alpha -= contrib; + } } - - if (hasSkylight && alpha != 0) + + if (hasSkylight && alpha > 0.001) { - irradiance = lerp(irradiance, iblSkylightDiffuse(surface), alpha); - specular = lerp(specular, iblSkylightSpecular(surface), alpha); + irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha; + specular += TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz * alpha; } +#if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0 + return float4(specular, 1); +#elif DEBUGVIZ_DIFFCUBEMAP == 1 + return float4(irradiance, 1); +#endif + float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness); //energy conservation @@ -263,47 +193,11 @@ float4 main(PFXVertToPix IN) : SV_TARGET //apply brdf //Do it once to save on texture samples float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy; - specular *= (brdf.x + brdf.y)* F; + 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); return finalColor; - -#elif DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0 - - float3 cubeColor = float3(0, 0, 0); - for (i = 0; i < numProbes; ++i) - { - if (probeConfigData[i].r == 2) //skylight - { - cubeColor += iblSkylightSpecular(surface, i); - } - else - { - cubeColor += iblBoxSpecular(surface, i); - } - } - - return float4(cubeColor, 1); - -#elif DEBUGVIZ_DIFFCUBEMAP == 1 - - float3 cubeColor = float3(0, 0, 0); - for (i = 0; i < numProbes; ++i) - { - if (probeConfigData[i].r == 2) //skylight - { - cubeColor += iblSkylightDiffuse(surface); - } - else - { - cubeColor += iblBoxDiffuse(surface); - } - } - - return float4(cubeColor, 1); - -#endif } diff --git a/Templates/Full/game/shaders/common/shaderModel.hlsl b/Templates/Full/game/shaders/common/shaderModel.hlsl index b805e5b72..d3fcd946a 100644 --- a/Templates/Full/game/shaders/common/shaderModel.hlsl +++ b/Templates/Full/game/shaders/common/shaderModel.hlsl @@ -66,6 +66,8 @@ //Cube #define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex #define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex +#define TORQUE_SAMPLERCUBEARRAY(tex) TextureCubeArray texture_##tex, SamplerState tex +#define TORQUE_SAMPLERCUBEARRAY_MAKEARG(tex) texture_##tex, tex #endif // _TORQUE_SHADERMODEL_