From 64db2b1d15a3e44ff62a3a8b80bb7b40001329d9 Mon Sep 17 00:00:00 2001 From: Areloch Date: Mon, 11 Feb 2019 00:17:53 -0600 Subject: [PATCH] Ongoing PostFX org rework. --- Engine/source/postFx/postEffect.cpp | 11 +- Engine/source/postFx/postEffect.h | 4 + .../source/renderInstance/renderProbeMgr.cpp | 330 ++++++++++-------- Engine/source/renderInstance/renderProbeMgr.h | 38 +- .../client/lighting/advanced/shaders.cs | 8 +- .../advanced/reflectionProbeArrayP.hlsl | 8 +- 6 files changed, 221 insertions(+), 178 deletions(-) diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index 4054554f0..b123109e8 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -1434,6 +1434,11 @@ void PostEffect::_checkRequirements() // properly, we can find all the input textures, // and its formats are supported. + if (mShaderName == String("PFX_ReflectionProbeArray") || getName() == StringTable->insert("reflectionProbeArrayPostFX")) + { + bool derp = true; + } + mIsValid = false; mUpdateShader = false; mShader = NULL; @@ -1473,9 +1478,11 @@ void PostEffect::_checkRequirements() if ( texFilename.isNotEmpty() && texFilename[0] == '#' ) { NamedTexTarget *namedTarget = NamedTexTarget::find( texFilename.c_str() + 1 ); - if ( !namedTarget ) + if (!namedTarget) + { return; - + } + // Grab the macros for shader initialization. namedTarget->getShaderMacros( ¯os ); } diff --git a/Engine/source/postFx/postEffect.h b/Engine/source/postFx/postEffect.h index 53ee0b1d5..3f2001be0 100644 --- a/Engine/source/postFx/postEffect.h +++ b/Engine/source/postFx/postEffect.h @@ -353,6 +353,10 @@ public: bool isOneFrameOnly() { return mOneFrameOnly; } F32 getAspectRatio() const; + + GFXShaderRef getShader() { return mShader; } + Vector* getShaderMacros() { return &mShaderMacros; } + GFXShaderConstBufferRef getShaderConstBuffer() { return mShaderConsts; } enum PostEffectRequirements diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index b8ae72ee2..0a38686a7 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -243,7 +243,6 @@ bool ReflectProbeMatInstance::setupPass(SceneRenderState *state, const SceneData RenderProbeMgr::RenderProbeMgr() : RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f), mReflectProbeMaterial(nullptr), - mSceneManager(nullptr), mLastShader(nullptr), mLastConstants(nullptr) { @@ -276,6 +275,12 @@ RenderProbeMgr::RenderProbeMgr() irradMaps.setSize(MAXPROBECOUNT); irradMaps.fill(NULL); + + mEffectiveProbeCount = 0; + + mProbeArrayEffect = nullptr; + + numProbesSC = nullptr; } RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder) @@ -320,6 +325,21 @@ void RenderProbeMgr::registerProbe(U32 probeIdx) return; mRegisteredProbes.push_back_unique(probeIdx); + + //rebuild our probe data + //_setupStaticParameters(); +} + +void RenderProbeMgr::unregisterProbe(U32 probeIdx) +{ + //Mostly for consolidation, but also lets us sanity check or prep any other data we need for rendering this in one place at time of flagging for render + if (probeIdx >= ProbeRenderInst::all.size()) + return; + + mRegisteredProbes.remove(probeIdx); + + //rebuild our probe data + //_setupStaticParameters(); } // @@ -327,8 +347,12 @@ void RenderProbeMgr::registerProbe(U32 probeIdx) PostEffect* RenderProbeMgr::getProbeArrayEffect() { if (!mProbeArrayEffect) + { mProbeArrayEffect = dynamic_cast(Sim::findObject("reflectionProbeArrayPostFX")); + if (!mProbeArrayEffect) + return nullptr; + } return mProbeArrayEffect; } @@ -339,7 +363,115 @@ PostEffect* RenderProbeMgr::getProbeArrayEffect() void RenderProbeMgr::_setupStaticParameters() { + mLastShader = mProbeArrayEffect->getShader(); + if (mLastShader == nullptr) + return; + + mLastConstants = mLastShader->allocConstBuffer(); + + numProbesSC = mLastShader->getShaderConstHandle("$numProbes"); + + probePositionSC = mLastShader->getShaderConstHandle("$inProbePosArray"); + probeWorldToObjSC = mLastShader->getShaderConstHandle("$worldToObjArray"); + probeBBMinSC = mLastShader->getShaderConstHandle("$bbMinArray"); + probeBBMaxSC = mLastShader->getShaderConstHandle("$bbMaxArray"); + probeUseSphereModeSC = mLastShader->getShaderConstHandle("$useSphereMode"); + probeRadiusSC = mLastShader->getShaderConstHandle("$radius"); + probeAttenuationSC = mLastShader->getShaderConstHandle("$attenuation"); + + //Array rendering + U32 probeCount = ProbeRenderInst::all.size(); + + mEffectiveProbeCount = 0; + + for (U32 i = 0; i < probeCount; i++) + { + if (mEffectiveProbeCount >= MAXPROBECOUNT) + break; + + ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; + if (!curEntry->mIsEnabled) + continue; + + if (curEntry->mCubemap.isNull() || curEntry->mIrradianceCubemap.isNull()) + continue; + + if (!curEntry->mCubemap->isInitialised()) + continue; + + if (curEntry->mIsSkylight) + continue; + + //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[i] = curEntry->mCubemap; + irradMaps[i] = curEntry->mIrradianceCubemap; + + mEffectiveProbeCount++; + } + + if (mEffectiveProbeCount != 0) + { + mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); + mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); + + mCubemapArray->initStatic(cubeMaps.address(), mEffectiveProbeCount); + mIrradArray->initStatic(irradMaps.address(), mEffectiveProbeCount); + + /*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]; + //count = MAXPROBECOUNT; + //Final packing + mProbePositions = AlignedArray(mEffectiveProbeCount, sizeof(Point4F), (U8*)probePositions.address(), false); + mProbeBBMin = AlignedArray(mEffectiveProbeCount, sizeof(Point4F), (U8*)probeBBMin.address(), false); + mProbeBBMax = AlignedArray(mEffectiveProbeCount, sizeof(Point4F), (U8*)probeBBMax.address(), false); + mProbeUseSphereMode = AlignedArray(mEffectiveProbeCount, sizeof(float), (U8*)probeUseSphereMode.address(), false); + mProbeRadius = AlignedArray(mEffectiveProbeCount, sizeof(float), (U8*)probeRadius.address(), false); + mProbeAttenuation = AlignedArray(mEffectiveProbeCount, sizeof(float), (U8*)probeAttenuation.address(), false); + } } void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state) @@ -432,27 +564,27 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff ProbeConstantMap::Iterator iter = mConstantLookup.find(shader); if (iter != mConstantLookup.end()) { - mLastConstants = iter->value; + mLastForwardConstants = iter->value; } else { ProbeShaderConstants* psc = new ProbeShaderConstants(); mConstantLookup[shader] = psc; - mLastConstants = psc; + mLastForwardConstants = psc; } // Set our new shader mLastShader = shader; } - mLastConstants = new ProbeShaderConstants(); + mLastForwardConstants = new ProbeShaderConstants(); // Make sure that our current lighting constants are initialized - if (!mLastConstants->mInit) - mLastConstants->init(shader); + if (!mLastForwardConstants->mInit) + mLastForwardConstants->init(shader); - return mLastConstants; + return mLastForwardConstants; } void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData, @@ -629,7 +761,9 @@ void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat, //----------------------------------------------------------------------------- void RenderProbeMgr::render( SceneRenderState *state ) { - PROFILE_SCOPE(RenderProbeMgr_render); + //PROFILE_SCOPE(RenderProbeMgr_render); + if (getProbeArrayEffect() == nullptr) + return; // Early out if nothing to draw. if (!ProbeRenderInst::all.size()) @@ -638,129 +772,38 @@ void RenderProbeMgr::render( SceneRenderState *state ) if (!RenderProbeMgr::smRenderReflectionProbes) return; + if (mEffectiveProbeCount == 0) + _setupStaticParameters(); //return; + GFXTransformSaver saver; GFXDEBUGEVENT_SCOPE(RenderProbeMgr_render, ColorI::WHITE); - NamedTexTargetRef sceneColorTargetRef = NamedTexTarget::find("AL_FormatToken"); - if (sceneColorTargetRef.isNull()) - return; - - GFXTextureTargetRef probeLightingTargetRef = GFX->allocRenderToTextureTarget(); - - if (probeLightingTargetRef.isNull()) - return; - - //Do a quick pass to update our probes if they're dirty - //PROBEMGR->updateDirtyProbes(); - - probeLightingTargetRef->attachTexture(GFXTextureTarget::Color0, sceneColorTargetRef->getTexture(0)); - - GFX->pushActiveRenderTarget(); - GFX->setActiveRenderTarget(probeLightingTargetRef); - - GFX->setViewport(sceneColorTargetRef->getViewport()); - - // Restore transforms - MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); - matrixSet.restoreSceneViewProjection(); - - const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera(); - - // Set up the SG Data - SceneData sgData; - sgData.init(state); - // Initialize and set the per-frame parameters after getting // the vector light material as we use lazy creation. - _setupPerFrameParameters(state); - - //Order the probes by size, biggest to smallest - //dQsort(ProbeRenderInst::all.address(), ProbeRenderInst::all.size(), sizeof(const ProbeRenderInst*), AscendingReflectProbeInfluence); + //_setupPerFrameParameters(state); //Specular - PROFILE_START(RenderProbeManager_ReflectProbeRender); + //PROFILE_START(RenderProbeManager_ReflectProbeRender); - ReflectProbeMaterialInfo* reflProbeMat = getReflectProbeMaterial(); - - if (reflProbeMat == nullptr || reflProbeMat->matInstance == nullptr) + // If this is a non-diffuse pass or we have no objects to + // render then tell the effect to skip rendering. + if (!state->isDiffusePass()/* || binSize == 0*/|| !numProbesSC || !numProbesSC->isValid()) + { + getProbeArrayEffect()->setSkip(true); return; - - MaterialParameters *matParams = reflProbeMat->matInstance->getMaterialParameters(); - - MaterialParameterHandle *numProbesSC = reflProbeMat->matInstance->getMaterialParameterHandle("$numProbes"); - - 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 U32 probeCount = ProbeRenderInst::all.size(); if (probeCount == 0) return; - MatrixF trans = MatrixF::Identity; - sgData.objTrans = &trans; - - U32 effectiveProbeCount = 0; - for (U32 i = 0; i < probeCount; i++) + if (mEffectiveProbeCount != 0) { - if (effectiveProbeCount >= MAXPROBECOUNT) - break; - - ProbeRenderInst* curEntry = ProbeRenderInst::all[i]; - if (!curEntry->mIsEnabled) - continue; - - if (curEntry->mCubemap.isNull() || curEntry->mIrradianceCubemap.isNull()) - continue; - - if (!curEntry->mCubemap->isInitialised()) - continue; - - if (curEntry->mIsSkylight) - continue; - - //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[i] = curEntry->mCubemap; - irradMaps[i] = curEntry->mIrradianceCubemap; - - effectiveProbeCount++; - } - - if (effectiveProbeCount != 0) - { - U32 count = effectiveProbeCount; - matParams->setSafe(numProbesSC, (float)effectiveProbeCount); - - mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); - mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray()); - - mCubemapArray->initStatic(cubeMaps.address(), count); - mIrradArray->initStatic(irradMaps.address(), count); - - NamedTexTarget *deferredTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName); + //These will in theory be set by the postFX + /*NamedTexTarget *deferredTarget = NamedTexTarget::find(RenderDeferredMgr::BufferName); if (deferredTarget) GFX->setTexture(0, deferredTarget->getTexture()); else @@ -776,7 +819,7 @@ void RenderProbeMgr::render( SceneRenderState *state ) if (matinfoTarget) GFX->setTexture(2, matinfoTarget->getTexture()); else - GFX->setTexture(2, NULL); + GFX->setTexture(2, NULL);*/ if (mBrdfTexture) { @@ -785,54 +828,33 @@ void RenderProbeMgr::render( SceneRenderState *state ) else GFX->setTexture(3, NULL); - //GFX->setCubeArrayTexture(4, mCubemapArray); - //GFX->setCubeArrayTexture(5, mIrradArray); + GFX->setCubeArrayTexture(4, mCubemapArray); + GFX->setCubeArrayTexture(5, mIrradArray); - ProbeRenderInst* curEntry = ProbeRenderInst::all[0]; - count = MAXPROBECOUNT; - //Final packing - AlignedArray _probePositions(count, sizeof(Point4F), (U8*)probePositions.address(), false); - AlignedArray _probeBBMin(count, sizeof(Point4F), (U8*)probeBBMin.address(), false); - AlignedArray _probeBBMax(count, sizeof(Point4F), (U8*)probeBBMax.address(), false); - AlignedArray _probeUseSphereMode(count, sizeof(float), (U8*)probeUseSphereMode.address(), false); - AlignedArray _probeRadius(count, sizeof(float), (U8*)probeRadius.address(), false); - AlignedArray _probeAttenuation(count, sizeof(float), (U8*)probeAttenuation.address(), false); - - matParams->set(probePositionSC, _probePositions); - matParams->set(probeWorldToObjSC, probeWorldToObj.address(), count); - 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)) + if (numProbesSC->isValid()) { - // Set transforms - matrixSet.setWorld(*sgData.objTrans); - reflProbeMat->matInstance->setTransforms(matrixSet, state); - reflProbeMat->matInstance->setSceneInfo(state, sgData); + mLastConstants->set(numProbesSC, (float)mEffectiveProbeCount); - GFX->drawPrimitive(GFXTriangleStrip, 0, 2); + mLastConstants->set(probePositionSC, mProbePositions); + + mLastConstants->set(probePositionSC, mProbePositions); + mLastConstants->set(probeWorldToObjSC, probeWorldToObj.address(), mEffectiveProbeCount); + mLastConstants->set(probeBBMinSC, mProbeBBMin); + mLastConstants->set(probeBBMaxSC, mProbeBBMax); + mLastConstants->set(probeUseSphereModeSC, mProbeUseSphereMode); + mLastConstants->set(probeRadiusSC, mProbeRadius); + mLastConstants->set(probeAttenuationSC, mProbeAttenuation); } } - GFX->popActiveRenderTarget(); + // Finish up. + //if (isRenderingToTarget) + // _onPostRender(); - //PROBEMGR->unregisterAllProbes(); - //PROBEMGR->mRegisteredProbes.clear(); + // Make sure the effect is gonna render. + getProbeArrayEffect()->setSkip(false); - PROFILE_END(); - - GFX->setVertexBuffer(NULL); - GFX->setPrimitiveBuffer(NULL); - - // Fire off a signal to let others know that light-bin rendering is ending now - //getRenderSignal().trigger(state, this); + //PROFILE_END(); } // diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index ea735e29a..2142fe04d 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -268,12 +268,22 @@ class RenderProbeMgr : public RenderBinManager ReflectProbeMaterialInfo* mReflectProbeMaterial; + GFXShaderConstHandle *numProbesSC; + GFXShaderConstHandle *probePositionSC; + GFXShaderConstHandle *probeWorldToObjSC; + GFXShaderConstHandle *probeBBMinSC; + GFXShaderConstHandle *probeBBMaxSC; + GFXShaderConstHandle *probeUseSphereModeSC; + GFXShaderConstHandle *probeRadiusSC; + GFXShaderConstHandle *probeAttenuationSC; + /// The scene graph the light manager is associated with. - SceneManager *mSceneManager; + //SceneManager *mSceneManager; ProbeConstantMap mConstantLookup; GFXShaderRef mLastShader; - ProbeShaderConstants* mLastConstants; + GFXShaderConstBufferRef mLastConstants; + ProbeShaderConstants* mLastForwardConstants; // // @@ -306,7 +316,7 @@ protected: GFXTextureObject * mBrdfTexture; //Array rendering - + U32 mEffectiveProbeCount; Vector probePositions; Vector probeWorldToObj; Vector probeBBMin; @@ -317,6 +327,13 @@ protected: Vector cubeMaps; Vector irradMaps; + AlignedArray mProbePositions; + AlignedArray mProbeBBMin; + AlignedArray mProbeBBMax; + AlignedArray mProbeUseSphereMode; + AlignedArray mProbeRadius; + AlignedArray mProbeAttenuation; + GFXCubemapArrayHandle mCubemapArray; GFXCubemapArrayHandle mIrradArray; public: @@ -348,10 +365,7 @@ public: void registerProbe(U32 probeIdx); - // Returns the scene manager passed at activation. - SceneManager* getSceneManager() { return mSceneManager; } - - void setSceneManager(SceneManager* sceneManager) { mSceneManager = sceneManager; } + void unregisterProbe(U32 probeIdx); /// Debug rendering static bool smRenderReflectionProbes; @@ -363,15 +377,7 @@ RenderProbeMgr* RenderProbeMgr::getProbeManager() { RenderProbeMgr* probeManager = new RenderProbeMgr(); - if (gClientSceneGraph != nullptr) - { - probeManager->setSceneManager(gClientSceneGraph); - smProbeManager = probeManager; - } - else - { - delete probeManager; - } + smProbeManager = probeManager; } return smProbeManager; diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs index c70ea54e3..f646c95a4 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs @@ -500,12 +500,12 @@ singleton PostEffect( reflectionProbeArrayPostFX ) //texture[0] = "#highlight"; //texture[1] = "$backBuffer"; - texture[0] = "$deferredBuffer"; - texture[1] = "$colorBuffer"; - texture[2] = "$matInfoBuffer"; + texture[0] = "#deferred"; + texture[1] = "#color"; + texture[2] = "#matinfo"; texture[3] = "$BRDFTexture"; texture[4] = "$cubeMap"; texture[5] = "$irradianceCubemap"; - target = "$backBuffer"; + target = "AL_FormatToken"; }; \ 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 9ae026ba0..d320a99ed 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl @@ -1,5 +1,6 @@ -#include "../postFx.hlsl" - +#include "../../postFx/postFx.hlsl" +#include "../../shaderModel.hlsl" +#include "../../shaderModelAutoGen.hlsl" #include "../../lighting.hlsl" TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0); @@ -146,6 +147,9 @@ float4 main( PFXVertToPix IN ) : SV_TARGET float finalSum = blendSum; + return TORQUE_TEX2D(colorBuffer, IN.uv0.xy); + //return float4(surface.N,1); + //return float4(1,1,1, 1); //return float4(finalSum,finalSum,finalSum, 1); // Normalize blendVal