mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 08:34:40 +00:00
Implementation of reflection and skylight probes.
Moves lighting math to the diffuse/specular two-channel logic.
This commit is contained in:
parent
1f7cf55204
commit
b19a4b22c8
102 changed files with 12346 additions and 1911 deletions
573
Engine/source/T3D/lighting/IBLUtilities.cpp
Normal file
573
Engine/source/T3D/lighting/IBLUtilities.cpp
Normal file
|
|
@ -0,0 +1,573 @@
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "materials/shaderData.h"
|
||||||
|
#include "gfx/gfxTextureManager.h"
|
||||||
|
#include "gfx/gfxTransformSaver.h"
|
||||||
|
#include "gfx/bitmap/cubemapSaver.h"
|
||||||
|
|
||||||
|
namespace IBLUtilities
|
||||||
|
{
|
||||||
|
void GenerateIrradianceMap(GFXTextureTargetRef renderTarget, GFXCubemapHandle cubemap, GFXCubemapHandle &cubemapOut)
|
||||||
|
{
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
GFXStateBlockRef irrStateBlock;
|
||||||
|
|
||||||
|
ShaderData *irrShaderData;
|
||||||
|
GFXShaderRef irrShader = Sim::findObject("IrradianceShader", irrShaderData) ? irrShaderData->getShader() : NULL;
|
||||||
|
if (!irrShader)
|
||||||
|
{
|
||||||
|
Con::errorf("IBLUtilities::GenerateIrradianceMap() - could not find IrradianceShader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXShaderConstBufferRef irrConsts = irrShader->allocConstBuffer();
|
||||||
|
GFXShaderConstHandle* irrEnvMapSC = irrShader->getShaderConstHandle("$environmentMap");
|
||||||
|
GFXShaderConstHandle* irrFaceSC = irrShader->getShaderConstHandle("$face");
|
||||||
|
|
||||||
|
GFXStateBlockDesc desc;
|
||||||
|
desc.zEnable = false;
|
||||||
|
desc.samplersDefined = true;
|
||||||
|
desc.samplers[0].addressModeU = GFXAddressClamp;
|
||||||
|
desc.samplers[0].addressModeV = GFXAddressClamp;
|
||||||
|
desc.samplers[0].addressModeW = GFXAddressClamp;
|
||||||
|
desc.samplers[0].magFilter = GFXTextureFilterLinear;
|
||||||
|
desc.samplers[0].minFilter = GFXTextureFilterLinear;
|
||||||
|
desc.samplers[0].mipFilter = GFXTextureFilterLinear;
|
||||||
|
|
||||||
|
irrStateBlock = GFX->createStateBlock(desc);
|
||||||
|
|
||||||
|
GFX->pushActiveRenderTarget();
|
||||||
|
GFX->setShader(irrShader);
|
||||||
|
GFX->setShaderConstBuffer(irrConsts);
|
||||||
|
GFX->setStateBlock(irrStateBlock);
|
||||||
|
GFX->setVertexBuffer(NULL);
|
||||||
|
GFX->setCubeTexture(0, cubemap);
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
renderTarget->attachTexture(GFXTextureTarget::Color0, cubemapOut, i);
|
||||||
|
irrConsts->setSafe(irrFaceSC, (S32)i);
|
||||||
|
GFX->setActiveRenderTarget(renderTarget);
|
||||||
|
GFX->clear(GFXClearTarget, LinearColorF::BLACK, 1.0f, 0);
|
||||||
|
GFX->drawPrimitive(GFXTriangleList, 0, 3);
|
||||||
|
renderTarget->resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
GFX->popActiveRenderTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneratePrefilterMap(GFXTextureTargetRef renderTarget, GFXCubemapHandle cubemap, U32 mipLevels, GFXCubemapHandle &cubemapOut)
|
||||||
|
{
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
ShaderData *prefilterShaderData;
|
||||||
|
GFXShaderRef prefilterShader = Sim::findObject("PrefiterCubemapShader", prefilterShaderData) ? prefilterShaderData->getShader() : NULL;
|
||||||
|
if (!prefilterShader)
|
||||||
|
{
|
||||||
|
Con::errorf("IBLUtilities::GeneratePrefilterMap() - could not find PrefiterCubemapShader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GFXShaderConstBufferRef prefilterConsts = prefilterShader->allocConstBuffer();
|
||||||
|
GFXShaderConstHandle* prefilterEnvMapSC = prefilterShader->getShaderConstHandle("$environmentMap");
|
||||||
|
GFXShaderConstHandle* prefilterFaceSC = prefilterShader->getShaderConstHandle("$face");
|
||||||
|
GFXShaderConstHandle* prefilterRoughnessSC = prefilterShader->getShaderConstHandle("$roughness");
|
||||||
|
GFXShaderConstHandle* prefilterMipSizeSC = prefilterShader->getShaderConstHandle("$mipSize");
|
||||||
|
GFXShaderConstHandle* prefilterResolutionSC = prefilterShader->getShaderConstHandle("$resolution");
|
||||||
|
|
||||||
|
GFX->pushActiveRenderTarget();
|
||||||
|
GFX->setShader(prefilterShader);
|
||||||
|
GFX->setShaderConstBuffer(prefilterConsts);
|
||||||
|
GFX->setCubeTexture(0, cubemap);
|
||||||
|
|
||||||
|
U32 prefilterSize = cubemapOut->getSize();
|
||||||
|
|
||||||
|
for (U32 face = 0; face < 6; face++)
|
||||||
|
{
|
||||||
|
prefilterConsts->setSafe(prefilterFaceSC, (S32)face);
|
||||||
|
prefilterConsts->setSafe(prefilterResolutionSC, renderTarget->getSize().x);
|
||||||
|
for (U32 mip = 0; mip < mipLevels; mip++)
|
||||||
|
{
|
||||||
|
S32 mipSize = prefilterSize >> mip;
|
||||||
|
F32 roughness = (float)mip / (float)(mipLevels - 1);
|
||||||
|
prefilterConsts->setSafe(prefilterRoughnessSC, roughness);
|
||||||
|
prefilterConsts->setSafe(prefilterMipSizeSC, mipSize);
|
||||||
|
U32 size = prefilterSize * mPow(0.5f, mip);
|
||||||
|
renderTarget->attachTexture(GFXTextureTarget::Color0, cubemapOut, face, mip);
|
||||||
|
GFX->setActiveRenderTarget(renderTarget, false);//we set the viewport ourselves
|
||||||
|
GFX->setViewport(RectI(0, 0, size, size));
|
||||||
|
GFX->clear(GFXClearTarget, LinearColorF::BLACK, 1.0f, 0);
|
||||||
|
GFX->drawPrimitive(GFXTriangleList, 0, 3);
|
||||||
|
renderTarget->resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GFX->popActiveRenderTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateBRDFTexture(GFXTexHandle &textureOut)
|
||||||
|
{
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
ShaderData *brdfShaderData;
|
||||||
|
GFXShaderRef brdfShader = Sim::findObject("BRDFLookupShader", brdfShaderData) ? brdfShaderData->getShader() : NULL;
|
||||||
|
if (!brdfShader)
|
||||||
|
{
|
||||||
|
Con::errorf("IBLUtilities::GenerateBRDFTexture() - could not find BRDFLookupShader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 textureSize = textureOut->getWidth();
|
||||||
|
|
||||||
|
GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget();
|
||||||
|
GFX->pushActiveRenderTarget();
|
||||||
|
|
||||||
|
GFX->setShader(brdfShader);
|
||||||
|
renderTarget->attachTexture(GFXTextureTarget::Color0, textureOut);
|
||||||
|
GFX->setActiveRenderTarget(renderTarget);//potential bug here with the viewport not updating with the new size
|
||||||
|
GFX->setViewport(RectI(0, 0, textureSize, textureSize));//see above comment
|
||||||
|
GFX->clear(GFXClearTarget, LinearColorF::BLUE, 1.0f, 0);
|
||||||
|
GFX->drawPrimitive(GFXTriangleList, 0, 3);
|
||||||
|
renderTarget->resolve();
|
||||||
|
|
||||||
|
GFX->popActiveRenderTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bakeReflection(String outputPath, S32 resolution)
|
||||||
|
{
|
||||||
|
//GFXDEBUGEVENT_SCOPE(ReflectionProbe_Bake, ColorI::WHITE);
|
||||||
|
|
||||||
|
/*PostEffect *preCapture = dynamic_cast<PostEffect*>(Sim::findObject("AL_PreCapture"));
|
||||||
|
PostEffect *deferredShading = dynamic_cast<PostEffect*>(Sim::findObject("AL_DeferredShading"));
|
||||||
|
if (preCapture)
|
||||||
|
preCapture->enable();
|
||||||
|
if (deferredShading)
|
||||||
|
deferredShading->disable();
|
||||||
|
|
||||||
|
//if (mReflectionModeType == StaticCubemap || mReflectionModeType == BakedCubemap || mReflectionModeType == SkyLight)
|
||||||
|
{
|
||||||
|
if (!mCubemap)
|
||||||
|
{
|
||||||
|
mCubemap = new CubemapData();
|
||||||
|
mCubemap->registerObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReflectionModeType == DynamicCubemap && mDynamicCubemap.isNull())
|
||||||
|
{
|
||||||
|
//mCubemap->createMap();
|
||||||
|
mDynamicCubemap = GFX->createCubemap();
|
||||||
|
mDynamicCubemap->initDynamic(resolution, GFXFormatR8G8B8);
|
||||||
|
}
|
||||||
|
else if (mReflectionModeType != DynamicCubemap)
|
||||||
|
{
|
||||||
|
if (mReflectionPath.isEmpty() || !mPersistentId)
|
||||||
|
{
|
||||||
|
if (!mPersistentId)
|
||||||
|
mPersistentId = getOrCreatePersistentId();
|
||||||
|
|
||||||
|
mReflectionPath = outputPath.c_str();
|
||||||
|
|
||||||
|
mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validCubemap = true;
|
||||||
|
|
||||||
|
// Save the current transforms so we can restore
|
||||||
|
// it for child control rendering below.
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
//bool saveEditingMission = gEditingMission;
|
||||||
|
//gEditingMission = false;
|
||||||
|
|
||||||
|
//Set this to true to use the prior method where it goes through the SPT_Reflect path for the bake
|
||||||
|
bool probeRenderState = ReflectionProbe::smRenderReflectionProbes;
|
||||||
|
ReflectionProbe::smRenderReflectionProbes = false;
|
||||||
|
for (U32 i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
GFXTexHandle blendTex;
|
||||||
|
blendTex.set(resolution, resolution, GFXFormatR8G8B8A8, &GFXRenderTargetProfile, "");
|
||||||
|
|
||||||
|
GFXTextureTargetRef mBaseTarget = GFX->allocRenderToTextureTarget();
|
||||||
|
|
||||||
|
GFX->clearTextureStateImmediate(0);
|
||||||
|
if (mReflectionModeType == DynamicCubemap)
|
||||||
|
mBaseTarget->attachTexture(GFXTextureTarget::Color0, mDynamicCubemap, i);
|
||||||
|
else
|
||||||
|
mBaseTarget->attachTexture(GFXTextureTarget::Color0, blendTex);
|
||||||
|
|
||||||
|
// Standard view that will be overridden below.
|
||||||
|
VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: // D3DCUBEMAP_FACE_POSITIVE_X:
|
||||||
|
vLookatPt = VectorF(1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 1: // D3DCUBEMAP_FACE_NEGATIVE_X:
|
||||||
|
vLookatPt = VectorF(-1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 2: // D3DCUBEMAP_FACE_POSITIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
break;
|
||||||
|
case 3: // D3DCUBEMAP_FACE_NEGATIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, -1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case 4: // D3DCUBEMAP_FACE_POSITIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create camera matrix
|
||||||
|
VectorF cross = mCross(vUpVec, vLookatPt);
|
||||||
|
cross.normalizeSafe();
|
||||||
|
|
||||||
|
MatrixF matView(true);
|
||||||
|
matView.setColumn(0, cross);
|
||||||
|
matView.setColumn(1, vLookatPt);
|
||||||
|
matView.setColumn(2, vUpVec);
|
||||||
|
matView.setPosition(getPosition());
|
||||||
|
matView.inverse();
|
||||||
|
|
||||||
|
// set projection to 90 degrees vertical and horizontal
|
||||||
|
F32 left, right, top, bottom;
|
||||||
|
F32 nearPlane = 0.01f;
|
||||||
|
F32 farDist = 1000.f;
|
||||||
|
|
||||||
|
MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane);
|
||||||
|
Frustum frustum(false, left, right, top, bottom, nearPlane, farDist);
|
||||||
|
|
||||||
|
renderFrame(&mBaseTarget, matView, frustum, StaticObjectType | StaticShapeObjectType & EDITOR_RENDER_TYPEMASK, gCanvasClearColor);
|
||||||
|
|
||||||
|
mBaseTarget->resolve();
|
||||||
|
|
||||||
|
mCubemap->setCubeFaceTexture(i, blendTex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReflectionModeType != DynamicCubemap && validCubemap)
|
||||||
|
{
|
||||||
|
if (mCubemap->mCubemap)
|
||||||
|
mCubemap->updateFaces();
|
||||||
|
else
|
||||||
|
mCubemap->createMap();
|
||||||
|
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str());
|
||||||
|
|
||||||
|
CubemapSaver::save(mCubemap->mCubemap, fileName);
|
||||||
|
|
||||||
|
if (!Platform::isFile(fileName))
|
||||||
|
{
|
||||||
|
validCubemap = false; //if we didn't save right, just
|
||||||
|
Con::errorf("Failed to properly save out the skylight baked cubemap!");
|
||||||
|
}
|
||||||
|
|
||||||
|
mDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculateSHTerms();
|
||||||
|
|
||||||
|
ReflectionProbe::smRenderReflectionProbes = probeRenderState;
|
||||||
|
setMaskBits(-1);
|
||||||
|
|
||||||
|
if (preCapture)
|
||||||
|
preCapture->disable();
|
||||||
|
if (deferredShading)
|
||||||
|
deferredShading->enable();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearColorF decodeSH(Point3F normal, const LinearColorF SHTerms[9], const F32 SHConstants[5])
|
||||||
|
{
|
||||||
|
float x = normal.x;
|
||||||
|
float y = normal.y;
|
||||||
|
float z = normal.z;
|
||||||
|
|
||||||
|
LinearColorF l00 = SHTerms[0];
|
||||||
|
|
||||||
|
LinearColorF l10 = SHTerms[1];
|
||||||
|
LinearColorF l11 = SHTerms[2];
|
||||||
|
LinearColorF l12 = SHTerms[3];
|
||||||
|
|
||||||
|
LinearColorF l20 = SHTerms[4];
|
||||||
|
LinearColorF l21 = SHTerms[5];
|
||||||
|
LinearColorF l22 = SHTerms[6];
|
||||||
|
LinearColorF l23 = SHTerms[7];
|
||||||
|
LinearColorF l24 = SHTerms[8];
|
||||||
|
|
||||||
|
LinearColorF result = (
|
||||||
|
l00 * SHConstants[0] +
|
||||||
|
|
||||||
|
l12 * SHConstants[1] * x +
|
||||||
|
l10 * SHConstants[1] * y +
|
||||||
|
l11 * SHConstants[1] * z +
|
||||||
|
|
||||||
|
l20 * SHConstants[2] * x*y +
|
||||||
|
l21 * SHConstants[2] * y*z +
|
||||||
|
l22 * SHConstants[3] * (3.0*z*z - 1.0) +
|
||||||
|
l23 * SHConstants[2] * x*z +
|
||||||
|
l24 * SHConstants[4] * (x*x - y * y)
|
||||||
|
);
|
||||||
|
|
||||||
|
return LinearColorF(mMax(result.red, 0), mMax(result.green, 0), mMax(result.blue, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
MatrixF getSideMatrix(U32 side)
|
||||||
|
{
|
||||||
|
// Standard view that will be overridden below.
|
||||||
|
VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
switch (side)
|
||||||
|
{
|
||||||
|
case 0: // D3DCUBEMAP_FACE_POSITIVE_X:
|
||||||
|
vLookatPt = VectorF(1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 1: // D3DCUBEMAP_FACE_NEGATIVE_X:
|
||||||
|
vLookatPt = VectorF(-1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 2: // D3DCUBEMAP_FACE_POSITIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
break;
|
||||||
|
case 3: // D3DCUBEMAP_FACE_NEGATIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, -1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case 4: // D3DCUBEMAP_FACE_POSITIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create camera matrix
|
||||||
|
VectorF cross = mCross(vUpVec, vLookatPt);
|
||||||
|
cross.normalizeSafe();
|
||||||
|
|
||||||
|
MatrixF rotMat(true);
|
||||||
|
rotMat.setColumn(0, cross);
|
||||||
|
rotMat.setColumn(1, vLookatPt);
|
||||||
|
rotMat.setColumn(2, vUpVec);
|
||||||
|
//rotMat.inverse();
|
||||||
|
|
||||||
|
return rotMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
F32 harmonics(U32 termId, Point3F normal)
|
||||||
|
{
|
||||||
|
F32 x = normal.x;
|
||||||
|
F32 y = normal.y;
|
||||||
|
F32 z = normal.z;
|
||||||
|
|
||||||
|
switch (termId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return 1.0;
|
||||||
|
case 1:
|
||||||
|
return y;
|
||||||
|
case 2:
|
||||||
|
return z;
|
||||||
|
case 3:
|
||||||
|
return x;
|
||||||
|
case 4:
|
||||||
|
return x * y;
|
||||||
|
case 5:
|
||||||
|
return y * z;
|
||||||
|
case 6:
|
||||||
|
return 3.0*z*z - 1.0;
|
||||||
|
case 7:
|
||||||
|
return x * z;
|
||||||
|
default:
|
||||||
|
return x * x - y * y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearColorF sampleSide(GBitmap* cubeFaceBitmaps[6], const U32& cubemapResolution, const U32& termindex, const U32& sideIndex)
|
||||||
|
{
|
||||||
|
MatrixF sideRot = getSideMatrix(sideIndex);
|
||||||
|
|
||||||
|
LinearColorF result = LinearColorF::ZERO;
|
||||||
|
F32 divider = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y<cubemapResolution; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x<cubemapResolution; x++)
|
||||||
|
{
|
||||||
|
Point2F sidecoord = ((Point2F(x, y) + Point2F(0.5, 0.5)) / Point2F(cubemapResolution, cubemapResolution))*2.0 - Point2F(1.0, 1.0);
|
||||||
|
Point3F normal = Point3F(sidecoord.x, sidecoord.y, -1.0);
|
||||||
|
normal.normalize();
|
||||||
|
|
||||||
|
F32 minBrightness = Con::getFloatVariable("$pref::GI::Cubemap_Sample_MinBrightness", 0.001f);
|
||||||
|
|
||||||
|
LinearColorF texel = cubeFaceBitmaps[sideIndex]->sampleTexel(y, x);
|
||||||
|
texel = LinearColorF(mMax(texel.red, minBrightness), mMax(texel.green, minBrightness), mMax(texel.blue, minBrightness)) * Con::getFloatVariable("$pref::GI::Cubemap_Gain", 1.5);
|
||||||
|
|
||||||
|
Point3F dir;
|
||||||
|
sideRot.mulP(normal, &dir);
|
||||||
|
|
||||||
|
result += texel * harmonics(termindex, dir) * -normal.z;
|
||||||
|
divider += -normal.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result /= divider;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//SH Calculations
|
||||||
|
// From http://sunandblackcat.com/tipFullView.php?l=eng&topicid=32&topic=Spherical-Harmonics-From-Cube-Texture
|
||||||
|
// With shader decode logic from https://github.com/nicknikolov/cubemap-sh
|
||||||
|
void calculateSHTerms(GFXCubemapHandle cubemap, LinearColorF SHTerms[9], F32 SHConstants[5])
|
||||||
|
{
|
||||||
|
if (!cubemap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const VectorF cubemapFaceNormals[6] =
|
||||||
|
{
|
||||||
|
// D3DCUBEMAP_FACE_POSITIVE_X:
|
||||||
|
VectorF(1.0f, 0.0f, 0.0f),
|
||||||
|
// D3DCUBEMAP_FACE_NEGATIVE_X:
|
||||||
|
VectorF(-1.0f, 0.0f, 0.0f),
|
||||||
|
// D3DCUBEMAP_FACE_POSITIVE_Y:
|
||||||
|
VectorF(0.0f, 1.0f, 0.0f),
|
||||||
|
// D3DCUBEMAP_FACE_NEGATIVE_Y:
|
||||||
|
VectorF(0.0f, -1.0f, 0.0f),
|
||||||
|
// D3DCUBEMAP_FACE_POSITIVE_Z:
|
||||||
|
VectorF(0.0f, 0.0f, 1.0f),
|
||||||
|
// D3DCUBEMAP_FACE_NEGATIVE_Z:
|
||||||
|
VectorF(0.0f, 0.0f, -1.0f),
|
||||||
|
};
|
||||||
|
|
||||||
|
U32 cubemapResolution = cubemap->getSize();
|
||||||
|
|
||||||
|
GBitmap* cubeFaceBitmaps[6];
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
cubeFaceBitmaps[i] = new GBitmap(cubemapResolution, cubemapResolution, false, GFXFormatR16G16B16A16F);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we fail to parse the cubemap for whatever reason, we really can't continue
|
||||||
|
if (!CubemapSaver::getBitmaps(cubemap, GFXFormatR8G8B8, cubeFaceBitmaps))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Set up our constants
|
||||||
|
F32 L0 = Con::getFloatVariable("$pref::GI::SH_Term_L0", 1.0f);
|
||||||
|
F32 L1 = Con::getFloatVariable("$pref::GI::SH_Term_L1", 1.8f);
|
||||||
|
F32 L2 = Con::getFloatVariable("$pref::GI::SH_Term_L2", 0.83f);
|
||||||
|
F32 L2m2_L2m1_L21 = Con::getFloatVariable("$pref::GI::SH_Term_L2m2", 2.9f);
|
||||||
|
F32 L20 = Con::getFloatVariable("$pref::GI::SH_Term_L20", 0.58f);
|
||||||
|
F32 L22 = Con::getFloatVariable("$pref::GI::SH_Term_L22", 1.1f);
|
||||||
|
|
||||||
|
SHConstants[0] = L0;
|
||||||
|
SHConstants[1] = L1;
|
||||||
|
SHConstants[2] = L2 * L2m2_L2m1_L21;
|
||||||
|
SHConstants[3] = L2 * L20;
|
||||||
|
SHConstants[4] = L2 * L22;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
//Clear it, just to be sure
|
||||||
|
SHTerms[i] = LinearColorF(0.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
//Now, encode for each side
|
||||||
|
SHTerms[i] = sampleSide(cubeFaceBitmaps, cubemapResolution, i, 0); //POS_X
|
||||||
|
SHTerms[i] += sampleSide(cubeFaceBitmaps, cubemapResolution, i, 1); //NEG_X
|
||||||
|
SHTerms[i] += sampleSide(cubeFaceBitmaps, cubemapResolution, i, 2); //POS_Y
|
||||||
|
SHTerms[i] += sampleSide(cubeFaceBitmaps, cubemapResolution, i, 3); //NEG_Y
|
||||||
|
SHTerms[i] += sampleSide(cubeFaceBitmaps, cubemapResolution, i, 4); //POS_Z
|
||||||
|
SHTerms[i] += sampleSide(cubeFaceBitmaps, cubemapResolution, i, 5); //NEG_Z
|
||||||
|
|
||||||
|
//Average
|
||||||
|
SHTerms[i] /= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 6; i++)
|
||||||
|
SAFE_DELETE(cubeFaceBitmaps[i]);
|
||||||
|
|
||||||
|
/*bool mExportSHTerms = false;
|
||||||
|
if (mExportSHTerms)
|
||||||
|
{
|
||||||
|
for (U32 f = 0; f < 6; f++)
|
||||||
|
{
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s_DecodedFaces_%d.png", mReflectionPath.c_str(),
|
||||||
|
mProbeUniqueID.c_str(), f);
|
||||||
|
|
||||||
|
LinearColorF color = decodeSH(cubemapFaceNormals[f]);
|
||||||
|
|
||||||
|
FileStream stream;
|
||||||
|
if (stream.open(fileName, Torque::FS::File::Write))
|
||||||
|
{
|
||||||
|
GBitmap bitmap(mCubemapResolution, mCubemapResolution, false, GFXFormatR8G8B8);
|
||||||
|
|
||||||
|
bitmap.fill(color.toColorI());
|
||||||
|
|
||||||
|
bitmap.writeBitmap("png", stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 f = 0; f < 9; f++)
|
||||||
|
{
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s_SHTerms_%d.png", mReflectionPath.c_str(),
|
||||||
|
mProbeUniqueID.c_str(), f);
|
||||||
|
|
||||||
|
LinearColorF color = mProbeInfo->SHTerms[f];
|
||||||
|
|
||||||
|
FileStream stream;
|
||||||
|
if (stream.open(fileName, Torque::FS::File::Write))
|
||||||
|
{
|
||||||
|
GBitmap bitmap(mCubemapResolution, mCubemapResolution, false, GFXFormatR8G8B8);
|
||||||
|
|
||||||
|
bitmap.fill(color.toColorI());
|
||||||
|
|
||||||
|
bitmap.writeBitmap("png", stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
F32 areaElement(F32 x, F32 y)
|
||||||
|
{
|
||||||
|
return mAtan2(x * y, (F32)mSqrt(x * x + y * y + 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
F32 texelSolidAngle(F32 aU, F32 aV, U32 width, U32 height)
|
||||||
|
{
|
||||||
|
// transform from [0..res - 1] to [- (1 - 1 / res) .. (1 - 1 / res)]
|
||||||
|
// ( 0.5 is for texel center addressing)
|
||||||
|
const F32 U = (2.0 * (aU + 0.5) / width) - 1.0;
|
||||||
|
const F32 V = (2.0 * (aV + 0.5) / height) - 1.0;
|
||||||
|
|
||||||
|
// shift from a demi texel, mean 1.0 / size with U and V in [-1..1]
|
||||||
|
const F32 invResolutionW = 1.0 / width;
|
||||||
|
const F32 invResolutionH = 1.0 / height;
|
||||||
|
|
||||||
|
// U and V are the -1..1 texture coordinate on the current face.
|
||||||
|
// get projected area for this texel
|
||||||
|
const F32 x0 = U - invResolutionW;
|
||||||
|
const F32 y0 = V - invResolutionH;
|
||||||
|
const F32 x1 = U + invResolutionW;
|
||||||
|
const F32 y1 = V + invResolutionH;
|
||||||
|
const F32 angle = areaElement(x0, y0) - areaElement(x0, y1) - areaElement(x1, y0) + areaElement(x1, y1);
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
};
|
||||||
30
Engine/source/T3D/lighting/IBLUtilities.h
Normal file
30
Engine/source/T3D/lighting/IBLUtilities.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace IBLUtilities
|
||||||
|
{
|
||||||
|
void GenerateIrradianceMap(GFXTextureTargetRef renderTarget, GFXCubemapHandle cubemap, GFXCubemapHandle &cubemapOut);
|
||||||
|
|
||||||
|
void GeneratePrefilterMap(GFXTextureTargetRef renderTarget, GFXCubemapHandle cubemap, U32 mipLevels, GFXCubemapHandle &cubemapOut);
|
||||||
|
|
||||||
|
void GenerateBRDFTexture(GFXTexHandle &textureOut);
|
||||||
|
|
||||||
|
void bakeReflection(String outputPath, S32 resolution);
|
||||||
|
|
||||||
|
LinearColorF decodeSH(Point3F normal, const LinearColorF SHTerms[9], const F32 SHConstants[5]);
|
||||||
|
|
||||||
|
MatrixF getSideMatrix(U32 side);
|
||||||
|
|
||||||
|
F32 harmonics(U32 termId, Point3F normal);
|
||||||
|
|
||||||
|
LinearColorF sampleSide(GBitmap* cubeFaceBitmaps[6], const U32& cubemapResolution, const U32& termindex, const U32& sideIndex);
|
||||||
|
|
||||||
|
//
|
||||||
|
//SH Calculations
|
||||||
|
// From http://sunandblackcat.com/tipFullView.php?l=eng&topicid=32&topic=Spherical-Harmonics-From-Cube-Texture
|
||||||
|
// With shader decode logic from https://github.com/nicknikolov/cubemap-sh
|
||||||
|
void calculateSHTerms(GFXCubemapHandle cubemap, LinearColorF SHTerms[9], F32 SHConstants[5]);
|
||||||
|
|
||||||
|
F32 texelSolidAngle(F32 aU, F32 aV, U32 width, U32 height);
|
||||||
|
|
||||||
|
F32 areaElement(F32 x, F32 y);
|
||||||
|
};
|
||||||
1285
Engine/source/T3D/lighting/reflectionProbe.cpp
Normal file
1285
Engine/source/T3D/lighting/reflectionProbe.cpp
Normal file
File diff suppressed because it is too large
Load diff
278
Engine/source/T3D/lighting/reflectionProbe.h
Normal file
278
Engine/source/T3D/lighting/reflectionProbe.h
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef REFLECTIONPROBE_H
|
||||||
|
#define REFLECTIONPROBE_H
|
||||||
|
|
||||||
|
#ifndef _SCENEOBJECT_H_
|
||||||
|
#include "scene/sceneObject.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXVERTEXBUFFER_H_
|
||||||
|
#include "gfx/gfxVertexBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||||
|
#include "gfx/gfxPrimitiveBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _TSSHAPEINSTANCE_H_
|
||||||
|
#include "ts/tsShapeInstance.h"
|
||||||
|
#endif
|
||||||
|
#include "lighting/lightInfo.h"
|
||||||
|
|
||||||
|
#ifndef _RENDERPASSMANAGER_H_
|
||||||
|
#include "renderInstance/renderPassManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROBEMANAGER_H
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class BaseMatInstance;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// This class implements a basic SceneObject that can exist in the world at a
|
||||||
|
// 3D position and render itself. There are several valid ways to render an
|
||||||
|
// object in Torque. This class implements the preferred rendering method which
|
||||||
|
// is to submit a MeshRenderInst along with a Material, vertex buffer,
|
||||||
|
// primitive buffer, and transform and allow the RenderMeshMgr handle the
|
||||||
|
// actual setup and rendering for you.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ReflectionProbe : public SceneObject
|
||||||
|
{
|
||||||
|
typedef SceneObject Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum IndrectLightingModeType
|
||||||
|
{
|
||||||
|
NoIndirect = 0,
|
||||||
|
AmbientColor = 1,
|
||||||
|
SphericalHarmonics = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReflectionModeType
|
||||||
|
{
|
||||||
|
NoReflection = 0,
|
||||||
|
StaticCubemap = 1,
|
||||||
|
BakedCubemap = 2,
|
||||||
|
DynamicCubemap = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Networking masks
|
||||||
|
// We need to implement a mask specifically to handle
|
||||||
|
// updating our transform from the server object to its
|
||||||
|
// client-side "ghost". We also need to implement a
|
||||||
|
// maks for handling editor updates to our properties
|
||||||
|
// (like material).
|
||||||
|
enum MaskBits
|
||||||
|
{
|
||||||
|
TransformMask = Parent::NextFreeMask << 0,
|
||||||
|
UpdateMask = Parent::NextFreeMask << 1,
|
||||||
|
EnabledMask = Parent::NextFreeMask << 2,
|
||||||
|
CubemapMask = Parent::NextFreeMask << 3,
|
||||||
|
ModeMask = Parent::NextFreeMask << 4,
|
||||||
|
RadiusMask = Parent::NextFreeMask << 5,
|
||||||
|
ShapeTypeMask = Parent::NextFreeMask << 6,
|
||||||
|
BakeInfoMask = Parent::NextFreeMask << 7,
|
||||||
|
NextFreeMask = Parent::NextFreeMask << 8
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mBake;
|
||||||
|
bool mEnabled;
|
||||||
|
bool mDirty;
|
||||||
|
|
||||||
|
Resource<TSShape> mEditorShape;
|
||||||
|
TSShapeInstance* mEditorShapeInst;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Rendering variables
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
ProbeInfo::ProbeShapeType mProbeShapeType;
|
||||||
|
|
||||||
|
ProbeInfo* mProbeInfo;
|
||||||
|
|
||||||
|
//Indirect Lighting Contribution stuff
|
||||||
|
IndrectLightingModeType mIndrectLightingModeType;
|
||||||
|
LinearColorF mAmbientColor;
|
||||||
|
LinearColorF mSphericalHarmonics;
|
||||||
|
|
||||||
|
//Reflection Contribution stuff
|
||||||
|
ReflectionModeType mReflectionModeType;
|
||||||
|
|
||||||
|
F32 mRadius;
|
||||||
|
|
||||||
|
String mCubemapName;
|
||||||
|
CubemapData *mCubemap;
|
||||||
|
GFXCubemapHandle mDynamicCubemap;
|
||||||
|
bool mUseCubemap;
|
||||||
|
|
||||||
|
//irridiance resources
|
||||||
|
GFXCubemapHandle mIrridianceMap;
|
||||||
|
|
||||||
|
//prefilter resources
|
||||||
|
GFXCubemapHandle mPrefilterMap;
|
||||||
|
U32 mPrefilterMipLevels;
|
||||||
|
U32 mPrefilterSize;
|
||||||
|
|
||||||
|
//brdflookup resources - shares the texture target with the prefilter
|
||||||
|
GFXTexHandle mBrdfTexture;
|
||||||
|
|
||||||
|
String mReflectionPath;
|
||||||
|
String mProbeUniqueID;
|
||||||
|
|
||||||
|
// Define our vertex format here so we don't have to
|
||||||
|
// change it in multiple spots later
|
||||||
|
typedef GFXVertexPNTTB VertexType;
|
||||||
|
|
||||||
|
// The GFX vertex and primitive buffers
|
||||||
|
GFXVertexBufferHandle< VertexType > mVertexBuffer;
|
||||||
|
GFXPrimitiveBufferHandle mPrimitiveBuffer;
|
||||||
|
|
||||||
|
U32 mSphereVertCount;
|
||||||
|
U32 mSpherePrimitiveCount;
|
||||||
|
|
||||||
|
//Debug rendering
|
||||||
|
static bool smRenderReflectionProbes;
|
||||||
|
static bool smRenderPreviewProbes;
|
||||||
|
|
||||||
|
U32 mDynamicLastBakeMS;
|
||||||
|
U32 mRefreshRateMS;
|
||||||
|
|
||||||
|
GBitmap* mCubeFaceBitmaps[6];
|
||||||
|
U32 mCubemapResolution;
|
||||||
|
|
||||||
|
F32 mMaxDrawDistance;
|
||||||
|
|
||||||
|
bool mResourcesCreated;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReflectionProbe();
|
||||||
|
virtual ~ReflectionProbe();
|
||||||
|
|
||||||
|
// Declare this object as a ConsoleObject so that we can
|
||||||
|
// instantiate it into the world and network it
|
||||||
|
DECLARE_CONOBJECT(ReflectionProbe);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Object Editing
|
||||||
|
// Since there is always a server and a client object in Torque and we
|
||||||
|
// actually edit the server object we need to implement some basic
|
||||||
|
// networking functions
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Set up any fields that we want to be editable (like position)
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
// Allows the object to update its editable settings
|
||||||
|
// from the server object to the client
|
||||||
|
virtual void inspectPostApply();
|
||||||
|
|
||||||
|
static bool _setEnabled(void *object, const char *index, const char *data);
|
||||||
|
static bool _doBake(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
static bool protectedSetSHTerms(void *object, const char *index, const char *data);
|
||||||
|
static bool protectedSetSHConsts(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
// Handle when we are added to the scene and removed from the scene
|
||||||
|
bool onAdd();
|
||||||
|
void onRemove();
|
||||||
|
|
||||||
|
virtual void writeFields(Stream &stream, U32 tabStop);
|
||||||
|
virtual bool writeField(StringTableEntry fieldname, const char *value);
|
||||||
|
|
||||||
|
// Override this so that we can dirty the network flag when it is called
|
||||||
|
void setTransform(const MatrixF &mat);
|
||||||
|
|
||||||
|
// This function handles sending the relevant data from the server
|
||||||
|
// object to the client object
|
||||||
|
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
|
||||||
|
// This function handles receiving relevant data from the server
|
||||||
|
// object and applying it to the client object
|
||||||
|
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Object Rendering
|
||||||
|
// Torque utilizes a "batch" rendering system. This means that it builds a
|
||||||
|
// list of objects that need to render (via RenderInst's) and then renders
|
||||||
|
// them all in one batch. This allows it to optimized on things like
|
||||||
|
// minimizing texture, state, and shader switching by grouping objects that
|
||||||
|
// use the same Materials.
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create the geometry for rendering
|
||||||
|
void createGeometry();
|
||||||
|
|
||||||
|
// Get the Material instance
|
||||||
|
void updateMaterial();
|
||||||
|
|
||||||
|
void updateProbeParams();
|
||||||
|
|
||||||
|
bool createClientResources();
|
||||||
|
void generateTextures();
|
||||||
|
|
||||||
|
// This is the function that allows this object to submit itself for rendering
|
||||||
|
void prepRenderImage(SceneRenderState *state);
|
||||||
|
|
||||||
|
void _onRenderViz(ObjectRenderInst *ri,
|
||||||
|
SceneRenderState *state,
|
||||||
|
BaseMatInstance *overrideMat);
|
||||||
|
|
||||||
|
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
|
||||||
|
|
||||||
|
//Spherical Harmonics
|
||||||
|
void calculateSHTerms();
|
||||||
|
F32 texelSolidAngle(F32 aU, F32 aV, U32 width, U32 height);
|
||||||
|
F32 areaElement(F32 x, F32 y);
|
||||||
|
|
||||||
|
//
|
||||||
|
MatrixF getSideMatrix(U32 side);
|
||||||
|
LinearColorF decodeSH(Point3F normal);
|
||||||
|
|
||||||
|
//
|
||||||
|
void calcDirectionVector(U32 face, U32 face_x, U32 face_y, F32& out_x, F32& out_y, F32& out_z) const;
|
||||||
|
F32 calcSolidAngle(U32 face, U32 x, U32 y) const;
|
||||||
|
LinearColorF sampleFace(U32 face, F32 s, F32 t);
|
||||||
|
LinearColorF readTexelClamped(U32 face, U32 x, U32 y);
|
||||||
|
void computeTexCoords(F32 x, F32 y, F32 z, U32& out_face, F32& out_s, F32& out_t);
|
||||||
|
LinearColorF readTexel(U32 face, U32 x, U32 y) const;
|
||||||
|
|
||||||
|
//
|
||||||
|
LinearColorF sampleSide(U32 termindex, U32 sideIndex);
|
||||||
|
F32 harmonics(U32 termId, Point3F normal);
|
||||||
|
|
||||||
|
|
||||||
|
//Baking
|
||||||
|
void bake(String outputPath, S32 resolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ProbeInfo::ProbeShapeType ReflectProbeType;
|
||||||
|
DefineEnumType(ReflectProbeType);
|
||||||
|
|
||||||
|
typedef ReflectionProbe::IndrectLightingModeType IndrectLightingModeEnum;
|
||||||
|
DefineEnumType(IndrectLightingModeEnum);
|
||||||
|
|
||||||
|
typedef ReflectionProbe::ReflectionModeType ReflectionModeEnum;
|
||||||
|
DefineEnumType(ReflectionModeEnum);
|
||||||
|
|
||||||
|
#endif // _ReflectionProbe_H_
|
||||||
899
Engine/source/T3D/lighting/skylight.cpp
Normal file
899
Engine/source/T3D/lighting/skylight.cpp
Normal file
|
|
@ -0,0 +1,899 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "T3D/lighting/Skylight.h"
|
||||||
|
#include "math/mathIO.h"
|
||||||
|
#include "scene/sceneRenderState.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "core/stream/bitStream.h"
|
||||||
|
#include "materials/baseMatInstance.h"
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "gfx/gfxDrawUtil.h"
|
||||||
|
#include "gfx/gfxDebugEvent.h"
|
||||||
|
#include "gfx/gfxTransformSaver.h"
|
||||||
|
#include "math/mathUtils.h"
|
||||||
|
#include "gfx/bitmap/gBitmap.h"
|
||||||
|
#include "core/stream/fileStream.h"
|
||||||
|
#include "core/fileObject.h"
|
||||||
|
#include "core/resourceManager.h"
|
||||||
|
#include "console/simPersistId.h"
|
||||||
|
#include <string>
|
||||||
|
#include "T3D/gameFunctions.h"
|
||||||
|
#include "postFx/postEffect.h"
|
||||||
|
#include "renderInstance/renderProbeMgr.h"
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
|
||||||
|
#include "math/util/sphereMesh.h"
|
||||||
|
#include "materials/materialManager.h"
|
||||||
|
#include "math/util/matrixSet.h"
|
||||||
|
#include "gfx/bitmap/cubemapSaver.h"
|
||||||
|
|
||||||
|
#include "materials/materialFeatureTypes.h"
|
||||||
|
|
||||||
|
#include "materials/shaderData.h"
|
||||||
|
#include "gfx/gfxTextureManager.h"
|
||||||
|
|
||||||
|
#include "gfx/bitmap/imageUtils.h"
|
||||||
|
|
||||||
|
#include "T3D/lighting/IBLUtilities.h"
|
||||||
|
|
||||||
|
extern bool gEditingMission;
|
||||||
|
extern ColorI gCanvasClearColor;
|
||||||
|
bool Skylight::smRenderSkylights = true;
|
||||||
|
bool Skylight::smRenderPreviewProbes = true;
|
||||||
|
|
||||||
|
IMPLEMENT_CO_NETOBJECT_V1(Skylight);
|
||||||
|
|
||||||
|
ConsoleDocClass(Skylight,
|
||||||
|
"@brief An example scene object which renders a mesh.\n\n"
|
||||||
|
"This class implements a basic SceneObject that can exist in the world at a "
|
||||||
|
"3D position and render itself. There are several valid ways to render an "
|
||||||
|
"object in Torque. This class implements the preferred rendering method which "
|
||||||
|
"is to submit a MeshRenderInst along with a Material, vertex buffer, "
|
||||||
|
"primitive buffer, and transform and allow the RenderMeshMgr handle the "
|
||||||
|
"actual setup and rendering for you.\n\n"
|
||||||
|
"See the C++ code for implementation details.\n\n"
|
||||||
|
"@ingroup Examples\n");
|
||||||
|
|
||||||
|
ImplementEnumType(SkylightReflectionModeEnum,
|
||||||
|
"Type of mesh data available in a shape.\n"
|
||||||
|
"@ingroup gameObjects")
|
||||||
|
{ Skylight::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" },
|
||||||
|
{ Skylight::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" },
|
||||||
|
EndImplementEnumType;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Object setup and teardown
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
Skylight::Skylight()
|
||||||
|
{
|
||||||
|
// Flag this object so that it will always
|
||||||
|
// be sent across the network to clients
|
||||||
|
mNetFlags.set(Ghostable | ScopeAlways);
|
||||||
|
|
||||||
|
mTypeMask = LightObjectType | MarkerObjectType;
|
||||||
|
|
||||||
|
mReflectionModeType = StaticCubemap;
|
||||||
|
|
||||||
|
mEnabled = true;
|
||||||
|
mBake = false;
|
||||||
|
mDirty = false;
|
||||||
|
|
||||||
|
mCubemap = NULL;
|
||||||
|
mReflectionPath = "";
|
||||||
|
mProbeUniqueID = "";
|
||||||
|
|
||||||
|
mEditorShapeInst = NULL;
|
||||||
|
mEditorShape = NULL;
|
||||||
|
|
||||||
|
mIrridianceMap = NULL;
|
||||||
|
mPrefilterMap = NULL;
|
||||||
|
mBrdfTexture = NULL;
|
||||||
|
mResourcesCreated = false;
|
||||||
|
mPrefilterSize = 512;
|
||||||
|
mPrefilterMipLevels = 6;
|
||||||
|
|
||||||
|
mProbeInfo = new ProbeInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
Skylight::~Skylight()
|
||||||
|
{
|
||||||
|
if (mEditorShapeInst)
|
||||||
|
SAFE_DELETE(mEditorShapeInst);
|
||||||
|
|
||||||
|
if (mReflectionModeType != StaticCubemap && mCubemap)
|
||||||
|
mCubemap->deleteObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Object Editing
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void Skylight::initPersistFields()
|
||||||
|
{
|
||||||
|
addGroup("Rendering");
|
||||||
|
addProtectedField("enabled", TypeBool, Offset(mEnabled, Skylight),
|
||||||
|
&_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
|
||||||
|
endGroup("Rendering");
|
||||||
|
|
||||||
|
addGroup("Reflection");
|
||||||
|
//addField("ReflectionMode", TypeSkylightReflectionModeEnum, Offset(mReflectionModeType, Skylight),
|
||||||
|
// "The type of mesh data to use for collision queries.");
|
||||||
|
|
||||||
|
//addField("reflectionPath", TypeImageFilename, Offset(mReflectionPath, Skylight),
|
||||||
|
// "The type of mesh data to use for collision queries.");
|
||||||
|
|
||||||
|
addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, Skylight), "Cubemap used instead of reflection texture if fullReflect is off.");
|
||||||
|
|
||||||
|
//addProtectedField("Bake", TypeBool, Offset(mBake, Skylight),
|
||||||
|
// &_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
||||||
|
endGroup("Reflection");
|
||||||
|
|
||||||
|
Con::addVariable("$Light::renderSkylights", TypeBool, &Skylight::smRenderSkylights,
|
||||||
|
"Toggles rendering of light frustums when the light is selected in the editor.\n\n"
|
||||||
|
"@note Only works for shadow mapped lights.\n\n"
|
||||||
|
"@ingroup Lighting");
|
||||||
|
|
||||||
|
Con::addVariable("$Light::renderPreviewProbes", TypeBool, &Skylight::smRenderPreviewProbes,
|
||||||
|
"Toggles rendering of light frustums when the light is selected in the editor.\n\n"
|
||||||
|
"@note Only works for shadow mapped lights.\n\n"
|
||||||
|
"@ingroup Lighting");
|
||||||
|
|
||||||
|
// SceneObject already handles exposing the transform
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::inspectPostApply()
|
||||||
|
{
|
||||||
|
Parent::inspectPostApply();
|
||||||
|
|
||||||
|
mDirty = true;
|
||||||
|
|
||||||
|
// Flag the network mask to send the updates
|
||||||
|
// to the client object
|
||||||
|
setMaskBits(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Skylight::_setEnabled(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
Skylight* probe = reinterpret_cast< Skylight* >(object);
|
||||||
|
|
||||||
|
probe->mEnabled = dAtob(data);
|
||||||
|
probe->setMaskBits(-1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Skylight::_doBake(void *object, const char *index, const char *data)
|
||||||
|
{
|
||||||
|
Skylight* probe = reinterpret_cast< Skylight* >(object);
|
||||||
|
|
||||||
|
if (probe->mDirty)
|
||||||
|
probe->bake(probe->mReflectionPath, 256);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Skylight::onAdd()
|
||||||
|
{
|
||||||
|
if (!Parent::onAdd())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mObjBox.minExtents.set(-1, -1, -1);
|
||||||
|
mObjBox.maxExtents.set(1, 1, 1);
|
||||||
|
|
||||||
|
// Skip our transform... it just dirties mask bits.
|
||||||
|
Parent::setTransform(mObjToWorld);
|
||||||
|
|
||||||
|
resetWorldBox();
|
||||||
|
|
||||||
|
// Add this object to the scene
|
||||||
|
addToScene();
|
||||||
|
|
||||||
|
if (isServerObject())
|
||||||
|
{
|
||||||
|
if (!mPersistentId)
|
||||||
|
mPersistentId = getOrCreatePersistentId();
|
||||||
|
|
||||||
|
mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh this object's material (if any)
|
||||||
|
if (isClientObject())
|
||||||
|
updateMaterial();
|
||||||
|
|
||||||
|
setMaskBits(-1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::onRemove()
|
||||||
|
{
|
||||||
|
// Remove this object from the scene
|
||||||
|
removeFromScene();
|
||||||
|
|
||||||
|
Parent::onRemove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::setTransform(const MatrixF & mat)
|
||||||
|
{
|
||||||
|
// Let SceneObject handle all of the matrix manipulation
|
||||||
|
Parent::setTransform(mat);
|
||||||
|
|
||||||
|
mDirty = true;
|
||||||
|
|
||||||
|
// Dirty our network mask so that the new transform gets
|
||||||
|
// transmitted to the client object
|
||||||
|
setMaskBits(TransformMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 Skylight::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
|
||||||
|
{
|
||||||
|
// Allow the Parent to get a crack at writing its info
|
||||||
|
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
||||||
|
|
||||||
|
if (stream->writeFlag(mask & InitialUpdateMask))
|
||||||
|
{
|
||||||
|
//initial work, just in case?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write our transform information
|
||||||
|
if (stream->writeFlag(mask & TransformMask))
|
||||||
|
{
|
||||||
|
mathWrite(*stream, getTransform());
|
||||||
|
mathWrite(*stream, getScale());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (stream->writeFlag(mask & BakeInfoMask))
|
||||||
|
{
|
||||||
|
stream->write(mReflectionPath);
|
||||||
|
stream->write(mProbeUniqueID);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (stream->writeFlag(mask & EnabledMask))
|
||||||
|
{
|
||||||
|
stream->writeFlag(mEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (stream->writeFlag(mask & ModeMask))
|
||||||
|
{
|
||||||
|
stream->write((U32)mReflectionModeType);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (stream->writeFlag(mask & CubemapMask))
|
||||||
|
{
|
||||||
|
stream->write(mCubemapName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
|
||||||
|
{
|
||||||
|
// Let the Parent read any info it sent
|
||||||
|
Parent::unpackUpdate(conn, stream);
|
||||||
|
|
||||||
|
if (stream->readFlag())
|
||||||
|
{
|
||||||
|
//some initial work?
|
||||||
|
createGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream->readFlag()) // TransformMask
|
||||||
|
{
|
||||||
|
mathRead(*stream, &mObjToWorld);
|
||||||
|
mathRead(*stream, &mObjScale);
|
||||||
|
|
||||||
|
setTransform(mObjToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (stream->readFlag()) // BakeInfoMask
|
||||||
|
{
|
||||||
|
stream->read(&mReflectionPath);
|
||||||
|
stream->read(&mProbeUniqueID);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (stream->readFlag()) // EnabledMask
|
||||||
|
{
|
||||||
|
mEnabled = stream->readFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMaterialDirty = false;
|
||||||
|
|
||||||
|
/*if (stream->readFlag()) // ModeMask
|
||||||
|
{
|
||||||
|
U32 reflectModeType = StaticCubemap;
|
||||||
|
stream->read(&reflectModeType);
|
||||||
|
mReflectionModeType = (ReflectionModeType)reflectModeType;
|
||||||
|
|
||||||
|
isMaterialDirty = true;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (stream->readFlag()) // CubemapMask
|
||||||
|
{
|
||||||
|
stream->read(&mCubemapName);
|
||||||
|
|
||||||
|
isMaterialDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProbeParams();
|
||||||
|
|
||||||
|
if(isMaterialDirty)
|
||||||
|
updateMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::createGeometry()
|
||||||
|
{
|
||||||
|
// Clean up our previous shape
|
||||||
|
if (mEditorShapeInst)
|
||||||
|
SAFE_DELETE(mEditorShapeInst);
|
||||||
|
|
||||||
|
mEditorShape = NULL;
|
||||||
|
|
||||||
|
String shapeFile = "tools/resources/ReflectProbeSphere.dae";
|
||||||
|
|
||||||
|
// Attempt to get the resource from the ResourceManager
|
||||||
|
mEditorShape = ResourceManager::get().load(shapeFile);
|
||||||
|
if (mEditorShape)
|
||||||
|
{
|
||||||
|
mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Object Rendering
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Skylight::updateProbeParams()
|
||||||
|
{
|
||||||
|
if (mProbeInfo == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mProbeInfo->mIntensity = 1;
|
||||||
|
|
||||||
|
mProbeInfo->mAmbient = LinearColorF(0, 0, 0, 0);
|
||||||
|
|
||||||
|
mProbeInfo->mProbeShapeType = ProbeInfo::Sphere;
|
||||||
|
|
||||||
|
mProbeInfo->setPosition(getPosition());
|
||||||
|
|
||||||
|
//Update the bounds
|
||||||
|
mObjBox.minExtents.set(-1, -1, -1);
|
||||||
|
mObjBox.maxExtents.set(1, 1, 1);
|
||||||
|
|
||||||
|
// Skip our transform... it just dirties mask bits.
|
||||||
|
Parent::setTransform(mObjToWorld);
|
||||||
|
|
||||||
|
resetWorldBox();
|
||||||
|
|
||||||
|
F32 visDist = gClientSceneGraph->getVisibleDistance();
|
||||||
|
Box3F skylightBounds = Box3F(visDist * 2);
|
||||||
|
|
||||||
|
skylightBounds.setCenter(Point3F::Zero);
|
||||||
|
|
||||||
|
mProbeInfo->setPosition(Point3F::Zero);
|
||||||
|
|
||||||
|
mProbeInfo->mBounds = skylightBounds;
|
||||||
|
|
||||||
|
setGlobalBounds();
|
||||||
|
|
||||||
|
mProbeInfo->mIsSkylight = true;
|
||||||
|
mProbeInfo->mScore = -1.0f; //sky comes first
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Skylight::createClientResources()
|
||||||
|
{
|
||||||
|
//irridiance resources
|
||||||
|
mIrridianceMap = GFX->createCubemap();
|
||||||
|
mIrridianceMap->initDynamic(128, GFXFormatR16G16B16A16F, 1);
|
||||||
|
|
||||||
|
//prefilter resources - we share the irridiance stateblock
|
||||||
|
mPrefilterMap = GFX->createCubemap();
|
||||||
|
mPrefilterMap->initDynamic(mPrefilterSize, GFXFormatR16G16B16A16F, mPrefilterMipLevels);
|
||||||
|
|
||||||
|
//brdf lookup resources
|
||||||
|
//make the brdf lookup texture the same size as the prefilter texture
|
||||||
|
mBrdfTexture = TEXMGR->createTexture(mPrefilterSize, mPrefilterSize, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, 1, 0);
|
||||||
|
|
||||||
|
mResourcesCreated = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::updateMaterial()
|
||||||
|
{
|
||||||
|
if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty())
|
||||||
|
{
|
||||||
|
bool validCubemap = true;
|
||||||
|
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str());
|
||||||
|
|
||||||
|
Vector<FileName> fileNames;
|
||||||
|
|
||||||
|
if (Platform::isFile(fileName))
|
||||||
|
{
|
||||||
|
if (!mCubemap)
|
||||||
|
{
|
||||||
|
mCubemap = new CubemapData();
|
||||||
|
mCubemap->registerObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
mCubemap->setCubemapFile(FileName(fileName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
validCubemap = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validCubemap)
|
||||||
|
{
|
||||||
|
if (mCubemap->mCubemap)
|
||||||
|
mCubemap->updateFaces();
|
||||||
|
else
|
||||||
|
mCubemap->createMap();
|
||||||
|
|
||||||
|
mDirty = false;
|
||||||
|
|
||||||
|
mProbeInfo->mCubemap = &mCubemap->mCubemap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (U32 i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
char faceFile[256];
|
||||||
|
dSprintf(faceFile, sizeof(faceFile), "%s%s_%i.png", mReflectionPath.c_str(),
|
||||||
|
mProbeUniqueID.c_str(), i);
|
||||||
|
|
||||||
|
if (Platform::isFile(faceFile))
|
||||||
|
{
|
||||||
|
fileNames.push_back(FileName(faceFile));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
validCubemap = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validCubemap)
|
||||||
|
{
|
||||||
|
if (!mCubemap)
|
||||||
|
{
|
||||||
|
mCubemap = new CubemapData();
|
||||||
|
mCubemap->registerObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(U32 i=0; i < 6; i++)
|
||||||
|
mCubemap->setCubeFaceFile(i, fileNames[i]);
|
||||||
|
|
||||||
|
mCubemap->createMap();
|
||||||
|
mCubemap->updateFaces();
|
||||||
|
|
||||||
|
mProbeInfo->mCubemap = &mCubemap->mCubemap;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
else if (mReflectionModeType == StaticCubemap && !mCubemapName.isEmpty())
|
||||||
|
{
|
||||||
|
Sim::findObject(mCubemapName, mCubemap);
|
||||||
|
|
||||||
|
if (!mCubemap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mCubemap->mCubemap)
|
||||||
|
mCubemap->updateFaces();
|
||||||
|
else
|
||||||
|
mCubemap->createMap();
|
||||||
|
|
||||||
|
mProbeInfo->mCubemap = &mCubemap->mCubemap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculateSHTerms();
|
||||||
|
|
||||||
|
generateTextures();
|
||||||
|
|
||||||
|
//Now that the work is done, assign the relevent maps
|
||||||
|
if (mPrefilterMap.isValid())
|
||||||
|
{
|
||||||
|
mProbeInfo->mCubemap = &mPrefilterMap;
|
||||||
|
mProbeInfo->mIrradianceCubemap = &mIrridianceMap;
|
||||||
|
mProbeInfo->mBRDFTexture = &mBrdfTexture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::generateTextures()
|
||||||
|
{
|
||||||
|
if (!mCubemap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mResourcesCreated)
|
||||||
|
{
|
||||||
|
if (!createClientResources())
|
||||||
|
{
|
||||||
|
Con::errorf("SkyLight::createIrridianceMap: Failed to create resources");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//GFXTransformSaver saver;
|
||||||
|
|
||||||
|
GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
|
||||||
|
|
||||||
|
IBLUtilities::GenerateIrradianceMap(renderTarget, mCubemap->mCubemap, mIrridianceMap);
|
||||||
|
|
||||||
|
//Write it out
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "levels/test/irradiance.DDS");
|
||||||
|
|
||||||
|
CubemapSaver::save(mIrridianceMap, fileName);
|
||||||
|
|
||||||
|
if (!Platform::isFile(fileName))
|
||||||
|
{
|
||||||
|
Con::errorf("Failed to properly save out the skylight baked irradiance!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//create prefilter cubemap (radiance)
|
||||||
|
IBLUtilities::GeneratePrefilterMap(renderTarget, mCubemap->mCubemap, mPrefilterMipLevels, mPrefilterMap);
|
||||||
|
|
||||||
|
//Write it out
|
||||||
|
fileName[256];
|
||||||
|
dSprintf(fileName, 256, "levels/test/prefilter.DDS");
|
||||||
|
|
||||||
|
CubemapSaver::save(mPrefilterMap, fileName);
|
||||||
|
|
||||||
|
if (!Platform::isFile(fileName))
|
||||||
|
{
|
||||||
|
Con::errorf("Failed to properly save out the skylight baked irradiance!");
|
||||||
|
}
|
||||||
|
|
||||||
|
//create brdf lookup
|
||||||
|
IBLUtilities::GenerateBRDFTexture(mBrdfTexture);
|
||||||
|
|
||||||
|
/*FileStream fs;
|
||||||
|
if (fs.open("levels/test/brdf.DDS", Torque::FS::File::Write))
|
||||||
|
{
|
||||||
|
// Read back the render target, dxt compress it, and write it to disk.
|
||||||
|
GBitmap brdfBmp(mBrdfTexture.getHeight(), mBrdfTexture.getWidth(), false, GFXFormatR8G8B8A8);
|
||||||
|
mBrdfTexture.copyToBmp(&brdfBmp);
|
||||||
|
|
||||||
|
brdfBmp.extrudeMipLevels();
|
||||||
|
|
||||||
|
DDSFile *brdfDDS = DDSFile::createDDSFileFromGBitmap(&brdfBmp);
|
||||||
|
ImageUtil::ddsCompress(brdfDDS, GFXFormatBC1);
|
||||||
|
|
||||||
|
// Write result to file stream
|
||||||
|
brdfDDS->write(fs);
|
||||||
|
|
||||||
|
delete brdfDDS;
|
||||||
|
}
|
||||||
|
fs.close();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::prepRenderImage(SceneRenderState *state)
|
||||||
|
{
|
||||||
|
if (!mEnabled || !Skylight::smRenderSkylights)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Point3F distVec = getPosition() - state->getCameraPosition();
|
||||||
|
F32 dist = distVec.len();
|
||||||
|
|
||||||
|
//special hook-in for skylights
|
||||||
|
Point3F camPos = state->getCameraPosition();
|
||||||
|
mProbeInfo->mBounds.setCenter(camPos);
|
||||||
|
|
||||||
|
mProbeInfo->setPosition(camPos);
|
||||||
|
|
||||||
|
//Submit our probe to actually do the probe action
|
||||||
|
// Get a handy pointer to our RenderPassmanager
|
||||||
|
//RenderPassManager *renderPass = state->getRenderPass();
|
||||||
|
|
||||||
|
PROBEMGR->registerSkylight(mProbeInfo, this);
|
||||||
|
|
||||||
|
if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mCubemap != nullptr)
|
||||||
|
{
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
// Calculate the distance of this object from the camera
|
||||||
|
Point3F cameraOffset;
|
||||||
|
getRenderTransform().getColumn(3, &cameraOffset);
|
||||||
|
cameraOffset -= state->getDiffuseCameraPosition();
|
||||||
|
F32 dist = cameraOffset.len();
|
||||||
|
if (dist < 0.01f)
|
||||||
|
dist = 0.01f;
|
||||||
|
|
||||||
|
// Set up the LOD for the shape
|
||||||
|
F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
|
||||||
|
|
||||||
|
mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
|
||||||
|
|
||||||
|
// Make sure we have a valid level of detail
|
||||||
|
if (mEditorShapeInst->getCurrentDetail() < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
|
||||||
|
|
||||||
|
setPreviewMatParameters(state, probePrevMat);
|
||||||
|
|
||||||
|
// GFXTransformSaver is a handy helper class that restores
|
||||||
|
// the current GFX matrices to their original values when
|
||||||
|
// it goes out of scope at the end of the function
|
||||||
|
|
||||||
|
// Set up our TS render state
|
||||||
|
TSRenderState rdata;
|
||||||
|
rdata.setSceneState(state);
|
||||||
|
rdata.setFadeOverride(1.0f);
|
||||||
|
|
||||||
|
// We might have some forward lit materials
|
||||||
|
// so pass down a query to gather lights.
|
||||||
|
LightQuery query;
|
||||||
|
query.init(getWorldSphere());
|
||||||
|
rdata.setLightQuery(&query);
|
||||||
|
|
||||||
|
// Set the world matrix to the objects render transform
|
||||||
|
MatrixF mat = getRenderTransform();
|
||||||
|
mat.scale(Point3F(1, 1, 1));
|
||||||
|
GFX->setWorldMatrix(mat);
|
||||||
|
|
||||||
|
// Animate the the shape
|
||||||
|
mEditorShapeInst->animate();
|
||||||
|
|
||||||
|
// Allow the shape to submit the RenderInst(s) for itself
|
||||||
|
mEditorShapeInst->render(rdata);
|
||||||
|
|
||||||
|
saver.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the light is selected or light visualization
|
||||||
|
// is enabled then register the callback.
|
||||||
|
const bool isSelectedInEditor = (gEditingMission && isSelected());
|
||||||
|
if (isSelectedInEditor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
|
||||||
|
{
|
||||||
|
if (!mat->getFeatures().hasFeature(MFT_isDeferred))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Set up the params
|
||||||
|
MaterialParameters *matParams = mat->getMaterialParameters();
|
||||||
|
|
||||||
|
//Get the deferred render target
|
||||||
|
NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
|
||||||
|
|
||||||
|
GFXTextureObject *deferredTexObject = deferredTexTarget->getTexture();
|
||||||
|
if (!deferredTexObject)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GFX->setTexture(0, deferredTexObject);
|
||||||
|
|
||||||
|
//Set the cubemap
|
||||||
|
GFX->setCubeTexture(1, mCubemap->mCubemap);
|
||||||
|
|
||||||
|
//Set the invViewMat
|
||||||
|
MatrixSet &matrixSet = renderState->getRenderPass()->getMatrixSet();
|
||||||
|
const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
|
||||||
|
|
||||||
|
MaterialParameterHandle *invViewMat = mat->getMaterialParameterHandle("$invViewMat");
|
||||||
|
|
||||||
|
matParams->setSafe(invViewMat, worldToCameraXfm);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(Skylight, postApply, void, (), ,
|
||||||
|
"A utility method for forcing a network update.\n")
|
||||||
|
{
|
||||||
|
object->inspectPostApply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skylight::bake(String outputPath, S32 resolution)
|
||||||
|
{
|
||||||
|
GFXDEBUGEVENT_SCOPE(Skylight_Bake, ColorI::WHITE);
|
||||||
|
|
||||||
|
PostEffect *preCapture = dynamic_cast<PostEffect*>(Sim::findObject("AL_PreCapture"));
|
||||||
|
PostEffect *deferredShading = dynamic_cast<PostEffect*>(Sim::findObject("AL_DeferredShading"));
|
||||||
|
if (preCapture)
|
||||||
|
preCapture->enable();
|
||||||
|
if (deferredShading)
|
||||||
|
deferredShading->disable();
|
||||||
|
|
||||||
|
//if (mReflectionModeType == StaticCubemap || mReflectionModeType == BakedCubemap || mReflectionModeType == SkyLight)
|
||||||
|
{
|
||||||
|
if (!mCubemap)
|
||||||
|
{
|
||||||
|
mCubemap = new CubemapData();
|
||||||
|
mCubemap->registerObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReflectionModeType == BakedCubemap)
|
||||||
|
{
|
||||||
|
if (mReflectionPath.isEmpty() || !mPersistentId)
|
||||||
|
{
|
||||||
|
if (!mPersistentId)
|
||||||
|
mPersistentId = getOrCreatePersistentId();
|
||||||
|
|
||||||
|
mReflectionPath = outputPath.c_str();
|
||||||
|
|
||||||
|
mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validCubemap = true;
|
||||||
|
|
||||||
|
// Save the current transforms so we can restore
|
||||||
|
// it for child control rendering below.
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
//bool saveEditingMission = gEditingMission;
|
||||||
|
//gEditingMission = false;
|
||||||
|
|
||||||
|
//Set this to true to use the prior method where it goes through the SPT_Reflect path for the bake
|
||||||
|
bool probeRenderState = Skylight::smRenderSkylights;
|
||||||
|
Skylight::smRenderSkylights = false;
|
||||||
|
for (U32 i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
GFXTexHandle blendTex;
|
||||||
|
blendTex.set(resolution, resolution, GFXFormatR8G8B8A8, &GFXRenderTargetProfile, "");
|
||||||
|
|
||||||
|
GFXTextureTargetRef mBaseTarget = GFX->allocRenderToTextureTarget();
|
||||||
|
|
||||||
|
GFX->clearTextureStateImmediate(0);
|
||||||
|
mBaseTarget->attachTexture(GFXTextureTarget::Color0, blendTex);
|
||||||
|
|
||||||
|
// Standard view that will be overridden below.
|
||||||
|
VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: // D3DCUBEMAP_FACE_POSITIVE_X:
|
||||||
|
vLookatPt = VectorF(1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 1: // D3DCUBEMAP_FACE_NEGATIVE_X:
|
||||||
|
vLookatPt = VectorF(-1.0f, 0.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 2: // D3DCUBEMAP_FACE_POSITIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
break;
|
||||||
|
case 3: // D3DCUBEMAP_FACE_NEGATIVE_Y:
|
||||||
|
vLookatPt = VectorF(0.0f, -1.0f, 0.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case 4: // D3DCUBEMAP_FACE_POSITIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, 1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
|
||||||
|
vLookatPt = VectorF(0.0f, 0.0f, -1.0f);
|
||||||
|
vUpVec = VectorF(0.0f, 1.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create camera matrix
|
||||||
|
VectorF cross = mCross(vUpVec, vLookatPt);
|
||||||
|
cross.normalizeSafe();
|
||||||
|
|
||||||
|
MatrixF matView(true);
|
||||||
|
matView.setColumn(0, cross);
|
||||||
|
matView.setColumn(1, vLookatPt);
|
||||||
|
matView.setColumn(2, vUpVec);
|
||||||
|
matView.setPosition(getPosition());
|
||||||
|
matView.inverse();
|
||||||
|
|
||||||
|
// set projection to 90 degrees vertical and horizontal
|
||||||
|
F32 left, right, top, bottom;
|
||||||
|
F32 nearPlane = 100.f;
|
||||||
|
F32 farDist = 10000.f;
|
||||||
|
|
||||||
|
MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane);
|
||||||
|
Frustum frustum(false, left, right, top, bottom, nearPlane, farDist);
|
||||||
|
|
||||||
|
renderFrame(&mBaseTarget, matView, frustum, StaticObjectType | StaticShapeObjectType & EDITOR_RENDER_TYPEMASK, ColorI::RED);
|
||||||
|
|
||||||
|
mBaseTarget->resolve();
|
||||||
|
|
||||||
|
mCubemap->setCubeFaceTexture(i, blendTex);
|
||||||
|
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s_%i.png", mReflectionPath.c_str(),
|
||||||
|
mProbeUniqueID.c_str(), i);
|
||||||
|
|
||||||
|
FileStream stream;
|
||||||
|
if (!stream.open(fileName, Torque::FS::File::Write))
|
||||||
|
{
|
||||||
|
Con::errorf("ReflectionProbe::bake(): Couldn't open cubemap face file fo writing " + String(fileName));
|
||||||
|
if (preCapture)
|
||||||
|
preCapture->disable();
|
||||||
|
if (deferredShading)
|
||||||
|
deferredShading->enable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8);
|
||||||
|
blendTex->copyToBmp(&bitmap);
|
||||||
|
bitmap.writeBitmap("png", stream);
|
||||||
|
|
||||||
|
if (Platform::isFile(fileName) && mCubemap)
|
||||||
|
{
|
||||||
|
mCubemap->setCubeFaceFile(i, FileName(fileName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
validCubemap = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap.deleteImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validCubemap)
|
||||||
|
{
|
||||||
|
if (mCubemap->mCubemap)
|
||||||
|
mCubemap->updateFaces();
|
||||||
|
else
|
||||||
|
mCubemap->createMap();
|
||||||
|
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str());
|
||||||
|
|
||||||
|
CubemapSaver::save(mCubemap->mCubemap, fileName);
|
||||||
|
|
||||||
|
if (!Platform::isFile(fileName))
|
||||||
|
{
|
||||||
|
validCubemap = false; //if we didn't save right, just
|
||||||
|
Con::errorf("Failed to properly save out the skylight baked cubemap!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validCubemap)
|
||||||
|
{
|
||||||
|
mDirty = false;
|
||||||
|
|
||||||
|
//remove the temp files
|
||||||
|
for (U32 i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
char fileName[256];
|
||||||
|
dSprintf(fileName, 256, "%s%s_%i.png", mReflectionPath.c_str(),
|
||||||
|
mProbeUniqueID.c_str(), i);
|
||||||
|
|
||||||
|
Platform::fileDelete(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculateSHTerms();
|
||||||
|
|
||||||
|
Skylight::smRenderSkylights = probeRenderState;
|
||||||
|
setMaskBits(-1);
|
||||||
|
|
||||||
|
if (preCapture)
|
||||||
|
preCapture->disable();
|
||||||
|
|
||||||
|
if (deferredShading)
|
||||||
|
deferredShading->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineMethod(Skylight, Bake, void, (String outputPath, S32 resolution), ("", 256),
|
||||||
|
"@brief returns true if control object is inside the fog\n\n.")
|
||||||
|
{
|
||||||
|
object->bake(outputPath, resolution);
|
||||||
|
}
|
||||||
212
Engine/source/T3D/lighting/skylight.h
Normal file
212
Engine/source/T3D/lighting/skylight.h
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef SKYLIGHT_H
|
||||||
|
#define SKYLIGHT_H
|
||||||
|
|
||||||
|
#ifndef _SCENEOBJECT_H_
|
||||||
|
#include "scene/sceneObject.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXVERTEXBUFFER_H_
|
||||||
|
#include "gfx/gfxVertexBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||||
|
#include "gfx/gfxPrimitiveBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _TSSHAPEINSTANCE_H_
|
||||||
|
#include "ts/tsShapeInstance.h"
|
||||||
|
#endif
|
||||||
|
#include "lighting/lightInfo.h"
|
||||||
|
|
||||||
|
#ifndef _RENDERPASSMANAGER_H_
|
||||||
|
#include "renderInstance/renderPassManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROBEMANAGER_H
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class BaseMatInstance;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// This class implements a basic SceneObject that can exist in the world at a
|
||||||
|
// 3D position and render itself. There are several valid ways to render an
|
||||||
|
// object in Torque. This class implements the preferred rendering method which
|
||||||
|
// is to submit a MeshRenderInst along with a Material, vertex buffer,
|
||||||
|
// primitive buffer, and transform and allow the RenderMeshMgr handle the
|
||||||
|
// actual setup and rendering for you.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Skylight : public SceneObject
|
||||||
|
{
|
||||||
|
typedef SceneObject Parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum IndrectLightingModeType
|
||||||
|
{
|
||||||
|
NoIndirect = 0,
|
||||||
|
AmbientColor = 1,
|
||||||
|
SphericalHarmonics = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReflectionModeType
|
||||||
|
{
|
||||||
|
StaticCubemap = 1,
|
||||||
|
BakedCubemap = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Networking masks
|
||||||
|
// We need to implement a mask specifically to handle
|
||||||
|
// updating our transform from the server object to its
|
||||||
|
// client-side "ghost". We also need to implement a
|
||||||
|
// maks for handling editor updates to our properties
|
||||||
|
// (like material).
|
||||||
|
enum MaskBits
|
||||||
|
{
|
||||||
|
TransformMask = Parent::NextFreeMask << 0,
|
||||||
|
UpdateMask = Parent::NextFreeMask << 1,
|
||||||
|
EnabledMask = Parent::NextFreeMask << 2,
|
||||||
|
CubemapMask = Parent::NextFreeMask << 3,
|
||||||
|
ModeMask = Parent::NextFreeMask << 4,
|
||||||
|
RadiusMask = Parent::NextFreeMask << 5,
|
||||||
|
ShapeTypeMask = Parent::NextFreeMask << 6,
|
||||||
|
BakeInfoMask = Parent::NextFreeMask << 7,
|
||||||
|
NextFreeMask = Parent::NextFreeMask << 8
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mBake;
|
||||||
|
bool mEnabled;
|
||||||
|
bool mDirty;
|
||||||
|
|
||||||
|
Resource<TSShape> mEditorShape;
|
||||||
|
TSShapeInstance* mEditorShapeInst;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Rendering variables
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
ProbeInfo* mProbeInfo;
|
||||||
|
|
||||||
|
//Reflection Contribution stuff
|
||||||
|
ReflectionModeType mReflectionModeType;
|
||||||
|
|
||||||
|
String mCubemapName;
|
||||||
|
CubemapData *mCubemap;
|
||||||
|
|
||||||
|
String mReflectionPath;
|
||||||
|
String mProbeUniqueID;
|
||||||
|
|
||||||
|
//Debug rendering
|
||||||
|
static bool smRenderSkylights;
|
||||||
|
static bool smRenderPreviewProbes;
|
||||||
|
|
||||||
|
//irridiance resources
|
||||||
|
GFXCubemapHandle mIrridianceMap;
|
||||||
|
|
||||||
|
//prefilter resources
|
||||||
|
GFXCubemapHandle mPrefilterMap;
|
||||||
|
U32 mPrefilterMipLevels;
|
||||||
|
U32 mPrefilterSize;
|
||||||
|
|
||||||
|
//brdflookup resources - shares the texture target with the prefilter
|
||||||
|
GFXTexHandle mBrdfTexture;
|
||||||
|
|
||||||
|
bool mResourcesCreated;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Skylight();
|
||||||
|
virtual ~Skylight();
|
||||||
|
|
||||||
|
// Declare this object as a ConsoleObject so that we can
|
||||||
|
// instantiate it into the world and network it
|
||||||
|
DECLARE_CONOBJECT(Skylight);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Object Editing
|
||||||
|
// Since there is always a server and a client object in Torque and we
|
||||||
|
// actually edit the server object we need to implement some basic
|
||||||
|
// networking functions
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Set up any fields that we want to be editable (like position)
|
||||||
|
static void initPersistFields();
|
||||||
|
|
||||||
|
// Allows the object to update its editable settings
|
||||||
|
// from the server object to the client
|
||||||
|
virtual void inspectPostApply();
|
||||||
|
|
||||||
|
static bool _setEnabled(void *object, const char *index, const char *data);
|
||||||
|
static bool _doBake(void *object, const char *index, const char *data);
|
||||||
|
|
||||||
|
// Handle when we are added to the scene and removed from the scene
|
||||||
|
bool onAdd();
|
||||||
|
void onRemove();
|
||||||
|
|
||||||
|
// Override this so that we can dirty the network flag when it is called
|
||||||
|
void setTransform(const MatrixF &mat);
|
||||||
|
|
||||||
|
// This function handles sending the relevant data from the server
|
||||||
|
// object to the client object
|
||||||
|
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
|
||||||
|
// This function handles receiving relevant data from the server
|
||||||
|
// object and applying it to the client object
|
||||||
|
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Object Rendering
|
||||||
|
// Torque utilizes a "batch" rendering system. This means that it builds a
|
||||||
|
// list of objects that need to render (via RenderInst's) and then renders
|
||||||
|
// them all in one batch. This allows it to optimized on things like
|
||||||
|
// minimizing texture, state, and shader switching by grouping objects that
|
||||||
|
// use the same Materials.
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Create the geometry for rendering
|
||||||
|
void createGeometry();
|
||||||
|
|
||||||
|
bool createClientResources();
|
||||||
|
|
||||||
|
// Get the Material instance
|
||||||
|
void updateMaterial();
|
||||||
|
|
||||||
|
void generateTextures();
|
||||||
|
|
||||||
|
void updateProbeParams();
|
||||||
|
|
||||||
|
// This is the function that allows this object to submit itself for rendering
|
||||||
|
void prepRenderImage(SceneRenderState *state);
|
||||||
|
|
||||||
|
void setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat);
|
||||||
|
|
||||||
|
//Baking
|
||||||
|
void bake(String outputPath, S32 resolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Skylight::IndrectLightingModeType SkylightIndrectLightingModeEnum;
|
||||||
|
DefineEnumType(SkylightIndrectLightingModeEnum);
|
||||||
|
|
||||||
|
typedef Skylight::ReflectionModeType SkylightReflectionModeEnum;
|
||||||
|
DefineEnumType(SkylightReflectionModeEnum);
|
||||||
|
|
||||||
|
#endif // _Skylight_H_
|
||||||
|
|
@ -497,7 +497,6 @@ enum GFXTextureTransformFlags
|
||||||
// CodeReview: This number is used for the declaration of variables, but it
|
// CodeReview: This number is used for the declaration of variables, but it
|
||||||
// should *not* be used for any run-time purposes [7/2/2007 Pat]
|
// should *not* be used for any run-time purposes [7/2/2007 Pat]
|
||||||
#define TEXTURE_STAGE_COUNT 32
|
#define TEXTURE_STAGE_COUNT 32
|
||||||
#define TEXTURE_STAGE_COUNT 16
|
|
||||||
|
|
||||||
enum GFXSamplerState
|
enum GFXSamplerState
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,10 @@
|
||||||
#include "gfx/gfxDebugEvent.h"
|
#include "gfx/gfxDebugEvent.h"
|
||||||
#include "math/util/matrixSet.h"
|
#include "math/util/matrixSet.h"
|
||||||
#include "console/consoleTypes.h"
|
#include "console/consoleTypes.h"
|
||||||
|
#include "gfx/gfxTextureManager.h"
|
||||||
|
|
||||||
const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "directLighting" );
|
const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "specularLighting" );
|
||||||
const String AdvancedLightBinManager::smBufferName( "directLighting" );
|
const String AdvancedLightBinManager::smBufferName( "specularLighting" );
|
||||||
|
|
||||||
ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
|
ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
|
||||||
bool AdvancedLightBinManager::smPSSMDebugRender = false;
|
bool AdvancedLightBinManager::smPSSMDebugRender = false;
|
||||||
|
|
@ -180,6 +181,26 @@ bool AdvancedLightBinManager::setTargetSize(const Point2I &newTargetSize)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AdvancedLightBinManager::_updateTargets()
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(AdvancedLightBinManager_updateTargets);
|
||||||
|
|
||||||
|
bool ret = Parent::_updateTargets();
|
||||||
|
|
||||||
|
mDiffuseLightingTarget = NamedTexTarget::find("diffuseLighting");
|
||||||
|
if (mDiffuseLightingTarget.isValid())
|
||||||
|
{
|
||||||
|
mDiffuseLightingTex = mDiffuseLightingTarget->getTexture();
|
||||||
|
|
||||||
|
for (U32 i = 0; i < mTargetChainLength; i++)
|
||||||
|
mTargetChain[i]->attachTexture(GFXTextureTarget::Color1, mDiffuseLightingTex);
|
||||||
|
}
|
||||||
|
|
||||||
|
GFX->finalizeReset();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void AdvancedLightBinManager::addLight( LightInfo *light )
|
void AdvancedLightBinManager::addLight( LightInfo *light )
|
||||||
{
|
{
|
||||||
// Get the light type.
|
// Get the light type.
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,9 @@ public:
|
||||||
// registered buffer name
|
// registered buffer name
|
||||||
static const String smBufferName;
|
static const String smBufferName;
|
||||||
|
|
||||||
|
NamedTexTargetRef mDiffuseLightingTarget;
|
||||||
|
GFXTexHandle mDiffuseLightingTex;
|
||||||
|
|
||||||
/// The shadow filter mode to use on shadowed light materials.
|
/// The shadow filter mode to use on shadowed light materials.
|
||||||
static ShadowFilterMode smShadowFilterMode;
|
static ShadowFilterMode smShadowFilterMode;
|
||||||
|
|
||||||
|
|
@ -128,6 +131,7 @@ public:
|
||||||
bool MRTLightmapsDuringDeferred() const { return mMRTLightmapsDuringDeferred; }
|
bool MRTLightmapsDuringDeferred() const { return mMRTLightmapsDuringDeferred; }
|
||||||
void MRTLightmapsDuringDeferred(bool val);
|
void MRTLightmapsDuringDeferred(bool val);
|
||||||
|
|
||||||
|
bool _updateTargets();
|
||||||
|
|
||||||
typedef Signal<void(SceneRenderState *, AdvancedLightBinManager *)> RenderSignal;
|
typedef Signal<void(SceneRenderState *, AdvancedLightBinManager *)> RenderSignal;
|
||||||
static RenderSignal &getRenderSignal();
|
static RenderSignal &getRenderSignal();
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ void AdvancedLightingFeatures::registerFeatures( const GFXFormat &deferredTarget
|
||||||
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularGLSL());
|
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularGLSL());
|
||||||
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertGLSL());
|
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertGLSL());
|
||||||
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceGLSL());
|
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceGLSL());
|
||||||
|
FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -75,6 +76,7 @@ void AdvancedLightingFeatures::registerFeatures( const GFXFormat &deferredTarget
|
||||||
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularHLSL());
|
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularHLSL());
|
||||||
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertHLSL());
|
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertHLSL());
|
||||||
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceHLSL());
|
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceHLSL());
|
||||||
|
FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
|
||||||
uvScene->setName( "uvScene" );
|
uvScene->setName( "uvScene" );
|
||||||
LangElement *uvSceneDecl = new DecOp( uvScene );
|
LangElement *uvSceneDecl = new DecOp( uvScene );
|
||||||
|
|
||||||
String rtParamName = String::ToString( "rtParams%s", "directLightingBuffer" );
|
String rtParamName = String::ToString( "rtParams%s", "diffuseLightingBuffer" );
|
||||||
Var *rtParams = (Var*) LangElement::find( rtParamName );
|
Var *rtParams = (Var*) LangElement::find( rtParamName );
|
||||||
if( !rtParams )
|
if( !rtParams )
|
||||||
{
|
{
|
||||||
|
|
@ -121,7 +121,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
|
||||||
// create texture var
|
// create texture var
|
||||||
Var *lightInfoBuffer = new Var;
|
Var *lightInfoBuffer = new Var;
|
||||||
lightInfoBuffer->setType( "sampler2D" );
|
lightInfoBuffer->setType( "sampler2D" );
|
||||||
lightInfoBuffer->setName( "directLightingBuffer" );
|
lightInfoBuffer->setName( "diffuseLightingBuffer" );
|
||||||
lightInfoBuffer->uniform = true;
|
lightInfoBuffer->uniform = true;
|
||||||
lightInfoBuffer->sampler = true;
|
lightInfoBuffer->sampler = true;
|
||||||
lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||||
|
|
@ -207,7 +207,7 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat,
|
||||||
mLastTexIndex = texIndex;
|
mLastTexIndex = texIndex;
|
||||||
|
|
||||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||||
passData.mSamplerNames[ texIndex ]= "directLightingBuffer";
|
passData.mSamplerNames[ texIndex ]= "diffuseLightingBuffer";
|
||||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ void DeferredRTLightingFeatHLSL::processPix( Vector<ShaderComponent*> &component
|
||||||
uvScene->setName("uvScene");
|
uvScene->setName("uvScene");
|
||||||
LangElement *uvSceneDecl = new DecOp(uvScene);
|
LangElement *uvSceneDecl = new DecOp(uvScene);
|
||||||
|
|
||||||
String rtParamName = String::ToString("rtParams%s", "directLightingBuffer");
|
String rtParamName = String::ToString("rtParams%s", "diffuseLightingBuffer");
|
||||||
Var *rtParams = (Var*)LangElement::find(rtParamName);
|
Var *rtParams = (Var*)LangElement::find(rtParamName);
|
||||||
if (!rtParams)
|
if (!rtParams)
|
||||||
{
|
{
|
||||||
|
|
@ -215,7 +215,7 @@ void DeferredRTLightingFeatHLSL::setTexData( Material::StageData &stageDat,
|
||||||
mLastTexIndex = texIndex;
|
mLastTexIndex = texIndex;
|
||||||
|
|
||||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||||
passData.mSamplerNames[ texIndex ]= "directLightingBuffer";
|
passData.mSamplerNames[ texIndex ]= "diffuseLightingBuffer";
|
||||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ void BasicLightManager::activate( SceneManager *sceneManager )
|
||||||
FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL );
|
FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL );
|
FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularGLSL );
|
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularGLSL );
|
||||||
|
FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -178,6 +179,7 @@ void BasicLightManager::activate( SceneManager *sceneManager )
|
||||||
FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL );
|
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL );
|
||||||
|
FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
809
Engine/source/lighting/probeManager.cpp
Normal file
809
Engine/source/lighting/probeManager.cpp
Normal file
|
|
@ -0,0 +1,809 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "core/util/safeDelete.h"
|
||||||
|
#include "console/sim.h"
|
||||||
|
#include "console/simSet.h"
|
||||||
|
#include "scene/sceneManager.h"
|
||||||
|
#include "materials/materialManager.h"
|
||||||
|
#include "materials/sceneData.h"
|
||||||
|
#include "lighting/lightInfo.h"
|
||||||
|
#include "lighting/lightingInterfaces.h"
|
||||||
|
#include "T3D/gameBase/gameConnection.h"
|
||||||
|
#include "gfx/gfxStringEnumTranslate.h"
|
||||||
|
#include "console/engineAPI.h"
|
||||||
|
#include "renderInstance/renderDeferredMgr.h"
|
||||||
|
#include "shaderGen/shaderGenVars.h"
|
||||||
|
|
||||||
|
Signal<void(const char*,bool)> ProbeManager::smActivateSignal;
|
||||||
|
ProbeManager *ProbeManager::smProbeManager = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
ProbeInfo::ProbeInfo()
|
||||||
|
: mTransform(true),
|
||||||
|
mAmbient(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
|
mPriority(1.0f),
|
||||||
|
mScore(0.0f),
|
||||||
|
mDebugRender(false),
|
||||||
|
mCubemap(NULL),
|
||||||
|
mIrradianceCubemap(NULL),
|
||||||
|
mBRDFTexture(NULL),
|
||||||
|
mRadius(1.0f),
|
||||||
|
mIntensity(1.0f)
|
||||||
|
{
|
||||||
|
for (U32 i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
mSHConstants[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeInfo::~ProbeInfo()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(mCubemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeInfo::set(const ProbeInfo *probeInfo)
|
||||||
|
{
|
||||||
|
mTransform = probeInfo->mTransform;
|
||||||
|
mAmbient = probeInfo->mAmbient;
|
||||||
|
mCubemap = probeInfo->mCubemap;
|
||||||
|
mIrradianceCubemap = probeInfo->mIrradianceCubemap;
|
||||||
|
mBRDFTexture = probeInfo->mBRDFTexture;
|
||||||
|
mRadius = probeInfo->mRadius;
|
||||||
|
mIntensity = probeInfo->mIntensity;
|
||||||
|
mProbeShapeType = probeInfo->mProbeShapeType;
|
||||||
|
numPrims = probeInfo->numPrims;
|
||||||
|
numVerts = probeInfo->numVerts;
|
||||||
|
numIndicesForPoly = probeInfo->numIndicesForPoly;
|
||||||
|
mBounds = probeInfo->mBounds;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
mSHTerms[i] = probeInfo->mSHTerms[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
mSHConstants[i] = probeInfo->mSHConstants[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeInfo::getWorldToLightProj(MatrixF *outMatrix) const
|
||||||
|
{
|
||||||
|
*outMatrix = getTransform();
|
||||||
|
outMatrix->inverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProbeInfoList::registerProbe(ProbeInfo *light)
|
||||||
|
{
|
||||||
|
if (!light)
|
||||||
|
return;
|
||||||
|
// just add the light, we'll try to scan for dupes later...
|
||||||
|
push_back(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeInfoList::unregisterProbe(ProbeInfo *light)
|
||||||
|
{
|
||||||
|
// remove all of them...
|
||||||
|
ProbeInfoList &list = *this;
|
||||||
|
for (U32 i = 0; i<list.size(); i++)
|
||||||
|
{
|
||||||
|
if (list[i] != light)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// this moves last to i, which allows
|
||||||
|
// the search to continue forward...
|
||||||
|
list.erase_fast(i);
|
||||||
|
// want to check this location again...
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeShaderConstants::ProbeShaderConstants()
|
||||||
|
: mInit(false),
|
||||||
|
mShader(NULL),
|
||||||
|
mProbeParamsSC(NULL),
|
||||||
|
mProbePositionSC(NULL),
|
||||||
|
mProbeRadiusSC(NULL),
|
||||||
|
mProbeBoxMinSC(NULL),
|
||||||
|
mProbeBoxMaxSC(NULL),
|
||||||
|
mProbeIsSphereSC(NULL),
|
||||||
|
mProbeLocalPosSC(NULL),
|
||||||
|
mProbeCubemapSC(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeShaderConstants::~ProbeShaderConstants()
|
||||||
|
{
|
||||||
|
if (mShader.isValid())
|
||||||
|
{
|
||||||
|
mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
|
||||||
|
mShader = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeShaderConstants::init(GFXShader* shader)
|
||||||
|
{
|
||||||
|
if (mShader.getPointer() != shader)
|
||||||
|
{
|
||||||
|
if (mShader.isValid())
|
||||||
|
mShader->getReloadSignal().remove(this, &ProbeShaderConstants::_onShaderReload);
|
||||||
|
|
||||||
|
mShader = shader;
|
||||||
|
mShader->getReloadSignal().notify(this, &ProbeShaderConstants::_onShaderReload);
|
||||||
|
}
|
||||||
|
|
||||||
|
mProbeParamsSC = shader->getShaderConstHandle("$probeParams");
|
||||||
|
|
||||||
|
//Reflection Probes
|
||||||
|
mProbePositionSC = shader->getShaderConstHandle(ShaderGenVars::probePosition);
|
||||||
|
mProbeRadiusSC = shader->getShaderConstHandle(ShaderGenVars::probeRadius);
|
||||||
|
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);
|
||||||
|
|
||||||
|
mInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeShaderConstants::_onShaderReload()
|
||||||
|
{
|
||||||
|
if (mShader.isValid())
|
||||||
|
init(mShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeManager::ProbeManager()
|
||||||
|
: mDefaultProbe( NULL ),
|
||||||
|
mSceneManager( NULL ),
|
||||||
|
mCullPos( Point3F::Zero )
|
||||||
|
{
|
||||||
|
dMemset( &mSpecialProbes, 0, sizeof(mSpecialProbes) );
|
||||||
|
|
||||||
|
mLastShader = NULL;
|
||||||
|
mLastConstants = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeManager::~ProbeManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeInfo* ProbeManager::createProbeInfo(ProbeInfo* probe /* = NULL */)
|
||||||
|
{
|
||||||
|
ProbeInfo *outProbe = (probe != NULL) ? probe : new ProbeInfo;
|
||||||
|
|
||||||
|
/*ProbeManagerMap &ProbeManagers = _getProbeManagers();
|
||||||
|
ProbeManagerMap::Iterator iter = ProbeManagers.begin();
|
||||||
|
for ( ; iter != ProbeManagers.end(); iter++ )
|
||||||
|
{
|
||||||
|
ProbeManager *lm = iter->value;
|
||||||
|
lm->_addLightInfoEx( outLight );
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return outProbe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void ProbeManager::initLightFields()
|
||||||
|
{
|
||||||
|
ProbeManagerMap &ProbeManagers = _getProbeManagers();
|
||||||
|
|
||||||
|
ProbeManagerMap::Iterator iter = ProbeManagers.begin();
|
||||||
|
for ( ; iter != ProbeManagers.end(); iter++ )
|
||||||
|
{
|
||||||
|
ProbeManager *lm = iter->value;
|
||||||
|
lm->_initLightFields();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
IMPLEMENT_GLOBAL_CALLBACK( onProbeManagerActivate, void, ( const char *name ), ( name ),
|
||||||
|
"A callback called by the engine when a light manager is activated.\n"
|
||||||
|
"@param name The name of the light manager being activated.\n"
|
||||||
|
"@ingroup Lighting\n" );
|
||||||
|
|
||||||
|
void ProbeManager::activate( SceneManager *sceneManager )
|
||||||
|
{
|
||||||
|
AssertFatal( sceneManager, "ProbeManager::activate() - Got null scene manager!" );
|
||||||
|
//AssertFatal( mIsActive == false, "ProbeManager::activate() - Already activated!" );
|
||||||
|
AssertFatal(smProbeManager == NULL, "ProbeManager::activate() - A previous ProbeManager is still active!" );
|
||||||
|
|
||||||
|
mSceneManager = sceneManager;
|
||||||
|
smProbeManager = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_GLOBAL_CALLBACK( onProbeManagerDeactivate, void, ( const char *name ), ( name ),
|
||||||
|
"A callback called by the engine when a light manager is deactivated.\n"
|
||||||
|
"@param name The name of the light manager being deactivated.\n"
|
||||||
|
"@ingroup Lighting\n" );
|
||||||
|
|
||||||
|
void ProbeManager::deactivate()
|
||||||
|
{
|
||||||
|
//AssertFatal( mIsActive == true, "ProbeManager::deactivate() - Already deactivated!" );
|
||||||
|
AssertFatal( smProbeManager == this, "ProbeManager::activate() - This isn't the active light manager!" );
|
||||||
|
|
||||||
|
//if( Sim::getRootGroup() ) // To protect against shutdown.
|
||||||
|
// onProbeManagerDeactivate_callback( getName() );
|
||||||
|
|
||||||
|
//mIsActive = false;
|
||||||
|
mSceneManager = NULL;
|
||||||
|
smProbeManager = NULL;
|
||||||
|
|
||||||
|
// Just in case... make sure we're all clear.
|
||||||
|
unregisterAllProbes();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeInfo* ProbeManager::getDefaultLight()
|
||||||
|
{
|
||||||
|
// The sun is always our default light when
|
||||||
|
// when its registered.
|
||||||
|
if ( mSpecialProbes[ ProbeManager::SkylightProbeType ] )
|
||||||
|
return mSpecialProbes[ ProbeManager::SkylightProbeType ];
|
||||||
|
|
||||||
|
// Else return a dummy special light.
|
||||||
|
//if ( !mDefaultLight )
|
||||||
|
// mDefaultLight = createLightInfo();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeInfo* ProbeManager::getSpecialProbe( ProbeManager::SpecialProbeTypesEnum type, bool useDefault )
|
||||||
|
{
|
||||||
|
//if ( mSpecialLights[type] )
|
||||||
|
// return mSpecialLights[type];
|
||||||
|
|
||||||
|
if ( useDefault )
|
||||||
|
return getDefaultLight();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::setSpecialProbe( ProbeManager::SpecialProbeTypesEnum type, ProbeInfo *probe )
|
||||||
|
{
|
||||||
|
if (probe && type == SkylightProbeType )
|
||||||
|
{
|
||||||
|
// The sun must be specially positioned and ranged
|
||||||
|
// so that it can be processed like a point light
|
||||||
|
// in the stock light shader used by Basic Lighting.
|
||||||
|
|
||||||
|
probe->setPosition( mCullPos - (probe->getDirection() * 10000.0f ) );
|
||||||
|
probe->mRadius = 2000000.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpecialProbes[type] = probe;
|
||||||
|
registerProbe(probe, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::registerProbes( const Frustum *frustum, bool staticLighting )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE( ProbeManager_RegisterProbes );
|
||||||
|
|
||||||
|
// TODO: We need to work this out...
|
||||||
|
//
|
||||||
|
// 1. Why do we register and unregister lights on every
|
||||||
|
// render when they don't often change... shouldn't we
|
||||||
|
// just register once and keep them?
|
||||||
|
//
|
||||||
|
// 2. If we do culling of lights should this happen as part
|
||||||
|
// of registration or somewhere else?
|
||||||
|
//
|
||||||
|
|
||||||
|
// Grab the lights to process.
|
||||||
|
Vector<SceneObject*> activeLights;
|
||||||
|
const U32 lightMask = LightObjectType;
|
||||||
|
|
||||||
|
if ( staticLighting || !frustum )
|
||||||
|
{
|
||||||
|
// We're processing static lighting or want all the lights
|
||||||
|
// in the container registerd... so no culling.
|
||||||
|
getSceneManager()->getContainer()->findObjectList( lightMask, &activeLights );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cull the lights using the frustum.
|
||||||
|
getSceneManager()->getContainer()->findObjectList( *frustum, lightMask, &activeLights );
|
||||||
|
/* supress light culling filter until we can sort out why that's misbehaving with dynamic cube mapping
|
||||||
|
for (U32 i = 0; i < activeLights.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!getSceneManager()->mRenderedObjectsList.contains(activeLights[i]))
|
||||||
|
{
|
||||||
|
activeLights.erase(i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Store the culling position for sun placement
|
||||||
|
// later... see setSpecialLight.
|
||||||
|
mCullPos = frustum->getPosition();
|
||||||
|
|
||||||
|
// HACK: Make sure the control object always gets
|
||||||
|
// processed as lights mounted to it don't change
|
||||||
|
// the shape bounds and can often get culled.
|
||||||
|
|
||||||
|
GameConnection *conn = GameConnection::getConnectionToServer();
|
||||||
|
if ( conn->getControlObject() )
|
||||||
|
{
|
||||||
|
GameBase *conObject = conn->getControlObject();
|
||||||
|
activeLights.push_back_unique( conObject );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the lights register themselves.
|
||||||
|
/*for ( U32 i = 0; i < activeLights.size(); i++ )
|
||||||
|
{
|
||||||
|
ISceneLight *lightInterface = dynamic_cast<ISceneLight*>( activeLights[i] );
|
||||||
|
if ( lightInterface )
|
||||||
|
lightInterface->submitLights( this, staticLighting );
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::registerSkylight(ProbeInfo *probe, SimObject *obj)
|
||||||
|
{
|
||||||
|
mSkylight = probe;
|
||||||
|
|
||||||
|
if (String("Advanced Lighting").equal(LIGHTMGR->getName(), String::NoCase))
|
||||||
|
{
|
||||||
|
SceneRenderState* state = mSceneManager->getCurrentRenderState();
|
||||||
|
|
||||||
|
RenderPassManager *renderPass = state->getRenderPass();
|
||||||
|
|
||||||
|
// Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
|
||||||
|
ProbeRenderInst *probeInst = renderPass->allocInst<ProbeRenderInst>();
|
||||||
|
|
||||||
|
probeInst->set(probe);
|
||||||
|
|
||||||
|
probeInst->type = RenderPassManager::RIT_Probes;
|
||||||
|
|
||||||
|
// Submit our RenderInst to the RenderPassManager
|
||||||
|
state->getRenderPass()->addInst(probeInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::registerProbe(ProbeInfo *probe, SimObject *obj )
|
||||||
|
{
|
||||||
|
// AssertFatal( !mRegisteredProbes.contains(probe),
|
||||||
|
//"ProbeManager::registerGlobalLight - This light is already registered!" );
|
||||||
|
|
||||||
|
if (!mRegisteredProbes.contains(probe))
|
||||||
|
mRegisteredProbes.push_back(probe);
|
||||||
|
|
||||||
|
if (String("Advanced Lighting").equal(LIGHTMGR->getName(), String::NoCase))
|
||||||
|
{
|
||||||
|
SceneRenderState* state = mSceneManager->getCurrentRenderState();
|
||||||
|
|
||||||
|
RenderPassManager *renderPass = state->getRenderPass();
|
||||||
|
|
||||||
|
// Allocate an MeshRenderInst so that we can submit it to the RenderPassManager
|
||||||
|
ProbeRenderInst *probeInst = renderPass->allocInst<ProbeRenderInst>();
|
||||||
|
|
||||||
|
probeInst->set(probe);
|
||||||
|
|
||||||
|
probeInst->type = RenderPassManager::RIT_Probes;
|
||||||
|
|
||||||
|
// Submit our RenderInst to the RenderPassManager
|
||||||
|
state->getRenderPass()->addInst(probeInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::unregisterProbe(ProbeInfo *probe )
|
||||||
|
{
|
||||||
|
mRegisteredProbes.unregisterProbe(probe);
|
||||||
|
|
||||||
|
// If this is the sun... clear the special light too.
|
||||||
|
if (probe == mSpecialProbes[SkylightProbeType] )
|
||||||
|
dMemset(mSpecialProbes, 0, sizeof(mSpecialProbes) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::unregisterAllProbes()
|
||||||
|
{
|
||||||
|
//dMemset(mSpecialProbes, 0, sizeof(mSpecialProbes) );
|
||||||
|
mRegisteredProbes.clear();
|
||||||
|
|
||||||
|
mSkylight = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::getAllUnsortedProbes( Vector<ProbeInfo*> *list ) const
|
||||||
|
{
|
||||||
|
list->merge( mRegisteredProbes );
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeShaderConstants* ProbeManager::getProbeShaderConstants(GFXShaderConstBuffer* buffer)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PROFILE_SCOPE(ProbeManager_GetProbeShaderConstants);
|
||||||
|
|
||||||
|
GFXShader* shader = buffer->getShader();
|
||||||
|
|
||||||
|
// Check to see if this is the same shader, we'll get hit repeatedly by
|
||||||
|
// the same one due to the render bin loops.
|
||||||
|
if (mLastShader.getPointer() != shader)
|
||||||
|
{
|
||||||
|
ProbeConstantMap::Iterator iter = mConstantLookup.find(shader);
|
||||||
|
if (iter != mConstantLookup.end())
|
||||||
|
{
|
||||||
|
mLastConstants = iter->value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProbeShaderConstants* psc = new ProbeShaderConstants();
|
||||||
|
mConstantLookup[shader] = psc;
|
||||||
|
|
||||||
|
mLastConstants = psc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set our new shader
|
||||||
|
mLastShader = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLastConstants = new ProbeShaderConstants();
|
||||||
|
|
||||||
|
// Make sure that our current lighting constants are initialized
|
||||||
|
if (!mLastConstants->mInit)
|
||||||
|
mLastConstants->init(shader);
|
||||||
|
|
||||||
|
return mLastConstants;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::_update4ProbeConsts( const SceneData &sgData,
|
||||||
|
MatrixSet &matSet,
|
||||||
|
GFXShaderConstHandle *probePositionSC,
|
||||||
|
GFXShaderConstHandle *probeRadiusSC,
|
||||||
|
GFXShaderConstHandle *probeBoxMinSC,
|
||||||
|
GFXShaderConstHandle *probeBoxMaxSC,
|
||||||
|
GFXShaderConstHandle *probeCubemapSC,
|
||||||
|
GFXShaderConstHandle *probeIsSphereSC,
|
||||||
|
GFXShaderConstHandle *probeLocalPosSC,
|
||||||
|
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() && (!mRegisteredProbes.empty() || mSkylight))
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
|
||||||
|
|
||||||
|
static AlignedArray<Point3F> probePositions(4, sizeof(Point3F));
|
||||||
|
static AlignedArray<F32> probeRadius(4, sizeof(F32));
|
||||||
|
static AlignedArray<Point3F> probeBoxMins(4, sizeof(Point3F));
|
||||||
|
static AlignedArray<Point3F> probeBoxMaxs(4, sizeof(Point3F));
|
||||||
|
static AlignedArray<Point3F> probeLocalPositions(4, sizeof(Point3F));
|
||||||
|
static AlignedArray<F32> probeIsSphere(4, sizeof(F32));
|
||||||
|
//static AlignedArray<CubemapData> probeCubemap(4, sizeof(CubemapData));
|
||||||
|
F32 range;
|
||||||
|
|
||||||
|
// Need to clear the buffers so that we don't leak
|
||||||
|
// lights from previous passes or have NaNs.
|
||||||
|
dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize());
|
||||||
|
dMemset(probeRadius.getBuffer(), 0, probeRadius.getBufferSize());
|
||||||
|
dMemset(probeBoxMins.getBuffer(), 0, probeBoxMins.getBufferSize());
|
||||||
|
dMemset(probeBoxMaxs.getBuffer(), 0, probeBoxMaxs.getBufferSize());
|
||||||
|
dMemset(probeLocalPositions.getBuffer(), 0, probeLocalPositions.getBufferSize());
|
||||||
|
dMemset(probeIsSphere.getBuffer(), 0, probeRadius.getBufferSize());
|
||||||
|
//dMemset(probeCubemap.getBuffer(), 0, probeCubemap.getBufferSize());
|
||||||
|
|
||||||
|
matSet.restoreSceneViewProjection();
|
||||||
|
|
||||||
|
const MatrixF &worldToCameraXfm = matSet.getWorldToCamera();
|
||||||
|
|
||||||
|
// Gather the data for the first 4 probes.
|
||||||
|
const ProbeInfo *probe;
|
||||||
|
for (U32 i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (i >= mRegisteredProbes.size())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == 0 && mSkylight)
|
||||||
|
{
|
||||||
|
//quickly try and see if we have a skylight, and set that to always be probe 0
|
||||||
|
probe = mSkylight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probe = mRegisteredProbes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!probe)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
probePositions[i].y = probePos.y;
|
||||||
|
probePositions[i].z = probePos.z;
|
||||||
|
|
||||||
|
probeRadius[i] = probe->mRadius;
|
||||||
|
|
||||||
|
const Point3F &minExt = probe->mBounds.minExtents;
|
||||||
|
probeBoxMins[i].x = minExt.x;
|
||||||
|
probeBoxMins[i].y = minExt.y;
|
||||||
|
probeBoxMins[i].z = minExt.z;
|
||||||
|
|
||||||
|
const Point3F &maxExt = probe->mBounds.maxExtents;
|
||||||
|
probeBoxMaxs[i].x = maxExt.x;
|
||||||
|
probeBoxMaxs[i].y = maxExt.y;
|
||||||
|
probeBoxMaxs[i].z = maxExt.z;
|
||||||
|
|
||||||
|
probeIsSphere[i] = probe->mProbeShapeType == ProbeInfo::Sphere ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
Point3F localProbePos;
|
||||||
|
worldToCameraXfm.mulP(probe->getPosition(), &localProbePos);
|
||||||
|
|
||||||
|
probeLocalPositions[i].x = localProbePos.x;
|
||||||
|
probeLocalPositions[i].y = localProbePos.y;
|
||||||
|
probeLocalPositions[i].z = localProbePos.z;
|
||||||
|
|
||||||
|
if (probe->mCubemap && !probe->mCubemap->isNull())
|
||||||
|
{
|
||||||
|
S32 samplerReg = probeCubemapSC->getSamplerRegister();
|
||||||
|
|
||||||
|
if(samplerReg != -1)
|
||||||
|
GFX->setCubeTexture(samplerReg + i, probe->mCubemap->getPointer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderConsts->setSafe(probePositionSC, probePositions);
|
||||||
|
shaderConsts->setSafe(probeRadiusSC, probeRadius);
|
||||||
|
shaderConsts->setSafe(probeBoxMinSC, probeBoxMins);
|
||||||
|
shaderConsts->setSafe(probeBoxMaxSC, probeBoxMaxs);
|
||||||
|
shaderConsts->setSafe(probeLocalPosSC, probeLocalPositions);
|
||||||
|
shaderConsts->setSafe(probeIsSphereSC, probeIsSphere);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
//shaderConsts->setSafe(lightSpotAngleSC, lightSpotAngle);
|
||||||
|
//shaderConsts->setSafe(lightSpotFalloffSC, lightSpotFalloff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*if (probe->mCubemap && !probe->mCubemap->isNull())
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(1, probe->mCubemap->getPointer());
|
||||||
|
}*/
|
||||||
|
if (probeCubemapSC->isValid())
|
||||||
|
{
|
||||||
|
for(U32 i=0; i < 4; ++i)
|
||||||
|
GFX->setCubeTexture(probeCubemapSC->getSamplerRegister() + i, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeManager::setProbeInfo(ProcessedMaterial *pmat,
|
||||||
|
const Material *mat,
|
||||||
|
const SceneData &sgData,
|
||||||
|
const SceneRenderState *state,
|
||||||
|
U32 pass,
|
||||||
|
GFXShaderConstBuffer *shaderConsts)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Skip this if we're rendering from the deferred bin.
|
||||||
|
if ( sgData.binType == SceneData::DeferredBin )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if (mRegisteredProbes.empty())
|
||||||
|
// return;
|
||||||
|
|
||||||
|
PROFILE_SCOPE(ProbeManager_setProbeInfo);
|
||||||
|
|
||||||
|
ProbeShaderConstants *psc = getProbeShaderConstants(shaderConsts);
|
||||||
|
|
||||||
|
//ProbeInfo *probe;
|
||||||
|
//probe = mRegisteredProbes[0];
|
||||||
|
|
||||||
|
// NOTE: If you encounter a crash from this point forward
|
||||||
|
// while setting a shader constant its probably because the
|
||||||
|
// mConstantLookup has bad shaders/constants in it.
|
||||||
|
//
|
||||||
|
// This is a known crash bug that can occur if materials/shaders
|
||||||
|
// are reloaded and the light manager is not reset.
|
||||||
|
//
|
||||||
|
// We should look to fix this by clearing the table.
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// Static
|
||||||
|
/*if (lsm && light->getCastShadows())
|
||||||
|
{
|
||||||
|
if (psc->mWorldToLightProjSC->isValid())
|
||||||
|
shaderConsts->set(psc->mWorldToLightProjSC,
|
||||||
|
lsm->getWorldToLightProj(),
|
||||||
|
psc->mWorldToLightProjSC->getType());
|
||||||
|
|
||||||
|
if (psc->mViewToLightProjSC->isValid())
|
||||||
|
{
|
||||||
|
// TODO: Should probably cache these results and
|
||||||
|
// not do this mul here on every material that needs
|
||||||
|
// this transform.
|
||||||
|
|
||||||
|
shaderConsts->set(psc->mViewToLightProjSC,
|
||||||
|
lsm->getWorldToLightProj() * state->getCameraTransform(),
|
||||||
|
psc->mViewToLightProjSC->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderConsts->setSafe(psc->mShadowMapSizeSC, 1.0f / (F32)lsm->getTexSize());
|
||||||
|
|
||||||
|
// Do this last so that overrides can properly override parameters previously set
|
||||||
|
lsm->setShaderParameters(shaderConsts, psc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (psc->mViewToLightProjSC->isValid())
|
||||||
|
{
|
||||||
|
// TODO: Should probably cache these results and
|
||||||
|
// not do this mul here on every material that needs
|
||||||
|
// this transform.
|
||||||
|
MatrixF proj;
|
||||||
|
light->getWorldToLightProj(&proj);
|
||||||
|
|
||||||
|
shaderConsts->set(psc->mViewToLightProjSC,
|
||||||
|
proj * state->getCameraTransform(),
|
||||||
|
psc->mViewToLightProjSC->getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamic
|
||||||
|
if (dynamicShadowMap)
|
||||||
|
{
|
||||||
|
if (psc->mDynamicWorldToLightProjSC->isValid())
|
||||||
|
shaderConsts->set(psc->mDynamicWorldToLightProjSC,
|
||||||
|
dynamicShadowMap->getWorldToLightProj(),
|
||||||
|
psc->mDynamicWorldToLightProjSC->getType());
|
||||||
|
|
||||||
|
if (psc->mDynamicViewToLightProjSC->isValid())
|
||||||
|
{
|
||||||
|
// TODO: Should probably cache these results and
|
||||||
|
// not do this mul here on every material that needs
|
||||||
|
// this transform.
|
||||||
|
|
||||||
|
shaderConsts->set(psc->mDynamicViewToLightProjSC,
|
||||||
|
dynamicShadowMap->getWorldToLightProj() * state->getCameraTransform(),
|
||||||
|
psc->mDynamicViewToLightProjSC->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderConsts->setSafe(psc->mShadowMapSizeSC, 1.0f / (F32)dynamicShadowMap->getTexSize());
|
||||||
|
|
||||||
|
// Do this last so that overrides can properly override parameters previously set
|
||||||
|
dynamicShadowMap->setShaderParameters(shaderConsts, psc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (psc->mDynamicViewToLightProjSC->isValid())
|
||||||
|
{
|
||||||
|
// TODO: Should probably cache these results and
|
||||||
|
// not do this mul here on every material that needs
|
||||||
|
// this transform.
|
||||||
|
MatrixF proj;
|
||||||
|
light->getWorldToLightProj(&proj);
|
||||||
|
|
||||||
|
shaderConsts->set(psc->mDynamicViewToLightProjSC,
|
||||||
|
proj * state->getCameraTransform(),
|
||||||
|
psc->mDynamicViewToLightProjSC->getType());
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows us to set textures during the Material::setTextureStage call, return true if we've done work.
|
||||||
|
bool ProbeManager::setTextureStage(const SceneData &sgData,
|
||||||
|
const U32 currTexFlag,
|
||||||
|
const U32 textureSlot,
|
||||||
|
GFXShaderConstBuffer *shaderConsts,
|
||||||
|
ShaderConstHandles *handles)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AvailableSLInterfaces* ProbeManager::getSceneLightingInterface()
|
||||||
|
{
|
||||||
|
//if ( !mAvailableSLInterfaces )
|
||||||
|
// mAvailableSLInterfaces = new AvailableSLInterfaces();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*bool ProbeManager::lightScene( const char* callback, const char* param )
|
||||||
|
{
|
||||||
|
BitSet32 flags = 0;
|
||||||
|
|
||||||
|
if ( param )
|
||||||
|
{
|
||||||
|
if ( !dStricmp( param, "forceAlways" ) )
|
||||||
|
flags.set( SceneLighting::ForceAlways );
|
||||||
|
else if ( !dStricmp(param, "forceWritable" ) )
|
||||||
|
flags.set( SceneLighting::ForceWritable );
|
||||||
|
else if ( !dStricmp(param, "loadOnly" ) )
|
||||||
|
flags.set( SceneLighting::LoadOnly );
|
||||||
|
}
|
||||||
|
|
||||||
|
// The SceneLighting object will delete itself
|
||||||
|
// once the lighting process is complete.
|
||||||
|
SceneLighting* sl = new SceneLighting( getSceneLightingInterface() );
|
||||||
|
return sl->lightScene( callback, flags );
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*RenderDeferredMgr* ProbeManager::_findDeferredRenderBin()
|
||||||
|
{
|
||||||
|
RenderPassManager* rpm = getSceneManager()->getDefaultRenderPass();
|
||||||
|
for( U32 i = 0; i < rpm->getManagerCount(); i++ )
|
||||||
|
{
|
||||||
|
RenderBinManager *bin = rpm->getManager( i );
|
||||||
|
if( bin->getRenderInstType() == RenderDeferredMgr::RIT_Deferred )
|
||||||
|
{
|
||||||
|
return ( RenderDeferredMgr* ) bin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
DefineEngineFunction( CreateProbeManager, bool, (),,
|
||||||
|
"Finds and activates the named light manager.\n"
|
||||||
|
"@return Returns true if the light manager is found and activated.\n"
|
||||||
|
"@ingroup Lighting\n" )
|
||||||
|
{
|
||||||
|
ProbeManager* probeManager = new ProbeManager();
|
||||||
|
|
||||||
|
if (probeManager != nullptr && gClientSceneGraph != nullptr)
|
||||||
|
{
|
||||||
|
probeManager->activate(gClientSceneGraph);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefineEngineFunction( resetProbeManager, void, (),,
|
||||||
|
"@brief Deactivates and then activates the currently active light manager."
|
||||||
|
"This causes most shaders to be regenerated and is often used when global "
|
||||||
|
"rendering changes have occured.\n"
|
||||||
|
"@ingroup Lighting\n" )
|
||||||
|
{
|
||||||
|
ProbeManager *pm = PROBEMGR;
|
||||||
|
if ( !pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*SceneManager *sm = lm->getSceneManager();
|
||||||
|
lm->deactivate();
|
||||||
|
lm->activate( sm );*/
|
||||||
|
}
|
||||||
334
Engine/source/lighting/probeManager.h
Normal file
334
Engine/source/lighting/probeManager.h
Normal file
|
|
@ -0,0 +1,334 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef PROBEMANAGER_H
|
||||||
|
#define PROBEMANAGER_H
|
||||||
|
|
||||||
|
#ifndef _TORQUE_STRING_H_
|
||||||
|
#include "core/util/str.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _TSIGNAL_H_
|
||||||
|
#include "core/util/tSignal.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _LIGHTINFO_H_
|
||||||
|
#include "lighting/lightInfo.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _LIGHTQUERY_H_
|
||||||
|
#include "lighting/lightQuery.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _MATRIXSET_H_
|
||||||
|
#include "math/util/matrixSet.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _CUBEMAPDATA_H_
|
||||||
|
#include "gfx/sim/cubemapData.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class SimObject;
|
||||||
|
class ProbeManager;
|
||||||
|
class Material;
|
||||||
|
class ProcessedMaterial;
|
||||||
|
class SceneManager;
|
||||||
|
struct SceneData;
|
||||||
|
class Point3F;
|
||||||
|
class AvailableSLInterfaces;
|
||||||
|
class SceneObject;
|
||||||
|
class GFXShaderConstBuffer;
|
||||||
|
class GFXShaderConstHandle;
|
||||||
|
class ShaderConstHandles;
|
||||||
|
class SceneRenderState;
|
||||||
|
class RenderDeferredMgr;
|
||||||
|
class Frustum;
|
||||||
|
|
||||||
|
struct ProbeInfo
|
||||||
|
{
|
||||||
|
LinearColorF mAmbient;
|
||||||
|
|
||||||
|
MatrixF mTransform;
|
||||||
|
|
||||||
|
F32 mRadius;
|
||||||
|
F32 mIntensity;
|
||||||
|
|
||||||
|
Box3F mBounds;
|
||||||
|
|
||||||
|
GFXCubemapHandle *mCubemap;
|
||||||
|
|
||||||
|
GFXCubemapHandle *mIrradianceCubemap;
|
||||||
|
|
||||||
|
GFXTexHandle *mBRDFTexture;
|
||||||
|
|
||||||
|
/// The priority of this light used for
|
||||||
|
/// light and shadow scoring.
|
||||||
|
F32 mPriority;
|
||||||
|
|
||||||
|
/// A temporary which holds the score used
|
||||||
|
/// when prioritizing lights for rendering.
|
||||||
|
F32 mScore;
|
||||||
|
|
||||||
|
bool mIsSkylight;
|
||||||
|
|
||||||
|
/// Whether to render debugging visualizations
|
||||||
|
/// for this light.
|
||||||
|
bool mDebugRender;
|
||||||
|
|
||||||
|
//GFXPrimitiveBufferHandle primBuffer;
|
||||||
|
//GFXVertexBufferHandle<GFXVertexPC> vertBuffer;
|
||||||
|
U32 numPrims;
|
||||||
|
U32 numVerts;
|
||||||
|
Vector< U32 > numIndicesForPoly;
|
||||||
|
|
||||||
|
enum ProbeShapeType
|
||||||
|
{
|
||||||
|
Sphere = 0, ///< Sphere shaped
|
||||||
|
Box = 1, ///< Box-based shape
|
||||||
|
};
|
||||||
|
|
||||||
|
ProbeShapeType mProbeShapeType;
|
||||||
|
|
||||||
|
//Spherical Harmonics data
|
||||||
|
LinearColorF mSHTerms[9];
|
||||||
|
F32 mSHConstants[5];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProbeInfo();
|
||||||
|
~ProbeInfo();
|
||||||
|
|
||||||
|
// Copies data passed in from another probe
|
||||||
|
void set(const ProbeInfo *probe);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
const MatrixF& getTransform() const { return mTransform; }
|
||||||
|
void setTransform(const MatrixF &xfm) { mTransform = xfm; }
|
||||||
|
|
||||||
|
Point3F getPosition() const { return mTransform.getPosition(); }
|
||||||
|
void setPosition(const Point3F &pos) { mTransform.setPosition(pos); }
|
||||||
|
|
||||||
|
VectorF getDirection() const { return mTransform.getForwardVector(); }
|
||||||
|
void setDirection(const VectorF &val);
|
||||||
|
|
||||||
|
const LinearColorF& getAmbient() const { return mAmbient; }
|
||||||
|
void setAmbient(const LinearColorF &val) { mAmbient = val; }
|
||||||
|
|
||||||
|
void setPriority(F32 priority) { mPriority = priority; }
|
||||||
|
F32 getPriority() const { return mPriority; }
|
||||||
|
|
||||||
|
void setScore(F32 score) { mScore = score; }
|
||||||
|
F32 getScore() const { return mScore; }
|
||||||
|
|
||||||
|
bool isDebugRenderingEnabled() const { return mDebugRender; }
|
||||||
|
void enableDebugRendering(bool value) { mDebugRender = value; }
|
||||||
|
|
||||||
|
// Builds the world to light view projection used for
|
||||||
|
// shadow texture and cookie lookups.
|
||||||
|
void getWorldToLightProj(MatrixF *outMatrix) const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProbeInfoList : public Vector<ProbeInfo*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void registerProbe(ProbeInfo *probe);
|
||||||
|
void unregisterProbe(ProbeInfo *probe);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProbeShaderConstants
|
||||||
|
{
|
||||||
|
bool mInit;
|
||||||
|
|
||||||
|
GFXShaderRef mShader;
|
||||||
|
|
||||||
|
GFXShaderConstHandle* mProbeParamsSC;
|
||||||
|
|
||||||
|
//Reflection Probes
|
||||||
|
GFXShaderConstHandle *mProbePositionSC;
|
||||||
|
GFXShaderConstHandle *mProbeRadiusSC;
|
||||||
|
GFXShaderConstHandle *mProbeBoxMinSC;
|
||||||
|
GFXShaderConstHandle *mProbeBoxMaxSC;
|
||||||
|
GFXShaderConstHandle *mProbeIsSphereSC;
|
||||||
|
GFXShaderConstHandle *mProbeLocalPosSC;
|
||||||
|
GFXShaderConstHandle *mProbeCubemapSC;
|
||||||
|
|
||||||
|
ProbeShaderConstants();
|
||||||
|
~ProbeShaderConstants();
|
||||||
|
|
||||||
|
void init(GFXShader* buffer);
|
||||||
|
|
||||||
|
void _onShaderReload();
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Map<GFXShader*, ProbeShaderConstants*> ProbeConstantMap;
|
||||||
|
|
||||||
|
class ProbeManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum SpecialProbeTypesEnum
|
||||||
|
{
|
||||||
|
SkylightProbeType,
|
||||||
|
SpecialProbeTypesCount
|
||||||
|
};
|
||||||
|
|
||||||
|
ProbeManager();
|
||||||
|
|
||||||
|
~ProbeManager();
|
||||||
|
|
||||||
|
///
|
||||||
|
static void initProbeFields();
|
||||||
|
|
||||||
|
///
|
||||||
|
static ProbeInfo* createProbeInfo(ProbeInfo* light = NULL);
|
||||||
|
|
||||||
|
/// The light manager activation signal.
|
||||||
|
static Signal<void(const char*,bool)> smActivateSignal;
|
||||||
|
|
||||||
|
/// Returns the active LM.
|
||||||
|
static inline ProbeManager* getProbeManager();
|
||||||
|
|
||||||
|
// Returns the scene manager passed at activation.
|
||||||
|
SceneManager* getSceneManager() { return mSceneManager; }
|
||||||
|
|
||||||
|
// Called when the lighting manager should become active
|
||||||
|
virtual void activate( SceneManager *sceneManager );
|
||||||
|
|
||||||
|
// Called when we don't want the light manager active (should clean up)
|
||||||
|
virtual void deactivate();
|
||||||
|
|
||||||
|
// Returns the active scene lighting interface for this light manager.
|
||||||
|
virtual AvailableSLInterfaces* getSceneLightingInterface();
|
||||||
|
|
||||||
|
// Returns a "default" light info that callers should not free. Used for instances where we don't actually care about
|
||||||
|
// the light (for example, setting default data for SceneData)
|
||||||
|
virtual ProbeInfo* getDefaultLight();
|
||||||
|
|
||||||
|
/// Returns the special light or the default light if useDefault is true.
|
||||||
|
/// @see getDefaultLight
|
||||||
|
virtual ProbeInfo* getSpecialProbe(SpecialProbeTypesEnum type,
|
||||||
|
bool useDefault = true );
|
||||||
|
|
||||||
|
/// Set a special light type.
|
||||||
|
virtual void setSpecialProbe(SpecialProbeTypesEnum type, ProbeInfo *light );
|
||||||
|
|
||||||
|
void registerSkylight(ProbeInfo *probe, SimObject *obj);
|
||||||
|
|
||||||
|
// registered before scene traversal...
|
||||||
|
virtual void registerProbe(ProbeInfo *light, SimObject *obj );
|
||||||
|
virtual void unregisterProbe(ProbeInfo *light );
|
||||||
|
|
||||||
|
virtual void registerProbes( const Frustum *frustum, bool staticlighting );
|
||||||
|
virtual void unregisterAllProbes();
|
||||||
|
|
||||||
|
/// Returns all unsorted and un-scored lights (both global and local).
|
||||||
|
void getAllUnsortedProbes( Vector<ProbeInfo*> *list ) const;
|
||||||
|
|
||||||
|
/// Sets shader constants / textures for light infos
|
||||||
|
virtual void setProbeInfo( ProcessedMaterial *pmat,
|
||||||
|
const Material *mat,
|
||||||
|
const SceneData &sgData,
|
||||||
|
const SceneRenderState *state,
|
||||||
|
U32 pass,
|
||||||
|
GFXShaderConstBuffer *shaderConsts );
|
||||||
|
|
||||||
|
/// Allows us to set textures during the Material::setTextureStage call, return true if we've done work.
|
||||||
|
virtual bool setTextureStage( const SceneData &sgData,
|
||||||
|
const U32 currTexFlag,
|
||||||
|
const U32 textureSlot,
|
||||||
|
GFXShaderConstBuffer *shaderConsts,
|
||||||
|
ShaderConstHandles *handles );
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/// The current active light manager.
|
||||||
|
static ProbeManager *smProbeManager;
|
||||||
|
|
||||||
|
/// Find the pre-pass render bin on the scene's default render pass.
|
||||||
|
RenderDeferredMgr* _findDeferredRenderBin();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProbeShaderConstants* getProbeShaderConstants(GFXShaderConstBuffer* buffer);
|
||||||
|
protected:
|
||||||
|
/// This helper function sets the shader constansts
|
||||||
|
/// 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,
|
||||||
|
GFXShaderConstBuffer *shaderConsts );
|
||||||
|
|
||||||
|
/// A dummy default light used when no lights
|
||||||
|
/// happen to be registered with the manager.
|
||||||
|
ProbeInfo *mDefaultProbe;
|
||||||
|
|
||||||
|
/// The list of global registered lights which is
|
||||||
|
/// initialized before the scene is rendered.
|
||||||
|
ProbeInfoList mRegisteredProbes;
|
||||||
|
|
||||||
|
ProbeInfo* mSkylight;
|
||||||
|
|
||||||
|
/// The registered special light list.
|
||||||
|
ProbeInfo *mSpecialProbes[SpecialProbeTypesCount];
|
||||||
|
|
||||||
|
/// The root culling position used for
|
||||||
|
/// special sun light placement.
|
||||||
|
/// @see setSpecialLight
|
||||||
|
Point3F mCullPos;
|
||||||
|
|
||||||
|
///
|
||||||
|
//virtual void _initLightFields();
|
||||||
|
|
||||||
|
/// The scene graph the light manager is associated with.
|
||||||
|
SceneManager *mSceneManager;
|
||||||
|
|
||||||
|
ProbeConstantMap mConstantLookup;
|
||||||
|
|
||||||
|
GFXShaderRef mLastShader;
|
||||||
|
|
||||||
|
ProbeShaderConstants* mLastConstants;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProbeManager* ProbeManager::getProbeManager()
|
||||||
|
{
|
||||||
|
if (smProbeManager == nullptr)
|
||||||
|
{
|
||||||
|
ProbeManager* probeManager = new ProbeManager();
|
||||||
|
|
||||||
|
if (gClientSceneGraph != nullptr)
|
||||||
|
{
|
||||||
|
probeManager->activate(gClientSceneGraph);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete probeManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return smProbeManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the current active light manager.
|
||||||
|
#define PROBEMGR ProbeManager::getProbeManager()
|
||||||
|
|
||||||
|
#endif // PROBEMANAGER_H
|
||||||
|
|
@ -62,6 +62,8 @@ ImplementFeatureType( MFT_SubSurface, MFG_Lighting, 8.0f, true );
|
||||||
ImplementFeatureType( MFT_VertLit, MFG_Lighting, 9.0f, true );
|
ImplementFeatureType( MFT_VertLit, MFG_Lighting, 9.0f, true );
|
||||||
ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 10.0f, true );
|
ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 10.0f, true );
|
||||||
|
|
||||||
|
ImplementFeatureType(MFT_ReflectionProbes, MFG_Lighting, 11.0f, true);
|
||||||
|
|
||||||
ImplementFeatureType( MFT_GlowMask, MFG_PostLighting, 1.0f, true );
|
ImplementFeatureType( MFT_GlowMask, MFG_PostLighting, 1.0f, true );
|
||||||
ImplementFeatureType( MFT_Visibility, MFG_PostLighting, 2.0f, true );
|
ImplementFeatureType( MFT_Visibility, MFG_PostLighting, 2.0f, true );
|
||||||
ImplementFeatureType( MFT_Fog, MFG_PostProcess, 3.0f, true );
|
ImplementFeatureType( MFT_Fog, MFG_PostProcess, 3.0f, true );
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,8 @@ DeclareFeatureType( MFT_InvertSmoothness );
|
||||||
DeclareFeatureType( MFT_SpecularMap );
|
DeclareFeatureType( MFT_SpecularMap );
|
||||||
DeclareFeatureType( MFT_GlossMap );
|
DeclareFeatureType( MFT_GlossMap );
|
||||||
|
|
||||||
|
DeclareFeatureType( MFT_ReflectionProbes );
|
||||||
|
|
||||||
/// This feature is only used to detect alpha transparency
|
/// This feature is only used to detect alpha transparency
|
||||||
/// and does not have any code associtated with it.
|
/// and does not have any code associtated with it.
|
||||||
DeclareFeatureType( MFT_IsTranslucent );
|
DeclareFeatureType( MFT_IsTranslucent );
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "console/propertyParsing.h"
|
#include "console/propertyParsing.h"
|
||||||
#include "gfx/util/screenspace.h"
|
#include "gfx/util/screenspace.h"
|
||||||
#include "scene/reflectionManager.h"
|
#include "scene/reflectionManager.h"
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
|
||||||
|
|
||||||
ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat)
|
ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat)
|
||||||
|
|
@ -322,6 +323,10 @@ bool ProcessedCustomMaterial::setupPass( SceneRenderState *state, const SceneDat
|
||||||
if (lm)
|
if (lm)
|
||||||
lm->setLightInfo(this, NULL, sgData, state, pass, shaderConsts);
|
lm->setLightInfo(this, NULL, sgData, state, pass, shaderConsts);
|
||||||
|
|
||||||
|
ProbeManager* pm = state ? PROBEMGR : NULL;
|
||||||
|
if (pm)
|
||||||
|
pm->setProbeInfo(this, NULL, sgData, state, pass, shaderConsts);
|
||||||
|
|
||||||
shaderConsts->setSafe(rpd->shaderHandles.mAccumTimeSC, MATMGR->getTotalTime());
|
shaderConsts->setSafe(rpd->shaderHandles.mAccumTimeSC, MATMGR->getTotalTime());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@
|
||||||
#include "gfx/util/screenspace.h"
|
#include "gfx/util/screenspace.h"
|
||||||
#include "math/util/matrixSet.h"
|
#include "math/util/matrixSet.h"
|
||||||
|
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
|
||||||
// We need to include customMaterialDefinition for ShaderConstHandles::init
|
// We need to include customMaterialDefinition for ShaderConstHandles::init
|
||||||
#include "materials/customMaterialDefinition.h"
|
#include "materials/customMaterialDefinition.h"
|
||||||
|
|
||||||
|
|
@ -343,10 +345,16 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
|
||||||
if ( mMaterial->mAlphaTest )
|
if ( mMaterial->mAlphaTest )
|
||||||
fd.features.addFeature( MFT_AlphaTest );
|
fd.features.addFeature( MFT_AlphaTest );
|
||||||
|
|
||||||
if ( mMaterial->mEmissive[stageNum] )
|
if (mMaterial->mEmissive[stageNum])
|
||||||
fd.features.addFeature( MFT_IsEmissive );
|
{
|
||||||
|
fd.features.addFeature(MFT_IsEmissive);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fd.features.addFeature( MFT_RTLighting );
|
{
|
||||||
|
fd.features.addFeature(MFT_RTLighting);
|
||||||
|
if (mMaterial->isTranslucent())
|
||||||
|
fd.features.addFeature(MFT_ReflectionProbes);
|
||||||
|
}
|
||||||
|
|
||||||
if ( mMaterial->mAnimFlags[stageNum] )
|
if ( mMaterial->mAnimFlags[stageNum] )
|
||||||
fd.features.addFeature( MFT_TexAnim );
|
fd.features.addFeature( MFT_TexAnim );
|
||||||
|
|
@ -357,7 +365,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
|
||||||
// cubemaps only available on stage 0 for now - bramage
|
// cubemaps only available on stage 0 for now - bramage
|
||||||
if ( stageNum < 1 && mMaterial->isTranslucent() &&
|
if ( stageNum < 1 && mMaterial->isTranslucent() &&
|
||||||
( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) ||
|
( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) ||
|
||||||
mMaterial->mDynamicCubemap ) )
|
mMaterial->mDynamicCubemap ) && !features.hasFeature(MFT_ReflectionProbes))
|
||||||
{
|
{
|
||||||
fd.features.addFeature( MFT_CubeMap );
|
fd.features.addFeature( MFT_CubeMap );
|
||||||
}
|
}
|
||||||
|
|
@ -367,6 +375,8 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
|
||||||
fd.features.addFeature(MFT_StaticCubemap);
|
fd.features.addFeature(MFT_StaticCubemap);
|
||||||
fd.features.addFeature(MFT_CubeMap);
|
fd.features.addFeature(MFT_CubeMap);
|
||||||
fd.features.addFeature(MFT_SkyBox);
|
fd.features.addFeature(MFT_SkyBox);
|
||||||
|
|
||||||
|
fd.features.removeFeature(MFT_ReflectionProbes);
|
||||||
}
|
}
|
||||||
fd.features.addFeature( MFT_Visibility );
|
fd.features.addFeature( MFT_Visibility );
|
||||||
|
|
||||||
|
|
@ -1296,13 +1306,15 @@ void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const Scene
|
||||||
shaderConsts->set(handles->mEyePosSC, eyepos);
|
shaderConsts->set(handles->mEyePosSC, eyepos);
|
||||||
}
|
}
|
||||||
|
|
||||||
shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform());
|
shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform());
|
||||||
|
|
||||||
ShaderRenderPassData *rpd = _getRPD( pass );
|
ShaderRenderPassData *rpd = _getRPD(pass);
|
||||||
for ( U32 i=0; i < rpd->featureShaderHandles.size(); i++ )
|
for (U32 i = 0; i < rpd->featureShaderHandles.size(); i++)
|
||||||
rpd->featureShaderHandles[i]->setConsts( state, sgData, shaderConsts );
|
rpd->featureShaderHandles[i]->setConsts(state, sgData, shaderConsts);
|
||||||
|
|
||||||
LIGHTMGR->setLightInfo( this, mMaterial, sgData, state, pass, shaderConsts );
|
LIGHTMGR->setLightInfo(this, mMaterial, sgData, state, pass, shaderConsts);
|
||||||
|
|
||||||
|
PROBEMGR->setProbeInfo(this, mMaterial, sgData, state, pass, shaderConsts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessedShaderMaterial::setBuffers( GFXVertexBufferHandleBase *vertBuffer, GFXPrimitiveBufferHandle *primBuffer )
|
void ProcessedShaderMaterial::setBuffers( GFXVertexBufferHandleBase *vertBuffer, GFXPrimitiveBufferHandle *primBuffer )
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,6 @@ public:
|
||||||
|
|
||||||
MaterialOverrideDelegate& getMatOverrideDelegate() { return mMatOverrideDelegate; }
|
MaterialOverrideDelegate& getMatOverrideDelegate() { return mMatOverrideDelegate; }
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
struct MainSortElem
|
struct MainSortElem
|
||||||
{
|
{
|
||||||
RenderInst *inst;
|
RenderInst *inst;
|
||||||
|
|
@ -95,6 +93,7 @@ protected:
|
||||||
U32 key2;
|
U32 key2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
void setRenderPass( RenderPassManager *rpm );
|
void setRenderPass( RenderPassManager *rpm );
|
||||||
|
|
||||||
/// Called from derived bins to add additional
|
/// Called from derived bins to add additional
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ const String RenderDeferredMgr::BufferName("deferred");
|
||||||
const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred");
|
const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred");
|
||||||
const String RenderDeferredMgr::ColorBufferName("color");
|
const String RenderDeferredMgr::ColorBufferName("color");
|
||||||
const String RenderDeferredMgr::MatInfoBufferName("matinfo");
|
const String RenderDeferredMgr::MatInfoBufferName("matinfo");
|
||||||
const String RenderDeferredMgr::LightMapBufferName("indirectLighting");
|
const String RenderDeferredMgr::LightMapBufferName("diffuseLighting");
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(RenderDeferredMgr);
|
IMPLEMENT_CONOBJECT(RenderDeferredMgr);
|
||||||
|
|
||||||
|
|
@ -92,6 +92,7 @@ RenderDeferredMgr::RenderDeferredMgr( bool gatherDepth,
|
||||||
notifyType( RenderPassManager::RIT_Mesh );
|
notifyType( RenderPassManager::RIT_Mesh );
|
||||||
notifyType( RenderPassManager::RIT_Terrain );
|
notifyType( RenderPassManager::RIT_Terrain );
|
||||||
notifyType( RenderPassManager::RIT_Object );
|
notifyType( RenderPassManager::RIT_Object );
|
||||||
|
notifyType( RenderPassManager::RIT_Probes );
|
||||||
|
|
||||||
// We want a full-resolution buffer
|
// We want a full-resolution buffer
|
||||||
mTargetSizeType = RenderTexTargetBinManager::WindowSize;
|
mTargetSizeType = RenderTexTargetBinManager::WindowSize;
|
||||||
|
|
@ -186,10 +187,10 @@ bool RenderDeferredMgr::_updateTargets()
|
||||||
mTargetChain[i]->attachTexture(GFXTextureTarget::Color2, mMatInfoTarget.getTexture());
|
mTargetChain[i]->attachTexture(GFXTextureTarget::Color2, mMatInfoTarget.getTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLightMapTex.getFormat() != mTargetFormat || mLightMapTex.getWidthHeight() != mTargetSize || GFX->recentlyReset())
|
if (mLightMapTex.getFormat() != GFXFormatR16G16B16A16F || mLightMapTex.getWidthHeight() != mTargetSize || GFX->recentlyReset())
|
||||||
{
|
{
|
||||||
mLightMapTarget.release();
|
mLightMapTarget.release();
|
||||||
mLightMapTex.set(mTargetSize.x, mTargetSize.y, mTargetFormat,
|
mLightMapTex.set(mTargetSize.x, mTargetSize.y, GFXFormatR16G16B16A16F,
|
||||||
&GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
|
&GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__),
|
||||||
1, GFXTextureManager::AA_MATCH_BACKBUFFER);
|
1, GFXTextureManager::AA_MATCH_BACKBUFFER);
|
||||||
mLightMapTarget.setTexture(mLightMapTex);
|
mLightMapTarget.setTexture(mLightMapTex);
|
||||||
|
|
@ -238,6 +239,8 @@ void RenderDeferredMgr::addElement( RenderInst *inst )
|
||||||
|
|
||||||
const bool isTerrainInst = inst->type == RenderPassManager::RIT_Terrain;
|
const bool isTerrainInst = inst->type == RenderPassManager::RIT_Terrain;
|
||||||
|
|
||||||
|
const bool isProbeInst = inst->type == RenderPassManager::RIT_Probes;
|
||||||
|
|
||||||
// Get the material if its a mesh.
|
// Get the material if its a mesh.
|
||||||
BaseMatInstance* matInst = NULL;
|
BaseMatInstance* matInst = NULL;
|
||||||
if ( isMeshInst || isDecalMeshInst )
|
if ( isMeshInst || isDecalMeshInst )
|
||||||
|
|
@ -262,6 +265,8 @@ void RenderDeferredMgr::addElement( RenderInst *inst )
|
||||||
elementList = &mElementList;
|
elementList = &mElementList;
|
||||||
else if ( isTerrainInst )
|
else if ( isTerrainInst )
|
||||||
elementList = &mTerrainElementList;
|
elementList = &mTerrainElementList;
|
||||||
|
else if (isProbeInst)
|
||||||
|
elementList = &mProbeElementList;
|
||||||
else
|
else
|
||||||
elementList = &mObjectElementList;
|
elementList = &mObjectElementList;
|
||||||
|
|
||||||
|
|
@ -294,6 +299,7 @@ void RenderDeferredMgr::sort()
|
||||||
void RenderDeferredMgr::clear()
|
void RenderDeferredMgr::clear()
|
||||||
{
|
{
|
||||||
Parent::clear();
|
Parent::clear();
|
||||||
|
mProbeElementList.clear();
|
||||||
mTerrainElementList.clear();
|
mTerrainElementList.clear();
|
||||||
mObjectElementList.clear();
|
mObjectElementList.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,9 @@ protected:
|
||||||
|
|
||||||
DeferredMatInstance *mDeferredMatInstance;
|
DeferredMatInstance *mDeferredMatInstance;
|
||||||
|
|
||||||
|
///
|
||||||
|
Vector< MainSortElem > mProbeElementList;
|
||||||
|
|
||||||
virtual void _registerFeatures();
|
virtual void _registerFeatures();
|
||||||
virtual void _unregisterFeatures();
|
virtual void _unregisterFeatures();
|
||||||
virtual bool _updateTargets();
|
virtual bool _updateTargets();
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ const RenderInstType RenderPassManager::RIT_Custom("Custom");
|
||||||
const RenderInstType RenderPassManager::RIT_Particle("Particle");
|
const RenderInstType RenderPassManager::RIT_Particle("Particle");
|
||||||
const RenderInstType RenderPassManager::RIT_Occluder("Occluder");
|
const RenderInstType RenderPassManager::RIT_Occluder("Occluder");
|
||||||
const RenderInstType RenderPassManager::RIT_Editor("Editor");
|
const RenderInstType RenderPassManager::RIT_Editor("Editor");
|
||||||
|
const RenderInstType RenderPassManager::RIT_Probes("Probes");
|
||||||
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|
@ -102,6 +103,11 @@ void OccluderRenderInst::clear()
|
||||||
dMemset( this, 0, sizeof(OccluderRenderInst) );
|
dMemset( this, 0, sizeof(OccluderRenderInst) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProbeRenderInst::clear()
|
||||||
|
{
|
||||||
|
dMemset(this, 0, sizeof(ProbeRenderInst));
|
||||||
|
//mCubemap);
|
||||||
|
}
|
||||||
|
|
||||||
IMPLEMENT_CONOBJECT(RenderPassManager);
|
IMPLEMENT_CONOBJECT(RenderPassManager);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,18 @@
|
||||||
#ifndef _SCENEMANAGER_H_
|
#ifndef _SCENEMANAGER_H_
|
||||||
#include "scene/sceneManager.h"
|
#include "scene/sceneManager.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef _SCENEMANAGER_H_
|
||||||
|
#include "scene/sceneManager.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _CUBEMAPDATA_H_
|
||||||
|
#include "gfx/sim/cubemapData.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||||
|
#include "gfx/gfxPrimitiveBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef PROBEMANAGER_H
|
||||||
|
#include "lighting/probeManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class SceneRenderState;
|
class SceneRenderState;
|
||||||
class ISceneObject;
|
class ISceneObject;
|
||||||
|
|
@ -48,6 +60,7 @@ class LightInfo;
|
||||||
struct RenderInst;
|
struct RenderInst;
|
||||||
class MatrixSet;
|
class MatrixSet;
|
||||||
class GFXPrimitiveBufferHandle;
|
class GFXPrimitiveBufferHandle;
|
||||||
|
class CubemapData;
|
||||||
|
|
||||||
/// A RenderInstType hash value.
|
/// A RenderInstType hash value.
|
||||||
typedef U32 RenderInstTypeHash;
|
typedef U32 RenderInstTypeHash;
|
||||||
|
|
@ -118,6 +131,7 @@ public:
|
||||||
static const RenderInstType RIT_Particle;
|
static const RenderInstType RIT_Particle;
|
||||||
static const RenderInstType RIT_Occluder;
|
static const RenderInstType RIT_Occluder;
|
||||||
static const RenderInstType RIT_Editor;
|
static const RenderInstType RIT_Editor;
|
||||||
|
static const RenderInstType RIT_Probes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -463,4 +477,85 @@ struct OccluderRenderInst : public RenderInst
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ProbeRenderInst : public RenderInst
|
||||||
|
{
|
||||||
|
LinearColorF mAmbient;
|
||||||
|
|
||||||
|
MatrixF mTransform;
|
||||||
|
|
||||||
|
F32 mRadius;
|
||||||
|
F32 mIntensity;
|
||||||
|
|
||||||
|
Box3F mBounds;
|
||||||
|
|
||||||
|
GFXCubemapHandle *mCubemap;
|
||||||
|
|
||||||
|
GFXCubemapHandle *mIrradianceCubemap;
|
||||||
|
|
||||||
|
GFXTexHandle *mBRDFTexture;
|
||||||
|
|
||||||
|
/// The priority of this light used for
|
||||||
|
/// light and shadow scoring.
|
||||||
|
F32 mPriority;
|
||||||
|
|
||||||
|
/// A temporary which holds the score used
|
||||||
|
/// when prioritizing lights for rendering.
|
||||||
|
F32 mScore;
|
||||||
|
|
||||||
|
bool mIsSkylight;
|
||||||
|
|
||||||
|
/// Whether to render debugging visualizations
|
||||||
|
/// for this light.
|
||||||
|
bool mDebugRender;
|
||||||
|
|
||||||
|
GFXPrimitiveBufferHandle primBuffer;
|
||||||
|
GFXVertexBufferHandle<GFXVertexPC> vertBuffer;
|
||||||
|
U32 numPrims;
|
||||||
|
U32 numVerts;
|
||||||
|
Vector< U32 > numIndicesForPoly;
|
||||||
|
|
||||||
|
ProbeInfo::ProbeShapeType mProbeShapeType;
|
||||||
|
|
||||||
|
//Spherical Harmonics data
|
||||||
|
LinearColorF mSHTerms[9];
|
||||||
|
F32 mSHConstants[5];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProbeRenderInst();
|
||||||
|
~ProbeRenderInst();
|
||||||
|
|
||||||
|
// Copies data passed in from light
|
||||||
|
void set(const ProbeRenderInst *probeInfo);
|
||||||
|
void set(const ProbeInfo *probeInfo);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
const MatrixF& getTransform() const { return mTransform; }
|
||||||
|
void setTransform(const MatrixF &xfm) { mTransform = xfm; }
|
||||||
|
|
||||||
|
Point3F getPosition() const { return mTransform.getPosition(); }
|
||||||
|
void setPosition(const Point3F &pos) { mTransform.setPosition(pos); }
|
||||||
|
|
||||||
|
VectorF getDirection() const { return mTransform.getForwardVector(); }
|
||||||
|
void setDirection(const VectorF &val);
|
||||||
|
|
||||||
|
const LinearColorF& getAmbient() const { return mAmbient; }
|
||||||
|
void setAmbient(const LinearColorF &val) { mAmbient = val; }
|
||||||
|
|
||||||
|
void setPriority(F32 priority) { mPriority = priority; }
|
||||||
|
F32 getPriority() const { return mPriority; }
|
||||||
|
|
||||||
|
void setScore(F32 score) { mScore = score; }
|
||||||
|
F32 getScore() const { return mScore; }
|
||||||
|
|
||||||
|
bool isDebugRenderingEnabled() const { return mDebugRender; }
|
||||||
|
void enableDebugRendering(bool value) { mDebugRender = value; }
|
||||||
|
|
||||||
|
// Builds the world to light view projection used for
|
||||||
|
// shadow texture and cookie lookups.
|
||||||
|
void getWorldToLightProj(MatrixF *outMatrix) const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _RENDERPASSMANAGER_H_
|
#endif // _RENDERPASSMANAGER_H_
|
||||||
|
|
|
||||||
956
Engine/source/renderInstance/renderProbeMgr.cpp
Normal file
956
Engine/source/renderInstance/renderProbeMgr.cpp
Normal file
|
|
@ -0,0 +1,956 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#include "renderProbeMgr.h"
|
||||||
|
#include "console/consoleTypes.h"
|
||||||
|
#include "scene/sceneObject.h"
|
||||||
|
#include "materials/materialManager.h"
|
||||||
|
#include "scene/sceneRenderState.h"
|
||||||
|
#include "math/util/sphereMesh.h"
|
||||||
|
#include "math/util/matrixSet.h"
|
||||||
|
#include "materials/processedMaterial.h"
|
||||||
|
#include "renderInstance/renderDeferredMgr.h"
|
||||||
|
#include "math/mPolyhedron.impl.h"
|
||||||
|
#include "gfx/gfxTransformSaver.h"
|
||||||
|
|
||||||
|
IMPLEMENT_CONOBJECT(RenderProbeMgr);
|
||||||
|
|
||||||
|
ConsoleDocClass( RenderProbeMgr,
|
||||||
|
"@brief A render bin which uses object callbacks for rendering.\n\n"
|
||||||
|
"This render bin gathers object render instances and calls its delegate "
|
||||||
|
"method to perform rendering. It is used infrequently for specialized "
|
||||||
|
"scene objects which perform custom rendering.\n\n"
|
||||||
|
"@ingroup RenderBin\n" );
|
||||||
|
|
||||||
|
S32 QSORT_CALLBACK AscendingReflectProbeInfluence(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
// Debug Profiling.
|
||||||
|
PROFILE_SCOPE(AdvancedLightBinManager_AscendingReflectProbeInfluence);
|
||||||
|
|
||||||
|
// Fetch asset definitions.
|
||||||
|
const ProbeRenderInst* pReflectProbeA = static_cast<ProbeRenderInst*>(((RenderBinManager::MainSortElem*)(a))->inst);
|
||||||
|
const ProbeRenderInst* pReflectProbeB = static_cast<ProbeRenderInst*>(((RenderBinManager::MainSortElem*)(b))->inst);
|
||||||
|
|
||||||
|
// Sort.
|
||||||
|
//First, immediate check on if either is a skylight. Skylight always gets the highest priority
|
||||||
|
//if (pReflectProbeA->mIsSkylight)
|
||||||
|
// return 1;
|
||||||
|
//else if (pReflectProbeB->mIsSkylight)
|
||||||
|
// return -1;
|
||||||
|
//No? then sort by score
|
||||||
|
if (pReflectProbeA->mScore > pReflectProbeB->mScore)
|
||||||
|
return 1;
|
||||||
|
else if (pReflectProbeA->mScore < pReflectProbeB->mScore)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::RenderProbeMgr()
|
||||||
|
: RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f)
|
||||||
|
{
|
||||||
|
mReflectProbeMaterial = nullptr;
|
||||||
|
mSkylightMaterial = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder)
|
||||||
|
: RenderBinManager(riType, renderOrder, processAddOrder)
|
||||||
|
{
|
||||||
|
mReflectProbeMaterial = nullptr;
|
||||||
|
mSkylightMaterial = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::initPersistFields()
|
||||||
|
{
|
||||||
|
Parent::initPersistFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::addElement(RenderInst *inst)
|
||||||
|
{
|
||||||
|
// If this instance is translucent handle it in RenderTranslucentMgr
|
||||||
|
if (inst->translucentSort)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//AssertFatal(inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?");
|
||||||
|
|
||||||
|
internalAddElement(inst);
|
||||||
|
|
||||||
|
ProbeRenderInst* probeInst = static_cast<ProbeRenderInst*>(inst);
|
||||||
|
|
||||||
|
if (probeInst->mIsSkylight)
|
||||||
|
{
|
||||||
|
addSkylightProbe(probeInst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (probeInst->mProbeShapeType == ProbeInfo::Sphere)
|
||||||
|
addSphereReflectionProbe(probeInst);
|
||||||
|
else
|
||||||
|
addConvexReflectionProbe(probeInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove
|
||||||
|
//Con::setIntVariable("lightMetrics::activeReflectionProbes", mReflectProbeBin.size());
|
||||||
|
//Con::setIntVariable("lightMetrics::culledReflectProbes", 0/*mNumLightsCulled*/);
|
||||||
|
//
|
||||||
|
|
||||||
|
GFXVertexBufferHandle<GFXVertexPC> RenderProbeMgr::getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBufferHandle &outPrimitives)
|
||||||
|
{
|
||||||
|
static SphereMesh sSphereMesh;
|
||||||
|
|
||||||
|
if (mSphereGeometry.isNull())
|
||||||
|
{
|
||||||
|
const SphereMesh::TriangleMesh * sphereMesh = sSphereMesh.getMesh(3);
|
||||||
|
S32 numPoly = sphereMesh->numPoly;
|
||||||
|
mSpherePrimitiveCount = 0;
|
||||||
|
mSphereGeometry.set(GFX, numPoly * 3, GFXBufferTypeStatic);
|
||||||
|
mSphereGeometry.lock();
|
||||||
|
S32 vertexIndex = 0;
|
||||||
|
|
||||||
|
for (S32 i = 0; i<numPoly; i++)
|
||||||
|
{
|
||||||
|
mSpherePrimitiveCount++;
|
||||||
|
|
||||||
|
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[0];
|
||||||
|
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||||
|
vertexIndex++;
|
||||||
|
|
||||||
|
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[1];
|
||||||
|
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||||
|
vertexIndex++;
|
||||||
|
|
||||||
|
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[2];
|
||||||
|
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||||
|
vertexIndex++;
|
||||||
|
}
|
||||||
|
mSphereGeometry.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
outNumPrimitives = mSpherePrimitiveCount;
|
||||||
|
outPrimitives = NULL; // For now
|
||||||
|
return mSphereGeometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::addSkylightProbe(ProbeRenderInst *probeInfo)
|
||||||
|
{
|
||||||
|
probeInfo->vertBuffer = getSphereMesh(probeInfo->numPrims, probeInfo->primBuffer);
|
||||||
|
|
||||||
|
if (!mSkylightMaterial)
|
||||||
|
mSkylightMaterial = _getSkylightMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::addSphereReflectionProbe(ProbeRenderInst *probeInfo)
|
||||||
|
{
|
||||||
|
probeInfo->vertBuffer = getSphereMesh(probeInfo->numPrims, probeInfo->primBuffer);
|
||||||
|
|
||||||
|
if (!mReflectProbeMaterial)
|
||||||
|
mReflectProbeMaterial = _getReflectProbeMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::addConvexReflectionProbe(ProbeRenderInst *probeInfo)
|
||||||
|
{
|
||||||
|
static const Point3F cubePoints[8] =
|
||||||
|
{
|
||||||
|
Point3F(1, -1, -1), Point3F(1, -1, 1), Point3F(1, 1, -1), Point3F(1, 1, 1),
|
||||||
|
Point3F(-1, -1, -1), Point3F(-1, 1, -1), Point3F(-1, -1, 1), Point3F(-1, 1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
/*static const Point3F cubeNormals[6] =
|
||||||
|
{
|
||||||
|
Point3F(1, 0, 0), Point3F(-1, 0, 0), Point3F(0, 1, 0),
|
||||||
|
Point3F(0, -1, 0), Point3F(0, 0, 1), Point3F(0, 0, -1)
|
||||||
|
};*/
|
||||||
|
|
||||||
|
/*static const Point2F cubeTexCoords[4] =
|
||||||
|
{
|
||||||
|
Point2F(0, 0), Point2F(0, -1),
|
||||||
|
Point2F(1, 0), Point2F(1, -1)
|
||||||
|
};*/
|
||||||
|
|
||||||
|
static const U32 cubeFaces[36][3] =
|
||||||
|
{
|
||||||
|
{ 3, 0, 3 },{ 0, 0, 0 },{ 1, 0, 1 },
|
||||||
|
{ 2, 0, 2 },{ 0, 0, 0 },{ 3, 0, 3 },
|
||||||
|
{ 7, 1, 1 },{ 4, 1, 2 },{ 5, 1, 0 },
|
||||||
|
{ 6, 1, 3 },{ 4, 1, 2 },{ 7, 1, 1 },
|
||||||
|
{ 3, 2, 1 },{ 5, 2, 2 },{ 2, 2, 0 },
|
||||||
|
{ 7, 2, 3 },{ 5, 2, 2 },{ 3, 2, 1 },
|
||||||
|
{ 1, 3, 3 },{ 4, 3, 0 },{ 6, 3, 1 },
|
||||||
|
{ 0, 3, 2 },{ 4, 3, 0 },{ 1, 3, 3 },
|
||||||
|
{ 3, 4, 3 },{ 6, 4, 0 },{ 7, 4, 1 },
|
||||||
|
{ 1, 4, 2 },{ 6, 4, 0 },{ 3, 4, 3 },
|
||||||
|
{ 2, 5, 1 },{ 4, 5, 2 },{ 0, 5, 0 },
|
||||||
|
{ 5, 5, 3 },{ 4, 5, 2 },{ 2, 5, 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fill the vertex buffer
|
||||||
|
GFXVertexPC *pVert = NULL;
|
||||||
|
|
||||||
|
probeInfo->numVerts = 36;
|
||||||
|
|
||||||
|
probeInfo->vertBuffer.set(GFX, 36, GFXBufferTypeStatic);
|
||||||
|
pVert = probeInfo->vertBuffer.lock();
|
||||||
|
|
||||||
|
Point3F halfSize = Point3F(probeInfo->mRadius, probeInfo->mRadius, probeInfo->mRadius);
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 36; i++)
|
||||||
|
{
|
||||||
|
const U32& vdx = cubeFaces[i][0];
|
||||||
|
pVert[i].point = cubePoints[vdx] * halfSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
probeInfo->vertBuffer.unlock();
|
||||||
|
|
||||||
|
// Fill the primitive buffer
|
||||||
|
U16 *pIdx = NULL;
|
||||||
|
|
||||||
|
probeInfo->primBuffer.set(GFX, 36, 12, GFXBufferTypeStatic);
|
||||||
|
|
||||||
|
probeInfo->primBuffer.lock(&pIdx);
|
||||||
|
|
||||||
|
for (U16 i = 0; i < 36; i++)
|
||||||
|
pIdx[i] = i;
|
||||||
|
|
||||||
|
probeInfo->primBuffer.unlock();
|
||||||
|
|
||||||
|
probeInfo->numPrims = 12;
|
||||||
|
|
||||||
|
if (!mReflectProbeMaterial)
|
||||||
|
mReflectProbeMaterial = _getReflectProbeMaterial();
|
||||||
|
//
|
||||||
|
|
||||||
|
// mReflectProbeBin.push_back(pEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::_setupPerFrameParameters(const SceneRenderState *state)
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(RenderProbeMgr_SetupPerFrameParameters);
|
||||||
|
const Frustum &frustum = state->getCameraFrustum();
|
||||||
|
|
||||||
|
MatrixF invCam(frustum.getTransform());
|
||||||
|
invCam.inverse();
|
||||||
|
|
||||||
|
const Point3F *wsFrustumPoints = frustum.getPoints();
|
||||||
|
const Point3F& cameraPos = frustum.getPosition();
|
||||||
|
|
||||||
|
// Perform a camera offset. We need to manually perform this offset on the sun (or vector) light's
|
||||||
|
// polygon, which is at the far plane.
|
||||||
|
Point3F cameraOffsetPos = cameraPos;
|
||||||
|
|
||||||
|
// Now build the quad for drawing full-screen vector light
|
||||||
|
// passes.... this is a volatile VB and updates every frame.
|
||||||
|
FarFrustumQuadVert verts[4];
|
||||||
|
{
|
||||||
|
verts[0].point.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraPos);
|
||||||
|
invCam.mulP(wsFrustumPoints[Frustum::FarTopLeft], &verts[0].normal);
|
||||||
|
verts[0].texCoord.set(-1.0, 1.0);
|
||||||
|
verts[0].tangent.set(wsFrustumPoints[Frustum::FarTopLeft] - cameraOffsetPos);
|
||||||
|
|
||||||
|
verts[1].point.set(wsFrustumPoints[Frustum::FarTopRight] - cameraPos);
|
||||||
|
invCam.mulP(wsFrustumPoints[Frustum::FarTopRight], &verts[1].normal);
|
||||||
|
verts[1].texCoord.set(1.0, 1.0);
|
||||||
|
verts[1].tangent.set(wsFrustumPoints[Frustum::FarTopRight] - cameraOffsetPos);
|
||||||
|
|
||||||
|
verts[2].point.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraPos);
|
||||||
|
invCam.mulP(wsFrustumPoints[Frustum::FarBottomLeft], &verts[2].normal);
|
||||||
|
verts[2].texCoord.set(-1.0, -1.0);
|
||||||
|
verts[2].tangent.set(wsFrustumPoints[Frustum::FarBottomLeft] - cameraOffsetPos);
|
||||||
|
|
||||||
|
verts[3].point.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraPos);
|
||||||
|
invCam.mulP(wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal);
|
||||||
|
verts[3].texCoord.set(1.0, -1.0);
|
||||||
|
verts[3].tangent.set(wsFrustumPoints[Frustum::FarBottomRight] - cameraOffsetPos);
|
||||||
|
}
|
||||||
|
mFarFrustumQuadVerts.set(GFX, 4);
|
||||||
|
dMemcpy(mFarFrustumQuadVerts.lock(), verts, sizeof(verts));
|
||||||
|
mFarFrustumQuadVerts.unlock();
|
||||||
|
|
||||||
|
PlaneF farPlane(wsFrustumPoints[Frustum::FarBottomLeft], wsFrustumPoints[Frustum::FarTopLeft], wsFrustumPoints[Frustum::FarTopRight]);
|
||||||
|
PlaneF vsFarPlane(verts[0].normal, verts[1].normal, verts[2].normal);
|
||||||
|
|
||||||
|
MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
|
||||||
|
matrixSet.restoreSceneViewProjection();
|
||||||
|
|
||||||
|
const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
|
||||||
|
|
||||||
|
MatrixF inverseViewMatrix = worldToCameraXfm;
|
||||||
|
//inverseViewMatrix.fullInverse();
|
||||||
|
//inverseViewMatrix.transpose();
|
||||||
|
|
||||||
|
//inverseViewMatrix = MatrixF::Identity;
|
||||||
|
|
||||||
|
// Parameters calculated, assign them to the materials
|
||||||
|
if (mSkylightMaterial != nullptr && mSkylightMaterial->matInstance != nullptr)
|
||||||
|
{
|
||||||
|
mSkylightMaterial->setViewParameters(frustum.getNearDist(),
|
||||||
|
frustum.getFarDist(),
|
||||||
|
frustum.getPosition(),
|
||||||
|
farPlane,
|
||||||
|
vsFarPlane, inverseViewMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mReflectProbeMaterial != nullptr && mReflectProbeMaterial->matInstance != nullptr)
|
||||||
|
{
|
||||||
|
mReflectProbeMaterial->setViewParameters(frustum.getNearDist(),
|
||||||
|
frustum.getFarDist(),
|
||||||
|
frustum.getPosition(),
|
||||||
|
farPlane,
|
||||||
|
vsFarPlane, inverseViewMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// render objects
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void RenderProbeMgr::render( SceneRenderState *state )
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(RenderProbeMgr_render);
|
||||||
|
|
||||||
|
// Early out if nothing to draw.
|
||||||
|
if(!mElementList.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
GFXTransformSaver saver;
|
||||||
|
|
||||||
|
NamedTexTargetRef diffuseLightingTarget = NamedTexTarget::find("diffuseLighting");
|
||||||
|
|
||||||
|
if (diffuseLightingTarget.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
NamedTexTargetRef specularLightingTarget = NamedTexTarget::find("specularLighting");
|
||||||
|
|
||||||
|
if (specularLightingTarget.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
GFXTextureTargetRef probeLightingTargetRef = GFX->allocRenderToTextureTarget();
|
||||||
|
|
||||||
|
if (probeLightingTargetRef.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
probeLightingTargetRef->attachTexture(GFXTextureTarget::Color0, diffuseLightingTarget->getTexture());
|
||||||
|
probeLightingTargetRef->attachTexture(GFXTextureTarget::Color1, specularLightingTarget->getTexture());
|
||||||
|
|
||||||
|
GFX->pushActiveRenderTarget();
|
||||||
|
GFX->setActiveRenderTarget(probeLightingTargetRef);
|
||||||
|
|
||||||
|
GFX->setViewport(diffuseLightingTarget->getViewport());
|
||||||
|
//GFX->setViewport(specularLightingTarget->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(mElementList.address(), mElementList.size(), sizeof(const MainSortElem), AscendingReflectProbeInfluence);
|
||||||
|
|
||||||
|
//Specular
|
||||||
|
PROFILE_START(RenderProbeManager_ReflectProbeRender);
|
||||||
|
|
||||||
|
for (U32 i = 0; i<mElementList.size(); i++)
|
||||||
|
{
|
||||||
|
ProbeRenderInst *curEntry = static_cast<ProbeRenderInst*>(mElementList[i].inst);
|
||||||
|
|
||||||
|
if (curEntry->numPrims == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (curEntry->mIsSkylight && (!mSkylightMaterial || !mSkylightMaterial->matInstance))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!curEntry->mIsSkylight && (!mReflectProbeMaterial || !mReflectProbeMaterial->matInstance))
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Setup
|
||||||
|
MatrixF probeTrans = curEntry->getTransform();
|
||||||
|
|
||||||
|
if (!curEntry->mIsSkylight)
|
||||||
|
{
|
||||||
|
if (curEntry->mProbeShapeType == ProbeInfo::Sphere)
|
||||||
|
probeTrans.scale(curEntry->mRadius * 1.01f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
probeTrans.scale(10); //force it to be big enough to surround the camera
|
||||||
|
}
|
||||||
|
|
||||||
|
sgData.objTrans = &probeTrans;
|
||||||
|
|
||||||
|
if(curEntry->mIsSkylight)
|
||||||
|
mSkylightMaterial->setSkylightParameters(curEntry, state, worldToCameraXfm);
|
||||||
|
else
|
||||||
|
mReflectProbeMaterial->setProbeParameters(curEntry, state, worldToCameraXfm);
|
||||||
|
|
||||||
|
// Set geometry
|
||||||
|
GFX->setVertexBuffer(curEntry->vertBuffer);
|
||||||
|
GFX->setPrimitiveBuffer(curEntry->primBuffer);
|
||||||
|
|
||||||
|
if (curEntry->mIsSkylight)
|
||||||
|
{
|
||||||
|
while (mSkylightMaterial->matInstance->setupPass(state, sgData))
|
||||||
|
{
|
||||||
|
// Set transforms
|
||||||
|
matrixSet.setWorld(*sgData.objTrans);
|
||||||
|
mSkylightMaterial->matInstance->setTransforms(matrixSet, state);
|
||||||
|
mSkylightMaterial->matInstance->setSceneInfo(state, sgData);
|
||||||
|
|
||||||
|
GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (mReflectProbeMaterial->matInstance->setupPass(state, sgData))
|
||||||
|
{
|
||||||
|
// Set transforms
|
||||||
|
matrixSet.setWorld(*sgData.objTrans);
|
||||||
|
mReflectProbeMaterial->matInstance->setTransforms(matrixSet, state);
|
||||||
|
mReflectProbeMaterial->matInstance->setSceneInfo(state, sgData);
|
||||||
|
|
||||||
|
GFX->drawPrimitive(GFXTriangleList, 0, curEntry->numPrims);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
probeLightingTargetRef->resolve();
|
||||||
|
GFX->popActiveRenderTarget();
|
||||||
|
|
||||||
|
PROBEMGR->unregisterAllProbes();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
RenderProbeMgr::ReflectProbeMaterialInfo::ReflectProbeMaterialInfo(const String &matName,
|
||||||
|
const GFXVertexFormat *vertexFormat)
|
||||||
|
: matInstance(NULL),
|
||||||
|
zNearFarInvNearFar(NULL),
|
||||||
|
farPlane(NULL),
|
||||||
|
vsFarPlane(NULL),
|
||||||
|
negFarPlaneDotEye(NULL),
|
||||||
|
probeWSPos(NULL),
|
||||||
|
attenuation(NULL),
|
||||||
|
radius(NULL),
|
||||||
|
invViewMat(NULL)
|
||||||
|
{
|
||||||
|
Material *mat = MATMGR->getMaterialDefinitionByName(matName);
|
||||||
|
if (!mat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
matInstance = new ReflectProbeMatInstance(*mat);
|
||||||
|
|
||||||
|
const Vector<GFXShaderMacro> ¯os = Vector<GFXShaderMacro>();
|
||||||
|
|
||||||
|
for (U32 i = 0; i < macros.size(); i++)
|
||||||
|
matInstance->addShaderMacro(macros[i].name, macros[i].value);
|
||||||
|
|
||||||
|
matInstance->init(MATMGR->getDefaultFeatures(), vertexFormat);
|
||||||
|
|
||||||
|
attenuation = matInstance->getMaterialParameterHandle("$attenuation");
|
||||||
|
radius = matInstance->getMaterialParameterHandle("$radius");
|
||||||
|
probeLSPos = matInstance->getMaterialParameterHandle("$probeLSPos");
|
||||||
|
probeWSPos = matInstance->getMaterialParameterHandle("$probeWSPos");
|
||||||
|
farPlane = matInstance->getMaterialParameterHandle("$farPlane");
|
||||||
|
vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane");
|
||||||
|
negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye");
|
||||||
|
zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar");
|
||||||
|
|
||||||
|
invViewMat = matInstance->getMaterialParameterHandle("$invViewMat");
|
||||||
|
|
||||||
|
useCubemap = matInstance->getMaterialParameterHandle("$useCubemap");
|
||||||
|
|
||||||
|
cubemap = matInstance->getMaterialParameterHandle("$cubeMap");
|
||||||
|
|
||||||
|
eyePosWorld = matInstance->getMaterialParameterHandle("$eyePosWorld");
|
||||||
|
bbMin = matInstance->getMaterialParameterHandle("$bbMin");
|
||||||
|
bbMax = matInstance->getMaterialParameterHandle("$bbMax");
|
||||||
|
|
||||||
|
useSphereMode = matInstance->getMaterialParameterHandle("$useSphereMode");
|
||||||
|
|
||||||
|
for(U32 i=0; i < 9; i++)
|
||||||
|
shTerms[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHTerms%d",i));
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
shConsts[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHConsts%d", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::ReflectProbeMaterialInfo::~ReflectProbeMaterialInfo()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(matInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::ReflectProbeMaterialInfo::setViewParameters(const F32 _zNear,
|
||||||
|
const F32 _zFar,
|
||||||
|
const Point3F &_eyePos,
|
||||||
|
const PlaneF &_farPlane,
|
||||||
|
const PlaneF &_vsFarPlane, const MatrixF &_inverseViewMatrix)
|
||||||
|
{
|
||||||
|
MaterialParameters *matParams = matInstance->getMaterialParameters();
|
||||||
|
|
||||||
|
matParams->setSafe(farPlane, *((const Point4F *)&_farPlane));
|
||||||
|
|
||||||
|
matParams->setSafe(vsFarPlane, *((const Point4F *)&_vsFarPlane));
|
||||||
|
|
||||||
|
if (negFarPlaneDotEye->isValid())
|
||||||
|
{
|
||||||
|
// -dot( farPlane, eyePos )
|
||||||
|
const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
|
||||||
|
matParams->set(negFarPlaneDotEye, negFarPlaneDotEyeVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
matParams->setSafe(zNearFarInvNearFar, Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar));
|
||||||
|
|
||||||
|
matParams->setSafe(invViewMat, _inverseViewMatrix);
|
||||||
|
|
||||||
|
Point4F frPlane = *((const Point4F *)&_farPlane);
|
||||||
|
Point4F vsFrPlane = *((const Point4F *)&_vsFarPlane);
|
||||||
|
Point4F nearFarInvNearFar = Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar);
|
||||||
|
const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::ReflectProbeMaterialInfo::setProbeParameters(const ProbeRenderInst *probeInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly)
|
||||||
|
{
|
||||||
|
//Set up the params
|
||||||
|
MaterialParameters *matParams = matInstance->getMaterialParameters();
|
||||||
|
|
||||||
|
matParams->setSafe(radius, probeInfo->mRadius);
|
||||||
|
|
||||||
|
Point3F probePos = probeInfo->getPosition();
|
||||||
|
//worldViewOnly.mulP(probeInfo->getPosition(), &probePos);
|
||||||
|
matParams->setSafe(probeWSPos, probePos);
|
||||||
|
|
||||||
|
worldViewOnly.mulP(probeInfo->getPosition(), &probePos);
|
||||||
|
matParams->setSafe(probeLSPos, probePos);
|
||||||
|
|
||||||
|
// Get the attenuation falloff ratio and normalize it.
|
||||||
|
Point3F attenRatio = Point3F(0.0f, 1.0f, 1.0f);
|
||||||
|
F32 total = attenRatio.x + attenRatio.y + attenRatio.z;
|
||||||
|
if (total > 0.0f)
|
||||||
|
attenRatio /= total;
|
||||||
|
|
||||||
|
F32 radius = probeInfo->mRadius;
|
||||||
|
|
||||||
|
Point2F attenParams((1.0f / radius) * attenRatio.y,
|
||||||
|
(1.0f / (radius * radius)) * attenRatio.z);
|
||||||
|
|
||||||
|
matParams->setSafe(attenuation, attenParams);
|
||||||
|
|
||||||
|
NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
|
||||||
|
|
||||||
|
GFXTextureObject *deferredTexObject = deferredTexTarget->getTexture();
|
||||||
|
if (!deferredTexObject) return;
|
||||||
|
|
||||||
|
GFX->setTexture(0, deferredTexObject);
|
||||||
|
|
||||||
|
NamedTexTarget* matInfoTexTarget = NamedTexTarget::find("matinfo");
|
||||||
|
|
||||||
|
GFXTextureObject *matInfoTexObject = matInfoTexTarget->getTexture();
|
||||||
|
if (!matInfoTexObject) return;
|
||||||
|
|
||||||
|
GFX->setTexture(1, matInfoTexObject);
|
||||||
|
|
||||||
|
if (probeInfo->mCubemap && !probeInfo->mCubemap->isNull())
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(2, probeInfo->mCubemap->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probeInfo->mIrradianceCubemap && !probeInfo->mIrradianceCubemap->isNull())
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(3, probeInfo->mIrradianceCubemap->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(3, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probeInfo->mBRDFTexture && !probeInfo->mBRDFTexture->isNull())
|
||||||
|
{
|
||||||
|
GFX->setTexture(4, probeInfo->mBRDFTexture->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setTexture(4, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
matParams->setSafe(eyePosWorld, renderState->getCameraPosition());
|
||||||
|
matParams->setSafe(bbMin, probeInfo->mBounds.minExtents);
|
||||||
|
matParams->setSafe(bbMax, probeInfo->mBounds.maxExtents);
|
||||||
|
|
||||||
|
matParams->setSafe(useSphereMode, probeInfo->mProbeShapeType == ProbeInfo::Sphere ? 1.0f : 0.0f);
|
||||||
|
|
||||||
|
//SH Terms
|
||||||
|
//static AlignedArray<Point3F> shTermsArray(9, sizeof(Point3F));
|
||||||
|
//dMemset(shTermsArray.getBuffer(), 0, shTermsArray.getBufferSize());
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
matParams->setSafe(shTerms[i], probeInfo->mSHTerms[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
matParams->setSafe(shConsts[i], probeInfo->mSHConstants[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ReflectProbeMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat)
|
||||||
|
{
|
||||||
|
bool success = Parent::init(features, vertexFormat);
|
||||||
|
|
||||||
|
// If the initialization failed don't continue.
|
||||||
|
if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReflectProbeMatInstance::setupPass(SceneRenderState *state, const SceneData &sgData)
|
||||||
|
{
|
||||||
|
// Go no further if the material failed to initialize properly.
|
||||||
|
if (!mProcessedMaterial ||
|
||||||
|
mProcessedMaterial->getNumPasses() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool bRetVal = Parent::setupPass(state, sgData);;
|
||||||
|
|
||||||
|
AssertFatal(mProcessedMaterial->getNumPasses() > 0, "No passes created! Ohnoes");
|
||||||
|
const RenderPassData *rpd = mProcessedMaterial->getPass(0);
|
||||||
|
AssertFatal(rpd, "No render pass data!");
|
||||||
|
AssertFatal(rpd->mRenderStates[0], "No render state 0!");
|
||||||
|
|
||||||
|
if (!mProjectionState)
|
||||||
|
{
|
||||||
|
GFXStateBlockDesc desc;
|
||||||
|
desc.setZReadWrite(false);
|
||||||
|
desc.zWriteEnable = false;
|
||||||
|
desc.setCullMode(GFXCullNone);
|
||||||
|
desc.setBlend(true, GFXBlendOne, GFXBlendOne);
|
||||||
|
mProjectionState = GFX->createStateBlock(desc);
|
||||||
|
}
|
||||||
|
// Now override stateblock with our own
|
||||||
|
GFX->setStateBlock(mProjectionState);
|
||||||
|
|
||||||
|
return bRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::ReflectProbeMaterialInfo* RenderProbeMgr::_getReflectProbeMaterial()
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(AdvancedLightBinManager_getReflectProbeMaterial);
|
||||||
|
|
||||||
|
//ReflectProbeMaterialInfo *info = NULL;
|
||||||
|
|
||||||
|
if (!mReflectProbeMaterial)
|
||||||
|
|
||||||
|
// Now create the material info object.
|
||||||
|
mReflectProbeMaterial = new ReflectProbeMaterialInfo("ReflectionProbeMaterial",
|
||||||
|
getGFXVertexFormat<GFXVertexPC>());
|
||||||
|
|
||||||
|
return mReflectProbeMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
RenderProbeMgr::SkylightMaterialInfo::SkylightMaterialInfo(const String &matName,
|
||||||
|
const GFXVertexFormat *vertexFormat)
|
||||||
|
: matInstance(NULL),
|
||||||
|
zNearFarInvNearFar(NULL),
|
||||||
|
farPlane(NULL),
|
||||||
|
vsFarPlane(NULL),
|
||||||
|
negFarPlaneDotEye(NULL),
|
||||||
|
invViewMat(NULL)
|
||||||
|
{
|
||||||
|
Material *mat = MATMGR->getMaterialDefinitionByName(matName);
|
||||||
|
if (!mat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
matInstance = new SkylightMatInstance(*mat);
|
||||||
|
|
||||||
|
const Vector<GFXShaderMacro> ¯os = Vector<GFXShaderMacro>();
|
||||||
|
|
||||||
|
for (U32 i = 0; i < macros.size(); i++)
|
||||||
|
matInstance->addShaderMacro(macros[i].name, macros[i].value);
|
||||||
|
|
||||||
|
matInstance->init(MATMGR->getDefaultFeatures(), vertexFormat);
|
||||||
|
|
||||||
|
farPlane = matInstance->getMaterialParameterHandle("$farPlane");
|
||||||
|
vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane");
|
||||||
|
negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye");
|
||||||
|
zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar");
|
||||||
|
|
||||||
|
invViewMat = matInstance->getMaterialParameterHandle("$invViewMat");
|
||||||
|
|
||||||
|
useCubemap = matInstance->getMaterialParameterHandle("$useCubemap");
|
||||||
|
cubemap = matInstance->getMaterialParameterHandle("$cubeMap");
|
||||||
|
|
||||||
|
eyePosWorld = matInstance->getMaterialParameterHandle("$eyePosWorld");
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
shTerms[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHTerms%d", i));
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
shConsts[i] = matInstance->getMaterialParameterHandle(String::ToString("$SHConsts%d", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::SkylightMaterialInfo::~SkylightMaterialInfo()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(matInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::SkylightMaterialInfo::setViewParameters(const F32 _zNear,
|
||||||
|
const F32 _zFar,
|
||||||
|
const Point3F &_eyePos,
|
||||||
|
const PlaneF &_farPlane,
|
||||||
|
const PlaneF &_vsFarPlane, const MatrixF &_inverseViewMatrix)
|
||||||
|
{
|
||||||
|
MaterialParameters *matParams = matInstance->getMaterialParameters();
|
||||||
|
|
||||||
|
matParams->setSafe(farPlane, *((const Point4F *)&_farPlane));
|
||||||
|
|
||||||
|
matParams->setSafe(vsFarPlane, *((const Point4F *)&_vsFarPlane));
|
||||||
|
|
||||||
|
if (negFarPlaneDotEye->isValid())
|
||||||
|
{
|
||||||
|
// -dot( farPlane, eyePos )
|
||||||
|
const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
|
||||||
|
matParams->set(negFarPlaneDotEye, negFarPlaneDotEyeVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
matParams->setSafe(zNearFarInvNearFar, Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar));
|
||||||
|
|
||||||
|
matParams->setSafe(invViewMat, _inverseViewMatrix);
|
||||||
|
|
||||||
|
Point4F frPlane = *((const Point4F *)&_farPlane);
|
||||||
|
Point4F vsFrPlane = *((const Point4F *)&_vsFarPlane);
|
||||||
|
Point4F nearFarInvNearFar = Point4F(_zNear, _zFar, 1.0f / _zNear, 1.0f / _zFar);
|
||||||
|
const F32 negFarPlaneDotEyeVal = -(mDot(*((const Point3F *)&_farPlane), _eyePos) + _farPlane.d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderProbeMgr::SkylightMaterialInfo::setSkylightParameters(const ProbeRenderInst *probeInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly)
|
||||||
|
{
|
||||||
|
//Set up the params
|
||||||
|
MaterialParameters *matParams = matInstance->getMaterialParameters();
|
||||||
|
|
||||||
|
NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
|
||||||
|
|
||||||
|
GFXTextureObject *deferredTexObject = deferredTexTarget->getTexture();
|
||||||
|
if (!deferredTexObject) return;
|
||||||
|
|
||||||
|
GFX->setTexture(0, deferredTexObject);
|
||||||
|
|
||||||
|
NamedTexTarget* matInfoTexTarget = NamedTexTarget::find("matinfo");
|
||||||
|
|
||||||
|
GFXTextureObject *matInfoTexObject = matInfoTexTarget->getTexture();
|
||||||
|
if (!matInfoTexObject) return;
|
||||||
|
|
||||||
|
GFX->setTexture(1, matInfoTexObject);
|
||||||
|
|
||||||
|
if (probeInfo->mCubemap && !probeInfo->mCubemap->isNull())
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(2, probeInfo->mCubemap->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probeInfo->mIrradianceCubemap && !probeInfo->mIrradianceCubemap->isNull())
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(3, probeInfo->mIrradianceCubemap->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setCubeTexture(3, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probeInfo->mBRDFTexture && !probeInfo->mBRDFTexture->isNull())
|
||||||
|
{
|
||||||
|
GFX->setTexture(4, probeInfo->mBRDFTexture->getPointer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFX->setTexture(4, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
matParams->setSafe(eyePosWorld, renderState->getCameraPosition());
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
matParams->setSafe(shTerms[i], probeInfo->mSHTerms[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
matParams->setSafe(shConsts[i], probeInfo->mSHConstants[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SkylightMatInstance::init(const FeatureSet &features, const GFXVertexFormat *vertexFormat)
|
||||||
|
{
|
||||||
|
bool success = Parent::init(features, vertexFormat);
|
||||||
|
|
||||||
|
// If the initialization failed don't continue.
|
||||||
|
if (!success || !mProcessedMaterial || mProcessedMaterial->getNumPasses() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkylightMatInstance::setupPass(SceneRenderState *state, const SceneData &sgData)
|
||||||
|
{
|
||||||
|
// Go no further if the material failed to initialize properly.
|
||||||
|
if (!mProcessedMaterial ||
|
||||||
|
mProcessedMaterial->getNumPasses() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool bRetVal = Parent::setupPass(state, sgData);;
|
||||||
|
|
||||||
|
AssertFatal(mProcessedMaterial->getNumPasses() > 0, "No passes created! Ohnoes");
|
||||||
|
const RenderPassData *rpd = mProcessedMaterial->getPass(0);
|
||||||
|
AssertFatal(rpd, "No render pass data!");
|
||||||
|
AssertFatal(rpd->mRenderStates[0], "No render state 0!");
|
||||||
|
|
||||||
|
if (!mProjectionState)
|
||||||
|
{
|
||||||
|
GFXStateBlockDesc desc;
|
||||||
|
desc.setZReadWrite(false);
|
||||||
|
desc.zWriteEnable = false;
|
||||||
|
desc.setCullMode(GFXCullNone);
|
||||||
|
desc.setBlend(true, GFXBlendOne, GFXBlendOne);
|
||||||
|
mProjectionState = GFX->createStateBlock(desc);
|
||||||
|
}
|
||||||
|
// Now override stateblock with our own
|
||||||
|
GFX->setStateBlock(mProjectionState);
|
||||||
|
|
||||||
|
return bRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderProbeMgr::SkylightMaterialInfo* RenderProbeMgr::_getSkylightMaterial()
|
||||||
|
{
|
||||||
|
PROFILE_SCOPE(AdvancedLightBinManager_getSkylightMaterial);
|
||||||
|
|
||||||
|
//ReflectProbeMaterialInfo *info = NULL;
|
||||||
|
|
||||||
|
if (!mSkylightMaterial)
|
||||||
|
|
||||||
|
// Now create the material info object.
|
||||||
|
mSkylightMaterial = new SkylightMaterialInfo("SklyightMaterial",
|
||||||
|
getGFXVertexFormat<GFXVertexPC>());
|
||||||
|
|
||||||
|
return mSkylightMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
ProbeRenderInst::ProbeRenderInst()
|
||||||
|
: mTransform(true),
|
||||||
|
mAmbient(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
|
mPriority(1.0f),
|
||||||
|
mScore(0.0f),
|
||||||
|
mDebugRender(false),
|
||||||
|
mCubemap(NULL),
|
||||||
|
mRadius(1.0f),
|
||||||
|
mIntensity(1.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProbeRenderInst::~ProbeRenderInst()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(mCubemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeRenderInst::set(const ProbeRenderInst *probeInfo)
|
||||||
|
{
|
||||||
|
mTransform = probeInfo->mTransform;
|
||||||
|
mAmbient = probeInfo->mAmbient;
|
||||||
|
mCubemap = probeInfo->mCubemap;
|
||||||
|
mIrradianceCubemap = probeInfo->mIrradianceCubemap;
|
||||||
|
mBRDFTexture = probeInfo->mBRDFTexture;
|
||||||
|
mRadius = probeInfo->mRadius;
|
||||||
|
mIntensity = probeInfo->mIntensity;
|
||||||
|
mProbeShapeType = probeInfo->mProbeShapeType;
|
||||||
|
numPrims = probeInfo->numPrims;
|
||||||
|
numVerts = probeInfo->numVerts;
|
||||||
|
numIndicesForPoly = probeInfo->numIndicesForPoly;
|
||||||
|
mBounds = probeInfo->mBounds;
|
||||||
|
mScore = probeInfo->mScore;
|
||||||
|
mIsSkylight = probeInfo->mIsSkylight;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
mSHTerms[i] = probeInfo->mSHTerms[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
mSHConstants[i] = probeInfo->mSHConstants[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeRenderInst::set(const ProbeInfo *probeInfo)
|
||||||
|
{
|
||||||
|
mTransform = probeInfo->mTransform;
|
||||||
|
mAmbient = probeInfo->mAmbient;
|
||||||
|
mCubemap = probeInfo->mCubemap;
|
||||||
|
mIrradianceCubemap = probeInfo->mIrradianceCubemap;
|
||||||
|
mBRDFTexture = probeInfo->mBRDFTexture;
|
||||||
|
mRadius = probeInfo->mRadius;
|
||||||
|
mIntensity = probeInfo->mIntensity;
|
||||||
|
mProbeShapeType = probeInfo->mProbeShapeType;
|
||||||
|
numPrims = probeInfo->numPrims;
|
||||||
|
numVerts = probeInfo->numVerts;
|
||||||
|
numIndicesForPoly = probeInfo->numIndicesForPoly;
|
||||||
|
mBounds = probeInfo->mBounds;
|
||||||
|
mScore = probeInfo->mScore;
|
||||||
|
mIsSkylight = probeInfo->mIsSkylight;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
mSHTerms[i] = probeInfo->mSHTerms[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
mSHConstants[i] = probeInfo->mSHConstants[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProbeRenderInst::getWorldToLightProj(MatrixF *outMatrix) const
|
||||||
|
{
|
||||||
|
*outMatrix = getTransform();
|
||||||
|
outMatrix->inverse();
|
||||||
|
}
|
||||||
213
Engine/source/renderInstance/renderProbeMgr.h
Normal file
213
Engine/source/renderInstance/renderProbeMgr.h
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifndef RENDER_PROBE_MGR_H
|
||||||
|
#define RENDER_PROBE_MGR_H
|
||||||
|
|
||||||
|
#ifndef _RENDERBINMANAGER_H_
|
||||||
|
#include "renderInstance/renderBinManager.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _MATINSTANCE_H_
|
||||||
|
#include "materials/matInstance.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _MATTEXTURETARGET_H_
|
||||||
|
#include "materials/matTextureTarget.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||||
|
#include "gfx/gfxPrimitiveBuffer.h"
|
||||||
|
#endif
|
||||||
|
#ifndef _GFXVERTEXBUFFER_H_
|
||||||
|
#include "gfx/gfxVertexBuffer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ReflectProbeMatInstance : public MatInstance
|
||||||
|
{
|
||||||
|
typedef MatInstance Parent;
|
||||||
|
protected:
|
||||||
|
MaterialParameterHandle *mProbeParamsSC;
|
||||||
|
bool mInternalPass;
|
||||||
|
|
||||||
|
GFXStateBlockRef mProjectionState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReflectProbeMatInstance(Material &mat) : Parent(mat), mProbeParamsSC(NULL), mInternalPass(false), mProjectionState(NULL){}
|
||||||
|
|
||||||
|
virtual bool init(const FeatureSet &features, const GFXVertexFormat *vertexFormat);
|
||||||
|
virtual bool setupPass(SceneRenderState *state, const SceneData &sgData);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkylightMatInstance : public MatInstance
|
||||||
|
{
|
||||||
|
typedef MatInstance Parent;
|
||||||
|
protected:
|
||||||
|
MaterialParameterHandle * mSkylightParamsSC;
|
||||||
|
bool mInternalPass;
|
||||||
|
|
||||||
|
GFXStateBlockRef mProjectionState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SkylightMatInstance(Material &mat) : Parent(mat), mSkylightParamsSC(NULL), mInternalPass(false), mProjectionState(NULL) {}
|
||||||
|
|
||||||
|
virtual bool init(const FeatureSet &features, const GFXVertexFormat *vertexFormat);
|
||||||
|
virtual bool setupPass(SceneRenderState *state, const SceneData &sgData);
|
||||||
|
};
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// RenderObjectMgr
|
||||||
|
//**************************************************************************
|
||||||
|
class RenderProbeMgr : public RenderBinManager
|
||||||
|
{
|
||||||
|
typedef RenderBinManager Parent;
|
||||||
|
public:
|
||||||
|
typedef GFXVertexPNTT FarFrustumQuadVert;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct ReflectProbeMaterialInfo
|
||||||
|
{
|
||||||
|
ReflectProbeMatInstance *matInstance;
|
||||||
|
|
||||||
|
// { zNear, zFar, 1/zNear, 1/zFar }
|
||||||
|
MaterialParameterHandle *zNearFarInvNearFar;
|
||||||
|
|
||||||
|
// Far frustum plane (World Space)
|
||||||
|
MaterialParameterHandle *farPlane;
|
||||||
|
|
||||||
|
// Far frustum plane (View Space)
|
||||||
|
MaterialParameterHandle *vsFarPlane;
|
||||||
|
|
||||||
|
// -dot( farPlane, eyePos )
|
||||||
|
MaterialParameterHandle *negFarPlaneDotEye;
|
||||||
|
|
||||||
|
// Inverse View matrix
|
||||||
|
MaterialParameterHandle *invViewMat;
|
||||||
|
|
||||||
|
// Light Parameters
|
||||||
|
MaterialParameterHandle *probeLSPos;
|
||||||
|
MaterialParameterHandle *probeWSPos;
|
||||||
|
MaterialParameterHandle *attenuation;
|
||||||
|
MaterialParameterHandle *radius;
|
||||||
|
|
||||||
|
MaterialParameterHandle *useCubemap;
|
||||||
|
MaterialParameterHandle *cubemap;
|
||||||
|
|
||||||
|
MaterialParameterHandle *eyePosWorld;
|
||||||
|
MaterialParameterHandle *bbMin;
|
||||||
|
MaterialParameterHandle *bbMax;
|
||||||
|
|
||||||
|
MaterialParameterHandle *useSphereMode;
|
||||||
|
|
||||||
|
MaterialParameterHandle *shTerms[9];
|
||||||
|
MaterialParameterHandle *shConsts[5];
|
||||||
|
|
||||||
|
ReflectProbeMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat);
|
||||||
|
|
||||||
|
virtual ~ReflectProbeMaterialInfo();
|
||||||
|
|
||||||
|
|
||||||
|
void setViewParameters(const F32 zNear,
|
||||||
|
const F32 zFar,
|
||||||
|
const Point3F &eyePos,
|
||||||
|
const PlaneF &farPlane,
|
||||||
|
const PlaneF &_vsFarPlane,
|
||||||
|
const MatrixF &_inverseViewMatrix);
|
||||||
|
|
||||||
|
void setProbeParameters(const ProbeRenderInst *probe, const SceneRenderState* renderState, const MatrixF &worldViewOnly);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkylightMaterialInfo
|
||||||
|
{
|
||||||
|
SkylightMatInstance *matInstance;
|
||||||
|
|
||||||
|
// { zNear, zFar, 1/zNear, 1/zFar }
|
||||||
|
MaterialParameterHandle *zNearFarInvNearFar;
|
||||||
|
|
||||||
|
// Far frustum plane (World Space)
|
||||||
|
MaterialParameterHandle *farPlane;
|
||||||
|
|
||||||
|
// Far frustum plane (View Space)
|
||||||
|
MaterialParameterHandle *vsFarPlane;
|
||||||
|
|
||||||
|
// -dot( farPlane, eyePos )
|
||||||
|
MaterialParameterHandle *negFarPlaneDotEye;
|
||||||
|
|
||||||
|
// Inverse View matrix
|
||||||
|
MaterialParameterHandle *invViewMat;
|
||||||
|
|
||||||
|
MaterialParameterHandle *useCubemap;
|
||||||
|
MaterialParameterHandle *cubemap;
|
||||||
|
|
||||||
|
MaterialParameterHandle *eyePosWorld;
|
||||||
|
|
||||||
|
MaterialParameterHandle *shTerms[9];
|
||||||
|
MaterialParameterHandle *shConsts[5];
|
||||||
|
|
||||||
|
SkylightMaterialInfo(const String &matName, const GFXVertexFormat *vertexFormat);
|
||||||
|
|
||||||
|
virtual ~SkylightMaterialInfo();
|
||||||
|
|
||||||
|
|
||||||
|
void setViewParameters(const F32 zNear,
|
||||||
|
const F32 zFar,
|
||||||
|
const Point3F &eyePos,
|
||||||
|
const PlaneF &farPlane,
|
||||||
|
const PlaneF &_vsFarPlane,
|
||||||
|
const MatrixF &_inverseViewMatrix);
|
||||||
|
|
||||||
|
void setSkylightParameters(const ProbeRenderInst *probe, const SceneRenderState* renderState, const MatrixF &worldViewOnly);
|
||||||
|
};
|
||||||
|
|
||||||
|
GFXVertexBufferHandle<FarFrustumQuadVert> mFarFrustumQuadVerts;
|
||||||
|
|
||||||
|
GFXVertexBufferHandle<GFXVertexPC> getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBufferHandle &outPrimitives);
|
||||||
|
|
||||||
|
// Convex geometry for lights
|
||||||
|
GFXVertexBufferHandle<GFXVertexPC> mSphereGeometry;
|
||||||
|
|
||||||
|
GFXPrimitiveBufferHandle mSphereIndices;
|
||||||
|
|
||||||
|
U32 mSpherePrimitiveCount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderProbeMgr();
|
||||||
|
RenderProbeMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder);
|
||||||
|
|
||||||
|
// RenderBinMgr
|
||||||
|
void _setupPerFrameParameters(const SceneRenderState *state);
|
||||||
|
virtual void addElement(RenderInst *inst);
|
||||||
|
virtual void render(SceneRenderState * state);
|
||||||
|
|
||||||
|
// ConsoleObject
|
||||||
|
static void initPersistFields();
|
||||||
|
DECLARE_CONOBJECT(RenderProbeMgr);
|
||||||
|
|
||||||
|
ReflectProbeMaterialInfo* mReflectProbeMaterial;
|
||||||
|
ReflectProbeMaterialInfo* _getReflectProbeMaterial();
|
||||||
|
|
||||||
|
SkylightMaterialInfo* mSkylightMaterial;
|
||||||
|
SkylightMaterialInfo* _getSkylightMaterial();
|
||||||
|
|
||||||
|
// Add a reflection probe to the bin
|
||||||
|
void addSkylightProbe(ProbeRenderInst *probeInfo);
|
||||||
|
void addSphereReflectionProbe(ProbeRenderInst *probeInfo);
|
||||||
|
void addConvexReflectionProbe(ProbeRenderInst *probeInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RENDER_PROBE_MGR_H
|
||||||
|
|
@ -670,4 +670,29 @@ public:
|
||||||
virtual String getName() { return "Hardware Skinning"; }
|
virtual String getName() { return "Hardware Skinning"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Reflection Probes
|
||||||
|
class ReflectionProbeFeatGLSL : public ShaderFeatureGLSL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void processVert(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd) {}
|
||||||
|
|
||||||
|
virtual void processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd) {}
|
||||||
|
|
||||||
|
virtual Resources getResources(const MaterialFeatureData &fd) {
|
||||||
|
return Resources();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets textures and texture flags for current pass
|
||||||
|
virtual void setTexData(Material::StageData &stageDat,
|
||||||
|
const MaterialFeatureData &fd,
|
||||||
|
RenderPassData &passData,
|
||||||
|
U32 &texIndex) {}
|
||||||
|
|
||||||
|
virtual String getName()
|
||||||
|
{
|
||||||
|
return "Reflection Probes";
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif // _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_
|
#endif // _SHADERGEN_GLSL_SHADERFEATUREGLSL_H_
|
||||||
|
|
|
||||||
|
|
@ -2933,3 +2933,225 @@ void HardwareSkinningFeatureHLSL::processVert( Vector<ShaderComponent*> &compo
|
||||||
|
|
||||||
output = meta;
|
output = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//****************************************************************************
|
||||||
|
// ReflectionProbeFeatHLSL
|
||||||
|
//****************************************************************************
|
||||||
|
|
||||||
|
ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL()
|
||||||
|
: mDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/lighting.hlsl"))
|
||||||
|
{
|
||||||
|
addDependency(&mDep);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
// Skip out on realtime lighting if we don't have a normal
|
||||||
|
// or we're doing some sort of baked lighting.
|
||||||
|
//
|
||||||
|
// TODO: We can totally detect for this in the material
|
||||||
|
// feature setup... we should move it out of here!
|
||||||
|
//
|
||||||
|
if (fd.features[MFT_LightMap] || fd.features[MFT_ToneMap] || fd.features[MFT_VertLit])
|
||||||
|
return;
|
||||||
|
|
||||||
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
|
||||||
|
|
||||||
|
MultiLine *meta = new MultiLine;
|
||||||
|
|
||||||
|
// Look for a wsNormal or grab it from the connector.
|
||||||
|
Var *wsNormal = (Var*)LangElement::find("wsNormal");
|
||||||
|
if (!wsNormal)
|
||||||
|
{
|
||||||
|
wsNormal = connectComp->getElement(RT_TEXCOORD);
|
||||||
|
wsNormal->setName("wsNormal");
|
||||||
|
wsNormal->setStructName("IN");
|
||||||
|
wsNormal->setType("float3");
|
||||||
|
|
||||||
|
// If we loaded the normal its our responsibility
|
||||||
|
// to normalize it... the interpolators won't.
|
||||||
|
//
|
||||||
|
// Note we cast to half here to get partial precision
|
||||||
|
// optimized code which is an acceptable loss of
|
||||||
|
// precision for normals and performs much better
|
||||||
|
// on older Geforce cards.
|
||||||
|
//
|
||||||
|
meta->addStatement(new GenOp(" @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the wsPosition and wsView.
|
||||||
|
Var *wsPosition = getInWsPosition(componentList);
|
||||||
|
Var *wsView = getWsView(wsPosition, meta);
|
||||||
|
|
||||||
|
Var *metalness = (Var*)LangElement::find("metalness");
|
||||||
|
Var *smoothness = (Var*)LangElement::find("smoothness");
|
||||||
|
if (!fd.features[MFT_SpecularMap])
|
||||||
|
{
|
||||||
|
if (!metalness)
|
||||||
|
{
|
||||||
|
metalness = new Var("metalness", "float");
|
||||||
|
metalness->uniform = true;
|
||||||
|
metalness->constSortPos = cspPotentialPrimitive;
|
||||||
|
}
|
||||||
|
if (!smoothness)
|
||||||
|
{
|
||||||
|
smoothness = new Var("smoothness", "float");
|
||||||
|
smoothness->uniform = true;
|
||||||
|
smoothness->constSortPos = cspPotentialPrimitive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
|
||||||
|
|
||||||
|
//Reflection Probe WIP
|
||||||
|
Var *inProbePos = new Var("inProbePos", "float3");
|
||||||
|
inProbePos->arraySize = 4;
|
||||||
|
inProbePos->uniform = true;
|
||||||
|
inProbePos->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
|
Var *inProbeRadius = new Var("inProbeRadius", "float");
|
||||||
|
inProbeRadius->arraySize = 4;
|
||||||
|
inProbeRadius->uniform = true;
|
||||||
|
inProbeRadius->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
|
Var *inProbeBoxMin = new Var("inProbeBoxMin", "float3");
|
||||||
|
inProbeBoxMin->arraySize = 4;
|
||||||
|
inProbeBoxMin->uniform = true;
|
||||||
|
inProbeBoxMin->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
|
Var *inProbeBoxMax = new Var("inProbeBoxMax", "float3");
|
||||||
|
inProbeBoxMax->arraySize = 4;
|
||||||
|
inProbeBoxMax->uniform = true;
|
||||||
|
inProbeBoxMax->constSortPos = cspPotentialPrimitive;
|
||||||
|
|
||||||
|
Var *inProbeIsSphere = new Var("inProbeIsSphere", "float");
|
||||||
|
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 *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 *inProbeCubemapTex = new Var("inProbeCubemapTex", "TextureCube");
|
||||||
|
//inProbeCubemapTex->arraySize = 4;
|
||||||
|
inProbeCubemapTex->uniform = true;
|
||||||
|
inProbeCubemapTex->texture = true;
|
||||||
|
inProbeCubemapTex->constNum = inProbeCubemap->constNum;
|
||||||
|
|
||||||
|
//Var *nDotL = new Var("nDotL", "float3");
|
||||||
|
//meta->addStatement(new GenOp(" @ = abs(dot(@,@);\r\n", new DecOp(nDotL), wsView, wsNormal));
|
||||||
|
|
||||||
|
Var *probeVec = new Var("probeVec", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition));
|
||||||
|
|
||||||
|
Var *nDotL = new Var("nDotL", "float");
|
||||||
|
meta->addStatement(new GenOp(" @ = abs(dot(@, @));\r\n", new DecOp(nDotL), probeVec, wsNormal));
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" \r\n"));
|
||||||
|
|
||||||
|
Var *reflectDir = new Var("reflectDir", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = reflect(-float4(@,0),float4(@,@)).xyz;\r\n", new DecOp(reflectDir), wsView, wsNormal, nDotL));
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" \r\n"));
|
||||||
|
|
||||||
|
Var *nrDir = new Var("nrDir", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = normalize(@);\r\n", new DecOp(nrDir), reflectDir));
|
||||||
|
|
||||||
|
Var *rbmax = new Var("rbmax", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = (@[0] - @) / @;\r\n", new DecOp(rbmax), inProbeBoxMax, wsPosition, nrDir));
|
||||||
|
|
||||||
|
Var *rbmin = new Var("rbmin", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = (@[0] - @) / @;\r\n", new DecOp(rbmin), inProbeBoxMin, wsPosition, nrDir));
|
||||||
|
|
||||||
|
Var *rbMinMax = new Var("rbMinMax", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = (@ > 0.0) ? @ : @;\r\n", new DecOp(rbMinMax), nrDir, rbmax, rbmin));
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" \r\n"));
|
||||||
|
|
||||||
|
Var *fa = new Var("fa", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = min(min(@.x,@.y),@.z);\r\n", new DecOp(fa), rbMinMax, rbMinMax, rbMinMax));
|
||||||
|
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp("/* if (dot( @, @ ) < 0.0f)\r\n", probeVec, wsNormal));
|
||||||
|
meta->addStatement(new GenOp(" clip(@); */\r\n", fa));
|
||||||
|
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" \r\n"));
|
||||||
|
|
||||||
|
Var *posOnBox = new Var("posOnBox", "float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = @ + @ * @;\r\n", new DecOp(posOnBox), wsPosition, nrDir, fa));
|
||||||
|
meta->addStatement(new GenOp(" @ = @ - @[0];\r\n", reflectDir, posOnBox, inProbePos));
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" \r\n"));
|
||||||
|
|
||||||
|
Var *probeColor = new Var("wipProbeColor", "float3");
|
||||||
|
|
||||||
|
Var *probeMip = new Var("probeMip", "float");
|
||||||
|
meta->addStatement(new GenOp(" @ = min((1.0 - @)*11.0 + 1.0, 8.0);\r\n", new DecOp(probeMip), smoothness));
|
||||||
|
meta->addStatement(new GenOp(" @ = @.SampleLevel(@, @, @).rgb;\r\n", new DecOp(probeColor), inProbeCubemapTex, inProbeCubemap, reflectDir, probeMip));
|
||||||
|
//meta->addStatement(new GenOp(" @ = @.rgb;\r\n", new DecOp(probeColor), inProbeTestColor));
|
||||||
|
|
||||||
|
Var *FRESNEL_BIAS = new Var("FRESNEL_BIAS", "float");
|
||||||
|
meta->addStatement(new GenOp(" @ = 0.1;\r\n", new DecOp(FRESNEL_BIAS)));
|
||||||
|
|
||||||
|
Var *FRESNEL_POWER = new Var("FRESNEL_POWER", "float");
|
||||||
|
meta->addStatement(new GenOp(" @ = 1;\r\n", new DecOp(FRESNEL_POWER)));
|
||||||
|
|
||||||
|
Var *angle = new Var("angle", "float");
|
||||||
|
meta->addStatement(new GenOp(" @ = saturate(dot(@, @));\r\n", new DecOp(angle), wsView, wsNormal));
|
||||||
|
meta->addStatement(new GenOp("\r\n"));
|
||||||
|
|
||||||
|
if (metalness)
|
||||||
|
{
|
||||||
|
Var *dColor = new Var("difColor", "float3");
|
||||||
|
Var *reflectColor = new Var("reflctColor", "float3");
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" @ = @.rgb - (@.rgb * @);\r\n", new DecOp(dColor), albedo, albedo, metalness));
|
||||||
|
meta->addStatement(new GenOp(" @ = @; //@.rgb*(@).rgb*@;\r\n", new DecOp(reflectColor), probeColor, albedo, probeColor, metalness));
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" @.rgb = simpleFresnel(@, @, @, @, @, @);\r\n", albedo, dColor, reflectColor, metalness, angle, FRESNEL_BIAS, FRESNEL_POWER));
|
||||||
|
}
|
||||||
|
//else if (lerpVal)
|
||||||
|
// meta->addStatement(new GenOp(" @ *= float4(@.rgb*@.a, @.a);\r\n", targ, texCube, lerpVal, targ));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta->addStatement(new GenOp(" @.rgb = simpleFresnel(@.rgb, @, 0, @, @, @));\r\n", albedo, albedo, probeColor, angle, FRESNEL_BIAS, FRESNEL_POWER));
|
||||||
|
}
|
||||||
|
|
||||||
|
output = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
Resources res;
|
||||||
|
|
||||||
|
//res.numTex = 4;
|
||||||
|
//res.numTexReg = 4;
|
||||||
|
|
||||||
|
res.numTex = 4;
|
||||||
|
res.numTexReg = 4;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
|
||||||
|
const MaterialFeatureData &stageFeatures,
|
||||||
|
RenderPassData &passData,
|
||||||
|
U32 &texIndex)
|
||||||
|
{
|
||||||
|
if (stageFeatures.features[MFT_ReflectionProbes])
|
||||||
|
{
|
||||||
|
// assuming here that it is a scenegraph cubemap
|
||||||
|
passData.mSamplerNames[texIndex] = "inProbeCubemap";
|
||||||
|
passData.mTexType[texIndex++] = Material::SGCube;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -672,4 +672,30 @@ public:
|
||||||
virtual String getName() { return "Hardware Skinning"; }
|
virtual String getName() { return "Hardware Skinning"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Reflection Probes
|
||||||
|
class ReflectionProbeFeatHLSL : public ShaderFeatureHLSL
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
ShaderIncludeDependency mDep;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReflectionProbeFeatHLSL();
|
||||||
|
|
||||||
|
virtual void processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual Resources getResources(const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
// Sets textures and texture flags for current pass
|
||||||
|
virtual void setTexData(Material::StageData &stageDat,
|
||||||
|
const MaterialFeatureData &fd,
|
||||||
|
RenderPassData &passData,
|
||||||
|
U32 &texIndex);
|
||||||
|
|
||||||
|
virtual String getName()
|
||||||
|
{
|
||||||
|
return "Reflection Probes";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_
|
#endif // _SHADERGEN_HLSL_SHADERFEATUREHLSL_H_
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen )
|
||||||
FEATUREMGR->registerFeature( MFT_DetailMap, new DetailFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_DetailMap, new DetailFeatHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_StaticCubemap, new NamedFeatureHLSL( "Static Cubemap" ) );
|
FEATUREMGR->registerFeature( MFT_StaticCubemap, new NamedFeatureHLSL( "Static Cubemap" ) );
|
||||||
FEATUREMGR->registerFeature( MFT_CubeMap, new ReflectCubeFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_CubeMap, new ReflectCubeFeatHLSL );
|
||||||
|
FEATUREMGR->registerFeature( MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
|
||||||
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL );
|
FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_InvertSmoothness, new NamedFeatureHLSL( "Roughest = 1.0" ) );
|
FEATUREMGR->registerFeature( MFT_InvertSmoothness, new NamedFeatureHLSL( "Roughest = 1.0" ) );
|
||||||
FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureHLSL( "Translucent" ) );
|
FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureHLSL( "Translucent" ) );
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,15 @@ const String ShaderGenVars::specularColor("$specularColor");
|
||||||
const String ShaderGenVars::smoothness("$smoothness");
|
const String ShaderGenVars::smoothness("$smoothness");
|
||||||
const String ShaderGenVars::metalness("$metalness");
|
const String ShaderGenVars::metalness("$metalness");
|
||||||
|
|
||||||
|
//Reflection Probes
|
||||||
|
const String ShaderGenVars::probePosition("$inProbePos");
|
||||||
|
const String ShaderGenVars::probeRadius("$inProbeRadius");
|
||||||
|
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");
|
||||||
|
|
||||||
// These are ignored by the D3D layers.
|
// These are ignored by the D3D layers.
|
||||||
const String ShaderGenVars::fogMap("$fogMap");
|
const String ShaderGenVars::fogMap("$fogMap");
|
||||||
const String ShaderGenVars::dlightMap("$dlightMap");
|
const String ShaderGenVars::dlightMap("$dlightMap");
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,15 @@ struct ShaderGenVars
|
||||||
const static String specularColor;
|
const static String specularColor;
|
||||||
const static String smoothness;
|
const static String smoothness;
|
||||||
const static String metalness;
|
const static String metalness;
|
||||||
|
|
||||||
|
//Reflection Probes
|
||||||
|
const static String probePosition;
|
||||||
|
const static String probeRadius;
|
||||||
|
const static String probeBoxMin;
|
||||||
|
const static String probeBoxMax;
|
||||||
|
const static String probeLocalPos;
|
||||||
|
const static String probeIsSphere;
|
||||||
|
const static String probeCubemap;
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
const static String fogMap;
|
const static String fogMap;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ namespace
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL );
|
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) );
|
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) );
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL );
|
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL );
|
||||||
|
FEATUREMGR->registerFeature( MFT_TerrainCompositeMap, new TerrainCompositeMapFeatGLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL );
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +142,24 @@ Var* TerrainFeatGLSL::_getNormalMapTex()
|
||||||
return normalMap;
|
return normalMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Var* TerrainFeatGLSL::_getCompositeMapTex()
|
||||||
|
{
|
||||||
|
String name(String::ToString("compositeMap%d", getProcessIndex()));
|
||||||
|
Var *compositeMap = (Var*)LangElement::find(name);
|
||||||
|
|
||||||
|
if (!compositeMap)
|
||||||
|
{
|
||||||
|
compositeMap = new Var;
|
||||||
|
compositeMap->setType("sampler2D");
|
||||||
|
compositeMap->setName(name);
|
||||||
|
compositeMap->uniform = true;
|
||||||
|
compositeMap->sampler = true;
|
||||||
|
compositeMap->constNum = Var::getTexUnitNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
return compositeMap;
|
||||||
|
}
|
||||||
|
|
||||||
Var* TerrainFeatGLSL::_getDetailIdStrengthParallax()
|
Var* TerrainFeatGLSL::_getDetailIdStrengthParallax()
|
||||||
{
|
{
|
||||||
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
|
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
|
||||||
|
|
@ -203,7 +222,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
|
||||||
// So instead i fixed this by flipping the base and detail
|
// So instead i fixed this by flipping the base and detail
|
||||||
// coord y scale to compensate when rendering.
|
// coord y scale to compensate when rendering.
|
||||||
//
|
//
|
||||||
meta->addStatement( new GenOp( " @ = @.xyz * float3( @, @, -@ );\r\n",
|
meta->addStatement( new GenOp( " @ = @.xyz * vec3( @, @, -@ );\r\n",
|
||||||
new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
|
new DecOp( inTex ), inPos, oneOverTerrainSize, oneOverTerrainSize, oneOverTerrainSize ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +242,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
|
||||||
{
|
{
|
||||||
Var *inNormal = (Var*)LangElement::find( "normal" );
|
Var *inNormal = (Var*)LangElement::find( "normal" );
|
||||||
meta->addStatement(
|
meta->addStatement(
|
||||||
new GenOp( " @.z = pow( abs( dot( normalize( float3( @.x, @.y, 0 ) ), float3( 0, 1, 0 ) ) ), 10.0 );\r\n",
|
new GenOp( " @.z = pow( abs( dot( normalize( vec3( @.x, @.y, 0 ) ), vec3( 0, 1, 0 ) ) ), 10.0 );\r\n",
|
||||||
outTex, inNormal, inNormal ) );
|
outTex, inNormal, inNormal ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -239,8 +258,8 @@ void TerrainBaseMapFeatGLSL::processVert( Vector<ShaderComponent*> &componentLis
|
||||||
Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
|
Var *inTangentZ = getVertTexCoord( "tcTangentZ" );
|
||||||
Var *inTanget = new Var( "T", "vec3" );
|
Var *inTanget = new Var( "T", "vec3" );
|
||||||
Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
|
Var *squareSize = _getUniformVar( "squareSize", "float", cspPass );
|
||||||
meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n",
|
meta->addStatement( new GenOp( " @ = normalize( vec3( @, 0, @ ) );\r\n",
|
||||||
new DecOp( inTanget ), squareSize, inTangentZ ) );
|
new DecOp( inTanget ), squareSize, inTangentZ ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainBaseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
void TerrainBaseMapFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||||
|
|
@ -334,7 +353,7 @@ void TerrainDetailMapFeatGLSL::processVert( Vector<ShaderComponent*> &component
|
||||||
outNegViewTS->setName( "outNegViewTS" );
|
outNegViewTS->setName( "outNegViewTS" );
|
||||||
outNegViewTS->setStructName( "OUT" );
|
outNegViewTS->setStructName( "OUT" );
|
||||||
outNegViewTS->setType( "vec3" );
|
outNegViewTS->setType( "vec3" );
|
||||||
meta->addStatement( new GenOp( " @ = tMul( @, float3( @ - @.xyz ) );\r\n",
|
meta->addStatement( new GenOp( " @ = tMul( @, vec3( @ - @.xyz ) );\r\n",
|
||||||
outNegViewTS, objToTangentSpace, eyePos, inPos ) );
|
outNegViewTS, objToTangentSpace, eyePos, inPos ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -490,7 +509,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
|
||||||
{
|
{
|
||||||
// create color var
|
// create color var
|
||||||
outColor = new Var;
|
outColor = new Var;
|
||||||
outColor->setType("float4");
|
outColor->setType("vec4");
|
||||||
outColor->setName("col");
|
outColor->setName("col");
|
||||||
outColor->setStructName("OUT");
|
outColor->setStructName("OUT");
|
||||||
meta->addStatement(new GenOp(" @;\r\n", outColor));
|
meta->addStatement(new GenOp(" @;\r\n", outColor));
|
||||||
|
|
@ -500,7 +519,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector<ShaderComponent*> &component
|
||||||
if (!detailColor)
|
if (!detailColor)
|
||||||
{
|
{
|
||||||
detailColor = new Var;
|
detailColor = new Var;
|
||||||
detailColor->setType("float4");
|
detailColor->setType("vec4");
|
||||||
detailColor->setName("detailColor");
|
detailColor->setName("detailColor");
|
||||||
meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor)));
|
meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor)));
|
||||||
}
|
}
|
||||||
|
|
@ -1106,6 +1125,176 @@ void TerrainAdditiveFeatGLSL::processPix( Vector<ShaderComponent*> &componentLis
|
||||||
|
|
||||||
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
|
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
|
||||||
//.b = specular strength, a= spec power.
|
//.b = specular strength, a= spec power.
|
||||||
|
|
||||||
|
|
||||||
|
void TerrainCompositeMapFeatGLSL::processVert(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
const S32 detailIndex = getProcessIndex();
|
||||||
|
|
||||||
|
// Grab incoming texture coords... the base map feature
|
||||||
|
// made sure this was created.
|
||||||
|
Var *inTex = (Var*)LangElement::find("texCoord");
|
||||||
|
AssertFatal(inTex, "The texture coord is missing!");
|
||||||
|
|
||||||
|
// Grab the input position.
|
||||||
|
Var *inPos = (Var*)LangElement::find("inPosition");
|
||||||
|
if (!inPos)
|
||||||
|
inPos = (Var*)LangElement::find("position");
|
||||||
|
|
||||||
|
// Get the object space eye position.
|
||||||
|
Var *eyePos = _getUniformVar("eyePos", "vec3", cspPotentialPrimitive);
|
||||||
|
|
||||||
|
MultiLine *meta = new MultiLine;
|
||||||
|
|
||||||
|
// If we have parallax mapping then make sure we've sent
|
||||||
|
// the negative view vector to the pixel shader.
|
||||||
|
if (fd.features.hasFeature(MFT_TerrainParallaxMap) &&
|
||||||
|
!LangElement::find("outNegViewTS"))
|
||||||
|
{
|
||||||
|
// Get the object to tangent transform which
|
||||||
|
// will consume 3 output registers.
|
||||||
|
Var *objToTangentSpace = getOutObjToTangentSpace(componentList, meta, fd);
|
||||||
|
|
||||||
|
// Now use a single output register to send the negative
|
||||||
|
// view vector in tangent space to the pixel shader.
|
||||||
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
|
||||||
|
Var *outNegViewTS = connectComp->getElement(RT_TEXCOORD);
|
||||||
|
outNegViewTS->setName("outNegViewTS");
|
||||||
|
outNegViewTS->setStructName("OUT");
|
||||||
|
outNegViewTS->setType("vec3");
|
||||||
|
meta->addStatement(new GenOp(" @ = @ * vec3( @ - @.xyz );\r\n",
|
||||||
|
outNegViewTS, objToTangentSpace, eyePos, inPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the distance from the eye to this vertex.
|
||||||
|
Var *dist = (Var*)LangElement::find("dist");
|
||||||
|
if (!dist)
|
||||||
|
{
|
||||||
|
dist = new Var;
|
||||||
|
dist->setType("float");
|
||||||
|
dist->setName("dist");
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" @ = distance( @.xyz, @ );\r\n",
|
||||||
|
new DecOp(dist), inPos, eyePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab connector texcoord register
|
||||||
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
|
||||||
|
Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex));
|
||||||
|
if (outTex == NULL)
|
||||||
|
{
|
||||||
|
outTex = connectComp->getElement(RT_TEXCOORD);
|
||||||
|
outTex->setName(String::ToString("detCoord%d", detailIndex));
|
||||||
|
outTex->setStructName("OUT");
|
||||||
|
outTex->setType("vec4");
|
||||||
|
}
|
||||||
|
// Get the detail scale and fade info.
|
||||||
|
Var *detScaleAndFade = (Var*)LangElement::find(String::ToString("detailScaleAndFade%d", detailIndex));
|
||||||
|
if (detScaleAndFade == NULL)
|
||||||
|
{
|
||||||
|
detScaleAndFade->setType("vec4");
|
||||||
|
detScaleAndFade->setName(String::ToString("detailScaleAndFade%d", detailIndex));
|
||||||
|
detScaleAndFade->uniform = true;
|
||||||
|
detScaleAndFade->constSortPos = cspPotentialPrimitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the detail coord.
|
||||||
|
//
|
||||||
|
// NOTE: You see here we scale the texture coord by 'xyx'
|
||||||
|
// to generate the detail coord. This y is here because
|
||||||
|
// its scale is flipped to correct for the non negative y
|
||||||
|
// in texCoord.
|
||||||
|
//
|
||||||
|
// See TerrainBaseMapFeatGLSL::processVert().
|
||||||
|
//
|
||||||
|
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade));
|
||||||
|
|
||||||
|
// And sneak the detail fade thru the w detailCoord.
|
||||||
|
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
|
||||||
|
outTex, detScaleAndFade, dist, detScaleAndFade));
|
||||||
|
|
||||||
|
output = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 TerrainCompositeMapFeatGLSL::getOutputTargets(const MaterialFeatureData &fd) const
|
||||||
|
{
|
||||||
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainCompositeMapFeatGLSL::processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
/// Get the texture coord.
|
||||||
|
Var *inDet = _getInDetailCoord(componentList);
|
||||||
|
Var *inTex = getVertTexCoord("texCoord");
|
||||||
|
|
||||||
|
const S32 compositeIndex = getProcessIndex();
|
||||||
|
Var *compositeMap = _getCompositeMapTex();
|
||||||
|
// Sample the normal map.
|
||||||
|
//
|
||||||
|
// We take two normal samples and lerp between them for
|
||||||
|
// side projection layers... else a single sample.
|
||||||
|
LangElement *texOp;
|
||||||
|
|
||||||
|
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
|
||||||
|
{
|
||||||
|
texOp = new GenOp("lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z )",
|
||||||
|
compositeMap, inDet, compositeMap, inDet, inTex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
texOp = new GenOp("tex2D(@, @.xy)", compositeMap, inDet);
|
||||||
|
|
||||||
|
// search for material var
|
||||||
|
Var *material;
|
||||||
|
OutputTarget targ = RenderTarget1;
|
||||||
|
if (fd.features[MFT_isDeferred])
|
||||||
|
{
|
||||||
|
targ = RenderTarget2;
|
||||||
|
}
|
||||||
|
material = (Var*)LangElement::find(getOutputTargetVarName(targ));
|
||||||
|
|
||||||
|
MultiLine * meta = new MultiLine;
|
||||||
|
if (!material)
|
||||||
|
{
|
||||||
|
// create color var
|
||||||
|
material = new Var;
|
||||||
|
material->setType("fragout");
|
||||||
|
material->setName(getOutputTargetVarName(targ));
|
||||||
|
material->setStructName("OUT");
|
||||||
|
}
|
||||||
|
|
||||||
|
Var *detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", compositeIndex));
|
||||||
|
AssertFatal(detailBlend, "The detail blend is missing!");
|
||||||
|
|
||||||
|
String matinfoName(String::ToString("matinfoCol%d", compositeIndex));
|
||||||
|
Var *matinfoCol = new Var(matinfoName, "vec3");
|
||||||
|
|
||||||
|
Var *priorComp = (Var*)LangElement::find(String::ToString("matinfoCol%d", compositeIndex - 1));
|
||||||
|
if (priorComp)
|
||||||
|
{
|
||||||
|
meta->addStatement(new GenOp(" @ = @.grb*@;\r\n", new DecOp(matinfoCol), texOp, detailBlend));
|
||||||
|
meta->addStatement(new GenOp(" @.gba += @;\r\n", material, matinfoCol));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta->addStatement(new GenOp(" @ = lerp(vec3(1,0,0),@.grb,@);\r\n", new DecOp(matinfoCol), texOp, detailBlend));
|
||||||
|
meta->addStatement(new GenOp(" @ = vec4(0.0,@);\r\n", material, matinfoCol));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
output = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderFeature::Resources TerrainCompositeMapFeatGLSL::getResources(const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
Resources res;
|
||||||
|
res.numTex = 1;
|
||||||
|
res.numTexReg += 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
|
//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
|
||||||
//we'll most likely revisit that later. possibly several ways...
|
//we'll most likely revisit that later. possibly several ways...
|
||||||
|
|
||||||
|
|
@ -1136,7 +1325,7 @@ void TerrainBlankInfoMapFeatGLSL::processPix(Vector<ShaderComponent*> &component
|
||||||
material->setStructName("OUT");
|
material->setStructName("OUT");
|
||||||
}
|
}
|
||||||
|
|
||||||
meta->addStatement(new GenOp(" @ = float4(0.0,0.0,0.0,0.0001);\r\n", material));
|
meta->addStatement(new GenOp(" @ = vec4(0.0,1.0,0.0,0.0001);\r\n", material));
|
||||||
|
|
||||||
output = meta;
|
output = meta;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,9 @@ public:
|
||||||
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
|
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
|
||||||
|
|
||||||
Var* _getNormalMapTex();
|
Var* _getNormalMapTex();
|
||||||
|
|
||||||
|
Var* _getCompositeMapTex();
|
||||||
|
|
||||||
static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp );
|
static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp );
|
||||||
|
|
||||||
Var* _getDetailIdStrengthParallax();
|
Var* _getDetailIdStrengthParallax();
|
||||||
|
|
@ -160,6 +162,22 @@ public:
|
||||||
virtual String getName() { return "Terrain Additive"; }
|
virtual String getName() { return "Terrain Additive"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TerrainCompositeMapFeatGLSL : public TerrainFeatGLSL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void processVert(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual void processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual Resources getResources(const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual U32 getOutputTargets(const MaterialFeatureData &fd) const;
|
||||||
|
virtual String getName() { return "Composite Matinfo map"; }
|
||||||
|
};
|
||||||
|
|
||||||
class TerrainBlankInfoMapFeatGLSL : public ShaderFeatureGLSL
|
class TerrainBlankInfoMapFeatGLSL : public ShaderFeatureGLSL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ namespace
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
|
FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) );
|
||||||
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
|
||||||
|
FEATUREMGR->registerFeature( MFT_TerrainCompositeMap, new TerrainCompositeMapFeatHLSL );
|
||||||
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL );
|
FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -140,6 +141,24 @@ Var* TerrainFeatHLSL::_getNormalMapTex()
|
||||||
return normalMap;
|
return normalMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Var* TerrainFeatHLSL::_getCompositeMapTex()
|
||||||
|
{
|
||||||
|
String name(String::ToString("compositeMap%d", getProcessIndex()));
|
||||||
|
Var *compositeMap = (Var*)LangElement::find(name);
|
||||||
|
|
||||||
|
if (!compositeMap)
|
||||||
|
{
|
||||||
|
compositeMap = new Var;
|
||||||
|
compositeMap->setType("SamplerState");
|
||||||
|
compositeMap->setName(name);
|
||||||
|
compositeMap->uniform = true;
|
||||||
|
compositeMap->sampler = true;
|
||||||
|
compositeMap->constNum = Var::getTexUnitNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
return compositeMap;
|
||||||
|
}
|
||||||
|
|
||||||
Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
|
Var* TerrainFeatHLSL::_getDetailIdStrengthParallax()
|
||||||
{
|
{
|
||||||
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
|
String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) );
|
||||||
|
|
@ -1116,6 +1135,183 @@ void TerrainAdditiveFeatHLSL::processPix( Vector<ShaderComponent*> &componentLis
|
||||||
|
|
||||||
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
|
//standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO),
|
||||||
//.b = specular strength, a= spec power.
|
//.b = specular strength, a= spec power.
|
||||||
|
|
||||||
|
void TerrainCompositeMapFeatHLSL::processVert(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
const S32 detailIndex = getProcessIndex();
|
||||||
|
|
||||||
|
// Grab incoming texture coords... the base map feature
|
||||||
|
// made sure this was created.
|
||||||
|
Var *inTex = (Var*)LangElement::find("texCoord");
|
||||||
|
AssertFatal(inTex, "The texture coord is missing!");
|
||||||
|
|
||||||
|
// Grab the input position.
|
||||||
|
Var *inPos = (Var*)LangElement::find("inPosition");
|
||||||
|
if (!inPos)
|
||||||
|
inPos = (Var*)LangElement::find("position");
|
||||||
|
|
||||||
|
// Get the object space eye position.
|
||||||
|
Var *eyePos = _getUniformVar("eyePos", "float3", cspPotentialPrimitive);
|
||||||
|
|
||||||
|
MultiLine *meta = new MultiLine;
|
||||||
|
|
||||||
|
// If we have parallax mapping then make sure we've sent
|
||||||
|
// the negative view vector to the pixel shader.
|
||||||
|
if (fd.features.hasFeature(MFT_TerrainParallaxMap) &&
|
||||||
|
!LangElement::find("outNegViewTS"))
|
||||||
|
{
|
||||||
|
// Get the object to tangent transform which
|
||||||
|
// will consume 3 output registers.
|
||||||
|
Var *objToTangentSpace = getOutObjToTangentSpace(componentList, meta, fd);
|
||||||
|
|
||||||
|
// Now use a single output register to send the negative
|
||||||
|
// view vector in tangent space to the pixel shader.
|
||||||
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
|
||||||
|
Var *outNegViewTS = connectComp->getElement(RT_TEXCOORD);
|
||||||
|
outNegViewTS->setName("outNegViewTS");
|
||||||
|
outNegViewTS->setStructName("OUT");
|
||||||
|
outNegViewTS->setType("float3");
|
||||||
|
meta->addStatement(new GenOp(" @ = mul( @, float3( @ - @.xyz ) );\r\n",
|
||||||
|
outNegViewTS, objToTangentSpace, eyePos, inPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the distance from the eye to this vertex.
|
||||||
|
Var *dist = (Var*)LangElement::find("dist");
|
||||||
|
if (!dist)
|
||||||
|
{
|
||||||
|
dist = new Var;
|
||||||
|
dist->setType("float");
|
||||||
|
dist->setName("dist");
|
||||||
|
|
||||||
|
meta->addStatement(new GenOp(" @ = distance( @.xyz, @ );\r\n",
|
||||||
|
new DecOp(dist), inPos, eyePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab connector texcoord register
|
||||||
|
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>(componentList[C_CONNECTOR]);
|
||||||
|
Var *outTex = (Var*)LangElement::find(String::ToString("detCoord%d", detailIndex));
|
||||||
|
if (outTex == NULL)
|
||||||
|
{
|
||||||
|
outTex = connectComp->getElement(RT_TEXCOORD);
|
||||||
|
outTex->setName(String::ToString("detCoord%d", detailIndex));
|
||||||
|
outTex->setStructName("OUT");
|
||||||
|
outTex->setType("float4");
|
||||||
|
}
|
||||||
|
// Get the detail scale and fade info.
|
||||||
|
Var *detScaleAndFade = (Var*)LangElement::find(String::ToString("detailScaleAndFade%d", detailIndex));
|
||||||
|
if (detScaleAndFade == NULL)
|
||||||
|
{
|
||||||
|
detScaleAndFade->setType("float4");
|
||||||
|
detScaleAndFade->setName(String::ToString("detailScaleAndFade%d", detailIndex));
|
||||||
|
detScaleAndFade->uniform = true;
|
||||||
|
detScaleAndFade->constSortPos = cspPotentialPrimitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the detail coord.
|
||||||
|
//
|
||||||
|
// NOTE: You see here we scale the texture coord by 'xyx'
|
||||||
|
// to generate the detail coord. This y is here because
|
||||||
|
// its scale is flipped to correct for the non negative y
|
||||||
|
// in texCoord.
|
||||||
|
//
|
||||||
|
// See TerrainBaseMapFeatHLSL::processVert().
|
||||||
|
//
|
||||||
|
meta->addStatement(new GenOp(" @.xyz = @ * @.xyx;\r\n", outTex, inTex, detScaleAndFade));
|
||||||
|
|
||||||
|
// And sneak the detail fade thru the w detailCoord.
|
||||||
|
meta->addStatement(new GenOp(" @.w = clamp( ( @.z - @ ) * @.w, 0.0, 1.0 );\r\n",
|
||||||
|
outTex, detScaleAndFade, dist, detScaleAndFade));
|
||||||
|
|
||||||
|
output = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 TerrainCompositeMapFeatHLSL::getOutputTargets(const MaterialFeatureData &fd) const
|
||||||
|
{
|
||||||
|
return fd.features[MFT_isDeferred] ? ShaderFeature::RenderTarget2 : ShaderFeature::RenderTarget1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainCompositeMapFeatHLSL::processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
/// Get the texture coord.
|
||||||
|
Var *inDet = _getInDetailCoord(componentList);
|
||||||
|
Var *inTex = getVertTexCoord("texCoord");
|
||||||
|
|
||||||
|
const S32 compositeIndex = getProcessIndex();
|
||||||
|
Var *compositeMap = _getCompositeMapTex();
|
||||||
|
// Sample the normal map.
|
||||||
|
//
|
||||||
|
// We take two normal samples and lerp between them for
|
||||||
|
// side projection layers... else a single sample.
|
||||||
|
LangElement *texOp;
|
||||||
|
String name(String::ToString("compositeMapTex%d", getProcessIndex()));
|
||||||
|
Var *compositeMapTex = (Var*)LangElement::find(name);
|
||||||
|
if (!compositeMapTex)
|
||||||
|
{
|
||||||
|
compositeMapTex = new Var;
|
||||||
|
compositeMapTex->setName(String::ToString("compositeMapTex%d", getProcessIndex()));
|
||||||
|
compositeMapTex->setType("Texture2D");
|
||||||
|
compositeMapTex->uniform = true;
|
||||||
|
compositeMapTex->texture = true;
|
||||||
|
compositeMapTex->constNum = compositeMap->constNum;
|
||||||
|
}
|
||||||
|
if (fd.features.hasFeature(MFT_TerrainSideProject, compositeIndex))
|
||||||
|
{
|
||||||
|
texOp = new GenOp("lerp( @.Sample( @, @.yz ), @.Sample( @, @.xz ), @.z )",
|
||||||
|
compositeMapTex, compositeMap, inDet, compositeMapTex, compositeMap, inDet, inTex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
texOp = new GenOp("@.Sample(@, @.xy)", compositeMapTex, compositeMap, inDet);
|
||||||
|
|
||||||
|
// search for material var
|
||||||
|
Var *material;
|
||||||
|
OutputTarget targ = RenderTarget1;
|
||||||
|
if (fd.features[MFT_isDeferred])
|
||||||
|
{
|
||||||
|
targ = RenderTarget2;
|
||||||
|
}
|
||||||
|
material = (Var*)LangElement::find(getOutputTargetVarName(targ));
|
||||||
|
|
||||||
|
MultiLine * meta = new MultiLine;
|
||||||
|
if (!material)
|
||||||
|
{
|
||||||
|
// create color var
|
||||||
|
material = new Var;
|
||||||
|
material->setType("fragout");
|
||||||
|
material->setName(getOutputTargetVarName(targ));
|
||||||
|
material->setStructName("OUT");
|
||||||
|
}
|
||||||
|
|
||||||
|
Var *detailBlend = (Var*)LangElement::find(String::ToString("detailBlend%d", compositeIndex));
|
||||||
|
AssertFatal(detailBlend, "The detail blend is missing!");
|
||||||
|
|
||||||
|
String matinfoName(String::ToString("matinfoCol%d", compositeIndex));
|
||||||
|
Var *matinfoCol = new Var(matinfoName, "float3");
|
||||||
|
|
||||||
|
Var *priorComp = (Var*)LangElement::find(String::ToString("matinfoCol%d", compositeIndex - 1));
|
||||||
|
if (priorComp)
|
||||||
|
{
|
||||||
|
meta->addStatement(new GenOp(" @ = @.grb*@;\r\n", new DecOp(matinfoCol), texOp, detailBlend));
|
||||||
|
meta->addStatement(new GenOp(" @.gba += @;\r\n", material, matinfoCol));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta->addStatement(new GenOp(" @ = lerp(float3(1,0,0),@.grb,@);\r\n", new DecOp(matinfoCol), texOp, detailBlend));
|
||||||
|
meta->addStatement(new GenOp(" @ = float4(0.0,@);\r\n", material, matinfoCol));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
output = meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderFeature::Resources TerrainCompositeMapFeatHLSL::getResources(const MaterialFeatureData &fd)
|
||||||
|
{
|
||||||
|
Resources res;
|
||||||
|
res.numTex = 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
|
//here, it's merely a cutout for now, so that lightmapping (target3) doesn't get mangled.
|
||||||
//we'll most likely revisit that later. possibly several ways...
|
//we'll most likely revisit that later. possibly several ways...
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ public:
|
||||||
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
|
Var* _getInMacroCoord(Vector<ShaderComponent*> &componentList );
|
||||||
|
|
||||||
Var* _getNormalMapTex();
|
Var* _getNormalMapTex();
|
||||||
|
Var* _getCompositeMapTex();
|
||||||
|
|
||||||
static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp );
|
static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp );
|
||||||
|
|
||||||
|
|
@ -161,6 +162,22 @@ public:
|
||||||
virtual String getName() { return "Terrain Additive"; }
|
virtual String getName() { return "Terrain Additive"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TerrainCompositeMapFeatHLSL : public TerrainFeatHLSL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void processVert(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual void processPix(Vector<ShaderComponent*> &componentList,
|
||||||
|
const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual Resources getResources(const MaterialFeatureData &fd);
|
||||||
|
|
||||||
|
virtual U32 getOutputTargets(const MaterialFeatureData &fd) const;
|
||||||
|
virtual String getName() { return "Composite Matinfo map"; }
|
||||||
|
};
|
||||||
|
|
||||||
class TerrainBlankInfoMapFeatHLSL : public TerrainFeatHLSL
|
class TerrainBlankInfoMapFeatHLSL : public TerrainFeatHLSL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ Vector<String> _initSamplerNames()
|
||||||
{
|
{
|
||||||
samplerNames.push_back(avar("$normalMap%d",i));
|
samplerNames.push_back(avar("$normalMap%d",i));
|
||||||
samplerNames.push_back(avar("$detailMap%d",i));
|
samplerNames.push_back(avar("$detailMap%d",i));
|
||||||
samplerNames.push_back(avar("$macroMap%d",i));
|
samplerNames.push_back(avar("$macroMap%d", i));
|
||||||
|
samplerNames.push_back(avar("$compositeMap%d", i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return samplerNames;
|
return samplerNames;
|
||||||
|
|
@ -149,6 +150,19 @@ void TerrainCellMaterial::_updateDefaultAnisotropy()
|
||||||
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
|
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (matInfo->compositeTexConst->isValid())
|
||||||
|
{
|
||||||
|
const S32 sampler = matInfo->compositeTexConst->getSamplerRegister();
|
||||||
|
|
||||||
|
if (maxAnisotropy > 1)
|
||||||
|
{
|
||||||
|
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
|
||||||
|
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
|
||||||
|
}
|
||||||
|
|
||||||
} // for ( U32 m=0; m < pass.materials.size(); m++ )
|
} // for ( U32 m=0; m < pass.materials.size(); m++ )
|
||||||
|
|
||||||
// Set the updated stateblock.
|
// Set the updated stateblock.
|
||||||
|
|
@ -424,6 +438,14 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
|
||||||
features.addFeature(MFT_isDeferred, featureIndex);
|
features.addFeature(MFT_isDeferred, featureIndex);
|
||||||
features.addFeature( MFT_TerrainDetailMap, featureIndex );
|
features.addFeature( MFT_TerrainDetailMap, featureIndex );
|
||||||
|
|
||||||
|
if (!(mat->getCompositeMap().isEmpty()))
|
||||||
|
{
|
||||||
|
if (deferredMat)
|
||||||
|
features.addFeature(MFT_isDeferred, featureIndex);
|
||||||
|
features.addFeature(MFT_TerrainCompositeMap, featureIndex);
|
||||||
|
features.removeFeature(MFT_DeferredTerrainBlankInfoMap);
|
||||||
|
}
|
||||||
|
|
||||||
pass->materials.push_back( (*materials)[i] );
|
pass->materials.push_back( (*materials)[i] );
|
||||||
normalMaps.increment();
|
normalMaps.increment();
|
||||||
|
|
||||||
|
|
@ -496,7 +518,7 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
|
||||||
// isn't fooled into thinking there is a real bug. That is until
|
// isn't fooled into thinking there is a real bug. That is until
|
||||||
// we get down to a single material. If a single material case
|
// we get down to a single material. If a single material case
|
||||||
// fails it means it cannot generate any passes at all!
|
// fails it means it cannot generate any passes at all!
|
||||||
const bool logErrors = matCount == 1;
|
const bool logErrors = true;// matCount == 1;
|
||||||
GFXShader::setLogging( logErrors, true );
|
GFXShader::setLogging( logErrors, true );
|
||||||
|
|
||||||
pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
|
pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames );
|
||||||
|
|
@ -613,6 +635,27 @@ bool TerrainCellMaterial::_createPass( Vector<MaterialInfo*> *materials,
|
||||||
&GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - DetailMap" );
|
&GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - DetailMap" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matInfo->compositeTexConst = pass->shader->getShaderConstHandle(avar("$compositeMap%d", i));
|
||||||
|
if (matInfo->compositeTexConst->isValid())
|
||||||
|
{
|
||||||
|
matInfo->compositeTex.set(matInfo->mat->getCompositeMap(),
|
||||||
|
&GFXStaticTextureProfile, "TerrainCellMaterial::_createPass() - CompositeMap");
|
||||||
|
const S32 sampler = matInfo->compositeTexConst->getSamplerRegister();
|
||||||
|
Con::errorf("sampler=%i", sampler);
|
||||||
|
|
||||||
|
desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
|
||||||
|
desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
|
||||||
|
desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
|
||||||
|
|
||||||
|
if (maxAnisotropy > 1)
|
||||||
|
{
|
||||||
|
desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
|
||||||
|
desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
|
||||||
|
}
|
||||||
|
|
||||||
matInfo->macroInfoVConst = pass->shader->getShaderConstHandle( avar( "$macroScaleAndFade%d", i ) );
|
matInfo->macroInfoVConst = pass->shader->getShaderConstHandle( avar( "$macroScaleAndFade%d", i ) );
|
||||||
matInfo->macroInfoPConst = pass->shader->getShaderConstHandle( avar( "$macroIdStrengthParallax%d", i ) );
|
matInfo->macroInfoPConst = pass->shader->getShaderConstHandle( avar( "$macroIdStrengthParallax%d", i ) );
|
||||||
|
|
||||||
|
|
@ -810,6 +853,8 @@ bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
|
||||||
GFX->setTexture( matInfo->macroTexConst->getSamplerRegister(), matInfo->macroTex );
|
GFX->setTexture( matInfo->macroTexConst->getSamplerRegister(), matInfo->macroTex );
|
||||||
if ( matInfo->normalTexConst->isValid() )
|
if ( matInfo->normalTexConst->isValid() )
|
||||||
GFX->setTexture( matInfo->normalTexConst->getSamplerRegister(), matInfo->normalTex );
|
GFX->setTexture( matInfo->normalTexConst->getSamplerRegister(), matInfo->normalTex );
|
||||||
|
if ( matInfo->compositeTexConst->isValid() )
|
||||||
|
GFX->setTexture( matInfo->compositeTexConst->getSamplerRegister(), matInfo->compositeTex );
|
||||||
}
|
}
|
||||||
|
|
||||||
pass.consts->setSafe( pass.layerSizeConst, (F32)mTerrain->mLayerTex.getWidth() );
|
pass.consts->setSafe( pass.layerSizeConst, (F32)mTerrain->mLayerTex.getWidth() );
|
||||||
|
|
@ -837,7 +882,7 @@ bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
|
||||||
pass.lightParamsConst->isValid() )
|
pass.lightParamsConst->isValid() )
|
||||||
{
|
{
|
||||||
if ( !mLightInfoTarget )
|
if ( !mLightInfoTarget )
|
||||||
mLightInfoTarget = NamedTexTarget::find( "directLighting" );
|
mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" );
|
||||||
|
|
||||||
GFXTextureObject *texObject = mLightInfoTarget->getTexture();
|
GFXTextureObject *texObject = mLightInfoTarget->getTexture();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,9 @@ protected:
|
||||||
GFXShaderConstHandle *normalTexConst;
|
GFXShaderConstHandle *normalTexConst;
|
||||||
GFXTexHandle normalTex;
|
GFXTexHandle normalTex;
|
||||||
|
|
||||||
|
GFXShaderConstHandle *compositeTexConst;
|
||||||
|
GFXTexHandle compositeTex;
|
||||||
|
|
||||||
GFXShaderConstHandle *detailInfoVConst;
|
GFXShaderConstHandle *detailInfoVConst;
|
||||||
GFXShaderConstHandle *detailInfoPConst;
|
GFXShaderConstHandle *detailInfoPConst;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,3 +36,4 @@ ImplementFeatureType( MFT_TerrainSideProject, MFG_Texture, 106.0f, false );
|
||||||
ImplementFeatureType( MFT_TerrainAdditive, MFG_PostProcess, 999.0f, false );
|
ImplementFeatureType( MFT_TerrainAdditive, MFG_PostProcess, 999.0f, false );
|
||||||
//Deferred Shading
|
//Deferred Shading
|
||||||
ImplementFeatureType( MFT_DeferredTerrainBlankInfoMap, MFG_Texture, 104.1f, false);
|
ImplementFeatureType( MFT_DeferredTerrainBlankInfoMap, MFG_Texture, 104.1f, false);
|
||||||
|
ImplementFeatureType( MFT_TerrainCompositeMap, MFG_Texture, 104.2f, false);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ DeclareFeatureType( MFT_TerrainLightMap );
|
||||||
DeclareFeatureType( MFT_TerrainSideProject );
|
DeclareFeatureType( MFT_TerrainSideProject );
|
||||||
DeclareFeatureType( MFT_TerrainAdditive );
|
DeclareFeatureType( MFT_TerrainAdditive );
|
||||||
//Deferred Shading
|
//Deferred Shading
|
||||||
|
DeclareFeatureType( MFT_TerrainCompositeMap );
|
||||||
DeclareFeatureType( MFT_DeferredTerrainBlankInfoMap );
|
DeclareFeatureType( MFT_DeferredTerrainBlankInfoMap );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ void TerrainMaterial::initPersistFields()
|
||||||
addField( "parallaxScale", TypeF32, Offset( mParallaxScale, TerrainMaterial ), "Used to scale the height from the normal map to give some self "
|
addField( "parallaxScale", TypeF32, Offset( mParallaxScale, TerrainMaterial ), "Used to scale the height from the normal map to give some self "
|
||||||
"occlusion effect (aka parallax) to the terrain material" );
|
"occlusion effect (aka parallax) to the terrain material" );
|
||||||
|
|
||||||
|
addField("compositeMap", TypeStringFilename, Offset(mCompositeMap, TerrainMaterial), "Composite map for the material");
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
|
|
||||||
// Gotta call this at least once or it won't get created!
|
// Gotta call this at least once or it won't get created!
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ protected:
|
||||||
///
|
///
|
||||||
FileName mDetailMap;
|
FileName mDetailMap;
|
||||||
|
|
||||||
|
///
|
||||||
|
FileName mCompositeMap;
|
||||||
|
|
||||||
/// The size of the detail map in meters used
|
/// The size of the detail map in meters used
|
||||||
/// to generate the texture coordinates for the
|
/// to generate the texture coordinates for the
|
||||||
/// detail and normal maps.
|
/// detail and normal maps.
|
||||||
|
|
@ -103,6 +106,8 @@ public:
|
||||||
|
|
||||||
const String& getMacroMap() const { return mMacroMap; }
|
const String& getMacroMap() const { return mMacroMap; }
|
||||||
|
|
||||||
|
const String& getCompositeMap() const { return mCompositeMap; }
|
||||||
|
|
||||||
F32 getDetailSize() const { return mDetailSize; }
|
F32 getDetailSize() const { return mDetailSize; }
|
||||||
|
|
||||||
F32 getDetailStrength() const { return mDetailStrength; }
|
F32 getDetailStrength() const { return mDetailStrength; }
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,10 @@ singleton Material(Cheetah_Main)
|
||||||
specularPower[0] = "10";
|
specularPower[0] = "10";
|
||||||
translucentBlendOp = "None";
|
translucentBlendOp = "None";
|
||||||
normalMap[0] = "art/shapes/Cheetah/Cheetah_N";
|
normalMap[0] = "art/shapes/Cheetah/Cheetah_N";
|
||||||
specularMap[0] = "art/shapes/Cheetah/Cheetah_S";
|
|
||||||
castDynamicShadows = true;
|
castDynamicShadows = true;
|
||||||
|
diffuseColor[3] = "1 1 1 1";
|
||||||
|
specular0 = "0.9 0.9 0.9 1";
|
||||||
|
specularPower0 = "10";
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton Material(Cheetah_TailLights)
|
singleton Material(Cheetah_TailLights)
|
||||||
|
|
|
||||||
|
|
@ -24,19 +24,18 @@ singleton Material(Mat_Soldier_Main)
|
||||||
{
|
{
|
||||||
mapTo = "base_Soldier_Main";
|
mapTo = "base_Soldier_Main";
|
||||||
|
|
||||||
diffuseMap[0] = "Soldier_Dif.dds";
|
diffuseMap[0] = "art/shapes/actors/Soldier/Soldier_Dif.dds";
|
||||||
normalMap[0] = "Soldier_N.dds";
|
normalMap[0] = "art/shapes/actors/Soldier/Soldier_N.dds";
|
||||||
specularMap[0] = "Soldier_Spec.dds";
|
specularMap[0] = "art/shapes/actors/Soldier/Soldier_c";
|
||||||
|
FlipRB[0] = "1";
|
||||||
diffuseColor[0] = "1 1 1 1";
|
|
||||||
specular[0] = "0.9 0.9 0.9 1";
|
|
||||||
specularPower[0] = 10;
|
|
||||||
|
|
||||||
doubleSided = false;
|
|
||||||
translucent = false;
|
|
||||||
showFootprints = "0";
|
|
||||||
castDynamicShadows = true;
|
castDynamicShadows = true;
|
||||||
materialTag0 = "Player";
|
materialTag0 = "Player";
|
||||||
|
isSRGb[0] = "1";
|
||||||
|
roughness0 = "1";
|
||||||
|
FlipRB0 = "1";
|
||||||
|
specularPower0 = "10";
|
||||||
|
pixelSpecular0 = "0";
|
||||||
|
specular0 = "0.9 0.9 0.9 1";
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton Material(Mat_Soldier_Dazzle)
|
singleton Material(Mat_Soldier_Dazzle)
|
||||||
|
|
@ -110,7 +109,8 @@ singleton Material(Mat_Orange_Soldier_Main : Mat_Soldier_Main)
|
||||||
singleton Material(Mat_Red_Soldier_Main : Mat_Soldier_Main)
|
singleton Material(Mat_Red_Soldier_Main : Mat_Soldier_Main)
|
||||||
{
|
{
|
||||||
mapTo = "Red_Soldier_Main";
|
mapTo = "Red_Soldier_Main";
|
||||||
diffuseMap[0] = "Soldier_Red_Dif.dds";
|
diffuseMap[0] = "art/shapes/actors/Soldier/Soldier_Red_Dif.dds";
|
||||||
|
normalMap[0] = "art/shapes/actors/Soldier/Soldier_N.dds";
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton Material(Mat_Teal_Soldier_Main : Mat_Soldier_Main)
|
singleton Material(Mat_Teal_Soldier_Main : Mat_Soldier_Main)
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@ singleton Material(cube_GridMaterial)
|
||||||
{
|
{
|
||||||
mapTo = "GridMaterial";
|
mapTo = "GridMaterial";
|
||||||
|
|
||||||
diffuseMap[0] = "grid";
|
|
||||||
normalMap[0] = "";
|
|
||||||
specularMap[0] = "";
|
|
||||||
|
|
||||||
diffuseColor[0] = "1 1 1 1";
|
diffuseColor[0] = "1 1 1 1";
|
||||||
specular[0] = "0.9 0.9 0.9 1";
|
specular[0] = "0.9 0.9 0.9 1";
|
||||||
|
|
@ -38,6 +35,12 @@ singleton Material(cube_GridMaterial)
|
||||||
doubleSided = false;
|
doubleSided = false;
|
||||||
translucent = false;
|
translucent = false;
|
||||||
translucentBlendOp = "None";
|
translucentBlendOp = "None";
|
||||||
|
materialTag0 = "Miscellaneous";
|
||||||
|
smoothness[0] = "1";
|
||||||
|
metalness[0] = "1";
|
||||||
|
specularPower0 = "0.415939";
|
||||||
|
pixelSpecular0 = "0";
|
||||||
|
specular0 = "0.9 0.9 0.9 1";
|
||||||
};
|
};
|
||||||
|
|
||||||
//--- cube.dae MATERIALS END ---
|
//--- cube.dae MATERIALS END ---
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,11 @@ new Material(Structure_wall)
|
||||||
{
|
{
|
||||||
mapTo = "building01walls";
|
mapTo = "building01walls";
|
||||||
diffuseMap[0] = "art/shapes/station/building01walls";
|
diffuseMap[0] = "art/shapes/station/building01walls";
|
||||||
//emissive[0] = true;
|
normalMap[0] = "art/shapes/station/building01walls_n.dds";
|
||||||
};
|
specularMap[0] = "art/shapes/station/building01walls_c.dds";
|
||||||
|
effectColor[0] = "InvisibleBlack";
|
||||||
|
materialTag0 = "Miscellaneous";
|
||||||
new Material(Structure_grid)
|
pixelSpecular0 = "0";
|
||||||
{
|
|
||||||
mapTo = "grid";
|
|
||||||
diffuseMap[0] = "art/shapes/station/grid";
|
|
||||||
//emissive[0] = true;
|
//emissive[0] = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -40,6 +37,20 @@ new Material(Structure_plate)
|
||||||
{
|
{
|
||||||
mapTo = "plate";
|
mapTo = "plate";
|
||||||
diffuseMap[0] = "art/shapes/station/plate";
|
diffuseMap[0] = "art/shapes/station/plate";
|
||||||
|
normalMap[0] = "art/shapes/station/plate_n.dds";
|
||||||
|
specularMap[0] = "art/shapes/station/plate_c.dds";
|
||||||
|
pixelSpecular0 = "0";
|
||||||
|
materialTag0 = "Miscellaneous";
|
||||||
|
//emissive[0] = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
new Material(Structure_grid)
|
||||||
|
{
|
||||||
|
mapTo = "grid";
|
||||||
|
diffuseMap[0] = "art/shapes/station/grid";
|
||||||
|
normalMap[0] = "art/shapes/station/grid_n.dds";
|
||||||
|
specularMap[0] = "art/shapes/station/grid_c.dds";
|
||||||
//emissive[0] = true;
|
//emissive[0] = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ new TerrainMaterial()
|
||||||
detailBrightness = "1";
|
detailBrightness = "1";
|
||||||
Enabled = "1";
|
Enabled = "1";
|
||||||
diffuseSize = "400";
|
diffuseSize = "400";
|
||||||
|
compositeMap = "art/terrains/Example/snowtop";
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,12 @@ singleton Material( Grid512_ForestGreenLines_Mat )
|
||||||
singleton Material( Grid512_Green_Mat )
|
singleton Material( Grid512_Green_Mat )
|
||||||
{
|
{
|
||||||
mapTo = "Grid512_Green_Mat";
|
mapTo = "Grid512_Green_Mat";
|
||||||
diffuseMap[0] = "512_green";
|
diffuseMap[0] = "core/art/grids/512_green";
|
||||||
materialTag0 = "TestMaterial";
|
materialTag0 = "TestMaterial";
|
||||||
|
smoothness[0] = "1";
|
||||||
|
metalness[0] = "1";
|
||||||
|
translucent = "0";
|
||||||
|
translucentBlendOp = "Add";
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton Material( Grid512_Grey_Mat )
|
singleton Material( Grid512_Grey_Mat )
|
||||||
|
|
@ -65,8 +69,10 @@ singleton Material( Grid512_Grey_Mat )
|
||||||
singleton Material( Grid512_GreyBase_Mat )
|
singleton Material( Grid512_GreyBase_Mat )
|
||||||
{
|
{
|
||||||
mapTo = "Grid512_GreyBase_Mat";
|
mapTo = "Grid512_GreyBase_Mat";
|
||||||
diffuseMap[0] = "512_grey_base";
|
diffuseMap[0] = "core/art/grids/512_grey_base";
|
||||||
materialTag0 = "TestMaterial";
|
materialTag0 = "TestMaterial";
|
||||||
|
smoothness[0] = "1";
|
||||||
|
metalness[0] = "1";
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton Material( Grid512_Orange_Mat )
|
singleton Material( Grid512_Orange_Mat )
|
||||||
|
|
|
||||||
|
|
@ -47,23 +47,56 @@ new ShaderData( AL_DeferredShader )
|
||||||
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredShadingP.glsl";
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredShadingP.glsl";
|
||||||
|
|
||||||
samplerNames[0] = "colorBufferTex";
|
samplerNames[0] = "colorBufferTex";
|
||||||
samplerNames[1] = "directLightingBuffer";
|
samplerNames[1] = "diffuseLightingBuffer";
|
||||||
samplerNames[2] = "matInfoTex";
|
samplerNames[2] = "matInfoTex";
|
||||||
samplerNames[3] = "indirectLightingBuffer";
|
samplerNames[3] = "specularLightingBuffer";
|
||||||
samplerNames[4] = "deferredTex";
|
samplerNames[4] = "deferredTex";
|
||||||
pixVersion = 2.0;
|
pixVersion = 2.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
new ShaderData( AL_ProbeShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/probeShadingP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/probeShadingP.glsl";
|
||||||
|
|
||||||
|
samplerNames[0] = "colorBufferTex";
|
||||||
|
samplerNames[1] = "diffuseLightingBuffer";
|
||||||
|
samplerNames[2] = "matInfoTex";
|
||||||
|
samplerNames[3] = "specularLightingBuffer";
|
||||||
|
samplerNames[4] = "deferredTex";
|
||||||
|
pixVersion = 2.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
singleton PostEffect( AL_PreCapture )
|
||||||
|
{
|
||||||
|
renderTime = "PFXBeforeBin";
|
||||||
|
renderBin = "ProbeBin";
|
||||||
|
shader = AL_ProbeShader;
|
||||||
|
stateBlock = AL_DeferredShadingState;
|
||||||
|
texture[0] = "#color";
|
||||||
|
texture[1] = "#diffuseLighting";
|
||||||
|
texture[2] = "#matinfo";
|
||||||
|
texture[3] = "#specularLighting";
|
||||||
|
texture[4] = "#deferred";
|
||||||
|
target = "$backBuffer";
|
||||||
|
renderPriority = 10000;
|
||||||
|
allowReflectPass = true;
|
||||||
|
};
|
||||||
|
|
||||||
singleton PostEffect( AL_DeferredShading )
|
singleton PostEffect( AL_DeferredShading )
|
||||||
{
|
{
|
||||||
renderTime = "PFXAfterBin";
|
renderTime = "PFXAfterBin";
|
||||||
renderBin = "SkyBin";
|
renderBin = "ProbeBin";
|
||||||
shader = AL_DeferredShader;
|
shader = AL_DeferredShader;
|
||||||
stateBlock = AL_DeferredShadingState;
|
stateBlock = AL_DeferredShadingState;
|
||||||
texture[0] = "#color";
|
texture[0] = "#color";
|
||||||
texture[1] = "#directLighting";
|
texture[1] = "#diffuseLighting";
|
||||||
texture[2] = "#matinfo";
|
texture[2] = "#matinfo";
|
||||||
texture[3] = "#indirectLighting";
|
texture[3] = "#specularLighting";
|
||||||
texture[4] = "#deferred";
|
texture[4] = "#deferred";
|
||||||
|
|
||||||
target = "$backBuffer";
|
target = "$backBuffer";
|
||||||
|
|
@ -192,7 +225,7 @@ new ShaderData( AL_LightMapShader )
|
||||||
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
||||||
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl";
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl";
|
||||||
|
|
||||||
samplerNames[0] = "indirectLightingBuffer";
|
samplerNames[0] = "specularLightingBuffer";
|
||||||
pixVersion = 2.0;
|
pixVersion = 2.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -200,7 +233,7 @@ singleton PostEffect( AL_LightMapVisualize )
|
||||||
{
|
{
|
||||||
shader = AL_LightMapShader;
|
shader = AL_LightMapShader;
|
||||||
stateBlock = AL_DefaultVisualizeState;
|
stateBlock = AL_DefaultVisualizeState;
|
||||||
texture[0] = "#indirectLighting";
|
texture[0] = "#specularLighting";
|
||||||
target = "$backBuffer";
|
target = "$backBuffer";
|
||||||
renderPriority = 9999;
|
renderPriority = 9999;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ new ShaderData( AL_LightColorVisualizeShader )
|
||||||
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
||||||
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl";
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl";
|
||||||
|
|
||||||
samplerNames[0] = "directLightingBuffer";
|
samplerNames[0] = "diffuseLightingBuffer";
|
||||||
|
|
||||||
pixVersion = 2.0;
|
pixVersion = 2.0;
|
||||||
};
|
};
|
||||||
|
|
@ -158,7 +158,7 @@ singleton PostEffect( AL_LightColorVisualize )
|
||||||
{
|
{
|
||||||
shader = AL_LightColorVisualizeShader;
|
shader = AL_LightColorVisualizeShader;
|
||||||
stateBlock = AL_DefaultVisualizeState;
|
stateBlock = AL_DefaultVisualizeState;
|
||||||
texture[0] = "#directLighting";
|
texture[0] = "#diffuseLighting";
|
||||||
target = "$backBuffer";
|
target = "$backBuffer";
|
||||||
renderPriority = 9999;
|
renderPriority = 9999;
|
||||||
};
|
};
|
||||||
|
|
@ -184,16 +184,16 @@ new ShaderData( AL_LightSpecularVisualizeShader )
|
||||||
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl";
|
||||||
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl";
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl";
|
||||||
|
|
||||||
samplerNames[0] = "directLightingBuffer";
|
samplerNames[0] = "diffuseLightingBuffer";
|
||||||
|
|
||||||
pixVersion = 2.0;
|
pixVersion = 2.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
singleton PostEffect( AL_LightSpecularVisualize )
|
singleton PostEffect( AL_LightSpecularVisualize )
|
||||||
{
|
{
|
||||||
shader = AL_LightSpecularVisualizeShader;
|
shader = AL_LightColorVisualizeShader;
|
||||||
stateBlock = AL_DefaultVisualizeState;
|
stateBlock = AL_DefaultVisualizeState;
|
||||||
texture[0] = "#directLighting";
|
texture[0] = "#specularLighting";
|
||||||
target = "$backBuffer";
|
target = "$backBuffer";
|
||||||
renderPriority = 9999;
|
renderPriority = 9999;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,11 @@ new CustomMaterial( AL_VectorLightMaterial )
|
||||||
sampler["shadowMap"] = "$dynamiclight";
|
sampler["shadowMap"] = "$dynamiclight";
|
||||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||||
sampler["ssaoMask"] = "#ssaoMask";
|
sampler["ssaoMask"] = "#ssaoMask";
|
||||||
sampler["lightBuffer"] = "#indirectLighting";
|
sampler["lightBuffer"] = "#specularLighting";
|
||||||
sampler["colorBuffer"] = "#color";
|
sampler["colorBuffer"] = "#color";
|
||||||
sampler["matInfoBuffer"] = "#matinfo";
|
sampler["matInfoBuffer"] = "#matinfo";
|
||||||
|
|
||||||
target = "directLighting";
|
target = "diffuseLighting";
|
||||||
|
|
||||||
pixVersion = 3.0;
|
pixVersion = 3.0;
|
||||||
};
|
};
|
||||||
|
|
@ -163,11 +163,11 @@ new CustomMaterial( AL_PointLightMaterial )
|
||||||
sampler["shadowMap"] = "$dynamiclight";
|
sampler["shadowMap"] = "$dynamiclight";
|
||||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||||
sampler["cookieMap"] = "$dynamiclightmask";
|
sampler["cookieMap"] = "$dynamiclightmask";
|
||||||
sampler["lightBuffer"] = "#indirectLighting";
|
sampler["lightBuffer"] = "#specularLighting";
|
||||||
sampler["colorBuffer"] = "#color";
|
sampler["colorBuffer"] = "#color";
|
||||||
sampler["matInfoBuffer"] = "#matinfo";
|
sampler["matInfoBuffer"] = "#matinfo";
|
||||||
|
|
||||||
target = "directLighting";
|
target = "diffuseLighting";
|
||||||
|
|
||||||
pixVersion = 3.0;
|
pixVersion = 3.0;
|
||||||
};
|
};
|
||||||
|
|
@ -202,11 +202,11 @@ new CustomMaterial( AL_SpotLightMaterial )
|
||||||
sampler["shadowMap"] = "$dynamiclight";
|
sampler["shadowMap"] = "$dynamiclight";
|
||||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||||
sampler["cookieMap"] = "$dynamiclightmask";
|
sampler["cookieMap"] = "$dynamiclightmask";
|
||||||
sampler["lightBuffer"] = "#indirectLighting";
|
sampler["lightBuffer"] = "#specularLighting";
|
||||||
sampler["colorBuffer"] = "#color";
|
sampler["colorBuffer"] = "#color";
|
||||||
sampler["matInfoBuffer"] = "#matinfo";
|
sampler["matInfoBuffer"] = "#matinfo";
|
||||||
|
|
||||||
target = "directLighting";
|
target = "diffuseLighting";
|
||||||
|
|
||||||
pixVersion = 3.0;
|
pixVersion = 3.0;
|
||||||
};
|
};
|
||||||
|
|
@ -269,7 +269,124 @@ new CustomMaterial( AL_ParticlePointLightMaterial )
|
||||||
stateBlock = AL_ConvexLightState;
|
stateBlock = AL_ConvexLightState;
|
||||||
|
|
||||||
sampler["deferredBuffer"] = "#deferred";
|
sampler["deferredBuffer"] = "#deferred";
|
||||||
target = "directLighting";
|
target = "diffuseLighting";
|
||||||
|
|
||||||
pixVersion = 3.0;
|
pixVersion = 3.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Reflection probe Specular
|
||||||
|
new ShaderData( ReflectionProbeShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/reflectionProbeP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/reflectionProbeP.glsl";
|
||||||
|
|
||||||
|
samplerNames[0] = "$deferredBuffer";
|
||||||
|
samplerNames[1] = "$matInfoBuffer";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convex-geometry light states
|
||||||
|
new GFXStateBlockData( AL_ProbeState )
|
||||||
|
{
|
||||||
|
blendDefined = true;
|
||||||
|
blendEnable = true;
|
||||||
|
blendSrc = GFXBlendOne;
|
||||||
|
blendDest = GFXBlendOne;
|
||||||
|
blendOp = GFXBlendOpAdd;
|
||||||
|
|
||||||
|
zDefined = true;
|
||||||
|
zEnable = true;
|
||||||
|
zWriteEnable = false;
|
||||||
|
zFunc = GFXCmpGreaterEqual;
|
||||||
|
|
||||||
|
samplersDefined = true;
|
||||||
|
samplerStates[0] = SamplerClampPoint; // G-buffer
|
||||||
|
mSamplerNames[0] = "deferredBuffer";
|
||||||
|
samplerStates[1] = SamplerClampLinear; // Shadow Map (Do not use linear, these are perspective projections)
|
||||||
|
mSamplerNames[1] = "matInfoBuffer";
|
||||||
|
|
||||||
|
cullDefined = true;
|
||||||
|
cullMode = GFXCullCW;
|
||||||
|
|
||||||
|
stencilDefined = true;
|
||||||
|
stencilEnable = true;
|
||||||
|
stencilFailOp = GFXStencilOpKeep;
|
||||||
|
stencilZFailOp = GFXStencilOpKeep;
|
||||||
|
stencilPassOp = GFXStencilOpKeep;
|
||||||
|
stencilFunc = GFXCmpLess;
|
||||||
|
stencilRef = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
new CustomMaterial( ReflectionProbeMaterial )
|
||||||
|
{
|
||||||
|
shader = ReflectionProbeShader;
|
||||||
|
stateBlock = AL_ProbeState;
|
||||||
|
|
||||||
|
sampler["deferredBuffer"] = "#deferred";
|
||||||
|
sampler["matInfoBuffer"] = "#matinfo";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Skylight
|
||||||
|
new ShaderData( IrradianceShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/lighting/advanced/cubemapV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/irradianceP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/cubemapV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/irradianceP.glsl";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
new ShaderData( PrefiterCubemapShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/lighting/advanced/cubemapV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/prefilterP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/cubemapV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/prefilterP.glsl";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
new ShaderData( BRDFLookupShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/lighting/advanced/cubemapV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/brdfLookupP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/cubemapV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/brdfLookupP.glsl";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
new ShaderData( SklyightShader )
|
||||||
|
{
|
||||||
|
DXVertexShaderFile = "shaders/common/lighting/advanced/convexGeometryV.hlsl";
|
||||||
|
DXPixelShaderFile = "shaders/common/lighting/advanced/skylightP.hlsl";
|
||||||
|
|
||||||
|
OGLVertexShaderFile = "shaders/common/lighting/advanced/gl/convexGeometryV.glsl";
|
||||||
|
OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/skylightP.glsl";
|
||||||
|
|
||||||
|
samplerNames[0] = "$deferredBuffer";
|
||||||
|
samplerNames[1] = "$matInfoBuffer";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
new CustomMaterial( SklyightMaterial )
|
||||||
|
{
|
||||||
|
shader = SklyightShader;
|
||||||
|
stateBlock = AL_ProbeState;
|
||||||
|
|
||||||
|
sampler["deferredBuffer"] = "#deferred";
|
||||||
|
sampler["matInfoBuffer"] = "#matinfo";
|
||||||
|
|
||||||
|
pixVersion = 3.0;
|
||||||
|
};
|
||||||
|
|
@ -64,7 +64,7 @@ singleton CustomMaterial( BL_ProjectedShadowMaterial )
|
||||||
function onActivateBasicLM()
|
function onActivateBasicLM()
|
||||||
{
|
{
|
||||||
// If HDR is enabled... enable the special format token.
|
// If HDR is enabled... enable the special format token.
|
||||||
if ( $platform !$= "macos" && HDRPostFx.isEnabled )
|
if ( HDRPostFx.isEnabled )
|
||||||
AL_FormatToken.enable();
|
AL_FormatToken.enable();
|
||||||
|
|
||||||
// Create render pass for projected shadow.
|
// Create render pass for projected shadow.
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,8 @@ function initRenderManager()
|
||||||
// meshes... but that causes issues in reflections.
|
// meshes... but that causes issues in reflections.
|
||||||
DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } );
|
DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } );
|
||||||
|
|
||||||
//DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } );
|
DiffuseRenderPassManager.addManager( new RenderProbeMgr(ProbeBin) { bintype = "Probes"; renderOrder = 0.15; processAddOrder = 0.15; } );
|
||||||
|
//DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } );
|
||||||
|
|
||||||
DiffuseRenderPassManager.addManager( new RenderObjectMgr(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } );
|
DiffuseRenderPassManager.addManager( new RenderObjectMgr(BeginBin) { bintype = "Begin"; renderOrder = 0.2; processAddOrder = 0.2; } );
|
||||||
// Normal mesh rendering.
|
// Normal mesh rendering.
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ new SimGroup(MissionGroup) {
|
||||||
levelName = "A Probe Test";
|
levelName = "A Probe Test";
|
||||||
};
|
};
|
||||||
new SkyBox(theSky) {
|
new SkyBox(theSky) {
|
||||||
Material = "DesertSkyMat";
|
Material = "sky_day_hdr";
|
||||||
drawBottom = "0";
|
drawBottom = "0";
|
||||||
fogBandHeight = "0";
|
fogBandHeight = "0";
|
||||||
position = "0 0 0";
|
position = "0 0 0";
|
||||||
|
|
@ -37,48 +37,16 @@ new SimGroup(MissionGroup) {
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
};
|
};
|
||||||
new Sun(theSun) {
|
new Skylight() {
|
||||||
azimuth = "290";
|
enabled = "1";
|
||||||
elevation = "50";
|
StaticCubemap = "sky_day_hdr_cubemap";
|
||||||
color = "1 1 1 1";
|
|
||||||
ambient = "0.473532 0.473532 0.473532 1";
|
|
||||||
brightness = "1";
|
|
||||||
castShadows = "1";
|
|
||||||
staticRefreshFreq = "250";
|
|
||||||
dynamicRefreshFreq = "8";
|
|
||||||
coronaEnabled = "1";
|
|
||||||
coronaScale = "0.5";
|
|
||||||
coronaTint = "1 1 1 1";
|
|
||||||
coronaUseLightColor = "1";
|
|
||||||
flareScale = "1";
|
|
||||||
attenuationRatio = "0 1 1";
|
|
||||||
shadowType = "PSSM";
|
|
||||||
texSize = "1024";
|
|
||||||
overDarkFactor = "3000 1500 750 250";
|
|
||||||
shadowDistance = "100";
|
|
||||||
shadowSoftness = "0.25";
|
|
||||||
numSplits = "4";
|
|
||||||
logWeight = "0.9";
|
|
||||||
fadeStartDistance = "0";
|
|
||||||
lastSplitTerrainOnly = "0";
|
|
||||||
representedInLightmap = "0";
|
|
||||||
shadowDarkenColor = "0 0 0 -1";
|
|
||||||
includeLightmappedGeometryInShadow = "0";
|
|
||||||
position = "0 0 0";
|
position = "0 0 0";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
bias = "0.1";
|
persistentId = "e4c73467-4089-11e8-b478-cd227cd60b8b";
|
||||||
Blur = "1";
|
reflectionPath = "levels/AProbeTest/probes/";
|
||||||
enabled = "1";
|
|
||||||
height = "1024";
|
|
||||||
lightBleedFactor = "0.8";
|
|
||||||
minVariance = "0";
|
|
||||||
pointShadowType = "PointShadowType_Paraboloid";
|
|
||||||
shadowBox = "-100 -100 -100 100 100 100";
|
|
||||||
splitFadeDistances = "1 1 1 1";
|
|
||||||
width = "3072";
|
|
||||||
};
|
};
|
||||||
new SimGroup(PlayerDropPoints) {
|
new SimGroup(PlayerDropPoints) {
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
|
|
@ -117,13 +85,46 @@ new SimGroup(MissionGroup) {
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
};
|
};
|
||||||
|
new Sun() {
|
||||||
|
azimuth = "200";
|
||||||
|
elevation = "20";
|
||||||
|
color = "0.8 0.8 0.8 1";
|
||||||
|
ambient = "0.2 0.2 0.2 1";
|
||||||
|
brightness = "1";
|
||||||
|
castShadows = "1";
|
||||||
|
staticRefreshFreq = "250";
|
||||||
|
dynamicRefreshFreq = "8";
|
||||||
|
coronaEnabled = "1";
|
||||||
|
coronaMaterial = "Corona_Mat";
|
||||||
|
coronaScale = "0.5";
|
||||||
|
coronaTint = "1 1 1 1";
|
||||||
|
coronaUseLightColor = "1";
|
||||||
|
flareType = "SunFlareExample";
|
||||||
|
flareScale = "1";
|
||||||
|
attenuationRatio = "0 1 1";
|
||||||
|
shadowType = "PSSM";
|
||||||
|
texSize = "512";
|
||||||
|
overDarkFactor = "2000 1000 500 100";
|
||||||
|
shadowDistance = "400";
|
||||||
|
shadowSoftness = "0.15";
|
||||||
|
numSplits = "4";
|
||||||
|
logWeight = "0.91";
|
||||||
|
fadeStartDistance = "0";
|
||||||
|
lastSplitTerrainOnly = "0";
|
||||||
|
representedInLightmap = "0";
|
||||||
|
shadowDarkenColor = "0 0 0 -1";
|
||||||
|
includeLightmappedGeometryInShadow = "0";
|
||||||
|
position = "35.7492 65.5507 -15.5377";
|
||||||
|
rotation = "1 0 0 0";
|
||||||
|
scale = "1 1 1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "1";
|
||||||
|
direction = "1 1 -1";
|
||||||
|
};
|
||||||
new ReflectionProbe() {
|
new ReflectionProbe() {
|
||||||
enabled = "1";
|
enabled = "0";
|
||||||
ProbeShape = "Sphere";
|
ProbeShape = "Sphere";
|
||||||
radius = "10";
|
radius = "10";
|
||||||
Intensity = "1";
|
|
||||||
IndirectLightMode = "Ambient Color";
|
|
||||||
IndirectLight = "1 1 1 1";
|
|
||||||
ReflectionMode = "Baked Cubemap";
|
ReflectionMode = "Baked Cubemap";
|
||||||
reflectionPath = "levels/probeTest/probes/";
|
reflectionPath = "levels/probeTest/probes/";
|
||||||
Bake = "0";
|
Bake = "0";
|
||||||
|
|
@ -134,6 +135,9 @@ new SimGroup(MissionGroup) {
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
persistentId = "8072e1be-2846-11e7-9f56-abd46b190c60";
|
persistentId = "8072e1be-2846-11e7-9f56-abd46b190c60";
|
||||||
GroundColor = "0.8 0.7 0.5 1";
|
GroundColor = "0.8 0.7 0.5 1";
|
||||||
|
IndirectLight = "1 1 1 1";
|
||||||
|
IndirectLightMode = "Spherical Harmonics";
|
||||||
|
Intensity = "1";
|
||||||
SkyColor = "0.5 0.5 1 1";
|
SkyColor = "0.5 0.5 1 1";
|
||||||
};
|
};
|
||||||
new ConvexShape() {
|
new ConvexShape() {
|
||||||
|
|
@ -243,7 +247,7 @@ new SimGroup(MissionGroup) {
|
||||||
};
|
};
|
||||||
new PointLight() {
|
new PointLight() {
|
||||||
radius = "10";
|
radius = "10";
|
||||||
isEnabled = "1";
|
isEnabled = "0";
|
||||||
color = "0.887923 1 0.008023 1";
|
color = "0.887923 1 0.008023 1";
|
||||||
brightness = "1";
|
brightness = "1";
|
||||||
castShadows = "0";
|
castShadows = "0";
|
||||||
|
|
@ -272,5 +276,24 @@ new SimGroup(MissionGroup) {
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
};
|
};
|
||||||
|
new ReflectionProbe() {
|
||||||
|
enabled = "0";
|
||||||
|
ProbeShape = "Box";
|
||||||
|
radius = "10";
|
||||||
|
ReflectionMode = "Baked Cubemap";
|
||||||
|
reflectionPath = "levels/probeTest/probes/";
|
||||||
|
Bake = "0";
|
||||||
|
position = "15.4549 0.559989 4.53387";
|
||||||
|
rotation = "1 0 0 0";
|
||||||
|
scale = "5 5 5";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "1";
|
||||||
|
persistentId = "4ec88e62-4e8f-11e8-ae68-993c6bb8eb5b";
|
||||||
|
GroundColor = "0.8 0.7 0.5 1";
|
||||||
|
IndirectLight = "1 1 1 1";
|
||||||
|
IndirectLightMode = "Spherical Harmonics";
|
||||||
|
Intensity = "1";
|
||||||
|
SkyColor = "0.5 0.5 1 1";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
//--- OBJECT WRITE END ---
|
//--- OBJECT WRITE END ---
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,6 @@ new SimGroup(MissionGroup) {
|
||||||
canvasClearColor = "0 0 0 255";
|
canvasClearColor = "0 0 0 255";
|
||||||
ambientLightBlendPhase = "1";
|
ambientLightBlendPhase = "1";
|
||||||
ambientLightBlendCurve = "0 0 -1 -1";
|
ambientLightBlendCurve = "0 0 -1 -1";
|
||||||
LevelEnvMap = "DesertSkyCubemap";
|
|
||||||
soundAmbience = "AudioAmbienceDefault";
|
soundAmbience = "AudioAmbienceDefault";
|
||||||
soundDistanceModel = "Linear";
|
soundDistanceModel = "Linear";
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
|
|
@ -33,6 +32,7 @@ new SimGroup(MissionGroup) {
|
||||||
baseTexFormat = "DDS";
|
baseTexFormat = "DDS";
|
||||||
lightMapSize = "256";
|
lightMapSize = "256";
|
||||||
screenError = "16";
|
screenError = "16";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
position = "-1024 -1024 179.978";
|
position = "-1024 -1024 179.978";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
|
|
@ -67,8 +67,8 @@ new SimGroup(MissionGroup) {
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "1";
|
allowPlayerStep = "1";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -76,6 +76,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "9.42739 27.7428 241.767";
|
position = "9.42739 27.7428 241.767";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -133,8 +137,8 @@ new SimGroup(MissionGroup) {
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "1";
|
allowPlayerStep = "1";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -142,6 +146,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "17.8995 16.1596 241.136";
|
position = "17.8995 16.1596 241.136";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -158,27 +166,18 @@ new SimGroup(MissionGroup) {
|
||||||
|
|
||||||
surface = "0 0 0 1 1.29457 -0.42643 0.5";
|
surface = "0 0 0 1 1.29457 -0.42643 0.5";
|
||||||
surface = "0 1 0 0 1.29457 -0.42643 -0.5";
|
surface = "0 1 0 0 1.29457 -0.42643 -0.5";
|
||||||
surface = "0.707107 0 0 0.707107 1.29457 5.75621 0";
|
surface = "0.707107 0 0 0.707106 1.29457 5.75621 0";
|
||||||
surface = "0 0.707107 -0.707107 0 1.29457 -6.60907 -4.54747e-013";
|
surface = "0 0.707107 -0.707107 0 1.29457 -6.60907 -4.54747e-13";
|
||||||
surface = "0.5 0.5 -0.5 0.5 -3.35148 -0.42643 -1.28542e-008";
|
surface = "0.5 0.5 -0.5 0.5 -3.35148 -0.42643 -1.28542e-08";
|
||||||
surface = "0.5 -0.5 0.5 0.5 5.94063 -0.42643 -1.28542e-008";
|
surface = "0.5 -0.5 0.5 0.5 5.94063 -0.42643 -1.28542e-08";
|
||||||
};
|
|
||||||
new EnvVolume() {
|
|
||||||
AreaEnvMap = "MipCubemap";
|
|
||||||
cubeReflectorDesc = "DefaultCubeDesc";
|
|
||||||
position = "8.21068 19.3464 241.855";
|
|
||||||
rotation = "1 0 0 0";
|
|
||||||
scale = "10 10 10";
|
|
||||||
canSave = "1";
|
|
||||||
canSaveDynamicFields = "1";
|
|
||||||
};
|
};
|
||||||
new TSStatic() {
|
new TSStatic() {
|
||||||
shapeName = "art/shapes/textures/PBRTEST2.dae";
|
shapeName = "art/shapes/textures/PBRTEST2.dae";
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "1";
|
allowPlayerStep = "1";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -186,6 +185,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "5.60579 18.8689 241.462";
|
position = "5.60579 18.8689 241.462";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -198,8 +201,8 @@ new SimGroup(MissionGroup) {
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
cubeReflectorDesc = "DefaultCubeDesc";
|
cubeReflectorDesc = "DefaultCubeDesc";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "1";
|
allowPlayerStep = "1";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -207,6 +210,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "22.1653 4.41543 241.364";
|
position = "22.1653 4.41543 241.364";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -218,8 +225,8 @@ new SimGroup(MissionGroup) {
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "1";
|
allowPlayerStep = "1";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -227,6 +234,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "15.72 5.9186 241.191";
|
position = "15.72 5.9186 241.191";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -246,8 +257,8 @@ new SimGroup(MissionGroup) {
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "0";
|
allowPlayerStep = "0";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -255,6 +266,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "12.8895 -2.18239 238.765";
|
position = "12.8895 -2.18239 238.765";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -266,8 +281,8 @@ new SimGroup(MissionGroup) {
|
||||||
playAmbient = "1";
|
playAmbient = "1";
|
||||||
meshCulling = "0";
|
meshCulling = "0";
|
||||||
originSort = "0";
|
originSort = "0";
|
||||||
collisionType = "Collision Mesh";
|
CollisionType = "Collision Mesh";
|
||||||
decalType = "Collision Mesh";
|
DecalType = "Collision Mesh";
|
||||||
allowPlayerStep = "0";
|
allowPlayerStep = "0";
|
||||||
alphaFadeEnable = "0";
|
alphaFadeEnable = "0";
|
||||||
alphaFadeStart = "100";
|
alphaFadeStart = "100";
|
||||||
|
|
@ -275,6 +290,10 @@ new SimGroup(MissionGroup) {
|
||||||
alphaFadeInverse = "0";
|
alphaFadeInverse = "0";
|
||||||
renderNormals = "0";
|
renderNormals = "0";
|
||||||
forceDetail = "-1";
|
forceDetail = "-1";
|
||||||
|
ignoreZodiacs = "0";
|
||||||
|
useGradientRange = "0";
|
||||||
|
gradientRange = "0 180";
|
||||||
|
invertGradientRange = "0";
|
||||||
position = "10.406 10.0939 240.551";
|
position = "10.406 10.0939 240.551";
|
||||||
rotation = "1 0 0 0";
|
rotation = "1 0 0 0";
|
||||||
scale = "1 1 1";
|
scale = "1 1 1";
|
||||||
|
|
@ -300,9 +319,6 @@ new SimGroup(MissionGroup) {
|
||||||
enabled = "1";
|
enabled = "1";
|
||||||
ProbeShape = "Sphere";
|
ProbeShape = "Sphere";
|
||||||
radius = "10";
|
radius = "10";
|
||||||
Intensity = "1";
|
|
||||||
IndirectLightMode = "Ambient Color";
|
|
||||||
IndirectLight = "1 1 1 1";
|
|
||||||
ReflectionMode = "Baked Cubemap";
|
ReflectionMode = "Baked Cubemap";
|
||||||
reflectionPath = "levels/empty terrain/";
|
reflectionPath = "levels/empty terrain/";
|
||||||
Bake = "0";
|
Bake = "0";
|
||||||
|
|
@ -312,14 +328,14 @@ new SimGroup(MissionGroup) {
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
persistentId = "fc28816f-65a6-11e7-b9a1-b6f5317ad553";
|
persistentId = "fc28816f-65a6-11e7-b9a1-b6f5317ad553";
|
||||||
|
IndirectLight = "1 1 1 1";
|
||||||
|
IndirectLightMode = "Ambient Color";
|
||||||
|
Intensity = "1";
|
||||||
};
|
};
|
||||||
new ReflectionProbe() {
|
new ReflectionProbe() {
|
||||||
enabled = "1";
|
enabled = "1";
|
||||||
ProbeShape = "Sphere";
|
ProbeShape = "Sphere";
|
||||||
radius = "10";
|
radius = "10";
|
||||||
Intensity = "1";
|
|
||||||
IndirectLightMode = "Ambient Color";
|
|
||||||
IndirectLight = "1 1 1 1";
|
|
||||||
ReflectionMode = "Baked Cubemap";
|
ReflectionMode = "Baked Cubemap";
|
||||||
reflectionPath = "levels/empty terrain/";
|
reflectionPath = "levels/empty terrain/";
|
||||||
Bake = "0";
|
Bake = "0";
|
||||||
|
|
@ -329,6 +345,20 @@ new SimGroup(MissionGroup) {
|
||||||
canSave = "1";
|
canSave = "1";
|
||||||
canSaveDynamicFields = "1";
|
canSaveDynamicFields = "1";
|
||||||
persistentId = "10bb5f41-65a7-11e7-b9a1-b6f5317ad553";
|
persistentId = "10bb5f41-65a7-11e7-b9a1-b6f5317ad553";
|
||||||
|
IndirectLight = "1 1 1 1";
|
||||||
|
IndirectLightMode = "Ambient Color";
|
||||||
|
Intensity = "1";
|
||||||
|
};
|
||||||
|
new Skylight() {
|
||||||
|
enabled = "1";
|
||||||
|
StaticCubemap = "HdrSkyCubemap";
|
||||||
|
position = "16.4688 10.5898 241.399";
|
||||||
|
rotation = "1 0 0 0";
|
||||||
|
scale = "1 1 1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "1";
|
||||||
|
persistentId = "de646cc8-4f49-11e8-8a25-ec48d38e6b49";
|
||||||
|
reflectionPath = "levels/Empty Terrain/probes/";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
//--- OBJECT WRITE END ---
|
//--- OBJECT WRITE END ---
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (c) 2012 GarageGames, LLC
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
//
|
// Portions Copyright Zefiros
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
// deal in the Software without restriction, including without limitation the
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
|
@ -38,12 +38,140 @@ uniform vec4 inLightColor[4];
|
||||||
|
|
||||||
uniform vec4 ambient;
|
uniform vec4 ambient;
|
||||||
#define ambientCameraFactor 0.3
|
#define ambientCameraFactor 0.3
|
||||||
uniform float specularPower;
|
uniform float smoothness;
|
||||||
uniform vec4 specularColor;
|
uniform float metalness;
|
||||||
|
uniform vec4 albedo;
|
||||||
|
|
||||||
#endif // !TORQUE_SHADERGEN
|
#endif // !TORQUE_SHADERGEN
|
||||||
|
|
||||||
|
|
||||||
|
vec3 F_schlick( in vec3 f0, in vec3 f90, in float u )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// F( v, h ) = F0 + ( 1.0 - F0 ) * pow( 1.0f - HdotV, 5.0f )
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// where
|
||||||
|
//
|
||||||
|
// F0 = BaseColor * nDotL
|
||||||
|
//
|
||||||
|
// Dielectric materials always have a range of 0.02 < F0 < 0.05 , use a stock value of 0.04 ( roughly plastics )
|
||||||
|
//
|
||||||
|
|
||||||
|
return f0 + ( f90 - f0 ) * pow( 1.0f - u , 5.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Fr_DisneyDiffuse ( float NdotV , float NdotL , float LdotH , float linearRoughness )
|
||||||
|
{
|
||||||
|
float energyBias = mix (0 , 0.5 , linearRoughness );
|
||||||
|
float energyFactor = mix (1.0 , 1.0 / 1.51 , linearRoughness );
|
||||||
|
float fd90 = energyBias + 2.0 * LdotH * LdotH * linearRoughness ;
|
||||||
|
vec3 f0 = vec3 ( 1.0f , 1.0f , 1.0f );
|
||||||
|
float lightScatter = F_schlick( f0 , vec3(fd90), NdotL ).r;
|
||||||
|
float viewScatter = F_schlick(f0 , vec3(fd90), NdotV ).r;
|
||||||
|
|
||||||
|
return lightScatter * viewScatter * energyFactor ;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SmithGGX( float NdotL, float NdotV, float alpha )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// G( L, V, h ) = G( L ) G( V )
|
||||||
|
//
|
||||||
|
// nDotL
|
||||||
|
// G( L ) = _________________________
|
||||||
|
// nDotL ( 1 - k ) + k
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// NdotV
|
||||||
|
// G( V ) = _________________________
|
||||||
|
// NdotV ( 1 - k ) + k
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// pow( ( Roughness + 1 ), 2)
|
||||||
|
// , Where k = __________________________ ( unreal 4 )
|
||||||
|
// 8
|
||||||
|
//
|
||||||
|
|
||||||
|
float alphaSqr = alpha * alpha;
|
||||||
|
|
||||||
|
//float GGX_V = NdotL * sqrt ( ( - NdotV * alphaSqr + NdotV ) * NdotV + alphaSqr );
|
||||||
|
//float GGX_L = NdotV * sqrt ( ( - NdotL * alphaSqr + NdotL ) * NdotL + alphaSqr );
|
||||||
|
|
||||||
|
float GGX_V = NdotL + sqrt ( ( - NdotV * alphaSqr + NdotV ) * NdotV + alphaSqr );
|
||||||
|
float GGX_L = NdotV + sqrt ( ( - NdotL * alphaSqr + NdotL ) * NdotL + alphaSqr );
|
||||||
|
|
||||||
|
return 1.0/( GGX_V + GGX_L );
|
||||||
|
//return 0.5f / ( GGX_V + GGX_L );
|
||||||
|
}
|
||||||
|
|
||||||
|
float D_GGX( float NdotH , float alpha )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// or GGX ( disney / unreal 4 )
|
||||||
|
//
|
||||||
|
// alpha = pow( roughness, 2 );
|
||||||
|
//
|
||||||
|
// pow( alpha, 2 )
|
||||||
|
// D( h ) = ________________________________________________________________
|
||||||
|
// PI pow( pow( NdotH , 2 ) ( pow( alpha, 2 ) - 1 ) + 1 ), 2 )
|
||||||
|
//
|
||||||
|
|
||||||
|
float alphaSqr = alpha*alpha;
|
||||||
|
float f = ( NdotH * alphaSqr - NdotH ) * NdotH + 1;
|
||||||
|
return alphaSqr / ( M_PI_F * (f * f) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 EvalBDRF( vec3 baseColor, vec3 lightColor, vec3 toLight, vec3 position, vec3 normal, float roughness, float metallic )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Microfacet Specular Cook-Torrance
|
||||||
|
//
|
||||||
|
// D( h ) F( v, h ) G( l, v, h )
|
||||||
|
// f( l, v ) = ____________________________
|
||||||
|
// 4 ( dot( n, l ) dot( n, v )
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
vec3 L = normalize( toLight );
|
||||||
|
vec3 V = normalize( -position );
|
||||||
|
vec3 H = normalize( L + V );
|
||||||
|
vec3 N = normal;
|
||||||
|
|
||||||
|
float NdotV = abs( dot( N, V ) ) + 1e-5f;
|
||||||
|
float NdotH = saturate( dot( N, H ) );
|
||||||
|
float NdotL = saturate( dot( N, L ) );
|
||||||
|
float LdotH = saturate( dot( L, H ) );
|
||||||
|
|
||||||
|
float VdotH = saturate( dot( V, H ) );
|
||||||
|
|
||||||
|
if ( NdotL == 0 )
|
||||||
|
return vec4( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||||
|
|
||||||
|
float alpha = roughness;
|
||||||
|
float visLinAlpha = alpha * alpha;
|
||||||
|
|
||||||
|
vec3 f0 = baseColor;
|
||||||
|
float metal = metallic;
|
||||||
|
|
||||||
|
vec3 F_conductor= F_schlick( f0, vec3( 1.0, 1.0, 1.0 ), VdotH );
|
||||||
|
vec3 F_dielec = F_schlick( vec3( 0.04, 0.04, 0.04 ), vec3( 1.0, 1.0, 1.0 ), VdotH );
|
||||||
|
float Vis = SmithGGX( NdotL, NdotV, visLinAlpha );
|
||||||
|
float D = D_GGX( NdotH, visLinAlpha );
|
||||||
|
|
||||||
|
vec3 Fr_dielec = D * F_dielec * Vis;
|
||||||
|
vec3 Fr_conductor = D * F_conductor * Vis;
|
||||||
|
|
||||||
|
vec3 Fd = vec3(Fr_DisneyDiffuse( NdotV , NdotL , LdotH , visLinAlpha ) / M_PI_F);
|
||||||
|
vec3 specular = ( 1.0f - metal ) * Fr_dielec + metal * Fr_conductor;
|
||||||
|
vec3 diffuse = ( 1.0f - metal ) * Fd * f0;
|
||||||
|
|
||||||
|
vec3 ret = ( diffuse + specular + lightColor) * vec3(NdotL);
|
||||||
|
|
||||||
|
float FR = saturate(length(specular));
|
||||||
|
return vec4(ret,FR);
|
||||||
|
}
|
||||||
|
|
||||||
void compute4Lights( vec3 wsView,
|
void compute4Lights( vec3 wsView,
|
||||||
vec3 wsPosition,
|
vec3 wsPosition,
|
||||||
vec3 wsNormal,
|
vec3 wsNormal,
|
||||||
|
|
@ -57,8 +185,9 @@ void compute4Lights( vec3 wsView,
|
||||||
vec4 inLightSpotDir[3],
|
vec4 inLightSpotDir[3],
|
||||||
vec4 inLightSpotAngle,
|
vec4 inLightSpotAngle,
|
||||||
vec4 inLightSpotFalloff,
|
vec4 inLightSpotFalloff,
|
||||||
float specularPower,
|
float smoothness,
|
||||||
vec4 specularColor,
|
float metalness,
|
||||||
|
vec4 albedo,
|
||||||
|
|
||||||
#endif // TORQUE_SHADERGEN
|
#endif // TORQUE_SHADERGEN
|
||||||
|
|
||||||
|
|
@ -81,9 +210,6 @@ void compute4Lights( vec3 wsView,
|
||||||
for ( i = 0; i < 3; i++ )
|
for ( i = 0; i < 3; i++ )
|
||||||
lightVectors[i] = wsPosition[i] - inLightPos[i];
|
lightVectors[i] = wsPosition[i] - inLightPos[i];
|
||||||
|
|
||||||
vec4 squareDists = vec4(0);
|
|
||||||
for ( i = 0; i < 3; i++ )
|
|
||||||
squareDists += lightVectors[i] * lightVectors[i];
|
|
||||||
|
|
||||||
// Accumulate the dot product between the light
|
// Accumulate the dot product between the light
|
||||||
// vector and the normal.
|
// vector and the normal.
|
||||||
|
|
@ -99,40 +225,12 @@ void compute4Lights( vec3 wsView,
|
||||||
vec4 nDotL = vec4(0);
|
vec4 nDotL = vec4(0);
|
||||||
for ( i = 0; i < 3; i++ )
|
for ( i = 0; i < 3; i++ )
|
||||||
nDotL += lightVectors[i] * -wsNormal[i];
|
nDotL += lightVectors[i] * -wsNormal[i];
|
||||||
|
|
||||||
vec4 rDotL = vec4(0);
|
|
||||||
#ifndef TORQUE_BL_NOSPECULAR
|
|
||||||
|
|
||||||
// We're using the Phong specular reflection model
|
|
||||||
// here where traditionally Torque has used Blinn-Phong
|
|
||||||
// which has proven to be more accurate to real materials.
|
|
||||||
//
|
|
||||||
// We do so because its cheaper as do not need to
|
|
||||||
// calculate the half angle for all 4 lights.
|
|
||||||
//
|
|
||||||
// Advanced Lighting still uses Blinn-Phong, but the
|
|
||||||
// specular reconstruction it does looks fairly similar
|
|
||||||
// to this.
|
|
||||||
//
|
|
||||||
vec3 R = reflect( wsView, -wsNormal );
|
|
||||||
|
|
||||||
for ( i = 0; i < 3; i++ )
|
|
||||||
rDotL += lightVectors[i] * R[i];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Normalize the dots.
|
vec4 squareDists = vec4(0);
|
||||||
//
|
for ( i = 0; i < 3; i++ )
|
||||||
// Notice we're using the half type here to get a
|
squareDists += lightVectors[i] * lightVectors[i];
|
||||||
// much faster sqrt via the rsq_pp instruction at
|
|
||||||
// the loss of some precision.
|
|
||||||
//
|
|
||||||
// Unless we have some extremely large point lights
|
|
||||||
// i don't believe the precision loss will matter.
|
|
||||||
//
|
|
||||||
half4 correction = half4(inversesqrt( squareDists ));
|
half4 correction = half4(inversesqrt( squareDists ));
|
||||||
nDotL = saturate( nDotL * correction );
|
nDotL = saturate( nDotL * correction );
|
||||||
rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
|
|
||||||
|
|
||||||
// First calculate a simple point light linear
|
// First calculate a simple point light linear
|
||||||
// attenuation factor.
|
// attenuation factor.
|
||||||
|
|
@ -157,93 +255,18 @@ void compute4Lights( vec3 wsView,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Finally apply the shadow masking on the attenuation.
|
|
||||||
atten *= shadowMask;
|
|
||||||
|
|
||||||
// Get the final light intensity.
|
// Get the final light intensity.
|
||||||
vec4 intensity = nDotL * atten;
|
vec4 intensity = nDotL * atten;
|
||||||
|
|
||||||
// Combine the light colors for output.
|
|
||||||
outDiffuse = vec4(0);
|
|
||||||
for ( i = 0; i < 4; i++ )
|
|
||||||
outDiffuse += intensity[i] * inLightColor[i];
|
|
||||||
|
|
||||||
// Output the specular power.
|
|
||||||
vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten;
|
|
||||||
|
|
||||||
// Apply the per-light specular attenuation.
|
// Combine the light colors for output.
|
||||||
vec4 specular = vec4(0,0,0,1);
|
vec4 lightColor = vec4(0);
|
||||||
for ( i = 0; i < 4; i++ )
|
for ( i = 0; i < 4; i++ )
|
||||||
specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
|
lightColor += intensity[i] * inLightColor[i];
|
||||||
|
|
||||||
// Add the final specular intensity values together
|
|
||||||
// using a single dot product operation then get the
|
|
||||||
// final specular lighting color.
|
|
||||||
outSpecular = specularColor * specular;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This value is used in AL as a constant power to raise specular values
|
|
||||||
// to, before storing them into the light info buffer. The per-material
|
|
||||||
// specular value is then computer by using the integer identity of
|
|
||||||
// exponentiation:
|
|
||||||
//
|
|
||||||
// (a^m)^n = a^(m*n)
|
|
||||||
//
|
|
||||||
// or
|
|
||||||
//
|
|
||||||
// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)
|
|
||||||
//
|
|
||||||
#define AL_ConstantSpecularPower 12.0f
|
|
||||||
|
|
||||||
/// The specular calculation used in Advanced Lighting.
|
|
||||||
///
|
|
||||||
/// @param toLight Normalized vector representing direction from the pixel
|
|
||||||
/// being lit, to the light source, in world space.
|
|
||||||
///
|
|
||||||
/// @param normal Normalized surface normal.
|
|
||||||
///
|
|
||||||
/// @param toEye The normalized vector representing direction from the pixel
|
|
||||||
/// being lit to the camera.
|
|
||||||
///
|
|
||||||
float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye )
|
|
||||||
{
|
|
||||||
// (R.V)^c
|
|
||||||
float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
|
|
||||||
|
|
||||||
// Return the specular factor.
|
|
||||||
return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The output for Deferred Lighting
|
|
||||||
///
|
|
||||||
/// @param toLight Normalized vector representing direction from the pixel
|
|
||||||
/// being lit, to the light source, in world space.
|
|
||||||
///
|
|
||||||
/// @param normal Normalized surface normal.
|
|
||||||
///
|
|
||||||
/// @param toEye The normalized vector representing direction from the pixel
|
|
||||||
/// being lit to the camera.
|
|
||||||
///
|
|
||||||
vec4 AL_DeferredOutput(
|
|
||||||
vec3 lightColor,
|
|
||||||
vec3 diffuseColor,
|
|
||||||
vec4 matInfo,
|
|
||||||
vec4 ambient,
|
|
||||||
float specular,
|
|
||||||
float shadowAttenuation)
|
|
||||||
{
|
|
||||||
vec3 specularColor = vec3(specular);
|
|
||||||
bool metalness = getFlag(matInfo.r, 3);
|
|
||||||
if ( metalness )
|
|
||||||
{
|
|
||||||
specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
|
|
||||||
}
|
|
||||||
|
|
||||||
//specular = color * map * spec^gloss
|
|
||||||
float specularOut = (specularColor * matInfo.b * min(pow(max(specular,1.0f), max((matInfo.a / AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
|
|
||||||
|
|
||||||
lightColor *= vec3(shadowAttenuation);
|
vec3 toLight = vec3(0);
|
||||||
lightColor += ambient.rgb;
|
for ( i = 0; i < 3; i++ )
|
||||||
return vec4(lightColor.rgb, specularOut);
|
toLight += lightVectors[i].rgb;
|
||||||
}
|
|
||||||
|
outDiffuse = vec4(albedo.rgb*(1.0-metalness),albedo.a);
|
||||||
|
outSpecular = EvalBDRF( vec3( 1.0, 1.0, 1.0 ), lightColor.rgb, toLight, wsPosition, wsNormal, smoothness, metalness );
|
||||||
|
}
|
||||||
|
|
@ -336,4 +336,20 @@ vec3 toGamma(vec3 tex)
|
||||||
}
|
}
|
||||||
#endif //
|
#endif //
|
||||||
|
|
||||||
|
vec3 PBRFresnel(vec3 albedo, vec3 indirect, float metalness, float fresnel)
|
||||||
|
{
|
||||||
|
vec3 diffuseColor = albedo - (albedo * metalness);
|
||||||
|
vec3 reflectColor = mix(indirect*albedo, indirect, fresnel);
|
||||||
|
|
||||||
|
return diffuseColor + reflectColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 simpleFresnel(vec3 diffuseColor, vec3 reflectColor, float metalness, float angle, float bias, float power)
|
||||||
|
{
|
||||||
|
float fresnelTerm = bias + (1.0 - bias) * pow(abs(1.0 - max(angle, 0)), power);
|
||||||
|
|
||||||
|
fresnelTerm *= metalness;
|
||||||
|
|
||||||
|
return mix(diffuseColor, reflectColor, fresnelTerm);
|
||||||
|
}
|
||||||
#endif // _TORQUE_GLSL_
|
#endif // _TORQUE_GLSL_
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ float Fr_DisneyDiffuse ( float NdotV , float NdotL , float LdotH , float linearR
|
||||||
float lightScatter = F_schlick( f0 , fd90 , NdotL ).r;
|
float lightScatter = F_schlick( f0 , fd90 , NdotL ).r;
|
||||||
float viewScatter = F_schlick(f0 , fd90 , NdotV ).r;
|
float viewScatter = F_schlick(f0 , fd90 , NdotV ).r;
|
||||||
|
|
||||||
return lightScatter * viewScatter * energyFactor ;
|
return lightScatter * viewScatter * energyFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SmithGGX( float NdotL, float NdotV, float alpha )
|
float SmithGGX( float NdotL, float NdotV, float alpha )
|
||||||
|
|
@ -268,4 +268,41 @@ void compute4Lights( float3 wsView,
|
||||||
|
|
||||||
outDiffuse = float4(albedo.rgb*(1.0-metalness),albedo.a);
|
outDiffuse = float4(albedo.rgb*(1.0-metalness),albedo.a);
|
||||||
outSpecular = EvalBDRF( float3( 1.0, 1.0, 1.0 ), lightColor.rgb, toLight, wsPosition, wsNormal, smoothness, metalness );
|
outSpecular = EvalBDRF( float3( 1.0, 1.0, 1.0 ), lightColor.rgb, toLight, wsPosition, wsNormal, smoothness, metalness );
|
||||||
|
}
|
||||||
|
|
||||||
|
float G1V(float dotNV, float k)
|
||||||
|
{
|
||||||
|
return 1.0f/(dotNV*(1.0f-k)+k);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 directSpecular(float3 N, float3 V, float3 L, float roughness, float F0)
|
||||||
|
{
|
||||||
|
float alpha = roughness*roughness;
|
||||||
|
|
||||||
|
//TODO don't need to calculate all this again timmy!!!!!!
|
||||||
|
float3 H = normalize(V + L);
|
||||||
|
float dotNL = clamp(dot(N,L), 0.0, 1.0);
|
||||||
|
float dotNV = clamp(dot(N,V), 0.0, 1.0);
|
||||||
|
float dotNH = clamp(dot(N,H), 0.0, 1.0);
|
||||||
|
float dotHV = clamp(dot(H,V), 0.0, 1.0);
|
||||||
|
float dotLH = clamp(dot(L,H), 0.0, 1.0);
|
||||||
|
|
||||||
|
float F, D, vis;
|
||||||
|
|
||||||
|
// D
|
||||||
|
float alphaSqr = alpha*alpha;
|
||||||
|
float pi = 3.14159f;
|
||||||
|
float denom = dotNH * dotNH *(alphaSqr-1.0) + 1.0f;
|
||||||
|
D = alphaSqr/(pi * denom * denom);
|
||||||
|
|
||||||
|
// F
|
||||||
|
float dotLH5 = pow(1.0f-dotLH,5);
|
||||||
|
F = F0 + (1.0-F0)*(dotLH5);
|
||||||
|
|
||||||
|
// V
|
||||||
|
float k = alpha/2.0f;
|
||||||
|
vis = G1V(dotNL,k)*G1V(dotNV,k);
|
||||||
|
|
||||||
|
float specular = dotNL * D * F * vis;
|
||||||
|
return float3(specular,specular,specular);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
struct ConnectData
|
||||||
|
{
|
||||||
|
float4 hpos : TORQUE_POSITION;
|
||||||
|
float2 uv : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||||
|
// efficient VanDerCorpus calculation.
|
||||||
|
float RadicalInverse_VdC(uint bits)
|
||||||
|
{
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float2 Hammersley(uint i, uint N)
|
||||||
|
{
|
||||||
|
return float2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float3 ImportanceSampleGGX(float2 Xi, float3 N, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness*roughness;
|
||||||
|
|
||||||
|
float phi = 2.0 * M_PI_F * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates - halfway vector
|
||||||
|
float3 H;
|
||||||
|
H.x = cos(phi) * sinTheta;
|
||||||
|
H.y = sin(phi) * sinTheta;
|
||||||
|
H.z = cosTheta;
|
||||||
|
|
||||||
|
// from tangent-space H vector to world-space sample vector
|
||||||
|
float3 up = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
|
||||||
|
float3 tangent = normalize(cross(up, N));
|
||||||
|
float3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
float3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
// note that we use a different k for IBL
|
||||||
|
float a = roughness;
|
||||||
|
float k = (a * a) / 2.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySmith(float3 N, float3 V, float3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float2 IntegrateBRDF(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float3 V;
|
||||||
|
V.x = sqrt(1.0 - NdotV*NdotV);
|
||||||
|
V.y = 0.0;
|
||||||
|
V.z = NdotV;
|
||||||
|
|
||||||
|
float A = 0.0;
|
||||||
|
float B = 0.0;
|
||||||
|
|
||||||
|
float3 N = float3(0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
const uint SAMPLE_COUNT = 1024u;
|
||||||
|
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
// generates a sample vector that's biased towards the
|
||||||
|
// preferred alignment direction (importance sampling).
|
||||||
|
float2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||||
|
float3 H = ImportanceSampleGGX(Xi, N, roughness);
|
||||||
|
float3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||||
|
|
||||||
|
float NdotL = max(L.z, 0.0);
|
||||||
|
float NdotH = max(H.z, 0.0);
|
||||||
|
float VdotH = max(dot(V, H), 0.0);
|
||||||
|
|
||||||
|
if(NdotL > 0.0)
|
||||||
|
{
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||||
|
float Fc = pow(1.0 - VdotH, 5.0);
|
||||||
|
|
||||||
|
A += (1.0 - Fc) * G_Vis;
|
||||||
|
B += Fc * G_Vis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
A /= float(SAMPLE_COUNT);
|
||||||
|
B /= float(SAMPLE_COUNT);
|
||||||
|
return float2(A, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||||
|
{
|
||||||
|
return float4(IntegrateBRDF(IN.uv.x, IN.uv.y).rg,0,1);
|
||||||
|
//return float2(1,1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../shaderModel.hlsl"
|
||||||
|
|
||||||
|
struct ConnectData
|
||||||
|
{
|
||||||
|
float4 hpos : TORQUE_POSITION;
|
||||||
|
float2 uv : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectData main( uint vertexID : SV_VertexID )
|
||||||
|
{
|
||||||
|
ConnectData result;
|
||||||
|
result.uv = float2((vertexID << 1) & 2, vertexID & 2);
|
||||||
|
result.hpos = float4(result.uv * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -23,11 +23,11 @@
|
||||||
#include "shadergen:/autogenConditioners.h"
|
#include "shadergen:/autogenConditioners.h"
|
||||||
#include "../../postfx/postFx.hlsl"
|
#include "../../postfx/postFx.hlsl"
|
||||||
|
|
||||||
TORQUE_UNIFORM_SAMPLER2D(indirectLightingBuffer,0);
|
TORQUE_UNIFORM_SAMPLER2D(specularLightingBuffer,0);
|
||||||
|
|
||||||
|
|
||||||
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||||
{
|
{
|
||||||
float4 directlighting = float4(TORQUE_TEX2D( indirectLightingBuffer, IN.uv0 ).rgb,1.0);
|
float4 diffuseLighting = float4(TORQUE_TEX2D( specularLightingBuffer, IN.uv0 ).rgb,1.0);
|
||||||
return directlighting;
|
return diffuseLighting;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@
|
||||||
#include "shaders/common/torque.hlsl"
|
#include "shaders/common/torque.hlsl"
|
||||||
|
|
||||||
TORQUE_UNIFORM_SAMPLER2D(colorBufferTex,0);
|
TORQUE_UNIFORM_SAMPLER2D(colorBufferTex,0);
|
||||||
TORQUE_UNIFORM_SAMPLER2D(directLightingBuffer,1);
|
TORQUE_UNIFORM_SAMPLER2D(diffuseLightingBuffer,1);
|
||||||
TORQUE_UNIFORM_SAMPLER2D(matInfoTex,2);
|
TORQUE_UNIFORM_SAMPLER2D(matInfoTex,2);
|
||||||
TORQUE_UNIFORM_SAMPLER2D(indirectLightingBuffer,3);
|
TORQUE_UNIFORM_SAMPLER2D(specularLightingBuffer,3);
|
||||||
TORQUE_UNIFORM_SAMPLER2D(deferredTex,4);
|
TORQUE_UNIFORM_SAMPLER2D(deferredTex,4);
|
||||||
|
|
||||||
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||||
|
|
@ -37,25 +37,27 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||||
if (depth>0.9999)
|
if (depth>0.9999)
|
||||||
return float4(0,0,0,0);
|
return float4(0,0,0,0);
|
||||||
|
|
||||||
float3 colorBuffer = TORQUE_TEX2D( colorBufferTex, IN.uv0 ).rgb; //albedo
|
float3 albedo = TORQUE_TEX2D( colorBufferTex, IN.uv0 ).rgb; //albedo
|
||||||
float4 matInfo = TORQUE_TEX2D(matInfoTex, IN.uv0); //flags|smoothness|ao|metallic
|
float4 matInfo = TORQUE_TEX2D(matInfoTex, IN.uv0); //flags|smoothness|ao|metallic
|
||||||
|
|
||||||
bool emissive = getFlag(matInfo.r, 0);
|
bool emissive = getFlag(matInfo.r, 0);
|
||||||
if (emissive)
|
if (emissive)
|
||||||
{
|
{
|
||||||
return float4(colorBuffer, 1.0);
|
return float4(albedo, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 directLighting = TORQUE_TEX2D( directLightingBuffer, IN.uv0 ); //shadowmap*specular
|
float4 diffuse = TORQUE_TEX2D( diffuseLightingBuffer, IN.uv0 ); //shadowmap*specular
|
||||||
float3 indirectLighting = TORQUE_TEX2D( indirectLightingBuffer, IN.uv0 ).rgb; //environment mapping*lightmaps
|
float4 specular = TORQUE_TEX2D( specularLightingBuffer, IN.uv0 ); //environment mapping*lightmaps
|
||||||
|
|
||||||
float metalness = matInfo.a;
|
float metalness = matInfo.a;
|
||||||
|
|
||||||
float frez = directLighting.a;
|
|
||||||
|
|
||||||
float3 diffuseColor = colorBuffer - (colorBuffer * metalness);
|
float3 diffuseColor = albedo - (albedo * metalness);
|
||||||
float3 reflectColor = indirectLighting*colorBuffer;
|
float3 specularColor = lerp(float3(0.04,0.04,0.04), albedo, metalness);
|
||||||
colorBuffer = diffuseColor+lerp(reflectColor,indirectLighting,frez);
|
|
||||||
colorBuffer *= max(directLighting.rgb,float3(0,0,0));
|
float3 light = (diffuseColor * diffuse.rgb) + (specularColor * specular.rgb);
|
||||||
|
|
||||||
|
//albedo = diffuseColor+lerp(reflectColor,indiffuseLighting,frez);
|
||||||
|
//albedo *= max(diffuseLighting.rgb,float3(0,0,0));
|
||||||
|
|
||||||
return hdrEncode( float4(colorBuffer.rgb, 1.0) );
|
return float4(light.rgb, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../../gl/hlslCompat.glsl"
|
||||||
|
out vec2 uv;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uv = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);
|
||||||
|
gl_Position = vec4(uv * vec2(2.0f, -2.0f) + vec2(-1.0f, 1.0f), 0.0f, 1.0f);
|
||||||
|
correctSSP(gl_Position);
|
||||||
|
}
|
||||||
|
|
@ -24,12 +24,12 @@
|
||||||
#include "shadergen:/autogenConditioners.h"
|
#include "shadergen:/autogenConditioners.h"
|
||||||
|
|
||||||
in vec2 uv0;
|
in vec2 uv0;
|
||||||
uniform sampler2D directLightingBuffer;
|
uniform sampler2D diffuseLightingBuffer;
|
||||||
|
|
||||||
out vec4 OUT_col;
|
out vec4 OUT_col;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 directLighting = vec4(texture( directLightingBuffer, uv0 ).rgb,1.0);
|
vec4 diffuseLighting = vec4(texture( diffuseLightingBuffer, uv0 ).rgb,1.0);
|
||||||
OUT_col = directLighting;
|
OUT_col = diffuseLighting;
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
out vec4 OUT_col;
|
out vec4 OUT_col;
|
||||||
out vec4 OUT_col1;
|
out vec4 OUT_col1;
|
||||||
out vec4 OUT_col2;
|
out vec4 OUT_col2;
|
||||||
|
out vec4 OUT_col3;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Main
|
// Main
|
||||||
|
|
@ -33,8 +34,11 @@ void main()
|
||||||
OUT_col = vec4(1.0, 1.0, 1.0, 1.0);
|
OUT_col = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
// Clear Color Buffer.
|
// Clear Color Buffer.
|
||||||
OUT_col1 = vec4(0.0, 0.0, 0.0, 1.0);
|
OUT_col1 = vec4(0.0, 0.0, 0.0, 0.0001);
|
||||||
|
|
||||||
// Clear Material Info Buffer.
|
// Clear Material Info Buffer.
|
||||||
OUT_col2 = vec4(0.0, 0.0, 0.0, 1.0);
|
OUT_col2 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
// Clear Light Info Buffer.
|
||||||
|
OUT_col3 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,9 @@
|
||||||
#include "../../../gl/torque.glsl"
|
#include "../../../gl/torque.glsl"
|
||||||
|
|
||||||
uniform sampler2D colorBufferTex;
|
uniform sampler2D colorBufferTex;
|
||||||
uniform sampler2D lightDeferredTex;
|
uniform sampler2D diffuseLightingBuffer;
|
||||||
uniform sampler2D matInfoTex;
|
uniform sampler2D matInfoTex;
|
||||||
|
uniform sampler2D specularLightingBuffer;
|
||||||
uniform sampler2D deferredTex;
|
uniform sampler2D deferredTex;
|
||||||
|
|
||||||
out vec4 OUT_col;
|
out vec4 OUT_col;
|
||||||
|
|
@ -40,20 +41,27 @@ void main()
|
||||||
OUT_col = vec4(0.0);
|
OUT_col = vec4(0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vec4 lightBuffer = texture( lightDeferredTex, uv0 );
|
|
||||||
vec4 colorBuffer = texture( colorBufferTex, uv0 );
|
vec3 colorBuffer = texture( colorBufferTex, uv0 ).rgb; //albedo
|
||||||
vec4 matInfo = texture( matInfoTex, uv0 );
|
vec4 matInfo = texture( matInfoTex, uv0 ); //flags|smoothness|ao|metallic
|
||||||
float specular = clamp(lightBuffer.a,0.0,1.0);
|
bool emissive = getFlag(matInfo.r, 0);
|
||||||
|
if (emissive)
|
||||||
// Diffuse Color Altered by Metalness
|
|
||||||
bool metalness = getFlag(matInfo.r, 3);
|
|
||||||
if ( metalness )
|
|
||||||
{
|
{
|
||||||
colorBuffer *= (1.0 - colorBuffer.a);
|
OUT_col = float4(colorBuffer, 1.0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
colorBuffer += vec4(specular, specular, specular, 1.0);
|
vec4 diffuseLighting = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
|
||||||
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
|
|
||||||
|
vec3 specularLighting = texture( specularLightingBuffer, uv0 ).rgb; //environment mapping*lightmaps
|
||||||
OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) );
|
float metalness = matInfo.a;
|
||||||
|
|
||||||
|
float frez = diffuseLighting.a;
|
||||||
|
|
||||||
|
vec3 diffuseColor = colorBuffer - (colorBuffer * metalness);
|
||||||
|
vec3 reflectColor = specularLighting*colorBuffer;
|
||||||
|
colorBuffer = diffuseColor+lerp(reflectColor,specularLighting,frez);
|
||||||
|
colorBuffer *= max(diffuseLighting.rgb,vec3(0,0,0));
|
||||||
|
|
||||||
|
OUT_col = hdrEncode(vec4(colorBuffer,1.0));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../../gl/torque.glsl"
|
||||||
|
|
||||||
|
in vec2 uv;
|
||||||
|
uniform int face;
|
||||||
|
|
||||||
|
uniform samplerCube environmentMap;
|
||||||
|
|
||||||
|
out vec4 outColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 N = getCubeDir(face, uv);
|
||||||
|
vec3 irradiance = vec3(0.0);
|
||||||
|
|
||||||
|
// tangent space calculation from origin point
|
||||||
|
vec3 up = vec3(0.0, 0.0, 1.0);
|
||||||
|
vec3 right = cross(up, N);
|
||||||
|
up = cross(N, right);
|
||||||
|
|
||||||
|
float sampleDelta = 0.025;
|
||||||
|
int nrSamples = 0;
|
||||||
|
for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
|
||||||
|
{
|
||||||
|
for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
|
||||||
|
{
|
||||||
|
// spherical to cartesian (in tangent space)
|
||||||
|
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||||
|
// tangent space to world
|
||||||
|
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||||
|
|
||||||
|
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
||||||
|
nrSamples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
|
||||||
|
|
||||||
|
outColor = vec4(irradiance, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -138,8 +138,9 @@ void main()
|
||||||
vec3 ssPos = ssPos.xyz / ssPos.w;
|
vec3 ssPos = ssPos.xyz / ssPos.w;
|
||||||
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
// Emissive.
|
// Matinfo flags
|
||||||
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
||||||
|
//early out if emissive
|
||||||
bool emissive = getFlag( matInfo.r, 0 );
|
bool emissive = getFlag( matInfo.r, 0 );
|
||||||
if ( emissive )
|
if ( emissive )
|
||||||
{
|
{
|
||||||
|
|
@ -245,12 +246,17 @@ void main()
|
||||||
// cause the hardware occlusion query to disable the shadow.
|
// cause the hardware occlusion query to disable the shadow.
|
||||||
|
|
||||||
// Specular term
|
// Specular term
|
||||||
float specular = AL_CalcSpecular( lightVec,
|
float specular = 0;
|
||||||
normal,
|
vec4 real_specular = EvalBDRF( colorSample.rgb,
|
||||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
lightcol,
|
||||||
|
lightVec,
|
||||||
|
viewSpacePos,
|
||||||
|
normal,
|
||||||
|
1.05-matInfo.b*0.9, //slightly compress roughness to allow for non-baked lighting
|
||||||
|
matInfo.a );
|
||||||
|
vec3 lightColorOut = real_specular.rgb * lightBrightness * shadowed* atten;
|
||||||
|
|
||||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||||
vec3 lightColorOut = lightMapParams.rgb * lightcol;
|
|
||||||
vec4 addToResult = vec4(0.0);
|
vec4 addToResult = vec4(0.0);
|
||||||
|
|
||||||
// TODO: This needs to be removed when lightmapping is disabled
|
// TODO: This needs to be removed when lightmapping is disabled
|
||||||
|
|
@ -269,5 +275,5 @@ void main()
|
||||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
OUT_col = vec4((lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../../gl/hlslCompat.glsl"
|
||||||
|
#include "shadergen:/autogenConditioners.h"
|
||||||
|
#include "../../../postFx/gl/postFX.glsl"
|
||||||
|
#include "../../../gl/torque.glsl"
|
||||||
|
|
||||||
|
uniform sampler2D colorBufferTex;
|
||||||
|
uniform sampler2D diffuseLightingBuffer;
|
||||||
|
uniform sampler2D matInfoTex;
|
||||||
|
uniform sampler2D specularLightingBuffer;
|
||||||
|
uniform sampler2D deferredTex;
|
||||||
|
|
||||||
|
out vec4 OUT_col;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float depth = deferredUncondition( deferredTex, uv0 ).w;
|
||||||
|
if (depth>0.9999)
|
||||||
|
{
|
||||||
|
OUT_col = vec4(0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 colorBuffer = texture( colorBufferTex, uv0 ).rgb; //albedo
|
||||||
|
vec4 matInfo = texture( matInfoTex, uv0 ); //flags|smoothness|ao|metallic
|
||||||
|
bool emissive = getFlag(matInfo.r, 0);
|
||||||
|
if (emissive)
|
||||||
|
{
|
||||||
|
OUT_col = float4(colorBuffer, 1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 diffuseLighting = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
|
||||||
|
|
||||||
|
colorBuffer *= max(diffuseLighting.rgb,vec3(0,0,0));
|
||||||
|
|
||||||
|
OUT_col = hdrEncode(vec4(colorBuffer,1.0));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
#include "../../../gl/hlslCompat.glsl"
|
||||||
|
#include "shadergen:/autogenConditioners.h"
|
||||||
|
|
||||||
|
#include "farFrustumQuad.glsl"
|
||||||
|
#include "lightingUtils.glsl"
|
||||||
|
#include "../../../gl/lighting.glsl"
|
||||||
|
#include "../../../gl/torque.glsl"
|
||||||
|
#line 8
|
||||||
|
|
||||||
|
in vec4 pos;
|
||||||
|
in vec4 wsEyeDir;
|
||||||
|
in vec4 ssPos;
|
||||||
|
in vec4 vsEyeDir;
|
||||||
|
|
||||||
|
uniform sampler2D deferredBuffer;
|
||||||
|
uniform sampler2D matInfoBuffer;
|
||||||
|
uniform samplerCube cubeMap;
|
||||||
|
|
||||||
|
uniform vec4 rtParams0;
|
||||||
|
|
||||||
|
uniform vec3 probeWSPos;
|
||||||
|
uniform vec3 probeLSPos;
|
||||||
|
uniform vec4 vsFarPlane;
|
||||||
|
|
||||||
|
uniform float lightRange;
|
||||||
|
uniform vec2 lightAttenuation;
|
||||||
|
|
||||||
|
uniform mat4 invViewMat;
|
||||||
|
|
||||||
|
uniform vec3 eyePosWorld;
|
||||||
|
uniform vec3 bbMin;
|
||||||
|
uniform vec3 bbMax;
|
||||||
|
|
||||||
|
uniform float Intensity;
|
||||||
|
|
||||||
|
//SHTerms
|
||||||
|
uniform vec4 SHTerms0;
|
||||||
|
uniform vec4 SHTerms1;
|
||||||
|
uniform vec4 SHTerms2;
|
||||||
|
uniform vec4 SHTerms3;
|
||||||
|
uniform vec4 SHTerms4;
|
||||||
|
uniform vec4 SHTerms5;
|
||||||
|
uniform vec4 SHTerms6;
|
||||||
|
uniform vec4 SHTerms7;
|
||||||
|
uniform vec4 SHTerms8;
|
||||||
|
|
||||||
|
uniform float SHConsts0;
|
||||||
|
uniform float SHConsts1;
|
||||||
|
uniform float SHConsts2;
|
||||||
|
uniform float SHConsts3;
|
||||||
|
uniform float SHConsts4;
|
||||||
|
|
||||||
|
uniform float useSphereMode;
|
||||||
|
|
||||||
|
vec4 decodeSH(vec3 normal)
|
||||||
|
{
|
||||||
|
float x = normal.x;
|
||||||
|
float y = normal.y;
|
||||||
|
float z = normal.z;
|
||||||
|
|
||||||
|
vec3 l00 = SHTerms0.rgb;
|
||||||
|
|
||||||
|
vec3 l10 = SHTerms1.rgb;
|
||||||
|
vec3 l11 = SHTerms2.rgb;
|
||||||
|
vec3 l12 = SHTerms3.rgb;
|
||||||
|
|
||||||
|
vec3 l20 = SHTerms4.rgb;
|
||||||
|
vec3 l21 = SHTerms5.rgb;
|
||||||
|
vec3 l22 = SHTerms6.rgb;
|
||||||
|
vec3 l23 = SHTerms7.rgb;
|
||||||
|
vec3 l24 = SHTerms8.rgb;
|
||||||
|
|
||||||
|
vec3 result = (
|
||||||
|
l00 * SHConsts0 +
|
||||||
|
|
||||||
|
l12 * SHConsts1 * x +
|
||||||
|
l10 * SHConsts1 * y +
|
||||||
|
l11 * SHConsts1 * z +
|
||||||
|
|
||||||
|
l20 * SHConsts2 * x*y +
|
||||||
|
l21 * SHConsts2 * y*z +
|
||||||
|
l22 * SHConsts3 * (3.0*z*z - 1.0) +
|
||||||
|
l23 * SHConsts2 * x*z +
|
||||||
|
l24 * SHConsts4 * (x*x - y*y)
|
||||||
|
);
|
||||||
|
|
||||||
|
return vec4(result,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
out vec4 OUT_col;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Compute scene UV
|
||||||
|
vec3 ssPos = ssPos.xyz / ssPos.w;
|
||||||
|
|
||||||
|
//vec4 hardCodedRTParams0 = vec4(0,0.0277777780,1,0.972222209);
|
||||||
|
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
|
// Matinfo flags
|
||||||
|
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
||||||
|
|
||||||
|
// Sample/unpack the normal/z data
|
||||||
|
vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene );
|
||||||
|
vec3 normal = deferredSample.rgb;
|
||||||
|
float depth = deferredSample.a;
|
||||||
|
if (depth>0.9999)
|
||||||
|
OUT_col = vec4(0,0,0,0);
|
||||||
|
|
||||||
|
// Need world-space normal.
|
||||||
|
vec3 wsNormal = tMul(vec4(normal, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
vec4 color = vec4(1, 1, 1, 1);
|
||||||
|
vec4 ref = vec4(0,0,0,0);
|
||||||
|
float alpha = 0;
|
||||||
|
|
||||||
|
vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||||
|
vec3 viewSpacePos = eyeRay * depth;
|
||||||
|
|
||||||
|
vec3 wsEyeRay = tMul(vec4(eyeRay, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
// Use eye ray to get ws pos
|
||||||
|
vec3 worldPos = vec3(eyePosWorld + wsEyeRay * depth);
|
||||||
|
float smoothness = min((1.0 - matInfo.b)*11.0 + 1.0, 8.0);//bump up to 8 for finalization
|
||||||
|
|
||||||
|
if(useSphereMode>0.0)
|
||||||
|
{
|
||||||
|
// Eye ray - Eye -> Pixel
|
||||||
|
|
||||||
|
|
||||||
|
// Build light vec, get length, clip pixel if needed
|
||||||
|
vec3 lightVec = probeLSPos - viewSpacePos;
|
||||||
|
float lenLightV = length( lightVec );
|
||||||
|
clip( lightRange - lenLightV );
|
||||||
|
|
||||||
|
// Get the attenuated falloff.
|
||||||
|
float atten = attenuate( vec4(1,1,1,1), lightAttenuation, lenLightV );
|
||||||
|
clip( atten - 1e-6 );
|
||||||
|
|
||||||
|
// Normalize lightVec
|
||||||
|
lightVec /= lenLightV;
|
||||||
|
|
||||||
|
// If we can do dynamic branching then avoid wasting
|
||||||
|
// fillrate on pixels that are backfacing to the light.
|
||||||
|
float nDotL = abs(dot( lightVec, normal ));
|
||||||
|
|
||||||
|
float Sat_NL_Att = saturate( nDotL * atten );
|
||||||
|
|
||||||
|
vec3 reflectionVec = reflect(wsEyeDir, vec4(wsNormal,nDotL)).xyz;
|
||||||
|
|
||||||
|
vec3 nrdir = normalize(reflectionVec);
|
||||||
|
vec3 rbmax = (bbMax - worldPos.xyz) / nrdir;
|
||||||
|
vec3 rbmin = (bbMin - worldPos.xyz) / nrdir;
|
||||||
|
|
||||||
|
vec3 rbminmax = rbmin;
|
||||||
|
if (nrdir.x > 0.0)
|
||||||
|
rbminmax.x = rbmax.x;
|
||||||
|
if (nrdir.y > 0.0)
|
||||||
|
rbminmax.y = rbmax.y;
|
||||||
|
if (nrdir.z > 0.0)
|
||||||
|
rbminmax.z = rbmax.z;
|
||||||
|
|
||||||
|
float fa = min(min(rbminmax.x,rbminmax.y),rbminmax.z);
|
||||||
|
if (dot( lightVec, normal )<0.0f)
|
||||||
|
clip(fa);
|
||||||
|
|
||||||
|
vec3 posOnBox = worldPos.xyz + nrdir * fa;
|
||||||
|
reflectionVec = posOnBox - probeWSPos;
|
||||||
|
|
||||||
|
//reflectionVec = tMul(probeWSPos,reflectionVec);
|
||||||
|
|
||||||
|
ref = vec4(reflectionVec, smoothness);
|
||||||
|
|
||||||
|
alpha = Sat_NL_Att;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Build light vec, get length, clip pixel if needed
|
||||||
|
vec3 lightVec = probeLSPos - viewSpacePos;
|
||||||
|
float lenLightV = length(lightVec);
|
||||||
|
//clip(lightRange - lenLightV);
|
||||||
|
|
||||||
|
// Normalize lightVec
|
||||||
|
lightVec /= lenLightV;
|
||||||
|
|
||||||
|
// If we can do dynamic branching then avoid wasting
|
||||||
|
// fillrate on pixels that are backfacing to the light.
|
||||||
|
float nDotL = abs(dot(lightVec, normal));
|
||||||
|
|
||||||
|
vec3 reflectionVec = reflect(wsEyeDir, vec4(wsNormal, nDotL)).xyz;
|
||||||
|
|
||||||
|
vec3 nrdir = normalize(reflectionVec);
|
||||||
|
vec3 rbmax = (bbMax - worldPos.xyz) / nrdir;
|
||||||
|
vec3 rbmin = (bbMin - worldPos.xyz) / nrdir;
|
||||||
|
|
||||||
|
vec3 rbminmax = rbmin;
|
||||||
|
if (nrdir.x > 0.0)
|
||||||
|
rbminmax.x = rbmax.x;
|
||||||
|
if (nrdir.y > 0.0)
|
||||||
|
rbminmax.y = rbmax.y;
|
||||||
|
if (nrdir.z > 0.0)
|
||||||
|
rbminmax.z = rbmax.z;
|
||||||
|
|
||||||
|
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
||||||
|
if (dot(lightVec, normal)<0.0f)
|
||||||
|
clip(fa);
|
||||||
|
|
||||||
|
//Try to clip anything that falls outside our box as well
|
||||||
|
//TODO: Make it support rotated boxes as well
|
||||||
|
if(worldPos.x > bbMax.x || worldPos.y > bbMax.y || worldPos.z > bbMax.z ||
|
||||||
|
worldPos.x < bbMin.x || worldPos.y < bbMin.y || worldPos.z < bbMin.z)
|
||||||
|
clip(-1);
|
||||||
|
|
||||||
|
vec3 posOnBox = worldPos.xyz + nrdir * fa;
|
||||||
|
reflectionVec = posOnBox - probeWSPos;
|
||||||
|
|
||||||
|
ref = vec4(reflectionVec, smoothness);
|
||||||
|
|
||||||
|
alpha = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = textureLod(cubeMap, vec3(ref.xyz), float(ref.w));
|
||||||
|
|
||||||
|
vec4 specularColor = (color);
|
||||||
|
vec4 indirectColor = (decodeSH(wsNormal));
|
||||||
|
|
||||||
|
color.rgb = lerp(indirectColor.rgb * 1.5, specularColor.rgb * 1.5, matInfo.b);
|
||||||
|
|
||||||
|
OUT_col = vec4(color.rgb, alpha);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "shadergen:/autogenConditioners.h"
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
// This is the shader input
|
||||||
|
struct Vert
|
||||||
|
{
|
||||||
|
float4 position : POSITION;
|
||||||
|
float2 uv0 : TEXCOORD0;
|
||||||
|
float3 wsEyeRay : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is the shader output data.
|
||||||
|
struct Conn
|
||||||
|
{
|
||||||
|
float4 position : POSITION;
|
||||||
|
float2 uv0 : TEXCOORD0;
|
||||||
|
float3 wsEyeRay : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render Target Paramaters
|
||||||
|
float4 rtParams0;
|
||||||
|
|
||||||
|
Conn main(Vert IN,
|
||||||
|
uniform float4x4 modelView : register(C0))
|
||||||
|
{
|
||||||
|
Conn OUT;
|
||||||
|
OUT.position = IN.position;
|
||||||
|
OUT.uv0 = viewportCoordToRenderTarget( IN.uv0, rtParams0 );
|
||||||
|
OUT.wsEyeRay = IN.wsEyeRay;
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -80,12 +80,13 @@ void main()
|
||||||
vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
|
vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
|
||||||
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
// Emissive.
|
// Matinfo flags
|
||||||
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
||||||
|
//early out if emissive
|
||||||
bool emissive = getFlag( matInfo.r, 0 );
|
bool emissive = getFlag( matInfo.r, 0 );
|
||||||
if ( emissive )
|
if ( emissive )
|
||||||
{
|
{
|
||||||
OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
|
OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,12 +183,19 @@ void main()
|
||||||
// cause the hardware occlusion query to disable the shadow.
|
// cause the hardware occlusion query to disable the shadow.
|
||||||
|
|
||||||
// Specular term
|
// Specular term
|
||||||
float specular = AL_CalcSpecular( -lightToPxlVec,
|
float specular = 0;
|
||||||
normal,
|
|
||||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
|
||||||
|
|
||||||
|
vec3 lightVec = lightPosition - viewSpacePos;
|
||||||
|
vec4 real_specular = EvalBDRF( colorSample.rgb,
|
||||||
|
lightcol,
|
||||||
|
lightVec,
|
||||||
|
viewSpacePos,
|
||||||
|
normal,
|
||||||
|
1.05-matInfo.b*0.9, //slightly compress roughness to allow for non-baked lighting
|
||||||
|
matInfo.a );
|
||||||
|
vec3 lightColorOut = real_specular.rgb * lightBrightness * shadowed* atten;
|
||||||
|
|
||||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||||
vec3 lightColorOut = lightMapParams.rgb * lightcol;
|
|
||||||
vec4 addToResult = vec4(0.0);
|
vec4 addToResult = vec4(0.0);
|
||||||
|
|
||||||
// TODO: This needs to be removed when lightmapping is disabled
|
// TODO: This needs to be removed when lightmapping is disabled
|
||||||
|
|
@ -206,5 +214,5 @@ void main()
|
||||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
OUT_col = vec4((lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,12 +193,13 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
|
||||||
out vec4 OUT_col;
|
out vec4 OUT_col;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Emissive.
|
// Matinfo flags
|
||||||
float4 matInfo = texture( matInfoBuffer, uv0 );
|
float4 matInfo = texture( matInfoBuffer, uv0 );
|
||||||
|
//early out if emissive
|
||||||
bool emissive = getFlag( matInfo.r, 0 );
|
bool emissive = getFlag( matInfo.r, 0 );
|
||||||
if ( emissive )
|
if ( emissive )
|
||||||
{
|
{
|
||||||
OUT_col = vec4(1.0, 1.0, 1.0, 0.0);
|
OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,29 +290,20 @@ void main()
|
||||||
|
|
||||||
#endif // !NO_SHADOW
|
#endif // !NO_SHADOW
|
||||||
|
|
||||||
// Specular term
|
// Specular term
|
||||||
float specular = AL_CalcSpecular( -lightDirection,
|
vec3 viewSpacePos = vsEyeRay * depth;
|
||||||
normal,
|
vec4 real_specular = EvalBDRF( colorSample.rgb,
|
||||||
normalize(-vsEyeRay) ) * lightBrightness * shadowed;
|
lightColor.rgb,
|
||||||
|
normalize( -lightDirection ),
|
||||||
|
viewSpacePos,
|
||||||
|
normal,
|
||||||
|
1.0-matInfo.b,
|
||||||
|
matInfo.a );
|
||||||
|
vec3 lightColorOut = real_specular.rgb * lightBrightness * shadowed;
|
||||||
|
|
||||||
float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
|
float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
|
||||||
vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
|
float Sat_NdotV = saturate(dot(normalize(-vsEyeRay), normal));
|
||||||
vec4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-vsEyeRay), normal)) );
|
vec4 addToResult = ( lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * Sat_NdotV );
|
||||||
|
|
||||||
// TODO: This needs to be removed when lightmapping is disabled
|
|
||||||
// as its extra work per-pixel on dynamic lit scenes.
|
|
||||||
//
|
|
||||||
// Special lightmapping pass.
|
|
||||||
if ( lightMapParams.a < 0.0 )
|
|
||||||
{
|
|
||||||
// This disables shadows on the backsides of objects.
|
|
||||||
shadowed = dotNL < 0.0f ? 1.0f : shadowed;
|
|
||||||
|
|
||||||
Sat_NL_Att = 1.0f;
|
|
||||||
lightColorOut = vec3(shadowed);
|
|
||||||
specular *= lightBrightness;
|
|
||||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sample the AO texture.
|
// Sample the AO texture.
|
||||||
#ifdef USE_SSAO_MASK
|
#ifdef USE_SSAO_MASK
|
||||||
|
|
@ -323,5 +315,5 @@ void main()
|
||||||
lightColorOut = debugColor;
|
lightColorOut = debugColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
OUT_col = vec4(matInfo.g*(lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
struct ConnectData
|
||||||
|
{
|
||||||
|
float4 hpos : TORQUE_POSITION;
|
||||||
|
float2 uv : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform int face;
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
|
||||||
|
|
||||||
|
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||||
|
{
|
||||||
|
float3 N = getCubeDir(face,IN.uv);
|
||||||
|
float3 irradiance = 0;
|
||||||
|
|
||||||
|
// tangent space calculation from origin point
|
||||||
|
float3 up = float3(0.0, 0.0, 1.0);
|
||||||
|
float3 right = cross(up, N);
|
||||||
|
up = cross(N, right);
|
||||||
|
|
||||||
|
float sampleDelta = 0.025;
|
||||||
|
int nrSamples = 0;
|
||||||
|
for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
|
||||||
|
{
|
||||||
|
for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
|
||||||
|
{
|
||||||
|
// spherical to cartesian (in tangent space)
|
||||||
|
float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||||
|
// tangent space to world
|
||||||
|
float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||||
|
|
||||||
|
irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
||||||
|
nrSamples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
|
||||||
|
|
||||||
|
return float4(irradiance, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -136,48 +136,58 @@ uniform float2 lightAttenuation;
|
||||||
uniform float3x3 viewToLightProj;
|
uniform float3x3 viewToLightProj;
|
||||||
uniform float3x3 dynamicViewToLightProj;
|
uniform float3x3 dynamicViewToLightProj;
|
||||||
|
|
||||||
float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
struct PS_OUTPUT
|
||||||
{
|
{
|
||||||
|
float4 diffuse: TORQUE_TARGET0;
|
||||||
|
float4 spec: TORQUE_TARGET1;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_OUTPUT main(ConvexConnectP IN)
|
||||||
|
{
|
||||||
|
PS_OUTPUT Output = (PS_OUTPUT)0;
|
||||||
|
|
||||||
// Compute scene UV
|
// Compute scene UV
|
||||||
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||||
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
float2 uvScene = getUVFromSSPos(ssPos, rtParams0);
|
||||||
|
|
||||||
// Matinfo flags
|
// Matinfo flags
|
||||||
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );
|
float4 matInfo = TORQUE_TEX2D(matInfoBuffer, uvScene);
|
||||||
//early out if emissive
|
//early out if emissive
|
||||||
bool emissive = getFlag(matInfo.r, 0);
|
bool emissive = getFlag(matInfo.r, 0);
|
||||||
if (emissive)
|
if (emissive)
|
||||||
{
|
{
|
||||||
return float4(0.0, 0.0, 0.0, 0.0);
|
//return float4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
return Output;
|
||||||
}
|
}
|
||||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
|
||||||
float3 subsurface = float3(0.0,0.0,0.0);
|
float4 colorSample = TORQUE_TEX2D(colorBuffer, uvScene);
|
||||||
if (getFlag( matInfo.r, 1 ))
|
float3 subsurface = float3(0.0, 0.0, 0.0);
|
||||||
|
if (getFlag(matInfo.r, 1))
|
||||||
{
|
{
|
||||||
subsurface = colorSample.rgb;
|
subsurface = colorSample.rgb;
|
||||||
if (colorSample.r>colorSample.g)
|
if (colorSample.r > colorSample.g)
|
||||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||||
else
|
else
|
||||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sample/unpack the normal/z data
|
// Sample/unpack the normal/z data
|
||||||
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
|
||||||
float3 normal = deferredSample.rgb;
|
float3 normal = deferredSample.rgb;
|
||||||
float depth = deferredSample.a;
|
float depth = deferredSample.a;
|
||||||
|
|
||||||
// Eye ray - Eye -> Pixel
|
// Eye ray - Eye -> Pixel
|
||||||
float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
float3 eyeRay = getDistanceVectorToPlane(-vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane);
|
||||||
float3 viewSpacePos = eyeRay * depth;
|
float3 viewSpacePos = eyeRay * depth;
|
||||||
|
|
||||||
// Build light vec, get length, clip pixel if needed
|
// Build light vec, get length, clip pixel if needed
|
||||||
float3 lightVec = lightPosition - viewSpacePos;
|
float3 lightVec = lightPosition - viewSpacePos;
|
||||||
float lenLightV = length( lightVec );
|
float lenLightV = length(lightVec);
|
||||||
clip( lightRange - lenLightV );
|
clip(lightRange - lenLightV);
|
||||||
|
|
||||||
// Get the attenuated falloff.
|
// Get the attenuated falloff.
|
||||||
float atten = attenuate( lightColor, lightAttenuation, lenLightV );
|
float atten = attenuate(lightColor, lightAttenuation, lenLightV);
|
||||||
clip( atten - 1e-6 );
|
clip(atten - 1e-6);
|
||||||
|
|
||||||
// Normalize lightVec
|
// Normalize lightVec
|
||||||
lightVec /= lenLightV;
|
lightVec /= lenLightV;
|
||||||
|
|
@ -187,97 +197,93 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
||||||
float nDotL = dot( lightVec, normal );
|
float nDotL = dot( lightVec, normal );
|
||||||
//DB_CLIP( nDotL < 0 );
|
//DB_CLIP( nDotL < 0 );
|
||||||
|
|
||||||
#ifdef NO_SHADOW
|
#ifdef NO_SHADOW
|
||||||
|
|
||||||
float shadowed = 1.0;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Get a linear depth from the light source.
|
float shadowed = 1.0;
|
||||||
float distToLight = lenLightV / lightRange;
|
|
||||||
|
|
||||||
#ifdef SHADOW_CUBE
|
#else
|
||||||
|
|
||||||
// TODO: We need to fix shadow cube to handle soft shadows!
|
|
||||||
float occ = TORQUE_TEXCUBE( shadowMap, mul( viewToLightProj, -lightVec ) ).r;
|
|
||||||
float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Static
|
// Get a linear depth from the light source.
|
||||||
float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
|
float distToLight = lenLightV / lightRange;
|
||||||
float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
|
||||||
ssPos.xy,
|
|
||||||
shadowCoord,
|
|
||||||
shadowSoftness,
|
|
||||||
distToLight,
|
|
||||||
nDotL,
|
|
||||||
lightParams.y );
|
|
||||||
|
|
||||||
// Dynamic
|
#ifdef SHADOW_CUBE
|
||||||
float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy;
|
|
||||||
float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
|
||||||
ssPos.xy,
|
|
||||||
dynamicShadowCoord,
|
|
||||||
shadowSoftness,
|
|
||||||
distToLight,
|
|
||||||
nDotL,
|
|
||||||
lightParams.y );
|
|
||||||
|
|
||||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
// TODO: We need to fix shadow cube to handle soft shadows!
|
||||||
|
float occ = TORQUE_TEXCUBE(shadowMap, mul(viewToLightProj, -lightVec)).r;
|
||||||
|
float shadowed = saturate(exp(lightParams.y * (occ - distToLight)));
|
||||||
|
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
|
// Static
|
||||||
|
float2 shadowCoord = decodeShadowCoord(mul(viewToLightProj, -lightVec)).xy;
|
||||||
|
float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
||||||
|
ssPos.xy,
|
||||||
|
shadowCoord,
|
||||||
|
shadowSoftness,
|
||||||
|
distToLight,
|
||||||
|
nDotL,
|
||||||
|
lightParams.y);
|
||||||
|
|
||||||
|
// Dynamic
|
||||||
|
float2 dynamicShadowCoord = decodeShadowCoord(mul(dynamicViewToLightProj, -lightVec)).xy;
|
||||||
|
float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
||||||
|
ssPos.xy,
|
||||||
|
dynamicShadowCoord,
|
||||||
|
shadowSoftness,
|
||||||
|
distToLight,
|
||||||
|
nDotL,
|
||||||
|
lightParams.y);
|
||||||
|
|
||||||
|
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !NO_SHADOW
|
||||||
|
|
||||||
#endif // !NO_SHADOW
|
|
||||||
|
|
||||||
float3 lightcol = lightColor.rgb;
|
float3 lightcol = lightColor.rgb;
|
||||||
#ifdef USE_COOKIE_TEX
|
#ifdef USE_COOKIE_TEX
|
||||||
|
|
||||||
// Lookup the cookie sample.
|
// Lookup the cookie sample.
|
||||||
float4 cookie = TORQUE_TEXCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
|
float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(viewToLightProj, -lightVec));
|
||||||
|
|
||||||
// Multiply the light with the cookie tex.
|
// Multiply the light with the cookie tex.
|
||||||
lightcol *= cookie.rgb;
|
lightcol *= cookie.rgb;
|
||||||
|
|
||||||
// Use a maximum channel luminance to attenuate
|
// Use a maximum channel luminance to attenuate
|
||||||
// the lighting else we get specular in the dark
|
// the lighting else we get specular in the dark
|
||||||
// regions of the cookie texture.
|
// regions of the cookie texture.
|
||||||
atten *= max( cookie.r, max( cookie.g, cookie.b ) );
|
atten *= max(cookie.r, max(cookie.g, cookie.b));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NOTE: Do not clip on fully shadowed pixels as it would
|
// NOTE: Do not clip on fully shadowed pixels as it would
|
||||||
// cause the hardware occlusion query to disable the shadow.
|
// cause the hardware occlusion query to disable the shadow.
|
||||||
|
|
||||||
// Specular term
|
float3 l = lightVec;// normalize(-lightDirection);
|
||||||
float specular = 0;
|
float3 v = eyeRay;// normalize(eyePosWorld - worldPos.xyz);
|
||||||
|
|
||||||
float4 real_specular = EvalBDRF( float3( 1.0, 1.0, 1.0 ),
|
|
||||||
lightcol,
|
|
||||||
lightVec,
|
|
||||||
viewSpacePos,
|
|
||||||
normal,
|
|
||||||
1.0-matInfo.b,
|
|
||||||
matInfo.a );
|
|
||||||
float3 lightColorOut = real_specular.rgb * lightBrightness * shadowed* atten;
|
|
||||||
//lightColorOut /= colorSample.rgb;
|
|
||||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
|
||||||
float4 addToResult = 0.0;
|
|
||||||
|
|
||||||
// TODO: This needs to be removed when lightmapping is disabled
|
|
||||||
// as its extra work per-pixel on dynamic lit scenes.
|
|
||||||
//
|
|
||||||
// Special lightmapping pass.
|
|
||||||
if ( lightMapParams.a < 0.0 )
|
|
||||||
{
|
|
||||||
// This disables shadows on the backsides of objects.
|
|
||||||
shadowed = nDotL < 0.0f ? 1.0f : shadowed;
|
|
||||||
|
|
||||||
Sat_NL_Att = 1.0f;
|
float3 h = normalize(v + l);
|
||||||
shadowed = lerp( 1.0f, shadowed, atten );
|
float dotNLa = clamp(dot(normal, l), 0.0, 1.0);
|
||||||
lightColorOut = shadowed;
|
float dotNVa = clamp(dot(normal, v), 0.0, 1.0);
|
||||||
specular *= lightBrightness;
|
float dotNHa = clamp(dot(normal, h), 0.0, 1.0);
|
||||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
float dotHVa = clamp(dot(normal, v), 0.0, 1.0);
|
||||||
}
|
float dotLHa = clamp(dot(l, h), 0.0, 1.0);
|
||||||
return float4((lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a);
|
|
||||||
|
float roughness = matInfo.g;
|
||||||
|
float metalness = matInfo.b;
|
||||||
|
|
||||||
|
//diffuse
|
||||||
|
float disDiff = Fr_DisneyDiffuse(dotNVa, dotNLa, dotLHa, roughness);
|
||||||
|
float3 diffuse = float3(disDiff, disDiff, disDiff) / M_PI_F;// alternative: (lightColor * dotNL) / Pi;
|
||||||
|
//specular
|
||||||
|
float3 specular = directSpecular(normal, v, l, roughness, 1.0) * lightColor.rgb;
|
||||||
|
|
||||||
|
|
||||||
|
if (nDotL<0) shadowed = 0;
|
||||||
|
float Sat_NL_Att = saturate( nDotL * shadowed ) * lightBrightness;
|
||||||
|
//output
|
||||||
|
Output.diffuse = float4(diffuse * lightBrightness*shadowed, Sat_NL_Att);
|
||||||
|
Output.spec = float4(specular * lightBrightness*shadowed, Sat_NL_Att);
|
||||||
|
|
||||||
|
return Output;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
struct ConnectData
|
||||||
|
{
|
||||||
|
float4 hpos : SV_Position;
|
||||||
|
float2 uv : TEXCOORD;
|
||||||
|
};
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
|
||||||
|
|
||||||
|
uniform float roughness;
|
||||||
|
uniform int face;
|
||||||
|
uniform int mipSize;
|
||||||
|
uniform int resolution;
|
||||||
|
float RadicalInverse_VdC(uint bits)
|
||||||
|
{
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 Hammersley(uint i, uint N)
|
||||||
|
{
|
||||||
|
return float2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
float DistributionGGX(float3 N, float3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
float a2 = a * a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH * NdotH;
|
||||||
|
|
||||||
|
float nom = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = M_PI_F * denom * denom;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 ImportanceSampleGGX(float2 Xi, float3 N)
|
||||||
|
{
|
||||||
|
float a = roughness * roughness;
|
||||||
|
|
||||||
|
float phi = 2.0 * M_PI_F * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates
|
||||||
|
float3 H;
|
||||||
|
H.x = cos(phi) * sinTheta;
|
||||||
|
H.y = sin(phi) * sinTheta;
|
||||||
|
H.z = cosTheta;
|
||||||
|
|
||||||
|
// from tangent-space vector to world-space sample vector
|
||||||
|
float3 up = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
|
||||||
|
float3 tangent = normalize(cross(up, N));
|
||||||
|
float3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
float3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 prefilterEnvMap(float3 R)
|
||||||
|
{
|
||||||
|
int sampleCount = resolution*2;
|
||||||
|
float3 N = R;
|
||||||
|
float3 V = R;
|
||||||
|
float totalWeight = 0.0;
|
||||||
|
float3 prefilteredColor = float3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < sampleCount; ++i)
|
||||||
|
{
|
||||||
|
float2 Xi = Hammersley(i, sampleCount);
|
||||||
|
float3 H = ImportanceSampleGGX(Xi, N);
|
||||||
|
float3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||||
|
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
if (NdotL > 0.0)
|
||||||
|
{
|
||||||
|
// sample from the environment's mip level based on roughness/pdf
|
||||||
|
float D = DistributionGGX(N, H, roughness);
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float HdotV = max(dot(H, V), 0.0);
|
||||||
|
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
|
||||||
|
|
||||||
|
float saTexel = 4.0 * M_PI_F / (6.0 * sampleCount * sampleCount);
|
||||||
|
float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001);
|
||||||
|
|
||||||
|
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
|
||||||
|
|
||||||
|
prefilteredColor += TORQUE_TEXCUBELOD(environmentMap, float4(L, mipLevel)).rgb * NdotL;
|
||||||
|
|
||||||
|
totalWeight += NdotL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (prefilteredColor / totalWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||||
|
{
|
||||||
|
float3 N = getCubeDir(face, IN.uv);
|
||||||
|
return float4(prefilterEnvMap(N), 1.0);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "../../shaderModelAutoGen.hlsl"
|
||||||
|
#include "../../postfx/postFx.hlsl"
|
||||||
|
#include "shaders/common/torque.hlsl"
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(colorBufferTex,0);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(diffuseLightingBuffer,1);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(matInfoTex,2);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(specularLightingBuffer,3);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(deferredTex,4);
|
||||||
|
|
||||||
|
float4 main( PFXVertToPix IN) : TORQUE_TARGET0
|
||||||
|
{
|
||||||
|
float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w;
|
||||||
|
if (depth>0.9999)
|
||||||
|
return float4(0,0,0,0);
|
||||||
|
|
||||||
|
float3 colorBuffer = TORQUE_TEX2D( colorBufferTex, IN.uv0 ).rgb; //albedo
|
||||||
|
float4 matInfo = TORQUE_TEX2D(matInfoTex, IN.uv0); //flags|smoothness|ao|metallic
|
||||||
|
|
||||||
|
bool emissive = getFlag(matInfo.r, 0);
|
||||||
|
if (emissive)
|
||||||
|
{
|
||||||
|
return float4(colorBuffer, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 diffuseLighting = TORQUE_TEX2D( diffuseLightingBuffer, IN.uv0 ); //shadowmap*specular
|
||||||
|
colorBuffer *= diffuseLighting.rgb;
|
||||||
|
|
||||||
|
return hdrEncode( float4(colorBuffer.rgb, 1.0) );
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
#include "../../shaderModelAutoGen.hlsl"
|
||||||
|
|
||||||
|
#include "farFrustumQuad.hlsl"
|
||||||
|
#include "lightingUtils.hlsl"
|
||||||
|
#include "../../lighting.hlsl"
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
struct ConvexConnectP
|
||||||
|
{
|
||||||
|
float4 pos : TORQUE_POSITION;
|
||||||
|
float4 wsEyeDir : TEXCOORD0;
|
||||||
|
float4 ssPos : TEXCOORD1;
|
||||||
|
float4 vsEyeDir : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 1);
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 2);
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 3);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 4);
|
||||||
|
|
||||||
|
uniform float4 rtParams0;
|
||||||
|
|
||||||
|
uniform float3 probeWSPos;
|
||||||
|
uniform float3 probeLSPos;
|
||||||
|
uniform float4 vsFarPlane;
|
||||||
|
|
||||||
|
uniform float radius;
|
||||||
|
uniform float2 attenuation;
|
||||||
|
|
||||||
|
uniform float4x4 invViewMat;
|
||||||
|
|
||||||
|
uniform float3 eyePosWorld;
|
||||||
|
uniform float3 bbMin;
|
||||||
|
uniform float3 bbMax;
|
||||||
|
|
||||||
|
uniform float useSphereMode;
|
||||||
|
|
||||||
|
float3 iblSpecular(float3 v, float3 n, float roughness)
|
||||||
|
{
|
||||||
|
float3 R = reflect(v, n);
|
||||||
|
const float MAX_REFLECTION_LOD = 6.0;
|
||||||
|
float3 prefilteredColor = TORQUE_TEXCUBELOD(cubeMap, float4(R, roughness * MAX_REFLECTION_LOD)).rgb;
|
||||||
|
float2 envBRDF = TORQUE_TEX2D(BRDFTexture, float2(max(dot(n, v), 0.0), roughness)).rg;
|
||||||
|
//return prefilteredColor * (envBRDF.x + envBRDF.y);
|
||||||
|
return prefilteredColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Box Projected IBL Lighting
|
||||||
|
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
||||||
|
|
||||||
|
float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
|
||||||
|
{
|
||||||
|
float3 nrdir = normalize(reflectDir);
|
||||||
|
float3 rbmax = (boxMax - wsPosition) / nrdir;
|
||||||
|
float3 rbmin = (boxMin - wsPosition) / nrdir;
|
||||||
|
|
||||||
|
float3 rbminmax;
|
||||||
|
rbminmax.x = (nrdir.x > 0.0) ? rbmax.x : rbmin.x;
|
||||||
|
rbminmax.y = (nrdir.y > 0.0) ? rbmax.y : rbmin.y;
|
||||||
|
rbminmax.z = (nrdir.z > 0.0) ? rbmax.z : rbmin.z;
|
||||||
|
|
||||||
|
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
||||||
|
float3 posonbox = wsPosition + nrdir * fa;
|
||||||
|
|
||||||
|
return posonbox - boxWSPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 iblBoxDiffuse(float3 normal,
|
||||||
|
float3 wsPos,
|
||||||
|
TORQUE_SAMPLERCUBE(irradianceCube),
|
||||||
|
float3 boxPos,
|
||||||
|
float3 boxMin,
|
||||||
|
float3 boxMax)
|
||||||
|
{
|
||||||
|
// Irradiance (Diffuse)
|
||||||
|
float3 cubeN = normalize(normal);
|
||||||
|
float3 irradiance = TORQUE_TEXCUBE(irradianceCube, cubeN).xyz;
|
||||||
|
|
||||||
|
return irradiance;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 iblBoxSpecular(float3 normal,
|
||||||
|
float3 wsPos,
|
||||||
|
float roughness,
|
||||||
|
float3 viewDir,
|
||||||
|
TORQUE_SAMPLER2D(brdfTexture),
|
||||||
|
TORQUE_SAMPLERCUBE(radianceCube),
|
||||||
|
float3 boxPos,
|
||||||
|
float3 boxMin,
|
||||||
|
float3 boxMax)
|
||||||
|
{
|
||||||
|
float3 v = viewDir;
|
||||||
|
float3 n = normalize(normal);
|
||||||
|
float ndotv = clamp(dot(n, v), 0.0, 1.0);
|
||||||
|
|
||||||
|
// BRDF
|
||||||
|
float2 brdf = TORQUE_TEX2D(brdfTexture, float2(roughness, ndotv)).xy;
|
||||||
|
|
||||||
|
// Radiance (Specular)
|
||||||
|
float lod = roughness * 6.0;
|
||||||
|
float3 r = 2.0 * ndotv * n - v; // reflect(v, n);
|
||||||
|
float3 cubeR = normalize(r);
|
||||||
|
cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
|
||||||
|
|
||||||
|
float3 radiance = TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y);
|
||||||
|
|
||||||
|
return radiance;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PS_OUTPUT
|
||||||
|
{
|
||||||
|
float4 diffuse: TORQUE_TARGET0;
|
||||||
|
float4 spec: TORQUE_TARGET1;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_OUTPUT main( ConvexConnectP IN )
|
||||||
|
{
|
||||||
|
PS_OUTPUT Output = (PS_OUTPUT)0;
|
||||||
|
|
||||||
|
// Compute scene UV
|
||||||
|
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||||
|
|
||||||
|
//float4 hardCodedRTParams0 = float4(0,0.0277777780,1,0.972222209);
|
||||||
|
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
|
// Matinfo flags
|
||||||
|
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );
|
||||||
|
|
||||||
|
// Sample/unpack the normal/z data
|
||||||
|
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
||||||
|
float3 normal = deferredSample.rgb;
|
||||||
|
float depth = deferredSample.a;
|
||||||
|
if (depth>0.9999)
|
||||||
|
clip(-1);
|
||||||
|
|
||||||
|
// Need world-space normal.
|
||||||
|
float3 wsNormal = mul(float4(normal, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
float4 color = float4(1, 1, 1, 1);
|
||||||
|
float4 ref = float4(0,0,0,0);
|
||||||
|
float alpha = 1;
|
||||||
|
|
||||||
|
float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||||
|
float3 viewSpacePos = eyeRay * depth;
|
||||||
|
|
||||||
|
float3 wsEyeRay = mul(float4(eyeRay, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
// Use eye ray to get ws pos
|
||||||
|
float3 worldPos = float3(eyePosWorld + wsEyeRay * depth);
|
||||||
|
float smoothness = min((1.0 - matInfo.b)*11.0 + 1.0, 8.0);//bump up to 8 for finalization
|
||||||
|
|
||||||
|
if(useSphereMode)
|
||||||
|
{
|
||||||
|
// Build light vec, get length, clip pixel if needed
|
||||||
|
float3 lightVec = probeLSPos - viewSpacePos;
|
||||||
|
float lenLightV = length( lightVec );
|
||||||
|
clip( radius - lenLightV );
|
||||||
|
|
||||||
|
// Get the attenuated falloff.
|
||||||
|
float atten = attenuate( float4(1,1,1,1), attenuation, lenLightV );
|
||||||
|
clip( atten - 1e-6 );
|
||||||
|
|
||||||
|
// Normalize lightVec
|
||||||
|
lightVec = normalize(lightVec);
|
||||||
|
|
||||||
|
// If we can do dynamic branching then avoid wasting
|
||||||
|
// fillrate on pixels that are backfacing to the light.
|
||||||
|
float nDotL = abs(dot( lightVec, normal ));
|
||||||
|
|
||||||
|
float Sat_NL_Att = saturate( nDotL * atten );
|
||||||
|
|
||||||
|
float3 reflectionVec = reflect(IN.wsEyeDir, float4(wsNormal,nDotL)).xyz;
|
||||||
|
|
||||||
|
float3 nrdir = normalize(reflectionVec);
|
||||||
|
float3 rbmax = (bbMax - worldPos.xyz) / nrdir;
|
||||||
|
float3 rbmin = (bbMin - worldPos.xyz) / nrdir;
|
||||||
|
|
||||||
|
float3 rbminmax = (nrdir > 0.0) ? rbmax : rbmin;
|
||||||
|
float fa = min(min(rbminmax.x,rbminmax.y),rbminmax.z);
|
||||||
|
if (dot( lightVec, normal )<0.0f)
|
||||||
|
clip(fa);
|
||||||
|
|
||||||
|
float3 posOnBox = worldPos.xyz + nrdir * fa;
|
||||||
|
reflectionVec = posOnBox - probeWSPos;
|
||||||
|
|
||||||
|
reflectionVec = mul(probeWSPos,reflectionVec);
|
||||||
|
|
||||||
|
ref = float4(reflectionVec, smoothness);
|
||||||
|
|
||||||
|
alpha = Sat_NL_Att;
|
||||||
|
float roughness = 1 - matInfo.b;
|
||||||
|
|
||||||
|
float3 irradiance = TORQUE_TEXCUBELOD(irradianceCubemap, ref).rgb;
|
||||||
|
|
||||||
|
float3 specular = TORQUE_TEXCUBELOD(cubeMap, ref).rgb;// iblSpecular(wsEyeRay, wsNormal, roughness);
|
||||||
|
|
||||||
|
Output.diffuse = float4(irradiance.rgb, alpha);
|
||||||
|
Output.spec = float4(specular.rgb, alpha);
|
||||||
|
|
||||||
|
return Output;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Try to clip anything that falls outside our box as well
|
||||||
|
//TODO: Make it support rotated boxes as well
|
||||||
|
if(worldPos.x > bbMax.x || worldPos.y > bbMax.y || worldPos.z > bbMax.z ||
|
||||||
|
worldPos.x < bbMin.x || worldPos.y < bbMin.y || worldPos.z < bbMin.z)
|
||||||
|
clip(-1);
|
||||||
|
|
||||||
|
float blendVal = 1.0;
|
||||||
|
float3 pixDir = normalize(eyePosWorld.xyz - worldPos.xyz);
|
||||||
|
Output.diffuse = float4(iblBoxDiffuse(wsNormal, worldPos, TORQUE_SAMPLERCUBE_MAKEARG(irradianceCubemap), probeWSPos, bbMin, bbMax), blendVal);
|
||||||
|
Output.spec = float4(iblBoxSpecular(wsNormal, worldPos, 1.0 - matInfo.b, pixDir, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap), probeWSPos, bbMin, bbMax), blendVal);
|
||||||
|
return Output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include "../../shaderModelAutoGen.hlsl"
|
||||||
|
|
||||||
|
#include "farFrustumQuad.hlsl"
|
||||||
|
#include "lightingUtils.hlsl"
|
||||||
|
#include "../../lighting.hlsl"
|
||||||
|
#include "../../torque.hlsl"
|
||||||
|
|
||||||
|
struct ConvexConnectP
|
||||||
|
{
|
||||||
|
float4 pos : TORQUE_POSITION;
|
||||||
|
float4 wsEyeDir : TEXCOORD0;
|
||||||
|
float4 ssPos : TEXCOORD1;
|
||||||
|
float4 vsEyeDir : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 1);
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 2);
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 3);
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 4);
|
||||||
|
|
||||||
|
|
||||||
|
uniform float4 rtParams0;
|
||||||
|
|
||||||
|
uniform float4 vsFarPlane;
|
||||||
|
|
||||||
|
uniform float4x4 invViewMat;
|
||||||
|
|
||||||
|
uniform float3 eyePosWorld;
|
||||||
|
|
||||||
|
//SHTerms
|
||||||
|
/*uniform float4 SHTerms0;
|
||||||
|
uniform float4 SHTerms1;
|
||||||
|
uniform float4 SHTerms2;
|
||||||
|
uniform float4 SHTerms3;
|
||||||
|
uniform float4 SHTerms4;
|
||||||
|
uniform float4 SHTerms5;
|
||||||
|
uniform float4 SHTerms6;
|
||||||
|
uniform float4 SHTerms7;
|
||||||
|
uniform float4 SHTerms8;
|
||||||
|
|
||||||
|
uniform float SHConsts0;
|
||||||
|
uniform float SHConsts1;
|
||||||
|
uniform float SHConsts2;
|
||||||
|
uniform float SHConsts3;
|
||||||
|
uniform float SHConsts4;
|
||||||
|
|
||||||
|
float4 decodeSH(float3 normal)
|
||||||
|
{
|
||||||
|
float x = normal.x;
|
||||||
|
float y = normal.y;
|
||||||
|
float z = normal.z;
|
||||||
|
|
||||||
|
float3 l00 = SHTerms0.rgb;
|
||||||
|
|
||||||
|
float3 l10 = SHTerms1.rgb;
|
||||||
|
float3 l11 = SHTerms2.rgb;
|
||||||
|
float3 l12 = SHTerms3.rgb;
|
||||||
|
|
||||||
|
float3 l20 = SHTerms4.rgb;
|
||||||
|
float3 l21 = SHTerms5.rgb;
|
||||||
|
float3 l22 = SHTerms6.rgb;
|
||||||
|
float3 l23 = SHTerms7.rgb;
|
||||||
|
float3 l24 = SHTerms8.rgb;
|
||||||
|
|
||||||
|
float3 result = (
|
||||||
|
l00 * SHConsts0 +
|
||||||
|
|
||||||
|
l12 * SHConsts1 * x +
|
||||||
|
l10 * SHConsts1 * y +
|
||||||
|
l11 * SHConsts1 * z +
|
||||||
|
|
||||||
|
l20 * SHConsts2 * x*y +
|
||||||
|
l21 * SHConsts2 * y*z +
|
||||||
|
l22 * SHConsts3 * (3.0*z*z - 1.0) +
|
||||||
|
l23 * SHConsts2 * x*z +
|
||||||
|
l24 * SHConsts4 * (x*x - y*y)
|
||||||
|
);
|
||||||
|
|
||||||
|
return float4(result,1);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
float3 iblSpecular(float3 v, float3 n, float roughness)
|
||||||
|
{
|
||||||
|
float3 R = reflect(v, n);
|
||||||
|
const float MAX_REFLECTION_LOD = 4.0;
|
||||||
|
float3 prefilteredColor = TORQUE_TEXCUBELOD(cubeMap, float4(R, roughness * MAX_REFLECTION_LOD)).rgb;
|
||||||
|
float2 envBRDF = TORQUE_TEX2D(BRDFTexture, float2(max(dot(n, v), 0.0), roughness)).rg;
|
||||||
|
return prefilteredColor * (envBRDF.x + envBRDF.y);
|
||||||
|
//return prefilteredColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PS_OUTPUT
|
||||||
|
{
|
||||||
|
float4 diffuse: TORQUE_TARGET0;
|
||||||
|
float4 spec: TORQUE_TARGET1;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_OUTPUT main( ConvexConnectP IN )
|
||||||
|
{
|
||||||
|
PS_OUTPUT Output = (PS_OUTPUT)0;
|
||||||
|
|
||||||
|
// Compute scene UV
|
||||||
|
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||||
|
|
||||||
|
//float4 hardCodedRTParams0 = float4(0,0.0277777780,1,0.972222209);
|
||||||
|
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
|
// Matinfo flags
|
||||||
|
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );
|
||||||
|
|
||||||
|
// Sample/unpack the normal/z data
|
||||||
|
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
||||||
|
float3 normal = deferredSample.rgb;
|
||||||
|
float depth = deferredSample.a;
|
||||||
|
if (depth>0.9999)
|
||||||
|
return Output;
|
||||||
|
|
||||||
|
// Need world-space normal.
|
||||||
|
float3 wsNormal = mul(float4(normal, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||||
|
|
||||||
|
float3 wsEyeRay = mul(float4(eyeRay, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
// Use eye ray to get ws pos
|
||||||
|
float3 worldPos = float3(eyePosWorld + wsEyeRay * depth);
|
||||||
|
|
||||||
|
float3 reflectionVec = reflect(IN.wsEyeDir, float4(wsNormal,1)).xyz;
|
||||||
|
|
||||||
|
float roughness = 1 - matInfo.b;
|
||||||
|
|
||||||
|
float3 v = normalize(eyePosWorld - worldPos);
|
||||||
|
|
||||||
|
float3 irradiance = TORQUE_TEXCUBE(irradianceCubemap, wsNormal).rgb;
|
||||||
|
|
||||||
|
float3 specular = iblSpecular(wsEyeRay, wsNormal, roughness);
|
||||||
|
|
||||||
|
|
||||||
|
Output.diffuse = float4(irradiance.rgb, 1);
|
||||||
|
Output.spec = float4(specular.rgb, 1);
|
||||||
|
|
||||||
|
return Output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -192,23 +192,24 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
|
||||||
dot( finalMask, overDarkPSSM ) ) );
|
dot( finalMask, overDarkPSSM ) ) );
|
||||||
};
|
};
|
||||||
|
|
||||||
float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
|
struct PS_OUTPUT
|
||||||
{
|
{
|
||||||
|
float4 spec: TORQUE_TARGET0;
|
||||||
|
float4 diffuse: TORQUE_TARGET1;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_OUTPUT main(FarFrustumQuadConnectP IN)
|
||||||
|
{
|
||||||
|
PS_OUTPUT Output = (PS_OUTPUT)0;
|
||||||
// Matinfo flags
|
// Matinfo flags
|
||||||
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, IN.uv0 );
|
float4 matInfo = TORQUE_TEX2D(matInfoBuffer, IN.uv0);
|
||||||
//early out if emissive
|
|
||||||
bool emissive = getFlag(matInfo.r, 0);
|
float4 colorSample = TORQUE_TEX2D(colorBuffer, IN.uv0);
|
||||||
if (emissive)
|
float3 subsurface = float3(0.0, 0.0, 0.0);
|
||||||
{
|
if (getFlag(matInfo.r, 1))
|
||||||
return float4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
|
|
||||||
float3 subsurface = float3(0.0,0.0,0.0);
|
|
||||||
if (getFlag( matInfo.r, 1 ))
|
|
||||||
{
|
{
|
||||||
subsurface = colorSample.rgb;
|
subsurface = colorSample.rgb;
|
||||||
if (colorSample.r>colorSample.g)
|
if (colorSample.r > colorSample.g)
|
||||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||||
else
|
else
|
||||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||||
|
|
@ -224,96 +225,97 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
|
||||||
// Get the light attenuation.
|
// Get the light attenuation.
|
||||||
float dotNL = dot(-lightDirection, normal);
|
float dotNL = dot(-lightDirection, normal);
|
||||||
|
|
||||||
#ifdef PSSM_DEBUG_RENDER
|
#ifdef PSSM_DEBUG_RENDER
|
||||||
float3 debugColor = float3(0,0,0);
|
float3 debugColor = float3(0, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_SHADOW
|
||||||
|
|
||||||
|
// Fully unshadowed.
|
||||||
|
float shadowed = 1.0;
|
||||||
|
|
||||||
|
#ifdef PSSM_DEBUG_RENDER
|
||||||
|
debugColor = float3(1.0, 1.0, 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
float4 static_shadowed_colors = AL_VectorLightShadowCast(TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
||||||
|
IN.uv0.xy,
|
||||||
|
worldToLightProj,
|
||||||
|
worldPos,
|
||||||
|
scaleX, scaleY,
|
||||||
|
offsetX, offsetY,
|
||||||
|
farPlaneScalePSSM,
|
||||||
|
atlasXOffset, atlasYOffset,
|
||||||
|
atlasScale,
|
||||||
|
shadowSoftness,
|
||||||
|
dotNL,
|
||||||
|
overDarkPSSM);
|
||||||
|
float4 dynamic_shadowed_colors = AL_VectorLightShadowCast(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
||||||
|
IN.uv0.xy,
|
||||||
|
dynamicWorldToLightProj,
|
||||||
|
worldPos,
|
||||||
|
dynamicScaleX, dynamicScaleY,
|
||||||
|
dynamicOffsetX, dynamicOffsetY,
|
||||||
|
dynamicFarPlaneScalePSSM,
|
||||||
|
atlasXOffset, atlasYOffset,
|
||||||
|
atlasScale,
|
||||||
|
shadowSoftness,
|
||||||
|
dotNL,
|
||||||
|
overDarkPSSM);
|
||||||
|
|
||||||
|
float static_shadowed = static_shadowed_colors.a;
|
||||||
|
float dynamic_shadowed = dynamic_shadowed_colors.a;
|
||||||
|
|
||||||
|
#ifdef PSSM_DEBUG_RENDER
|
||||||
|
debugColor = static_shadowed_colors.rgb*0.5 + dynamic_shadowed_colors.rgb*0.5;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fade out the shadow at the end of the range.
|
||||||
|
float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
|
||||||
|
float fadeOutAmt = (zDist.x - fadeStartLength.x) * fadeStartLength.y;
|
||||||
|
|
||||||
|
static_shadowed = lerp(static_shadowed, 1.0, saturate(fadeOutAmt));
|
||||||
|
dynamic_shadowed = lerp(dynamic_shadowed, 1.0, saturate(fadeOutAmt));
|
||||||
|
|
||||||
|
// temp for debugging. uncomment one or the other.
|
||||||
|
//float shadowed = static_shadowed;
|
||||||
|
//float shadowed = dynamic_shadowed;
|
||||||
|
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||||
|
|
||||||
|
#ifdef PSSM_DEBUG_RENDER
|
||||||
|
if (fadeOutAmt > 1.0)
|
||||||
|
debugColor = 1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !NO_SHADOW
|
||||||
|
|
||||||
|
float3 l = normalize(-lightDirection);
|
||||||
|
float3 v = normalize(eyePosWorld - worldPos.xyz);
|
||||||
|
|
||||||
|
float3 h = normalize(v + l);
|
||||||
|
float dotNLa = clamp(dot(normal, l), 0.0, 1.0);
|
||||||
|
float dotNVa = clamp(dot(normal, v), 0.0, 1.0);
|
||||||
|
float dotNHa = clamp(dot(normal, h), 0.0, 1.0);
|
||||||
|
float dotHVa = clamp(dot(normal, v), 0.0, 1.0);
|
||||||
|
float dotLHa = clamp(dot(l, h), 0.0, 1.0);
|
||||||
|
|
||||||
|
float roughness = matInfo.g;
|
||||||
|
float metalness = matInfo.b;
|
||||||
|
|
||||||
|
//diffuse
|
||||||
|
//float dotNL = clamp(dot(normal,l), 0.0, 1.0);
|
||||||
|
float disDiff = Fr_DisneyDiffuse(dotNVa, dotNLa, dotLHa, roughness);
|
||||||
|
float3 diffuse = float3(disDiff, disDiff, disDiff) / M_PI_F;// alternative: (lightColor * dotNL) / Pi;
|
||||||
|
//specular
|
||||||
|
float3 specular = directSpecular(normal, v, l, roughness, 1.0) * lightColor.rgb;
|
||||||
|
|
||||||
#ifdef NO_SHADOW
|
float finalShadowed = shadowed;
|
||||||
|
|
||||||
// Fully unshadowed.
|
//output
|
||||||
float shadowed = 1.0;
|
Output.diffuse = float4(diffuse * (lightBrightness*shadowed), dotNLa);
|
||||||
|
Output.spec = float4(specular * (lightBrightness*shadowed), dotNLa);
|
||||||
|
|
||||||
#ifdef PSSM_DEBUG_RENDER
|
return Output;
|
||||||
debugColor = float3(1.0,1.0,1.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
|
||||||
IN.uv0.xy,
|
|
||||||
worldToLightProj,
|
|
||||||
worldPos,
|
|
||||||
scaleX, scaleY,
|
|
||||||
offsetX, offsetY,
|
|
||||||
farPlaneScalePSSM,
|
|
||||||
atlasXOffset, atlasYOffset,
|
|
||||||
atlasScale,
|
|
||||||
shadowSoftness,
|
|
||||||
dotNL,
|
|
||||||
overDarkPSSM);
|
|
||||||
float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
|
||||||
IN.uv0.xy,
|
|
||||||
dynamicWorldToLightProj,
|
|
||||||
worldPos,
|
|
||||||
dynamicScaleX, dynamicScaleY,
|
|
||||||
dynamicOffsetX, dynamicOffsetY,
|
|
||||||
dynamicFarPlaneScalePSSM,
|
|
||||||
atlasXOffset, atlasYOffset,
|
|
||||||
atlasScale,
|
|
||||||
shadowSoftness,
|
|
||||||
dotNL,
|
|
||||||
overDarkPSSM);
|
|
||||||
|
|
||||||
float static_shadowed = static_shadowed_colors.a;
|
|
||||||
float dynamic_shadowed = dynamic_shadowed_colors.a;
|
|
||||||
|
|
||||||
#ifdef PSSM_DEBUG_RENDER
|
|
||||||
debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fade out the shadow at the end of the range.
|
|
||||||
float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
|
|
||||||
float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
|
|
||||||
|
|
||||||
static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
|
|
||||||
dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
|
|
||||||
|
|
||||||
// temp for debugging. uncomment one or the other.
|
|
||||||
//float shadowed = static_shadowed;
|
|
||||||
//float shadowed = dynamic_shadowed;
|
|
||||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
|
||||||
|
|
||||||
#ifdef PSSM_DEBUG_RENDER
|
|
||||||
if ( fadeOutAmt > 1.0 )
|
|
||||||
debugColor = 1.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // !NO_SHADOW
|
|
||||||
|
|
||||||
// Specular term
|
|
||||||
float3 viewSpacePos = IN.vsEyeRay * depth;
|
|
||||||
float4 real_specular = EvalBDRF( float3( 1.0, 1.0, 1.0 ),
|
|
||||||
lightColor.rgb,
|
|
||||||
normalize( -lightDirection ),
|
|
||||||
viewSpacePos,
|
|
||||||
normal,
|
|
||||||
1.0-matInfo.b,
|
|
||||||
matInfo.a );
|
|
||||||
float3 lightColorOut = real_specular.rgb * lightBrightness * shadowed;
|
|
||||||
|
|
||||||
float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
|
|
||||||
float Sat_NdotV = saturate(dot(normalize(-IN.vsEyeRay), normal));
|
|
||||||
float4 addToResult = ( lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * Sat_NdotV );
|
|
||||||
|
|
||||||
// Sample the AO texture.
|
|
||||||
#ifdef USE_SSAO_MASK
|
|
||||||
float ao = 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
|
|
||||||
addToResult *= ao;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PSSM_DEBUG_RENDER
|
|
||||||
lightColorOut = debugColor;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return float4(matInfo.g*(lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,15 +55,16 @@ float3 Uncharted2Tonemap(const float3 x)
|
||||||
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
|
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 tonemap(float3 c)
|
float3 tonemap(float3 color)
|
||||||
{
|
{
|
||||||
const float W = 11.2;
|
const float W = 11.2;
|
||||||
float ExposureBias = 2.0f;
|
float ExposureBias = 2.0f;
|
||||||
float ExposureAdjust = 1.5f;
|
//float ExposureAdjust = 1.5f;
|
||||||
c *= ExposureAdjust;
|
//c *= ExposureAdjust;
|
||||||
float3 curr = Uncharted2Tonemap(ExposureBias*c);
|
color = Uncharted2Tonemap(ExposureBias*color);
|
||||||
float3 whiteScale = 1.0f / Uncharted2Tonemap(W);
|
color = color * (1.0f / Uncharted2Tonemap(W));
|
||||||
return curr*whiteScale;
|
|
||||||
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||||
|
|
@ -100,5 +101,7 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||||
sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g;
|
sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g;
|
||||||
sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b;
|
sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b;
|
||||||
|
|
||||||
|
sample = float4(tonemap(sample.rgb),1);
|
||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,29 @@ uniform float Contrast;
|
||||||
|
|
||||||
out vec4 OUT_col;
|
out vec4 OUT_col;
|
||||||
|
|
||||||
|
// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
|
||||||
|
vec3 Uncharted2Tonemap(vec3 x)
|
||||||
|
{
|
||||||
|
const float A = 0.15;
|
||||||
|
const float B = 0.50;
|
||||||
|
const float C = 0.10;
|
||||||
|
const float D = 0.20;
|
||||||
|
const float E = 0.02;
|
||||||
|
const float F = 0.30;
|
||||||
|
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 tonemap(vec3 c)
|
||||||
|
{
|
||||||
|
const float W = 11.2;
|
||||||
|
float ExposureBias = 2.0f;
|
||||||
|
float ExposureAdjust = 1.5f;
|
||||||
|
c *= ExposureAdjust;
|
||||||
|
vec3 curr = Uncharted2Tonemap(ExposureBias*c);
|
||||||
|
vec3 whiteScale = 1.0f / Uncharted2Tonemap(vec3(W,W,W));
|
||||||
|
return curr*whiteScale;
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) );
|
vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) );
|
||||||
|
|
@ -76,17 +99,6 @@ void main()
|
||||||
|
|
||||||
// Add the bloom effect.
|
// Add the bloom effect.
|
||||||
_sample += g_fBloomScale * bloom;
|
_sample += g_fBloomScale * bloom;
|
||||||
|
|
||||||
// Map the high range of color values into a range appropriate for
|
|
||||||
// display, taking into account the user's adaptation level,
|
|
||||||
// white point, and selected value for for middle gray.
|
|
||||||
if ( g_fEnableToneMapping > 0.0f )
|
|
||||||
{
|
|
||||||
float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( _sample.rgb );
|
|
||||||
//float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp );
|
|
||||||
float toneScalar = Lp;
|
|
||||||
_sample.rgb = mix( _sample.rgb, _sample.rgb * toneScalar, g_fEnableToneMapping );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the color correction.
|
// Apply the color correction.
|
||||||
_sample.r = texture( colorCorrectionTex, _sample.r ).r;
|
_sample.r = texture( colorCorrectionTex, _sample.r ).r;
|
||||||
|
|
|
||||||
|
|
@ -310,4 +310,38 @@ float3 simpleFresnel(float3 diffuseColor, float3 reflectColor, float metalness,
|
||||||
|
|
||||||
return lerp(diffuseColor, reflectColor, fresnelTerm);
|
return lerp(diffuseColor, reflectColor, fresnelTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hlsl version of the glsl funcion mod - note hlsl fmod is different
|
||||||
|
#define mod(x,y) (x-y*floor(x/y))
|
||||||
|
|
||||||
|
//get direction for a cube face
|
||||||
|
float3 getCubeDir(int face, float2 uv)
|
||||||
|
{
|
||||||
|
float2 debiased = uv * 2.0f - 1.0f;
|
||||||
|
|
||||||
|
float3 dir = 0;
|
||||||
|
|
||||||
|
switch (face)
|
||||||
|
{
|
||||||
|
case 0: dir = float3(1, -debiased.y, -debiased.x);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: dir = float3(-1, -debiased.y, debiased.x);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: dir = float3(debiased.x, 1, debiased.y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: dir = float3(debiased.x, -1, -debiased.y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: dir = float3(debiased.x, -debiased.y, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: dir = float3(-debiased.x, -debiased.y, -1);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return normalize(dir);
|
||||||
|
}
|
||||||
#endif // _TORQUE_HLSL_
|
#endif // _TORQUE_HLSL_
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,6 @@ void main()
|
||||||
{
|
{
|
||||||
// Modulate baseColor by the ambientColor.
|
// Modulate baseColor by the ambientColor.
|
||||||
vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 );
|
vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 );
|
||||||
waterBaseColor = waterBaseColor;
|
|
||||||
|
|
||||||
// Get the bumpNorm...
|
// Get the bumpNorm...
|
||||||
vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x;
|
vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x;
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,6 @@ void main()
|
||||||
|
|
||||||
// Calculate the water "base" color based on depth.
|
// Calculate the water "base" color based on depth.
|
||||||
vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) );
|
vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) );
|
||||||
waterBaseColor = waterBaseColor;
|
|
||||||
|
|
||||||
// Modulate baseColor by the ambientColor.
|
// Modulate baseColor by the ambientColor.
|
||||||
waterBaseColor *= vec4( ambientColor.rgb, 1 );
|
waterBaseColor *= vec4( ambientColor.rgb, 1 );
|
||||||
|
|
|
||||||
1
Templates/Full/game/shaders/procedural/.gitignore
vendored
Normal file
1
Templates/Full/game/shaders/procedural/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/procedural/
|
||||||
115
Templates/Full/game/tools/resources/ReflectProbeSphere.dae
Normal file
115
Templates/Full/game/tools/resources/ReflectProbeSphere.dae
Normal file
File diff suppressed because one or more lines are too long
8
Templates/Full/game/tools/resources/materials.cs
Normal file
8
Templates/Full/game/tools/resources/materials.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
singleton Material(ReflectProbePreviewMat)
|
||||||
|
{
|
||||||
|
mapTo = "ReflectProbePreviewMat";
|
||||||
|
diffuseColor[0] = "1 1 1 1";
|
||||||
|
smoothness[0] = "1";
|
||||||
|
metalness[0] = "1";
|
||||||
|
translucentBlendOp = "None";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "shaders/common/shaderModelAutoGen.hlsl"
|
||||||
|
|
||||||
|
#include "shaders/common/lighting/advanced/farFrustumQuad.hlsl"
|
||||||
|
#include "shaders/common/lighting/advanced/lightingUtils.hlsl"
|
||||||
|
#include "shaders/common/lighting.hlsl"
|
||||||
|
#include "shaders/common/torque.hlsl"
|
||||||
|
|
||||||
|
struct ConvexConnectP
|
||||||
|
{
|
||||||
|
float4 pos : TORQUE_POSITION;
|
||||||
|
float4 wsEyeDir : TEXCOORD0;
|
||||||
|
float4 ssPos : TEXCOORD1;
|
||||||
|
float4 vsEyeDir : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
|
||||||
|
TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 1);
|
||||||
|
|
||||||
|
uniform float4 rtParams0;
|
||||||
|
|
||||||
|
uniform float4x4 invViewMat;
|
||||||
|
|
||||||
|
float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
||||||
|
{
|
||||||
|
// Compute scene UV
|
||||||
|
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||||
|
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||||
|
|
||||||
|
//float3 eyeRay = IN.vsEyeDir.xyz;
|
||||||
|
|
||||||
|
// Sample/unpack the normal/z data
|
||||||
|
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
||||||
|
float3 normal = deferredSample.rgb;
|
||||||
|
float depth = deferredSample.a;
|
||||||
|
if (depth>0.9999)
|
||||||
|
return float4(0,0,0,0);
|
||||||
|
|
||||||
|
// Need world-space normal.
|
||||||
|
float3 wsNormal = mul(float4(normal, 1), invViewMat).rgb;
|
||||||
|
|
||||||
|
float3 reflectionVec = reflect(IN.wsEyeDir, float4(normalize(wsNormal),1)).rgb;
|
||||||
|
|
||||||
|
float4 color = TORQUE_TEXCUBE(cubeMap, reflectionVec);
|
||||||
|
|
||||||
|
//simple visibility testing
|
||||||
|
//float4 color = float4(1,0,0,1);
|
||||||
|
|
||||||
|
return float4(color.rgb, 1);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2012 GarageGames, LLC
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to
|
||||||
|
// deal in the Software without restriction, including without limitation the
|
||||||
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
// sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE SOFTWARE.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "shaders/common/hlslStructs.hlsl"
|
||||||
|
#include "shaders/common/shaderModel.hlsl"
|
||||||
|
|
||||||
|
struct VertData
|
||||||
|
{
|
||||||
|
float3 pos : POSITION;
|
||||||
|
float tangentW : TEXCOORD3;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float3 T : TANGENT;
|
||||||
|
float2 texCoord : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConvexConnectV
|
||||||
|
{
|
||||||
|
float4 hpos : TORQUE_POSITION;
|
||||||
|
float4 wsEyeDir : TEXCOORD0;
|
||||||
|
float4 ssPos : TEXCOORD1;
|
||||||
|
float4 vsEyeDir : TEXCOORD2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform float4x4 modelview;
|
||||||
|
uniform float4x4 objTrans;
|
||||||
|
uniform float4x4 worldViewOnly;
|
||||||
|
uniform float3 eyePosWorld;
|
||||||
|
|
||||||
|
ConvexConnectV main( VertData IN )
|
||||||
|
{
|
||||||
|
ConvexConnectV OUT;
|
||||||
|
|
||||||
|
OUT.hpos = mul( modelview, float4(IN.pos,1.0) );
|
||||||
|
OUT.wsEyeDir = mul(objTrans, float4(IN.pos, 1.0)) - float4(eyePosWorld, 0.0);
|
||||||
|
OUT.vsEyeDir = mul(worldViewOnly, float4(IN.pos, 1.0));
|
||||||
|
OUT.ssPos = OUT.hpos;
|
||||||
|
|
||||||
|
return OUT;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -877,6 +877,24 @@ function ObjectBuilderGui::buildParticleSimulation(%this)
|
||||||
%this.process();
|
%this.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ObjectBuilderGui::buildReflectionProbe(%this)
|
||||||
|
{
|
||||||
|
%this.objectClassName = "ReflectionProbe";
|
||||||
|
%this.process();
|
||||||
|
|
||||||
|
%defaultPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
||||||
|
%this.addField("reflectionPath", "TypeFilepath", "reflectionPath", %defaultPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ObjectBuilderGui::buildSkylight(%this)
|
||||||
|
{
|
||||||
|
%this.objectClassName = "Skylight";
|
||||||
|
%this.process();
|
||||||
|
|
||||||
|
%defaultPath = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
||||||
|
%this.addField("reflectionPath", "TypeFilepath", "reflectionPath", %defaultPath);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Mission
|
// Mission
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
192
Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui
Normal file
192
Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
//--- OBJECT WRITE BEGIN ---
|
||||||
|
%guiContent = new GuiControl(ProbeBakeDlg) {
|
||||||
|
position = "0 0";
|
||||||
|
extent = "1024 768";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiDefaultProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "1";
|
||||||
|
|
||||||
|
new GuiWindowCtrl() {
|
||||||
|
text = "Update Environment Probes";
|
||||||
|
resizeWidth = "0";
|
||||||
|
resizeHeight = "0";
|
||||||
|
canMove = "1";
|
||||||
|
canClose = "1";
|
||||||
|
canMinimize = "0";
|
||||||
|
canMaximize = "0";
|
||||||
|
canCollapse = "0";
|
||||||
|
closeCommand = "Canvas.popDialog(ProbeBakeDlg);";
|
||||||
|
edgeSnap = "0";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "392 314";
|
||||||
|
extent = "270 164";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiWindowProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
|
||||||
|
new GuiTextCtrl() {
|
||||||
|
text = "Probe Resolution";
|
||||||
|
maxLength = "1024";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "11 32";
|
||||||
|
extent = "91 13";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiTextProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
new GuiPopUpMenuCtrl(ProbeBakeDlg_ProbeResList) {
|
||||||
|
maxPopupHeight = "200";
|
||||||
|
sbUsesNAColor = "0";
|
||||||
|
reverseTextList = "0";
|
||||||
|
bitmapBounds = "16 16";
|
||||||
|
text = "64";
|
||||||
|
maxLength = "1024";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "103 29";
|
||||||
|
extent = "157 19";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiPopUpMenuProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
new GuiTextCtrl() {
|
||||||
|
text = "Number of bake iterations";
|
||||||
|
maxLength = "1024";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "11 56";
|
||||||
|
extent = "129 13";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiTextProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
new GuiTextEditCtrl(ProbeBakeDlg_NumIterTxt) {
|
||||||
|
historySize = "0";
|
||||||
|
tabComplete = "0";
|
||||||
|
sinkAllKeyEvents = "0";
|
||||||
|
password = "0";
|
||||||
|
passwordMask = "*";
|
||||||
|
text = "1";
|
||||||
|
maxLength = "1024";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "150 53";
|
||||||
|
extent = "108 18";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiTextEditProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
new GuiButtonCtrl(ProbeBakeDlg_RunBake) {
|
||||||
|
text = "Update Probes";
|
||||||
|
groupNum = "-1";
|
||||||
|
buttonType = "PushButton";
|
||||||
|
useMouseEvents = "0";
|
||||||
|
position = "68 120";
|
||||||
|
extent = "140 30";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiButtonProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "0";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
new GuiProgressCtrl(ProbeBakeDlg_Progress) {
|
||||||
|
maxLength = "1024";
|
||||||
|
margin = "0 0 0 0";
|
||||||
|
padding = "0 0 0 0";
|
||||||
|
anchorTop = "1";
|
||||||
|
anchorBottom = "0";
|
||||||
|
anchorLeft = "1";
|
||||||
|
anchorRight = "0";
|
||||||
|
position = "8 80";
|
||||||
|
extent = "251 25";
|
||||||
|
minExtent = "8 2";
|
||||||
|
horizSizing = "right";
|
||||||
|
vertSizing = "bottom";
|
||||||
|
profile = "GuiProgressProfile";
|
||||||
|
visible = "1";
|
||||||
|
active = "1";
|
||||||
|
tooltipProfile = "GuiToolTipProfile";
|
||||||
|
hovertime = "1000";
|
||||||
|
isContainer = "1";
|
||||||
|
canSave = "1";
|
||||||
|
canSaveDynamicFields = "0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//--- OBJECT WRITE END ---
|
||||||
|
|
@ -43,6 +43,7 @@ function initializeWorldEditor()
|
||||||
exec("./gui/AddFMODProjectDlg.ed.gui");
|
exec("./gui/AddFMODProjectDlg.ed.gui");
|
||||||
exec("./gui/SelectObjectsWindow.ed.gui");
|
exec("./gui/SelectObjectsWindow.ed.gui");
|
||||||
exec("./gui/ProceduralTerrainPainterGui.gui" );
|
exec("./gui/ProceduralTerrainPainterGui.gui" );
|
||||||
|
exec("./gui/probeBakeDlg.gui" );
|
||||||
|
|
||||||
// Load Scripts.
|
// Load Scripts.
|
||||||
exec("./scripts/menus.ed.cs");
|
exec("./scripts/menus.ed.cs");
|
||||||
|
|
@ -61,6 +62,7 @@ function initializeWorldEditor()
|
||||||
exec("./scripts/ManageSFXParametersWindow.ed.cs");
|
exec("./scripts/ManageSFXParametersWindow.ed.cs");
|
||||||
exec("./scripts/AddFMODProjectDlg.ed.cs");
|
exec("./scripts/AddFMODProjectDlg.ed.cs");
|
||||||
exec("./scripts/SelectObjectsWindow.ed.cs");
|
exec("./scripts/SelectObjectsWindow.ed.cs");
|
||||||
|
exec("./scripts/probeBake.ed.cs");
|
||||||
|
|
||||||
// Load Custom Editors
|
// Load Custom Editors
|
||||||
loadDirectory(expandFilename("./scripts/editors"));
|
loadDirectory(expandFilename("./scripts/editors"));
|
||||||
|
|
@ -115,10 +117,11 @@ function initializeWorldEditor()
|
||||||
EVisibility.addOption( "Debug Render: Light Frustums", "$Light::renderLightFrustums", "" );
|
EVisibility.addOption( "Debug Render: Light Frustums", "$Light::renderLightFrustums", "" );
|
||||||
EVisibility.addOption( "Debug Render: Bounding Boxes", "$Scene::renderBoundingBoxes", "" );
|
EVisibility.addOption( "Debug Render: Bounding Boxes", "$Scene::renderBoundingBoxes", "" );
|
||||||
EVisibility.addOption( "Debug Render: Physics World", "$PhysicsWorld::render", "togglePhysicsDebugViz" );
|
EVisibility.addOption( "Debug Render: Physics World", "$PhysicsWorld::render", "togglePhysicsDebugViz" );
|
||||||
|
EVisibility.addOption( "Debug Render: Reflection Probes", "$Light::renderReflectionProbes", "" );
|
||||||
|
EVisibility.addOption( "Debug Render: Probe Previews", "$Light::renderPreviewProbes", "" );
|
||||||
EVisibility.addOption( "AL: Disable Shadows", "$Shadows::disable", "" );
|
EVisibility.addOption( "AL: Disable Shadows", "$Shadows::disable", "" );
|
||||||
EVisibility.addOption( "AL: Light Color Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" );
|
EVisibility.addOption( "AL: Diffuse Lighting Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" );
|
||||||
EVisibility.addOption( "AL: Environment Light", "$AL_LightMapShaderVar", "toggleLightMapViz" );
|
EVisibility.addOption( "AL: Specular Lighting Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" );
|
||||||
EVisibility.addOption( "AL: Light Specular Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" );
|
|
||||||
EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" );
|
EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" );
|
||||||
EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" );
|
EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" );
|
||||||
EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" );
|
EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" );
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ function EWCreatorWindow::init( %this )
|
||||||
|
|
||||||
%this.registerMissionObject( "PointLight", "Point Light" );
|
%this.registerMissionObject( "PointLight", "Point Light" );
|
||||||
%this.registerMissionObject( "SpotLight", "Spot Light" );
|
%this.registerMissionObject( "SpotLight", "Spot Light" );
|
||||||
|
|
||||||
|
%this.registerMissionObject( "ReflectionProbe", "Reflection Probe" );
|
||||||
|
%this.registerMissionObject( "Skylight", "Skylight" );
|
||||||
|
|
||||||
%this.registerMissionObject( "GroundCover", "Ground Cover" );
|
%this.registerMissionObject( "GroundCover", "Ground Cover" );
|
||||||
%this.registerMissionObject( "TerrainBlock", "Terrain Block" );
|
%this.registerMissionObject( "TerrainBlock", "Terrain Block" );
|
||||||
%this.registerMissionObject( "GroundPlane", "Ground Plane" );
|
%this.registerMissionObject( "GroundPlane", "Ground Plane" );
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,28 @@ function TerrainMaterialDlg::changeNormal( %this )
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TerrainMaterialDlg::changecomposite( %this )
|
||||||
|
{
|
||||||
|
%ctrl = %this-->compositeTexCtrl;
|
||||||
|
%file = %ctrl.bitmap;
|
||||||
|
if( getSubStr( %file, 0 , 6 ) $= "tools/" )
|
||||||
|
%file = "";
|
||||||
|
|
||||||
|
%file = TerrainMaterialDlg._selectTextureFileDialog( %file );
|
||||||
|
if( %file $= "" )
|
||||||
|
{
|
||||||
|
if( %ctrl.bitmap !$= "" )
|
||||||
|
%file = %ctrl.bitmap;
|
||||||
|
else
|
||||||
|
%file = "tools/materialEditor/gui/unknownImage";
|
||||||
|
}
|
||||||
|
|
||||||
|
%file = makeRelativePath( %file, getMainDotCsDir() );
|
||||||
|
%ctrl.setBitmap( %file );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
function TerrainMaterialDlg::newMat( %this )
|
function TerrainMaterialDlg::newMat( %this )
|
||||||
{
|
{
|
||||||
// Create a unique material name.
|
// Create a unique material name.
|
||||||
|
|
@ -394,7 +416,12 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat )
|
||||||
%this-->normTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
|
%this-->normTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
|
||||||
}else{
|
}else{
|
||||||
%this-->normTexCtrl.setBitmap( %mat.normalMap );
|
%this-->normTexCtrl.setBitmap( %mat.normalMap );
|
||||||
}
|
}
|
||||||
|
if (%mat.compositeMap $= ""){
|
||||||
|
%this-->compositeTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" );
|
||||||
|
}else{
|
||||||
|
%this-->compositeTexCtrl.setBitmap( %mat.compositeMap );
|
||||||
|
}
|
||||||
%this-->detSizeCtrl.setText( %mat.detailSize );
|
%this-->detSizeCtrl.setText( %mat.detailSize );
|
||||||
%this-->baseSizeCtrl.setText( %mat.diffuseSize );
|
%this-->baseSizeCtrl.setText( %mat.diffuseSize );
|
||||||
%this-->detStrengthCtrl.setText( %mat.detailStrength );
|
%this-->detStrengthCtrl.setText( %mat.detailStrength );
|
||||||
|
|
@ -448,6 +475,11 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
|
||||||
}else{
|
}else{
|
||||||
%newMacro = %this-->macroTexCtrl.bitmap;
|
%newMacro = %this-->macroTexCtrl.bitmap;
|
||||||
}
|
}
|
||||||
|
if (%this-->compositeTexCtrl.bitmap $= "tools/materialEditor/gui/unknownImage"){
|
||||||
|
%newComposite = "";
|
||||||
|
}else{
|
||||||
|
%newComposite = %this-->compositeTexCtrl.bitmap;
|
||||||
|
}
|
||||||
%detailSize = %this-->detSizeCtrl.getText();
|
%detailSize = %this-->detSizeCtrl.getText();
|
||||||
%diffuseSize = %this-->baseSizeCtrl.getText();
|
%diffuseSize = %this-->baseSizeCtrl.getText();
|
||||||
%detailStrength = %this-->detStrengthCtrl.getText();
|
%detailStrength = %this-->detStrengthCtrl.getText();
|
||||||
|
|
@ -466,6 +498,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
|
||||||
%mat.diffuseMap $= %newDiffuse &&
|
%mat.diffuseMap $= %newDiffuse &&
|
||||||
%mat.normalMap $= %newNormal &&
|
%mat.normalMap $= %newNormal &&
|
||||||
%mat.detailMap $= %newDetail &&
|
%mat.detailMap $= %newDetail &&
|
||||||
|
%mat.compositeMap $= %newComposite &&
|
||||||
%mat.macroMap $= %newMacro &&
|
%mat.macroMap $= %newMacro &&
|
||||||
%mat.detailSize == %detailSize &&
|
%mat.detailSize == %detailSize &&
|
||||||
%mat.diffuseSize == %diffuseSize &&
|
%mat.diffuseSize == %diffuseSize &&
|
||||||
|
|
@ -497,7 +530,8 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat )
|
||||||
}
|
}
|
||||||
|
|
||||||
%mat.diffuseMap = %newDiffuse;
|
%mat.diffuseMap = %newDiffuse;
|
||||||
%mat.normalMap = %newNormal;
|
%mat.normalMap = %newNormal;
|
||||||
|
%mat.compositeMap = %newComposite;
|
||||||
%mat.detailMap = %newDetail;
|
%mat.detailMap = %newDetail;
|
||||||
%mat.macroMap = %newMacro;
|
%mat.macroMap = %newMacro;
|
||||||
%mat.detailSize = %detailSize;
|
%mat.detailSize = %detailSize;
|
||||||
|
|
@ -544,6 +578,7 @@ function TerrainMaterialDlg::snapshotMaterials( %this )
|
||||||
diffuseMap = %mat.diffuseMap;
|
diffuseMap = %mat.diffuseMap;
|
||||||
normalMap = %mat.normalMap;
|
normalMap = %mat.normalMap;
|
||||||
detailMap = %mat.detailMap;
|
detailMap = %mat.detailMap;
|
||||||
|
compositeMap = %mat.compositeMap;
|
||||||
macroMap = %mat.macroMap;
|
macroMap = %mat.macroMap;
|
||||||
detailSize = %mat.detailSize;
|
detailSize = %mat.detailSize;
|
||||||
diffuseSize = %mat.diffuseSize;
|
diffuseSize = %mat.diffuseSize;
|
||||||
|
|
@ -578,6 +613,7 @@ function TerrainMaterialDlg::restoreMaterials( %this )
|
||||||
%mat.diffuseMap = %obj.diffuseMap;
|
%mat.diffuseMap = %obj.diffuseMap;
|
||||||
%mat.normalMap = %obj.normalMap;
|
%mat.normalMap = %obj.normalMap;
|
||||||
%mat.detailMap = %obj.detailMap;
|
%mat.detailMap = %obj.detailMap;
|
||||||
|
%mat.compositeMap = %obj.compositeMap;
|
||||||
%mat.macroMap = %obj.macroMap;
|
%mat.macroMap = %obj.macroMap;
|
||||||
%mat.detailSize = %obj.detailSize;
|
%mat.detailSize = %obj.detailSize;
|
||||||
%mat.diffuseSize = %obj.diffuseSize;
|
%mat.diffuseSize = %obj.diffuseSize;
|
||||||
|
|
|
||||||
|
|
@ -61,3 +61,21 @@ function EditorLightingMenu::onMenuSelect( %this )
|
||||||
//%selSize = EWorldEditor.getSelectionSize();
|
//%selSize = EWorldEditor.getSelectionSize();
|
||||||
%this.enableItem( 1, true /*%selSize == 1*/ );
|
%this.enableItem( 1, true /*%selSize == 1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateReflectionProbes()
|
||||||
|
{
|
||||||
|
/*%probeIds = parseMissionGroupForIds("ReflectionProbe", "");
|
||||||
|
%probeCount = getWordCount(%probeIds);
|
||||||
|
|
||||||
|
for(%i=0; %i < %probeCount; %i++)
|
||||||
|
{
|
||||||
|
%probe = getWord(%probeIds, %i);
|
||||||
|
|
||||||
|
%path = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
||||||
|
%probe.bake(%path, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
EWorldEditor.isDirty = true;*/
|
||||||
|
|
||||||
|
Canvas.pushDialog(ProbeBakeDlg);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,8 @@ function EditorGui::buildMenus(%this)
|
||||||
item[0] = "Full Relight" TAB "Alt L" TAB "Editor.lightScene(\"\", forceAlways);";
|
item[0] = "Full Relight" TAB "Alt L" TAB "Editor.lightScene(\"\", forceAlways);";
|
||||||
item[1] = "Toggle ShadowViz" TAB "" TAB "toggleShadowViz();";
|
item[1] = "Toggle ShadowViz" TAB "" TAB "toggleShadowViz();";
|
||||||
item[2] = "-";
|
item[2] = "-";
|
||||||
|
item[3] = "Update Reflection Probes" TAB "" TAB "updateReflectionProbes();";
|
||||||
|
item[4] = "-";
|
||||||
|
|
||||||
// NOTE: The light managers will be inserted as the
|
// NOTE: The light managers will be inserted as the
|
||||||
// last menu items in EditorLightingMenu::onAdd().
|
// last menu items in EditorLightingMenu::onAdd().
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
function ProbeBakeDlg::onWake(%this)
|
||||||
|
{
|
||||||
|
//set up
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "32" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "64" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "128" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "256" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "512" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "1024" );
|
||||||
|
ProbeBakeDlg_ProbeResList.add( "2048" );
|
||||||
|
|
||||||
|
ProbeBakeDlg_ProbeResList.setSelected( 1, false );
|
||||||
|
|
||||||
|
ProbeBakeDlg_NumIterTxt.setText("1");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProbeBakeDlg_RunBake::onClick(%this)
|
||||||
|
{
|
||||||
|
%probeIds = parseMissionGroupForIds("ReflectionProbe", "");
|
||||||
|
%skylightIds = parseMissionGroupForIds("Skylight", "");
|
||||||
|
|
||||||
|
%probeIds = rtrim(ltrim(%probeIds SPC %skylightIds));
|
||||||
|
%probeCount = getWordCount(%probeIds);
|
||||||
|
|
||||||
|
%numIter = ProbeBakeDlg_NumIterTxt.getText();
|
||||||
|
%resolution = ProbeBakeDlg_ProbeResList.getText();
|
||||||
|
%progressStep = 100 / (%numIter * %probeCount);
|
||||||
|
%currentProgressValue = 0;
|
||||||
|
|
||||||
|
ProbeBakeDlg_Progress.setValue(%currentProgressValue);
|
||||||
|
|
||||||
|
for(%iter=0; %iter < %numIter; %iter++)
|
||||||
|
{
|
||||||
|
for(%i=0; %i < %probeCount; %i++)
|
||||||
|
{
|
||||||
|
%probe = getWord(%probeIds, %i);
|
||||||
|
|
||||||
|
%path = filePath($Server::MissionFile) @ "/" @ fileBase($Server::MissionFile) @ "/probes/";
|
||||||
|
%probe.bake(%path, %resolution);
|
||||||
|
|
||||||
|
%currentProgressValue += %progressStep;
|
||||||
|
ProbeBakeDlg_Progress.setValue(%currentProgressValue);
|
||||||
|
Canvas.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EWorldEditor.isDirty = true;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue