mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-14 04:03:46 +00:00
WIP of timmy's changes merged in. Not properly initializing the probes/array slots just yet.
This commit is contained in:
parent
ead78ec588
commit
399088d09e
10 changed files with 485 additions and 159 deletions
|
|
@ -631,7 +631,7 @@ void ReflectionProbe::processStaticCubemap()
|
|||
IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
|
||||
}
|
||||
|
||||
mProbeInfo->mCubemap = mPrefilterMap->mCubemap;
|
||||
mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
|
||||
mProbeInfo->mIrradianceCubemap = mIrridianceMap->mCubemap;
|
||||
}
|
||||
|
||||
|
|
@ -647,7 +647,7 @@ void ReflectionProbe::updateMaterial()
|
|||
{
|
||||
if (mPrefilterMap != nullptr && mPrefilterMap->mCubemap.isValid())
|
||||
{
|
||||
mProbeInfo->mCubemap = mPrefilterMap->mCubemap;
|
||||
mProbeInfo->mPrefilterCubemap = mPrefilterMap->mCubemap;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -667,7 +667,7 @@ void ReflectionProbe::updateMaterial()
|
|||
{
|
||||
if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
|
||||
{
|
||||
mProbeInfo->mCubemap = mDynamicCubemap;
|
||||
mProbeInfo->mPrefilterCubemap = mDynamicCubemap;
|
||||
|
||||
mProbeInfo->mCubeReflector.registerReflector(this, reflectorDesc); //need to decide how we wanna do the reflectorDesc. static name or a field
|
||||
}
|
||||
|
|
@ -684,6 +684,9 @@ void ReflectionProbe::updateMaterial()
|
|||
mProbeInfo->mIsEnabled = false;
|
||||
|
||||
PROBEMGR->updateProbes();
|
||||
|
||||
if (mProbeInfo->mPrefilterCubemap->isInitialized() && mProbeInfo->mIrradianceCubemap->isInitialized())
|
||||
PROBEMGR->updateProbeTexture(mProbeInfo);
|
||||
}
|
||||
|
||||
bool ReflectionProbe::createClientResources()
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void GFXD3D11Cubemap::initStatic(GFXTexHandle *faces)
|
|||
mSRView->GetDesc(&viewDesc);
|
||||
mMipMapLevels = viewDesc.TextureCube.MipLevels;
|
||||
}
|
||||
mInitialized = true;
|
||||
|
||||
}
|
||||
|
||||
void GFXD3D11Cubemap::initStatic(DDSFile *dds)
|
||||
|
|
@ -208,7 +208,6 @@ void GFXD3D11Cubemap::initStatic(DDSFile *dds)
|
|||
{
|
||||
AssertFatal(false, "GFXD3D11Cubemap::initStatic(DDSFile *dds) - CreateTexture2D call failure");
|
||||
}
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLevels)
|
||||
|
|
@ -331,7 +330,7 @@ void GFXD3D11Cubemap::initDynamic(U32 texSize, GFXFormat faceFormat, U32 mipLeve
|
|||
}
|
||||
|
||||
SAFE_RELEASE(depthTex);
|
||||
mInitialized = true;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -392,10 +391,11 @@ GFXD3D11CubemapArray::~GFXD3D11CubemapArray()
|
|||
SAFE_RELEASE(mTexture);
|
||||
}
|
||||
|
||||
void GFXD3D11CubemapArray::initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
|
||||
//TODO: really need a common private 'init' function to avoid code double up with these init* functions
|
||||
void GFXD3D11CubemapArray::init(GFXCubemapHandle *cubemaps, const U32 cubemapCount)
|
||||
{
|
||||
AssertFatal(cubemaps, "GFXD3D11CubemapArray - Got null GFXCubemapHandle!");
|
||||
AssertFatal(*cubemaps, "GFXD3D11CubemapArray - Got empty cubemap!");
|
||||
AssertFatal(cubemaps, "GFXD3D11CubemapArray::initStatic - Got null GFXCubemapHandle!");
|
||||
AssertFatal(*cubemaps, "GFXD3D11CubemapArray::initStatic - Got empty cubemap!");
|
||||
|
||||
//all cubemaps must be the same size,format and number of mipmaps. Grab the details from the first cubemap
|
||||
mSize = cubemaps[0]->getSize();
|
||||
|
|
@ -424,7 +424,7 @@ void GFXD3D11CubemapArray::initStatic(GFXCubemapHandle *cubemaps, const U32 cube
|
|||
HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
|
||||
|
||||
if (FAILED(hr))
|
||||
AssertFatal(false, "GFXD3D11CubemapArray:initStatic(GFXCubemap *cubemaps,const U32 cubemapCount) - CreateTexture2D failure");
|
||||
AssertFatal(false, "GFXD3D11CubemapArray::initStatic - CreateTexture2D failure");
|
||||
|
||||
for (U32 i = 0; i < cubemapCount; i++)
|
||||
{
|
||||
|
|
@ -434,7 +434,7 @@ void GFXD3D11CubemapArray::initStatic(GFXCubemapHandle *cubemaps, const U32 cube
|
|||
{
|
||||
Con::printf("Trying to add an invalid Cubemap to a CubemapArray");
|
||||
//destroy array here first
|
||||
AssertFatal(false, "GFXD3D11CubemapArray:initStatic(GFXCubemap *cubemaps,const U32 cubemapCount) - invalid cubemap");
|
||||
AssertFatal(false, "GFXD3D11CubemapArray::initStatic - invalid cubemap");
|
||||
}
|
||||
|
||||
for (U32 face = 0; face < CubeFaces; face++)
|
||||
|
|
@ -460,7 +460,102 @@ void GFXD3D11CubemapArray::initStatic(GFXCubemapHandle *cubemaps, const U32 cube
|
|||
|
||||
hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
|
||||
if (FAILED(hr))
|
||||
AssertFatal(false, "GFXD3D11CubemapArray:initStatic(GFXCubemap *cubemaps,const U32 cubemapCount) - shader resource view creation failure");
|
||||
AssertFatal(false, "GFXD3D11CubemapArray::initStatic - shader resource view creation failure");
|
||||
|
||||
}
|
||||
|
||||
//Just allocate the cubemap array but we don't upload any data
|
||||
void GFXD3D11CubemapArray::init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format)
|
||||
{
|
||||
mSize = cubemapFaceSize;
|
||||
mMipMapLevels = ImageUtil::getMaxMipCount(cubemapFaceSize, cubemapFaceSize);
|
||||
mNumCubemaps = cubemapCount;
|
||||
mFormat = format;
|
||||
|
||||
//create texture object
|
||||
UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
UINT miscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
|
||||
desc.Width = mSize;
|
||||
desc.Height = mSize;
|
||||
desc.MipLevels = mMipMapLevels;
|
||||
desc.ArraySize = CubeFaces * cubemapCount;
|
||||
desc.Format = GFXD3D11TextureFormat[mFormat];
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = bindFlags;
|
||||
desc.MiscFlags = miscFlags;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
HRESULT hr = D3D11DEVICE->CreateTexture2D(&desc, NULL, &mTexture);
|
||||
|
||||
if (FAILED(hr))
|
||||
AssertFatal(false, "GFXD3D11CubemapArray::initStatic - CreateTexture2D failure");
|
||||
|
||||
//create shader resource view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
|
||||
SMViewDesc.Format = GFXD3D11TextureFormat[mFormat];
|
||||
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
|
||||
SMViewDesc.TextureCubeArray.MipLevels = mMipMapLevels;
|
||||
SMViewDesc.TextureCubeArray.MostDetailedMip = 0;
|
||||
SMViewDesc.TextureCubeArray.NumCubes = mNumCubemaps;
|
||||
SMViewDesc.TextureCubeArray.First2DArrayFace = 0;
|
||||
|
||||
hr = D3D11DEVICE->CreateShaderResourceView(mTexture, &SMViewDesc, &mSRView);
|
||||
if (FAILED(hr))
|
||||
AssertFatal(false, "GFXD3D11CubemapArray::initStatic - shader resource view creation failure");
|
||||
|
||||
}
|
||||
|
||||
void GFXD3D11CubemapArray::updateTexture(const GFXCubemapHandle &cubemap, const U32 slot)
|
||||
{
|
||||
AssertFatal(slot <= mNumCubemaps, "GFXD3D11CubemapArray::updateTexture - trying to update a cubemap texture that is out of bounds!");
|
||||
|
||||
GFXD3D11Cubemap *pCubeObj = static_cast<GFXD3D11Cubemap*>((GFXCubemap*)cubemap);
|
||||
ID3D11Resource *pDstRes = pCubeObj->get2DTex();
|
||||
for (U32 face = 0; face < CubeFaces; face++)
|
||||
{
|
||||
const U32 arraySlice = face + CubeFaces * slot;
|
||||
for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
|
||||
{
|
||||
const U32 srcSubResource = D3D11CalcSubresource(currentMip, face, mMipMapLevels);
|
||||
const U32 dstSubResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(mTexture, dstSubResource, 0, 0, 0, pDstRes, srcSubResource, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GFXD3D11CubemapArray::copyTo(GFXCubemapArray *pDstCubemap)
|
||||
{
|
||||
AssertFatal(pDstCubemap, "GFXD3D11CubemapArray::copyTo - Got null GFXCubemapArray");
|
||||
|
||||
const U32 dstCount = pDstCubemap->getNumCubemaps();
|
||||
const GFXFormat dstFmt = pDstCubemap->getFormat();
|
||||
const U32 dstSize = pDstCubemap->getSize();
|
||||
const U32 dstMips = pDstCubemap->getMipMapLevels();
|
||||
|
||||
AssertFatal(dstCount > mNumCubemaps, "GFXD3D11CubemapArray::copyTo - Destination too small");
|
||||
AssertFatal(dstFmt == mFormat, "GFXD3D11CubemapArray::copyTo - Destination format doesn't match");
|
||||
AssertFatal(dstSize == mSize, "GFXD3D11CubemapArray::copyTo - Destination size doesn't match");
|
||||
AssertFatal(dstMips == mMipMapLevels, "GFXD3D11CubemapArray::copyTo - Destination mip levels doesn't match");
|
||||
|
||||
GFXD3D11CubemapArray *pDstCube = static_cast<GFXD3D11CubemapArray*>(pDstCubemap);
|
||||
ID3D11Resource *pDstRes = pDstCube->get2DTex();
|
||||
for (U32 cubeMap = 0; cubeMap < mNumCubemaps; cubeMap++)
|
||||
{
|
||||
for (U32 face = 0; face < CubeFaces; face++)
|
||||
{
|
||||
const U32 arraySlice = face + CubeFaces * cubeMap;
|
||||
for (U32 currentMip = 0; currentMip < mMipMapLevels; currentMip++)
|
||||
{
|
||||
const U32 subResource = D3D11CalcSubresource(currentMip, arraySlice, mMipMapLevels);
|
||||
D3D11DEVICECONTEXT->CopySubresourceRegion(pDstRes, subResource, 0, 0, 0, mTexture, subResource, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public:
|
|||
virtual void zombify();
|
||||
virtual void resurrect();
|
||||
|
||||
virtual bool isInitialized() { return mTexture ? true : false; }
|
||||
|
||||
// Get functions
|
||||
ID3D11ShaderResourceView* getSRView();
|
||||
ID3D11RenderTargetView* getRTView(U32 faceIdx, U32 mipIndex=0);
|
||||
|
|
@ -81,7 +83,10 @@ class GFXD3D11CubemapArray : public GFXCubemapArray
|
|||
public:
|
||||
GFXD3D11CubemapArray();
|
||||
virtual ~GFXD3D11CubemapArray();
|
||||
virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount);
|
||||
virtual void init(GFXCubemapHandle *cubemaps, const U32 cubemapCount);
|
||||
virtual void init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format);
|
||||
virtual void updateTexture(const GFXCubemapHandle &cubemap, const U32 slot);
|
||||
virtual void copyTo(GFXCubemapArray *pDstCubemap);
|
||||
virtual void setToTexUnit(U32 tuNum);
|
||||
|
||||
ID3D11ShaderResourceView* getSRView() { return mSRView; }
|
||||
|
|
|
|||
|
|
@ -169,8 +169,10 @@ private:
|
|||
virtual void setToTexUnit(U32 tuNum) { };
|
||||
|
||||
public:
|
||||
virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount) { };
|
||||
|
||||
virtual void init(GFXCubemapHandle *cubemaps, const U32 cubemapCount) { };
|
||||
virtual void init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format) { };
|
||||
virtual void updateTexture(const GFXCubemapHandle &cubemap, const U32 slot) { };
|
||||
virtual void copyTo(GFXCubemapArray *pDstCubemap) { }
|
||||
virtual ~GFXNullCubemapArray() {};
|
||||
virtual void zombify() {}
|
||||
virtual void resurrect() {}
|
||||
|
|
|
|||
|
|
@ -301,4 +301,9 @@ namespace ImageUtil
|
|||
return format;
|
||||
};
|
||||
}
|
||||
|
||||
U32 getMaxMipCount(const U32 width, const U32 height)
|
||||
{
|
||||
return mFloor(mLog2(mMax(width, height))) + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,9 @@
|
|||
#ifndef _GFXENUMS_H_
|
||||
#include "gfx/gfxEnums.h"
|
||||
#endif
|
||||
#ifndef _MMATHFN_H_
|
||||
#include "math/mMathFn.h"
|
||||
#endif
|
||||
|
||||
struct DDSFile;
|
||||
|
||||
|
|
@ -57,6 +60,8 @@ namespace ImageUtil
|
|||
|
||||
//convert to sRGB format
|
||||
GFXFormat toSRGBFormat(const GFXFormat format);
|
||||
|
||||
U32 getMaxMipCount(const U32 width, const U32 height);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -49,6 +49,7 @@ protected:
|
|||
|
||||
|
||||
U32 mMipMapLevels;
|
||||
|
||||
bool mInitialized;
|
||||
public:
|
||||
|
||||
|
|
@ -62,6 +63,7 @@ public:
|
|||
virtual void initDynamic( U32 texSize, GFXFormat faceFormat = GFXFormatR8G8B8A8, U32 mipLevels = 0 ) = 0;
|
||||
|
||||
void initNormalize(U32 size);
|
||||
|
||||
GFXCubemap();
|
||||
virtual ~GFXCubemap();
|
||||
|
||||
|
|
@ -71,6 +73,9 @@ public:
|
|||
/// Returns the face texture format.
|
||||
virtual GFXFormat getFormat() const = 0;
|
||||
|
||||
/// Returns if this cubemap has been initialized
|
||||
virtual bool isInitialized() { return false; }
|
||||
|
||||
/// Returns the cubemap file path set at creation.
|
||||
const String& getPath() const { return mPath; }
|
||||
|
||||
|
|
@ -83,7 +88,6 @@ public:
|
|||
|
||||
/// Get Z up face index of the cubemap. DDS files will be stored Y up
|
||||
static U32 zUpFaceIndex(const U32 index);
|
||||
bool isInitialised() { return mInitialized; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -102,32 +106,43 @@ public:
|
|||
void free() { StrongObjectRef::set( NULL ); }
|
||||
};
|
||||
|
||||
/// Cubemap array
|
||||
/// Cubemap array - data lives on the GPU only with this class, but the data is not immutable so it can be updated
|
||||
class GFXCubemapArray : public StrongRefBase, public GFXResource
|
||||
{
|
||||
friend class GFXDevice;
|
||||
friend class GFXTextureManager;
|
||||
|
||||
protected:
|
||||
// should only be called by GFXDevice
|
||||
/// should only be called by GFXDevice
|
||||
virtual void setToTexUnit( U32 tuNum ) = 0;
|
||||
/// number of cubemaps in the array
|
||||
U32 mNumCubemaps;
|
||||
/// cubemap face size
|
||||
U32 mSize;
|
||||
/// number of mip levels
|
||||
U32 mMipMapLevels;
|
||||
/// format
|
||||
GFXFormat mFormat;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~GFXCubemapArray() {};
|
||||
|
||||
virtual void initStatic(GFXCubemapHandle *cubemaps, const U32 cubemapCount) = 0;
|
||||
/// Initialize from an array of cubemaps
|
||||
virtual void init(GFXCubemapHandle *cubemaps, const U32 cubemapCount) = 0;
|
||||
/// Initialize cubemapCount number of blank cubemaps in the array
|
||||
virtual void init(const U32 cubemapCount, const U32 cubemapFaceSize, const GFXFormat format) = 0;
|
||||
/// Update cubemap in the array
|
||||
virtual void updateTexture(const GFXCubemapHandle &cubemap, const U32 slot) = 0;
|
||||
/// Copy this cubemap to another - destination must be same format, same face size & at-least the same size(or larger)
|
||||
virtual void copyTo(GFXCubemapArray *pDstCubemap) = 0;
|
||||
/// Return number of textures in the array
|
||||
const U32 getNumCubemaps() const { return mNumCubemaps; }
|
||||
/// Get the number of mip maps
|
||||
const U32 getMipMapLevels() const { return mMipMapLevels; }
|
||||
/// Returns the size of the faces.
|
||||
const U32 getSize() const { return mSize; }
|
||||
/// Returns the format
|
||||
const GFXFormat getFormat() const { return mFormat; }
|
||||
|
||||
virtual const String describeSelf() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,20 +78,21 @@ ProbeRenderInst::ProbeRenderInst() : SystemInterface(),
|
|||
mDirty(false),
|
||||
mPriority(1.0f),
|
||||
mScore(0.0f),
|
||||
mCubemap(NULL),
|
||||
mPrefilterCubemap(NULL),
|
||||
mIrradianceCubemap(NULL),
|
||||
mRadius(1.0f),
|
||||
mProbeRefOffset(0, 0, 0),
|
||||
mProbeRefScale(1,1,1),
|
||||
mAtten(0.0)
|
||||
mAtten(0.0),
|
||||
mCubemapIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
ProbeRenderInst::~ProbeRenderInst()
|
||||
{
|
||||
if (mCubemap && mCubemap.isValid())
|
||||
if (mPrefilterCubemap && mPrefilterCubemap.isValid())
|
||||
{
|
||||
mCubemap.free();
|
||||
mPrefilterCubemap.free();
|
||||
}
|
||||
if (mIrradianceCubemap && mIrradianceCubemap.isValid())
|
||||
{
|
||||
|
|
@ -102,7 +103,7 @@ ProbeRenderInst::~ProbeRenderInst()
|
|||
void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
|
||||
{
|
||||
mTransform = probeInfo->mTransform;
|
||||
mCubemap = probeInfo->mCubemap;
|
||||
mPrefilterCubemap = probeInfo->mPrefilterCubemap;
|
||||
mIrradianceCubemap = probeInfo->mIrradianceCubemap;
|
||||
mRadius = probeInfo->mRadius;
|
||||
mProbeShapeType = probeInfo->mProbeShapeType;
|
||||
|
|
@ -183,6 +184,13 @@ RenderProbeMgr::RenderProbeMgr()
|
|||
mProbeArrayEffect = nullptr;
|
||||
|
||||
smProbeManager = this;
|
||||
|
||||
mCubeMapCount = 0;
|
||||
|
||||
for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
|
||||
{
|
||||
mCubeMapSlots[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
|
||||
|
|
@ -203,6 +211,37 @@ RenderProbeMgr::~RenderProbeMgr()
|
|||
mConstantLookup.clear();
|
||||
}
|
||||
|
||||
bool RenderProbeMgr::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
mIrradianceArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
mPrefilterArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
|
||||
//pre-allocate a few slots
|
||||
mIrradianceArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_IRRAD_SIZE, PROBE_FORMAT);
|
||||
mPrefilterArray->init(PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_PREFILTER_SIZE, PROBE_FORMAT);
|
||||
mCubeSlotCount = PROBE_ARRAY_SLOT_BUFFER_SIZE;
|
||||
|
||||
//create our own default default skylight
|
||||
mDefaultSkyLight = new ProbeRenderInst;
|
||||
mDefaultSkyLight->mProbeShapeType = ProbeRenderInst::Skylight;
|
||||
if (!mDefaultSkyLight->mIrradianceCubemap.set("core/art/pbr/default_irradiance.dds"))
|
||||
{
|
||||
Con::errorf("RenderProbeMgr::onAdd: Failed to load default irradiance cubemap");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDefaultSkyLight->mPrefilterCubemap.set("core/art/pbr/default_prefilter.dds"))
|
||||
{
|
||||
Con::errorf("RenderProbeMgr::onAdd: Failed to load default prefilter cubemap");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderProbeMgr::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
|
|
@ -246,6 +285,38 @@ void RenderProbeMgr::registerProbe(U32 probeIdx)
|
|||
|
||||
mRegisteredProbes.push_back_unique(probeIdx);
|
||||
|
||||
const U32 cubeIndex = _findNextEmptyCubeSlot();
|
||||
if (cubeIndex == INVALID_CUBE_SLOT)
|
||||
{
|
||||
Con::warnf("RenderProbeMgr::addProbe: Invalid cubemap slot.");
|
||||
return;
|
||||
}
|
||||
|
||||
//check if we need to resize the cubemap array
|
||||
if (cubeIndex >= mCubeSlotCount)
|
||||
{
|
||||
//alloc temp array handles
|
||||
GFXCubemapArrayHandle irr = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
GFXCubemapArrayHandle prefilter = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
|
||||
irr->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_IRRAD_SIZE, PROBE_FORMAT);
|
||||
prefilter->init(mCubeSlotCount + PROBE_ARRAY_SLOT_BUFFER_SIZE, PROBE_PREFILTER_SIZE, PROBE_FORMAT);
|
||||
|
||||
mIrradianceArray->copyTo(irr);
|
||||
mPrefilterArray->copyTo(prefilter);
|
||||
|
||||
//assign the temp handles to the new ones, this will destroy the old ones as well
|
||||
mIrradianceArray = irr;
|
||||
mPrefilterArray = prefilter;
|
||||
|
||||
mCubeSlotCount += PROBE_ARRAY_SLOT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
ProbeRenderInst::all[probeIdx]->mCubemapIndex = cubeIndex;
|
||||
//mark cubemap slot as taken
|
||||
mCubeMapSlots[cubeIndex] = true;
|
||||
mCubeMapCount++;
|
||||
|
||||
//rebuild our probe data
|
||||
_setupStaticParameters();
|
||||
}
|
||||
|
|
@ -258,6 +329,13 @@ void RenderProbeMgr::unregisterProbe(U32 probeIdx)
|
|||
|
||||
mRegisteredProbes.remove(probeIdx);
|
||||
|
||||
if (ProbeRenderInst::all[probeIdx]->mCubemapIndex == INVALID_CUBE_SLOT)
|
||||
return;
|
||||
|
||||
//mark cubemap slot as available now
|
||||
mCubeMapSlots[ProbeRenderInst::all[probeIdx]->mCubemapIndex] = false;
|
||||
mCubeMapCount--;
|
||||
|
||||
//rebuild our probe data
|
||||
_setupStaticParameters();
|
||||
}
|
||||
|
|
@ -314,6 +392,16 @@ void RenderProbeMgr::_setupStaticParameters()
|
|||
cubeMaps.clear();
|
||||
irradMaps.clear();
|
||||
|
||||
if (probeCount != 0 && ProbeRenderInst::all[0]->mPrefilterCubemap != nullptr)
|
||||
{
|
||||
//Get our mipCount
|
||||
mMipCount = ProbeRenderInst::all[0]->mPrefilterCubemap.getPointer()->getMipMapLevels();
|
||||
}
|
||||
else
|
||||
{
|
||||
mMipCount = 1;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < probeCount; i++)
|
||||
{
|
||||
if (mEffectiveProbeCount >= MAXPROBECOUNT)
|
||||
|
|
@ -323,19 +411,23 @@ void RenderProbeMgr::_setupStaticParameters()
|
|||
if (!curEntry.mIsEnabled)
|
||||
continue;
|
||||
|
||||
if (curEntry.mCubemap.isNull() || curEntry.mIrradianceCubemap.isNull())
|
||||
if (curEntry.mIsSkylight)
|
||||
{
|
||||
skylightPos = curEntry.getPosition();
|
||||
skylightPrefilterMap = curEntry.mPrefilterCubemap;
|
||||
skylightIrradMap = curEntry.mIrradianceCubemap;
|
||||
hasSkylight = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!curEntry.mCubemap->isInitialised())
|
||||
continue;
|
||||
|
||||
if (!curEntry.mIrradianceCubemap->isInitialised())
|
||||
continue;
|
||||
|
||||
//if (curEntry.mIsSkylight)
|
||||
//if (curEntry.mCubemap.isNull() || curEntry.mIrradianceCubemap.isNull())
|
||||
// continue;
|
||||
|
||||
mMipCount = curEntry.mCubemap.getPointer()->getMipMapLevels();
|
||||
//if (!curEntry.mCubemap->isInitialized())
|
||||
// continue;
|
||||
|
||||
//if (!curEntry.mIrradianceCubemap->isInitialized())
|
||||
// continue;
|
||||
|
||||
//Setup
|
||||
Point3F probePos = curEntry.getPosition();
|
||||
|
|
@ -354,22 +446,40 @@ void RenderProbeMgr::_setupStaticParameters()
|
|||
curEntry.mAtten,
|
||||
1);
|
||||
|
||||
cubeMaps.push_back(curEntry.mCubemap);
|
||||
irradMaps.push_back(curEntry.mIrradianceCubemap);
|
||||
//cubeMaps.push_back(curEntry.mCubemap);
|
||||
//irradMaps.push_back(curEntry.mIrradianceCubemap);
|
||||
|
||||
mEffectiveProbeCount++;
|
||||
}
|
||||
|
||||
if (mEffectiveProbeCount != 0)
|
||||
{
|
||||
mCubemapArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
mIrradArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
//mPrefilterArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
//mIrradianceArray = GFXCubemapArrayHandle(GFX->createCubemapArray());
|
||||
|
||||
mCubemapArray->initStatic(cubeMaps.address(), cubeMaps.size());
|
||||
mIrradArray->initStatic(irradMaps.address(), irradMaps.size());
|
||||
//mPrefilterArray->initStatic(cubeMaps.address(), cubeMaps.size());
|
||||
//mIrradianceArray->initStatic(irradMaps.address(), irradMaps.size());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProbeMgr::updateProbeTexture(ProbeRenderInst* probe)
|
||||
{
|
||||
S32 probeIdx = ProbeRenderInst::all.find_next(probe);
|
||||
|
||||
if (probeIdx != -1) //i mean, the opposite shouldn't even be possible
|
||||
updateProbeTexture(probeIdx);
|
||||
}
|
||||
|
||||
void RenderProbeMgr::updateProbeTexture(U32 probeIdx)
|
||||
{
|
||||
if (probeIdx >= ProbeRenderInst::all.size())
|
||||
return;
|
||||
|
||||
const U32 cubeIndex = ProbeRenderInst::all[probeIdx]->mCubemapIndex;
|
||||
mIrradianceArray->updateTexture(ProbeRenderInst::all[probeIdx]->mIrradianceCubemap, cubeIndex);
|
||||
mPrefilterArray->updateTexture(ProbeRenderInst::all[probeIdx]->mPrefilterCubemap, cubeIndex);
|
||||
}
|
||||
|
||||
void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
|
||||
{
|
||||
PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
|
||||
|
|
@ -607,11 +717,11 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
|||
//updateProbes();
|
||||
|
||||
// Early out if nothing to draw.
|
||||
if (!ProbeRenderInst::all.size() || !RenderProbeMgr::smRenderReflectionProbes || mEffectiveProbeCount == 0
|
||||
|| !state->isDiffusePass() || cubeMaps.empty() || irradMaps.empty())
|
||||
if (!ProbeRenderInst::all.size() || !RenderProbeMgr::smRenderReflectionProbes || !state->isDiffusePass() || (mEffectiveProbeCount == 0
|
||||
|| mCubeMapCount != 0 && !hasSkylight))
|
||||
{
|
||||
getProbeArrayEffect()->setSkip(true);
|
||||
return;
|
||||
getProbeArrayEffect()->setSkip(true);
|
||||
return;
|
||||
}
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
|
@ -625,10 +735,18 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
|||
//Array rendering
|
||||
//U32 probeCount = ProbeRenderInst::all.size();
|
||||
|
||||
mProbeArrayEffect->setShaderConst("$hasSkylight", (float)hasSkylight);
|
||||
if (hasSkylight)
|
||||
{
|
||||
mProbeArrayEffect->setCubemapTexture(6, skylightPrefilterMap);
|
||||
mProbeArrayEffect->setCubemapTexture(7, skylightIrradMap);
|
||||
|
||||
}
|
||||
|
||||
if (mEffectiveProbeCount != 0)
|
||||
{
|
||||
mProbeArrayEffect->setCubemapArrayTexture(4, mCubemapArray);
|
||||
mProbeArrayEffect->setCubemapArrayTexture(5, mIrradArray);
|
||||
mProbeArrayEffect->setCubemapArrayTexture(4, mPrefilterArray);
|
||||
mProbeArrayEffect->setCubemapArrayTexture(5, mIrradianceArray);
|
||||
|
||||
String useDebugAtten = Con::getVariable("$Probes::showAttenuation", "0");
|
||||
mProbeArrayEffect->setShaderMacro("DEBUGVIZ_ATTENUATION", useDebugAtten);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
|
|||
Point3F mProbeRefScale;
|
||||
F32 mAtten;
|
||||
|
||||
GFXCubemapHandle mCubemap;
|
||||
GFXCubemapHandle mPrefilterCubemap;
|
||||
GFXCubemapHandle mIrradianceCubemap;
|
||||
|
||||
//Utilized in dynamic reflections
|
||||
|
|
@ -97,6 +97,8 @@ struct ProbeRenderInst : public SystemInterface<ProbeRenderInst>
|
|||
|
||||
ProbeShapeType mProbeShapeType;
|
||||
|
||||
U32 mCubemapIndex;
|
||||
|
||||
public:
|
||||
|
||||
ProbeRenderInst();
|
||||
|
|
@ -161,6 +163,18 @@ class RenderProbeMgr : public RenderBinManager
|
|||
|
||||
Vector<U32> mRegisteredProbes;
|
||||
|
||||
//maximum number of allowed probes
|
||||
static const U32 PROBE_MAX_COUNT = 250;
|
||||
//maximum number of rendered probes per frame adjust as needed
|
||||
static const U32 PROBE_MAX_FRAME = 8;
|
||||
//number of slots to allocate at once in the cubemap array
|
||||
static const U32 PROBE_ARRAY_SLOT_BUFFER_SIZE = 10;
|
||||
|
||||
static const U32 PROBE_IRRAD_SIZE = 32;
|
||||
static const U32 PROBE_PREFILTER_SIZE = 128;
|
||||
static const GFXFormat PROBE_FORMAT = GFXFormatR8G8B8A8;// when hdr fixed GFXFormatR16G16B16A16F; look into bc6h compression
|
||||
static const U32 INVALID_CUBE_SLOT = U32_MAX;
|
||||
|
||||
//Array rendering
|
||||
U32 mEffectiveProbeCount;
|
||||
S32 mMipCount;
|
||||
|
|
@ -173,6 +187,11 @@ class RenderProbeMgr : public RenderBinManager
|
|||
Vector<GFXCubemapHandle> cubeMaps;
|
||||
Vector<GFXCubemapHandle> irradMaps;
|
||||
|
||||
bool hasSkylight;
|
||||
GFXCubemapHandle skylightIrradMap;
|
||||
GFXCubemapHandle skylightPrefilterMap;
|
||||
Point4F skylightPos;
|
||||
|
||||
AlignedArray<Point4F> mProbePositions;
|
||||
AlignedArray<Point4F> mProbeBBMin;
|
||||
AlignedArray<Point4F> mProbeBBMax;
|
||||
|
|
@ -180,8 +199,15 @@ class RenderProbeMgr : public RenderBinManager
|
|||
AlignedArray<float> mProbeRadius;
|
||||
AlignedArray<float> mProbeAttenuation;
|
||||
|
||||
GFXCubemapArrayHandle mCubemapArray;
|
||||
GFXCubemapArrayHandle mIrradArray;
|
||||
//number of cubemaps
|
||||
U32 mCubeMapCount;
|
||||
//number of cubemap slots allocated
|
||||
U32 mCubeSlotCount;
|
||||
//array of cubemap slots, due to the editor these may be mixed around as probes are added and deleted
|
||||
bool mCubeMapSlots[PROBE_MAX_COUNT];
|
||||
|
||||
GFXCubemapArrayHandle mPrefilterArray;
|
||||
GFXCubemapArrayHandle mIrradianceArray;
|
||||
|
||||
//Utilized in forward rendering
|
||||
ProbeConstantMap mConstantLookup;
|
||||
|
|
@ -191,10 +217,14 @@ class RenderProbeMgr : public RenderBinManager
|
|||
//
|
||||
SimObjectPtr<PostEffect> mProbeArrayEffect;
|
||||
|
||||
//Default skylight, used for shape editors, etc
|
||||
ProbeRenderInst* mDefaultSkyLight;
|
||||
|
||||
public:
|
||||
RenderProbeMgr();
|
||||
RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
|
||||
virtual ~RenderProbeMgr();
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
// ConsoleObject
|
||||
|
|
@ -219,6 +249,7 @@ protected:
|
|||
GFXShaderConstBuffer *shaderConsts);
|
||||
|
||||
void _setupStaticParameters();
|
||||
void updateProbeTexture(U32 probeIdx);
|
||||
void _setupPerFrameParameters(const SceneRenderState *state);
|
||||
virtual void addElement(RenderInst *inst);
|
||||
virtual void render(SceneRenderState * state);
|
||||
|
|
@ -230,6 +261,7 @@ protected:
|
|||
public:
|
||||
// RenderBinMgr
|
||||
void updateProbes();
|
||||
void updateProbeTexture(ProbeRenderInst* probe);
|
||||
|
||||
/// Returns the active LM.
|
||||
static inline RenderProbeMgr* getProbeManager();
|
||||
|
|
@ -249,6 +281,16 @@ public:
|
|||
|
||||
void bakeProbe(ReflectionProbe *probeInfo);
|
||||
void bakeProbes();
|
||||
|
||||
U32 _findNextEmptyCubeSlot()
|
||||
{
|
||||
for (U32 i = 0; i < PROBE_MAX_COUNT; i++)
|
||||
{
|
||||
if (!mCubeMapSlots[i])
|
||||
return i;
|
||||
}
|
||||
return INVALID_CUBE_SLOT;
|
||||
}
|
||||
};
|
||||
|
||||
RenderProbeMgr* RenderProbeMgr::getProbeManager()
|
||||
|
|
|
|||
|
|
@ -29,9 +29,13 @@ uniform float4 bbMaxArray[MAX_PROBES];
|
|||
uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
||||
|
||||
#if DEBUGVIZ_CONTRIB
|
||||
uniform float4 probeContribColors[MAX_PROBES];
|
||||
uniform float4 probeContribColors[MAX_PROBES];
|
||||
#endif
|
||||
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(skylightPrefilterMap, 6);
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7);
|
||||
uniform float hasSkylight;
|
||||
|
||||
//Probe IBL stuff
|
||||
struct ProbeData
|
||||
{
|
||||
|
|
@ -64,17 +68,18 @@ float defineSphereSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeR
|
|||
|
||||
float getDistBoxToPoint(float3 pt, float3 extents)
|
||||
{
|
||||
float3 d = max(max(-extents - pt, 0), pt - extents);
|
||||
return max(max(d.x,d.y),d.z);
|
||||
float3 d = max(max(-extents - pt, 0), pt - extents);
|
||||
return max(max(d.x, d.y), d.z);
|
||||
}
|
||||
|
||||
float defineBoxSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay)
|
||||
{
|
||||
float3 surfPosLS = mul(probe.worldToLocal, float4(surface.P, 1.0)).xyz;
|
||||
float atten = probe.attenuation;
|
||||
float probeattenuationvalue = 0.5; // feed meh
|
||||
float atten = 1.0 - probeattenuationvalue;
|
||||
float baseVal = 0.25;
|
||||
float dist = getDistBoxToPoint(surfPosLS,float3(baseVal,baseVal,baseVal));
|
||||
return saturate(smoothstep(baseVal+0.0001,atten*baseVal,dist));
|
||||
float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
|
||||
return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist));
|
||||
}
|
||||
|
||||
// Box Projected IBL Lighting
|
||||
|
|
@ -82,12 +87,12 @@ float defineBoxSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay)
|
|||
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||
float3 boxProject(Surface surface, ProbeData probe)
|
||||
{
|
||||
float3 RayLS = mul(probe.worldToLocal, float4(surface.R,0.0)).xyz;
|
||||
float3 PositionLS = mul( probe.worldToLocal, float4(surface.P,1.0)).xyz;
|
||||
|
||||
float3 unit = probe.boxMax-probe.boxMin;
|
||||
float3 plane1vec = (unit/2 - PositionLS) / RayLS;
|
||||
float3 plane2vec = (-unit/2 - PositionLS) / RayLS;
|
||||
float3 RayLS = mul(probe.worldToLocal, float4(surface.R, 0.0)).xyz;
|
||||
float3 PositionLS = mul(probe.worldToLocal, float4(surface.P, 1.0)).xyz;
|
||||
|
||||
float3 unit = probe.boxMax - probe.boxMin;
|
||||
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;
|
||||
|
|
@ -99,8 +104,7 @@ float3 iblBoxDiffuse(Surface surface, ProbeData probe)
|
|||
{
|
||||
float3 dir = boxProject(surface, probe);
|
||||
|
||||
float lod = surface.roughness*cubeMips;
|
||||
float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probe.probeIdx, lod).xyz;
|
||||
float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probe.probeIdx, 0).xyz;
|
||||
if (probe.contribution>0)
|
||||
return color*probe.contribution;
|
||||
else
|
||||
|
|
@ -154,129 +158,163 @@ float3 iblSkylightSpecular(Surface surface, ProbeData probe)
|
|||
return color;
|
||||
}
|
||||
|
||||
float4 main( PFXVertToPix IN ) : SV_TARGET
|
||||
float4 main(PFXVertToPix IN) : SV_TARGET
|
||||
{
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0.xy);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
IN.uv0.xy, eyePosWorld, IN.wsEyeRay, cameraToWorld);
|
||||
Surface surface = createSurface(normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
IN.uv0.xy, eyePosWorld, IN.wsEyeRay, cameraToWorld);
|
||||
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
float alpha = 1;
|
||||
|
||||
int i = 0;
|
||||
float blendFactor[MAX_PROBES];
|
||||
float blendSum = 0;
|
||||
float blendFacSum = 0;
|
||||
float invBlendSum = 0;
|
||||
int skyID = 0;
|
||||
float probehits = 0;
|
||||
//Set up our struct data
|
||||
ProbeData probes[MAX_PROBES];
|
||||
|
||||
//Process prooooobes
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
if (alpha > 0)
|
||||
{
|
||||
probes[i].wsPosition = inProbePosArray[i].xyz;
|
||||
probes[i].radius = probeConfigData[i].g;
|
||||
probes[i].boxMin = bbMinArray[i].xyz;
|
||||
probes[i].boxMax = bbMaxArray[i].xyz;
|
||||
probes[i].refPosition = inRefPosArray[i].xyz;
|
||||
probes[i].attenuation = probeConfigData[i].b;
|
||||
probes[i].worldToLocal = worldToObjArray[i];
|
||||
probes[i].probeIdx = i;
|
||||
probes[i].type = probeConfigData[i].r;
|
||||
probes[i].contribution = 0;
|
||||
|
||||
if (probes[i].type == 0) //box
|
||||
{
|
||||
probes[i].contribution = defineBoxSpaceInfluence(surface, probes[i], IN.wsEyeRay);
|
||||
probehits++;
|
||||
}
|
||||
else if (probes[i].type == 1) //sphere
|
||||
{
|
||||
probes[i].contribution = defineSphereSpaceInfluence(surface, probes[i], IN.wsEyeRay);
|
||||
probehits++;
|
||||
}
|
||||
else //skylight
|
||||
{
|
||||
//
|
||||
//probes[i].contribution = defineSkylightInfluence(surface, probes[i], IN.wsEyeRay);
|
||||
skyID = i;
|
||||
}
|
||||
|
||||
if (probes[i].contribution>1 || probes[i].contribution<0)
|
||||
probes[i].contribution = 0;
|
||||
|
||||
blendSum += probes[i].contribution;
|
||||
invBlendSum += (1.0f - probes[i].contribution);
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
if (probehits>1.0)
|
||||
{
|
||||
blendFactor[i] = ((probes[i].contribution / blendSum)) / (probehits - 1);
|
||||
blendFactor[i] *= ((probes[i].contribution) / invBlendSum);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
blendFactor[i] = probes[i].contribution;
|
||||
blendFacSum = probes[i].contribution;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
#endif
|
||||
//use probehits for sharp cuts when singular,
|
||||
//blendSum when wanting blend on all edging
|
||||
if (blendSum>1.0)
|
||||
{
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
//Process prooooobes
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
probes[i].contribution = blendFactor[i];
|
||||
probes[i].wsPosition = inProbePosArray[i].xyz;
|
||||
probes[i].radius = probeConfigData[i].g;
|
||||
probes[i].boxMin = bbMinArray[i].xyz;
|
||||
probes[i].boxMax = bbMaxArray[i].xyz;
|
||||
probes[i].refPosition = inRefPosArray[i].xyz;
|
||||
probes[i].attenuation = probeConfigData[i].b;
|
||||
probes[i].worldToLocal = worldToObjArray[i];
|
||||
probes[i].probeIdx = i;
|
||||
probes[i].type = probeConfigData[i].r;
|
||||
probes[i].contribution = 0;
|
||||
|
||||
if (probes[i].type == 0) //box
|
||||
{
|
||||
probes[i].contribution = defineBoxSpaceInfluence(surface, probes[i], IN.wsEyeRay);
|
||||
probehits++;
|
||||
}
|
||||
else if (probes[i].type == 1) //sphere
|
||||
{
|
||||
probes[i].contribution = defineSphereSpaceInfluence(surface, probes[i], IN.wsEyeRay);
|
||||
probehits++;
|
||||
}
|
||||
|
||||
if (probes[i].contribution>1 || probes[i].contribution<0)
|
||||
probes[i].contribution = 0;
|
||||
|
||||
blendSum += probes[i].contribution;
|
||||
invBlendSum += (1.0f - probes[i].contribution);
|
||||
|
||||
alpha -= probes[i].contribution;
|
||||
}
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
if (probehits>1.0)
|
||||
{
|
||||
blendFactor[i] = ((probes[i].contribution / blendSum)) / (probehits - 1);
|
||||
blendFactor[i] *= ((probes[i].contribution) / invBlendSum);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
blendFactor[i] = probes[i].contribution;
|
||||
blendFacSum = probes[i].contribution;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
//use probehits for sharp cuts when singular,
|
||||
//blendSum when wanting blend on all edging
|
||||
if (blendSum>1.0)
|
||||
{
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
probes[i].contribution = blendFactor[i];
|
||||
|
||||
alpha -= probes[i].contribution;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUGVIZ_ATTENUATION == 1
|
||||
float attenVis = 0;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
/*float attenVis = 0;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
attenVis += probes[i].contribution;
|
||||
}
|
||||
return float4(attenVis, attenVis, attenVis, 1);
|
||||
}
|
||||
return float4(attenVis, attenVis, attenVis, 1);*/
|
||||
return float4(alpha, alpha, alpha, 1);
|
||||
#endif
|
||||
|
||||
#if DEBUGVIZ_CONTRIB == 1
|
||||
|
||||
float3 finalContribColor = float3(0, 0, 0);
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
if (probes[i].contribution == 0)
|
||||
continue;
|
||||
float3 finalContribColor = float3(0, 0, 0);
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
if (probes[i].contribution == 0)
|
||||
continue;
|
||||
|
||||
finalContribColor += probes[i].contribution * probeContribColors[i].rgb;
|
||||
finalContribColor += probes[i].contribution * probeContribColors[i].rgb;
|
||||
}
|
||||
|
||||
return float4(finalContribColor, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return float4(finalContribColor, 1);
|
||||
if (hasSkylight && alpha == 1)
|
||||
{
|
||||
float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, surface.NdotV, 0.0, 0.0)).xy;
|
||||
float lod = surface.roughness*cubeMips;
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0
|
||||
float3 specular = TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz * (brdf.x + brdf.y);
|
||||
float3 irradiance = TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz;
|
||||
|
||||
float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
|
||||
//energy conservation
|
||||
float3 kD = 1.0.xxx - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
|
||||
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
float4 finalColor = float4(diffuse + specular * surface.ao, alpha);
|
||||
return finalColor;
|
||||
#elif DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
|
||||
float3 specular = TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz;
|
||||
float4 finalColor = float4(specular, 1);
|
||||
return finalColor;
|
||||
#elif DEBUGVIZ_DIFFCUBEMAP == 1
|
||||
float3 irradiance = TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz;
|
||||
float4 finalColor = float4(irradiance, 1);
|
||||
return finalColor;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0
|
||||
|
||||
|
|
@ -292,17 +330,15 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
|
|||
{
|
||||
if (probes[i].contribution == 0)
|
||||
continue;
|
||||
|
||||
|
||||
if (probes[i].type == 2) //skip skylight
|
||||
continue;
|
||||
|
||||
|
||||
irradiance += iblBoxDiffuse(surface, probes[i]);
|
||||
specular += F*iblBoxSpecular(surface, probes[i]);
|
||||
contrib +=probes[i].contribution;
|
||||
contrib += probes[i].contribution;
|
||||
}
|
||||
contrib = saturate(contrib);
|
||||
irradiance = lerp(iblSkylightDiffuse(surface, probes[skyID]),irradiance,contrib);
|
||||
specular = lerp(F*iblSkylightSpecular(surface, probes[skyID]),specular,contrib);
|
||||
|
||||
//final diffuse color
|
||||
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
|
|
@ -328,7 +364,7 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
|
|||
return float4(cubeColor, 1);
|
||||
|
||||
#elif DEBUGVIZ_DIFFCUBEMAP == 1
|
||||
|
||||
|
||||
float3 cubeColor = float3(0, 0, 0);
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue