diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index 415b70d5d..ae5793c77 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -638,210 +638,162 @@ void RenderProbeMgr::render( SceneRenderState *state ) ReflectProbeMaterialInfo* reflProbeMat = getReflectProbeMaterial(); - /*for (U32 i = 0; i < ProbeRenderInst::all.size(); i++) - { - ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; + if (reflProbeMat == nullptr || reflProbeMat->matInstance == nullptr) + return; - if (!curEntry->mIsEnabled) - continue; + MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters(); - if (curEntry->numPrims == 0) - continue; + MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes"); - if (curEntry->mIsSkylight && (!skylightMat || !skylightMat->matInstance)) - continue; - - if (!curEntry->mIsSkylight && (!reflProbeMat || !reflProbeMat->matInstance)) - break; - - if (curEntry->mIsSkylight) - { - //Setup - MatrixF probeTrans = curEntry->getTransform(); - - // Set geometry - GFX->setVertexBuffer(curEntry->vertBuffer); - GFX->setPrimitiveBuffer(curEntry->primBuffer); - probeTrans.scale(10); //force it to be big enough to surround the camera - sgData.objTrans = &probeTrans; - skylightMat->setProbeParameters(curEntry, state, worldToCameraXfm); - - while (skylightMat->matInstance->setupPass(state, sgData)) - { - // Set transforms - matrixSet.setWorld(*sgData.objTrans); - skylightMat->matInstance->setTransforms(matrixSet, state); - skylightMat->matInstance->setSceneInfo(state, sgData); - - GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims); - } - } - }*/ + MaterialParameterHandle *probePositionSC = reflProbeMat->matInstance->getMaterialParameterHandle("$inProbePosArray"); + MaterialParameterHandle *probeWorldToObjSC = reflProbeMat->matInstance->getMaterialParameterHandle("$worldToObjArray"); + MaterialParameterHandle *probeBBMinSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMinArray"); + MaterialParameterHandle *probeBBMaxSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMaxArray"); + MaterialParameterHandle *probeUseSphereModeSC = reflProbeMat->matInstance->getMaterialParameterHandle("$useSphereMode"); + MaterialParameterHandle *probeRadiusSC = reflProbeMat->matInstance->getMaterialParameterHandle("$radius"); + MaterialParameterHandle *probeAttenuationSC = reflProbeMat->matInstance->getMaterialParameterHandle("$attenuation"); //Array rendering - static U32 MAXPROBECOUNT = 1;// 50; + static U32 MAXPROBECOUNT = 50; U32 probeCount = ProbeRenderInst::all.size(); - if (probeCount != 0) + MatrixF trans = MatrixF::Identity; + sgData.objTrans = &trans; + + Vector probePositions; + Vector probeWorldToObj; + Vector probeBBMin; + Vector probeBBMax; + Vector probeUseSphereMode; + Vector probeRadius; + Vector probeAttenuation; + + probePositions.setSize(MAXPROBECOUNT); + probeWorldToObj.setSize(MAXPROBECOUNT); + probeBBMin.setSize(MAXPROBECOUNT); + probeBBMax.setSize(MAXPROBECOUNT); + probeUseSphereMode.setSize(MAXPROBECOUNT); + probeRadius.setSize(MAXPROBECOUNT); + probeAttenuation.setSize(MAXPROBECOUNT); + + //Vector cubeMaps; + //Vector irradMaps; + + U32 effectiveProbeCount = 0; + + for (U32 i = 0; i < probeCount; i++) { - MatrixF trans = MatrixF::Identity; - sgData.objTrans = &trans; + if (effectiveProbeCount >= MAXPROBECOUNT) + break; - /*AlignedArray probePositions(MAXPROBECOUNT, sizeof(Point3F)); - Vector probeWorldToObj; - AlignedArray probeBBMin(MAXPROBECOUNT, sizeof(Point3F)); - AlignedArray probeBBMax(MAXPROBECOUNT, sizeof(Point3F)); - AlignedArray probeUseSphereMode(MAXPROBECOUNT, sizeof(float)); - AlignedArray probeRadius(MAXPROBECOUNT, sizeof(float)); - AlignedArray probeAttenuation(MAXPROBECOUNT, sizeof(float)); + ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; + if (!curEntry->mIsEnabled) + continue; - dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize()); - probeWorldToObj.setSize(MAXPROBECOUNT); - dMemset(probeBBMin.getBuffer(), 0, probeBBMin.getBufferSize()); - dMemset(probeBBMax.getBuffer(), 0, probeBBMax.getBufferSize()); - dMemset(probeUseSphereMode.getBuffer(), 0, probeUseSphereMode.getBufferSize()); - dMemset(probeRadius.getBuffer(), 0, probeRadius.getBufferSize()); - dMemset(probeAttenuation.getBuffer(), 0, probeAttenuation.getBufferSize()); + if (curEntry->mCubemap.isNull() || curEntry->mIrradianceCubemap.isNull()) + continue; - Vector cubeMaps; - Vector irradMaps;*/ + if (!curEntry->mCubemap->isInitialised()) + continue; - if (reflProbeMat && reflProbeMat->matInstance) + //Setup + const Point3F &probePos = curEntry->getPosition(); + probePositions[i] = probePos + curEntry->mProbePosOffset; + + MatrixF trans = curEntry->getTransform(); + trans.inverse(); + + probeWorldToObj[i] = trans; + + probeBBMin[i] = curEntry->mBounds.minExtents; + probeBBMax[i] = curEntry->mBounds.maxExtents; + + probeUseSphereMode[i] = curEntry->mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0; + + probeRadius[i] = curEntry->mRadius; + probeAttenuation[i] = 1; + + //cubeMaps.push_back(curEntry->mCubemap); + //irradMaps.push_back(curEntry->mIrradianceCubemap); + + effectiveProbeCount++; + } + + if (effectiveProbeCount != 0) + { + matParams->setSafe(numProbesSC, (float)effectiveProbeCount); + + /*GFXCubemapArrayHandle mCubemapArray; + mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); + + GFXCubemapArrayHandle mIrradArray; + mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); + + mCubemapArray->initStatic(cubeMaps.address(), cubeMaps.size()); + mIrradArray->initStatic(irradMaps.address(), irradMaps.size());*/ + + NamedTexTarget *deferredTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName); + if (deferredTarget) + GFX->setTexture(0, deferredTarget->getTexture()); + else + GFX->setTexture(0, NULL); + + NamedTexTarget *colorTarget = NamedTexTarget::find(RenderDeferredMgr::ColorBufferName); + if (colorTarget) + GFX->setTexture(1, colorTarget->getTexture()); + else + GFX->setTexture(1, NULL); + + NamedTexTarget *matinfoTarget = NamedTexTarget::find(RenderDeferredMgr::MatInfoBufferName); + if (matinfoTarget) + GFX->setTexture(2, matinfoTarget->getTexture()); + else + GFX->setTexture(2, NULL); + + if (mBrdfTexture) { - MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters(); + GFX->setTexture(3, mBrdfTexture); + } + else + GFX->setTexture(3, NULL); - MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes"); + //GFX->setCubeArrayTexture(4, mCubemapArray); + //GFX->setCubeArrayTexture(5, mIrradArray); - MaterialParameterHandle *probePositionSC = reflProbeMat->matInstance->getMaterialParameterHandle("$inProbePosArray"); - MaterialParameterHandle *probeWorldToObjSC = reflProbeMat->matInstance->getMaterialParameterHandle("$worldToObjArray"); - MaterialParameterHandle *probeBBMinSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMinArray"); - MaterialParameterHandle *probeBBMaxSC = reflProbeMat->matInstance->getMaterialParameterHandle("$bbMaxArray"); - MaterialParameterHandle *probeUseSphereModeSC = reflProbeMat->matInstance->getMaterialParameterHandle("$useSphereMode"); - MaterialParameterHandle *probeRadiusSC = reflProbeMat->matInstance->getMaterialParameterHandle("$radius"); - MaterialParameterHandle *probeAttenuationSC = reflProbeMat->matInstance->getMaterialParameterHandle("$attenuation"); - - /*U32 effectiveProbeCount = 0; + ProbeRenderInst* curEntry = ProbeRenderInst::all[0]; - for (U32 i = 0; i < probeCount; i++) - { - if (effectiveProbeCount >= MAXPROBECOUNT) - break; + GFX->setCubeTexture(4, curEntry->mCubemap); + GFX->setCubeTexture(5, curEntry->mIrradianceCubemap); - ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; - if (!curEntry->mIsEnabled) - continue; + //Final packing + AlignedArray _probePositions(probePositions.size(), sizeof(Point4F), (U8*)probePositions.address(), false); + AlignedArray _probeBBMin(probeBBMin.size(), sizeof(Point4F), (U8*)probeBBMin.address(), false); + AlignedArray _probeBBMax(probeBBMax.size(), sizeof(Point4F), (U8*)probeBBMax.address(), false); + AlignedArray _probeUseSphereMode(probeUseSphereMode.size(), sizeof(float), (U8*)probeUseSphereMode.address(), false); + AlignedArray _probeRadius(probeRadius.size(), sizeof(float), (U8*)probeRadius.address(), false); + AlignedArray _probeAttenuation(probeAttenuation.size(), sizeof(float), (U8*)probeAttenuation.address(), false); - if (curEntry->mCubemap.isNull() || curEntry->mIrradianceCubemap.isNull()) - continue; + matParams->set(probePositionSC, _probePositions); + matParams->set(probeWorldToObjSC, probeWorldToObj.address(), probeWorldToObj.size()); + matParams->set(probeBBMinSC, _probeBBMin); + matParams->set(probeBBMaxSC, _probeBBMax); + matParams->set(probeUseSphereModeSC, _probeUseSphereMode); + matParams->set(probeRadiusSC, _probeRadius); + matParams->set(probeAttenuationSC, _probeAttenuation); - if (!curEntry->mCubemap->isInitialised()) - continue; + // Set geometry + GFX->setVertexBuffer(mFarFrustumQuadVerts); + GFX->setPrimitiveBuffer(NULL); + while (reflProbeMat->matInstance->setupPass(state, sgData)) + { + // Set transforms + matrixSet.setWorld(*sgData.objTrans); + reflProbeMat->matInstance->setTransforms(matrixSet, state); + reflProbeMat->matInstance->setSceneInfo(state, sgData); - //Setup - const Point3F &probePos = curEntry->getPosition(); - probePositions[i] = probePos + curEntry->mProbePosOffset; - - MatrixF trans = curEntry->getTransform(); - trans.inverse(); - - probeWorldToObj[i] = trans; - - probeBBMin[i] = curEntry->mBounds.minExtents; - probeBBMax[i] = curEntry->mBounds.maxExtents; - - probeUseSphereMode[i] = curEntry->mProbeShapeType == ProbeRenderInst::Sphere ? 1 : 0; - - probeRadius[i] = curEntry->mRadius; - probeAttenuation[i] = 1; - - cubeMaps.push_back(curEntry->mCubemap); - irradMaps.push_back(curEntry->mIrradianceCubemap); - - effectiveProbeCount++; - } - - if (effectiveProbeCount != 0) - {*/ - //matParams->setSafe(numProbesSC, (float)effectiveProbeCount); - - /*GFXCubemapArrayHandle mCubemapArray; - mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); - - GFXCubemapArrayHandle mIrradArray; - mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); - - mCubemapArray->initStatic(cubeMaps.address(), cubeMaps.size()); - mIrradArray->initStatic(irradMaps.address(), irradMaps.size());*/ - - NamedTexTarget *deferredTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName); - if (deferredTarget) - GFX->setTexture(0, deferredTarget->getTexture()); - else - GFX->setTexture(0, NULL); - - NamedTexTarget *colorTarget = NamedTexTarget::find(RenderDeferredMgr::ColorBufferName); - if (colorTarget) - GFX->setTexture(1, colorTarget->getTexture()); - else - GFX->setTexture(1, NULL); - - NamedTexTarget *matinfoTarget = NamedTexTarget::find(RenderDeferredMgr::MatInfoBufferName); - if (matinfoTarget) - GFX->setTexture(2, matinfoTarget->getTexture()); - else - GFX->setTexture(2, NULL); - - if (mBrdfTexture) - { - GFX->setTexture(3, mBrdfTexture); - } - else - GFX->setTexture(3, NULL); - - - //GFX->setCubeArrayTexture(4, mCubemapArray); - //GFX->setCubeArrayTexture(5, mIrradArray); - - ProbeRenderInst* curEntry = ProbeRenderInst::all[0]; - - Point3F probePosition = curEntry->getPosition(); - - MatrixF probeWorldToObj = curEntry->getTransform(); - probeWorldToObj.inverse(); - - Point3F probeBBMin = curEntry->mBounds.minExtents; - Point3F probeBBMax = curEntry->mBounds.maxExtents; - float probeUseSphereMode = 0; - float probeRadius = curEntry->mRadius; - float probeAttenuation = 1; - - GFX->setCubeTexture(4, curEntry->mCubemap); - GFX->setCubeTexture(5, curEntry->mIrradianceCubemap); - - matParams->set(probePositionSC, probePosition); - matParams->set(probeWorldToObjSC, probeWorldToObj); - matParams->set(probeBBMinSC, probeBBMin); - matParams->set(probeBBMaxSC, probeBBMax); - matParams->set(probeUseSphereModeSC, probeUseSphereMode); - matParams->set(probeRadiusSC, probeRadius); - matParams->set(probeAttenuationSC, probeAttenuation); - - // Set geometry - GFX->setVertexBuffer(mFarFrustumQuadVerts); - GFX->setPrimitiveBuffer(NULL); - - while (reflProbeMat->matInstance->setupPass(state, sgData)) - { - // Set transforms - matrixSet.setWorld(*sgData.objTrans); - reflProbeMat->matInstance->setTransforms(matrixSet, state); - reflProbeMat->matInstance->setSceneInfo(state, sgData); - - GFX->drawPrimitive(GFXTriangleStrip, 0, 2); - } - //} + GFX->drawPrimitive(GFXTriangleStrip, 0, 2); } } // diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl index d6ea44aac..054a4e08e 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -16,18 +16,18 @@ uniform float3 eyePosWorld; //cubemap arrays require all the same size. so shared mips# value uniform float cubeMips; -#define MAX_PROBES 1 //50 +#define MAX_PROBES 50 uniform float numProbes; TORQUE_UNIFORM_SAMPLERCUBE(cubeMapAR, 4); TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemapAR, 5); -uniform float3 inProbePosArray; -uniform float4x4 worldToObjArray; -uniform float3 bbMinArray; -uniform float3 bbMaxArray; -uniform float useSphereMode; -uniform float radius; -uniform float2 attenuation; +uniform float4 inProbePosArray[MAX_PROBES]; +uniform float4x4 worldToObjArray[MAX_PROBES]; +uniform float4 bbMinArray[MAX_PROBES]; +uniform float4 bbMaxArray[MAX_PROBES]; +uniform float useSphereMode[MAX_PROBES]; +uniform float radius[MAX_PROBES]; +uniform float2 attenuation[MAX_PROBES]; // Box Projected IBL Lighting // Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/ @@ -46,14 +46,14 @@ float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 return posonbox - boxWSPos; } -float3 iblBoxDiffuse( Surface surface) +float3 iblBoxDiffuse( Surface surface, int id) { - float3 cubeN = boxProject(surface.P, surface.N, inProbePosArray, bbMinArray, bbMaxArray); + float3 cubeN = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz); cubeN.z *=-1; return TORQUE_TEXCUBELOD(irradianceCubemapAR,float4(cubeN,0)).xyz; } -float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTexture)) +float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTexture), int id) { float ndotv = clamp(dot(surface.N, surfToEye), 0.0, 1.0); @@ -64,20 +64,20 @@ float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTe float lod = surface.roughness*cubeMips; float3 r = reflect(surfToEye, surface.N); float3 cubeR = normalize(r); - cubeR = boxProject(surface.P, surface.N, inProbePosArray, bbMinArray, bbMaxArray); + cubeR = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz); float3 radiance = TORQUE_TEXCUBELOD(cubeMapAR,float4(cubeR,lod)).xyz * (brdf.x + brdf.y); return radiance; } -float defineBoxSpaceInfluence(Surface surface) +float defineBoxSpaceInfluence(Surface surface, int id) { float tempAttenVal = 3.5; //replace with per probe atten - float3 surfPosLS = mul( worldToObjArray, float4(surface.P,1.0)).xyz; + float3 surfPosLS = mul( worldToObjArray[id], float4(surface.P,1.0)).xyz; - float3 boxMinLS = inProbePosArray-(float3(1,1,1)*radius); - float3 boxMaxLS = inProbePosArray+(float3(1,1,1)*radius); + float3 boxMinLS = inProbePosArray[id].xyz-(float3(1,1,1)*radius[0]); + float3 boxMaxLS = inProbePosArray[id].xyz+(float3(1,1,1)*radius[0]); float boxOuterRange = length(boxMaxLS - boxMinLS); float boxInnerRange = boxOuterRange / tempAttenVal; @@ -102,62 +102,52 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET { discard; } - float blendVal; + + float blendVal[MAX_PROBES]; float3 surfToEye = normalize(surface.P - eyePosWorld); - int i; - float blendSum = 0; - float invBlendSum = 0; + int i = 0; + float blendSum = 0; + float invBlendSum = 0; - /*for(i=0; i < numProbes; i++) + for(i=0; i < numProbes; i++) { - float3 probeWS = inProbePosArray[i]; + float3 probeWS = inProbePosArray[i].xyz; float3 L = probeWS - surface.P; - if(useSphereMode[i]) + /*if(useSphereMode[i]) { - float3 L = inProbePosArray[i] - surface.P; + float3 L = inProbePosArray[i].xyz - surface.P; blendVal[i] = 1.0-length(L)/radius[i]; blendVal[i] = max(0,blendVal[i]); } else - { + {*/ blendVal[i] = defineBoxSpaceInfluence(surface, i); blendVal[i] = max(0,blendVal[i]); - } + //} blendSum += blendVal[i]; invBlendSum +=(1.0f - blendVal[i]); - }*/ - - if(useSphereMode) - { - float3 L = inProbePosArray - surface.P; - blendVal = 1.0-length(L)/radius; - blendVal = max(0,blendVal); - } - else - { - blendVal = defineBoxSpaceInfluence(surface); - blendVal = max(0,blendVal); - } + } // Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary. // And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1). // respect constraint B. // Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary // and respect constraint A. - /*for(i=0; i < numProbes; i++) + for(i=0; i < numProbes; i++) { blendVal[i] = (1.0f - ( blendVal[i] / blendSum)) / (numProbes - 1); blendVal[i] *= ((1.0f - blendVal[i]) / invBlendSum); blendSum += blendVal[i]; - }*/ + } - //float asdasg = defineBoxSpaceInfluence(surface, 0); - //return float4(asdasg,asdasg,asdasg,1); + float finalSum = blendSum; + + //return float4(finalSum,finalSum,finalSum, 1); // Normalize blendVal - /*if (blendSum == 0.0f) // Possible with custom weight + if (blendSum == 0.0f) // Possible with custom weight { blendSum = 1.0f; } @@ -166,7 +156,7 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET for (i = 0; i < numProbes; ++i) { blendVal[i] *= invBlendSumWeighted; - }*/ + } float3 irradiance = float3(0,0,0); float3 specular = float3(0,0,0); @@ -175,12 +165,12 @@ float4 main( FarFrustumQuadConnectP IN ) : SV_TARGET //energy conservation float3 kD = 1.0.xxx - F; kD *= 1.0 - surface.metalness; - //for (i = 0; i < numProbes; ++i) - //{ - irradiance = blendVal*iblBoxDiffuse(surface); + for (i = 0; i < numProbes; ++i) + { + irradiance += blendVal[i]*iblBoxDiffuse(surface,i); - specular = blendVal*F*iblBoxSpecular(surface, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture)); - //} + specular += blendVal[i]*F*iblBoxSpecular(surface, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture),i); + } //final diffuse color float3 diffuse = kD * irradiance * surface.baseColor.rgb; float4 finalColor = float4(diffuse + specular * surface.ao, 1);