From b19a4b22c827d457f2b7a76263d67322991307a4 Mon Sep 17 00:00:00 2001 From: Areloch Date: Sun, 16 Sep 2018 22:15:07 -0500 Subject: [PATCH] Implementation of reflection and skylight probes. Moves lighting math to the diffuse/specular two-channel logic. --- Engine/source/T3D/lighting/IBLUtilities.cpp | 573 ++++ Engine/source/T3D/lighting/IBLUtilities.h | 30 + .../source/T3D/lighting/reflectionProbe.cpp | 1285 ++++++++ Engine/source/T3D/lighting/reflectionProbe.h | 278 ++ Engine/source/T3D/lighting/skylight.cpp | 899 +++++ Engine/source/T3D/lighting/skylight.h | 212 ++ Engine/source/gfx/gfxEnums.h | 1 - .../advanced/advancedLightBinManager.cpp | 25 +- .../advanced/advancedLightBinManager.h | 4 + .../advanced/advancedLightingFeatures.cpp | 2 + .../glsl/advancedLightingFeaturesGLSL.cpp | 6 +- .../hlsl/advancedLightingFeaturesHLSL.cpp | 4 +- .../lighting/basic/basicLightManager.cpp | 2 + Engine/source/lighting/probeManager.cpp | 809 +++++ Engine/source/lighting/probeManager.h | 334 ++ .../source/materials/materialFeatureTypes.cpp | 2 + .../source/materials/materialFeatureTypes.h | 2 + .../materials/processedCustomMaterial.cpp | 5 + .../materials/processedShaderMaterial.cpp | 30 +- .../source/renderInstance/renderBinManager.h | 3 +- .../renderInstance/renderDeferredMgr.cpp | 12 +- .../source/renderInstance/renderDeferredMgr.h | 3 + .../renderInstance/renderPassManager.cpp | 6 + .../source/renderInstance/renderPassManager.h | 95 + .../source/renderInstance/renderProbeMgr.cpp | 956 ++++++ Engine/source/renderInstance/renderProbeMgr.h | 213 ++ .../source/shaderGen/GLSL/shaderFeatureGLSL.h | 25 + .../shaderGen/HLSL/shaderFeatureHLSL.cpp | 222 ++ .../source/shaderGen/HLSL/shaderFeatureHLSL.h | 26 + .../shaderGen/HLSL/shaderGenHLSLInit.cpp | 1 + Engine/source/shaderGen/shaderGenVars.cpp | 9 + Engine/source/shaderGen/shaderGenVars.h | 9 + .../source/terrain/glsl/terrFeatureGLSL.cpp | 205 +- Engine/source/terrain/glsl/terrFeatureGLSL.h | 20 +- .../source/terrain/hlsl/terrFeatureHLSL.cpp | 196 ++ Engine/source/terrain/hlsl/terrFeatureHLSL.h | 17 + Engine/source/terrain/terrCellMaterial.cpp | 51 +- Engine/source/terrain/terrCellMaterial.h | 3 + Engine/source/terrain/terrFeatureTypes.cpp | 1 + Engine/source/terrain/terrFeatureTypes.h | 1 + Engine/source/terrain/terrMaterial.cpp | 1 + Engine/source/terrain/terrMaterial.h | 5 + .../Full/game/art/shapes/Cheetah/materials.cs | 4 +- .../art/shapes/actors/Soldier/materials.cs | 24 +- .../Full/game/art/shapes/cube/materials.cs | 9 +- .../Full/game/art/shapes/station/materials.cs | 27 +- Templates/Full/game/art/terrains/materials.cs | 1 + .../Full/game/core/art/grids/materials.cs | 10 +- .../lighting/advanced/deferredShading.cs | 47 +- .../client/lighting/advanced/lightViz.cs | 10 +- .../client/lighting/advanced/shaders.cs | 131 +- .../scripts/client/lighting/basic/init.cs | 2 +- .../game/core/scripts/client/renderManager.cs | 3 +- Templates/Full/game/levels/AProbeTest.mis | 109 +- Templates/Full/game/levels/Empty Room.mis | 1543 ++++++++- Templates/Full/game/levels/Empty Terrain.mis | 98 +- .../Full/game/shaders/common/gl/lighting.glsl | 271 +- .../Full/game/shaders/common/gl/torque.glsl | 16 + .../Full/game/shaders/common/lighting.hlsl | 39 +- .../common/lighting/advanced/brdfLookupP.hlsl | 138 + .../common/lighting/advanced/cubemapV.hlsl | 37 + .../advanced/dbgLightMapVisualizeP.hlsl | 6 +- .../lighting/advanced/deferredShadingP.hlsl | 28 +- .../common/lighting/advanced/gl/cubemapV.glsl | 31 + .../advanced/gl/dbgLightMapVisualizeP.glsl | 6 +- .../advanced/gl/deferredClearGBufferP.glsl | 8 +- .../advanced/gl/deferredShadingP.glsl | 38 +- .../lighting/advanced/gl/irradianceP.glsl | 60 + .../lighting/advanced/gl/pointLightP.glsl | 18 +- .../lighting/advanced/gl/probeShadingP.glsl | 59 + .../advanced/gl/reflectionProbeP.glsl | 229 ++ .../advanced/gl/reflectionProbeV.glsl | 32 + .../lighting/advanced/gl/spotLightP.glsl | 22 +- .../lighting/advanced/gl/vectorLightP.glsl | 40 +- .../common/lighting/advanced/irradianceP.hlsl | 63 + .../common/lighting/advanced/pointLightP.hlsl | 190 +- .../common/lighting/advanced/prefilterP.hlsl | 130 + .../lighting/advanced/probeShadingP.hlsl | 52 + .../lighting/advanced/reflectionProbeP.hlsl | 217 ++ .../common/lighting/advanced/skylightP.hlsl | 145 + .../lighting/advanced/vectorLightP.hlsl | 206 +- .../common/postFx/hdr/finalPassCombineP.hlsl | 15 +- .../postFx/hdr/gl/finalPassCombineP.glsl | 34 +- .../Full/game/shaders/common/torque.hlsl | 34 + .../shaders/common/water/gl/waterBasicP.glsl | 1 - .../game/shaders/common/water/gl/waterP.glsl | 1 - .../Full/game/shaders/procedural/.gitignore | 1 + .../tools/resources/ReflectProbeSphere.dae | 115 + .../Full/game/tools/resources/materials.cs | 8 + .../resources/reflectionProbePreviewP.hlsl | 49 + .../resources/reflectionProbePreviewV.hlsl | 58 + .../gui/guiTerrainMaterialDlg.ed.gui | 2913 +++++++++-------- .../worldEditor/gui/objectBuilderGui.ed.gui | 18 + .../tools/worldEditor/gui/probeBakeDlg.gui | 192 ++ Templates/Full/game/tools/worldEditor/main.cs | 9 +- .../worldEditor/scripts/editors/creator.ed.cs | 4 + .../interfaces/terrainMaterialDlg.ed.cs | 40 +- .../tools/worldEditor/scripts/lighting.ed.cs | 18 + .../tools/worldEditor/scripts/menus.ed.cs | 2 + .../tools/worldEditor/scripts/probeBake.ed.cs | 48 + Tools/CMake/torque3d.cmake | 1 + Tools/CMake/torqueConfig.h.in | 14 - 102 files changed, 12346 insertions(+), 1911 deletions(-) create mode 100644 Engine/source/T3D/lighting/IBLUtilities.cpp create mode 100644 Engine/source/T3D/lighting/IBLUtilities.h create mode 100644 Engine/source/T3D/lighting/reflectionProbe.cpp create mode 100644 Engine/source/T3D/lighting/reflectionProbe.h create mode 100644 Engine/source/T3D/lighting/skylight.cpp create mode 100644 Engine/source/T3D/lighting/skylight.h create mode 100644 Engine/source/lighting/probeManager.cpp create mode 100644 Engine/source/lighting/probeManager.h create mode 100644 Engine/source/renderInstance/renderProbeMgr.cpp create mode 100644 Engine/source/renderInstance/renderProbeMgr.h create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/brdfLookupP.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/cubemapV.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/gl/cubemapV.glsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/gl/irradianceP.glsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/gl/probeShadingP.glsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeP.glsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeV.glsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/irradianceP.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/prefilterP.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/probeShadingP.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl create mode 100644 Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl create mode 100644 Templates/Full/game/shaders/procedural/.gitignore create mode 100644 Templates/Full/game/tools/resources/ReflectProbeSphere.dae create mode 100644 Templates/Full/game/tools/resources/materials.cs create mode 100644 Templates/Full/game/tools/resources/reflectionProbePreviewP.hlsl create mode 100644 Templates/Full/game/tools/resources/reflectionProbePreviewV.hlsl create mode 100644 Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui create mode 100644 Templates/Full/game/tools/worldEditor/scripts/probeBake.ed.cs diff --git a/Engine/source/T3D/lighting/IBLUtilities.cpp b/Engine/source/T3D/lighting/IBLUtilities.cpp new file mode 100644 index 000000000..8f2de0efe --- /dev/null +++ b/Engine/source/T3D/lighting/IBLUtilities.cpp @@ -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(Sim::findObject("AL_PreCapture")); + PostEffect *deferredShading = dynamic_cast(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; ysampleTexel(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; + } +}; \ No newline at end of file diff --git a/Engine/source/T3D/lighting/IBLUtilities.h b/Engine/source/T3D/lighting/IBLUtilities.h new file mode 100644 index 000000000..f4392d368 --- /dev/null +++ b/Engine/source/T3D/lighting/IBLUtilities.h @@ -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); +}; \ No newline at end of file diff --git a/Engine/source/T3D/lighting/reflectionProbe.cpp b/Engine/source/T3D/lighting/reflectionProbe.cpp new file mode 100644 index 000000000..e4bcfbed5 --- /dev/null +++ b/Engine/source/T3D/lighting/reflectionProbe.cpp @@ -0,0 +1,1285 @@ +//----------------------------------------------------------------------------- +// 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/reflectionProbe.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 +#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 "gfx/gfxTextureManager.h" +#include "T3D/lighting/IBLUtilities.h" + +extern bool gEditingMission; +extern ColorI gCanvasClearColor; +bool ReflectionProbe::smRenderReflectionProbes = true; +bool ReflectionProbe::smRenderPreviewProbes = true; + +IMPLEMENT_CO_NETOBJECT_V1(ReflectionProbe); + +ConsoleDocClass(ReflectionProbe, + "@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(ReflectProbeType, + "Type of mesh data available in a shape.\n" + "@ingroup gameObjects") +{ ProbeInfo::Sphere, "Sphere", "Sphere shaped" }, +{ ProbeInfo::Box, "Box", "Box shape" } +EndImplementEnumType; + +ImplementEnumType(IndrectLightingModeEnum, + "Type of mesh data available in a shape.\n" + "@ingroup gameObjects") +{ ReflectionProbe::NoIndirect, "No Lighting", "This probe does not provide any local indirect lighting data" }, +{ ReflectionProbe::AmbientColor, "Ambient Color", "Adds a flat color to act as the local indirect lighting" }, +{ ReflectionProbe::SphericalHarmonics, "Spherical Harmonics", "Creates spherical harmonics data based off the reflection data" }, + EndImplementEnumType; + +ImplementEnumType(ReflectionModeEnum, + "Type of mesh data available in a shape.\n" + "@ingroup gameObjects") +{ ReflectionProbe::NoReflection, "No Reflections", "This probe does not provide any local reflection data"}, +{ ReflectionProbe::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" }, +{ ReflectionProbe::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" }, +//{ ReflectionProbe::DynamicCubemap, "Dynamic Cubemap", "Uses a cubemap baked from the probe's current position, updated at a set rate" }, + EndImplementEnumType; + +//----------------------------------------------------------------------------- +// Object setup and teardown +//----------------------------------------------------------------------------- +ReflectionProbe::ReflectionProbe() +{ + // Flag this object so that it will always + // be sent across the network to clients + mNetFlags.set(Ghostable | ScopeAlways); + + mTypeMask = LightObjectType | MarkerObjectType; + + mProbeShapeType = ProbeInfo::Sphere; + + mIndrectLightingModeType = NoIndirect; + mAmbientColor = LinearColorF(1, 1, 1, 1); + mSphericalHarmonics = LinearColorF(0, 0, 0, 1); + + mReflectionModeType = BakedCubemap; + + mEnabled = true; + mBake = false; + mDirty = false; + + mRadius = 10; + + mUseCubemap = false; + mCubemap = NULL; + mReflectionPath = ""; + mProbeUniqueID = ""; + + mEditorShapeInst = NULL; + mEditorShape = NULL; + + mRefreshRateMS = 200; + mDynamicLastBakeMS = 0; + + mMaxDrawDistance = 75; + + mResourcesCreated = false; + + mProbeInfo = new ProbeInfo(); + + mPrefilterSize = 64; + mPrefilterMipLevels = mLog2(F32(mPrefilterSize)); +} + +ReflectionProbe::~ReflectionProbe() +{ + if (mEditorShapeInst) + SAFE_DELETE(mEditorShapeInst); + + if (mReflectionModeType != StaticCubemap && mCubemap) + mCubemap->deleteObject(); +} + +//----------------------------------------------------------------------------- +// Object Editing +//----------------------------------------------------------------------------- +void ReflectionProbe::initPersistFields() +{ + addGroup("Rendering"); + addProtectedField("enabled", TypeBool, Offset(mEnabled, ReflectionProbe), + &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid"); + + addField("ProbeShape", TypeReflectProbeType, Offset(mProbeShapeType, ReflectionProbe), + "The type of mesh data to use for collision queries."); + addField("radius", TypeF32, Offset(mRadius, ReflectionProbe), "The name of the material used to render the mesh."); + endGroup("Rendering"); + + /*addGroup("IndirectLighting"); + addField("IndirectLightMode", TypeIndrectLightingModeEnum, Offset(mIndrectLightingModeType, ReflectionProbe), + "The type of mesh data to use for collision queries."); + + addField("IndirectLight", TypeColorF, Offset(mAmbientColor, ReflectionProbe), "Path of file to save and load results."); + endGroup("IndirectLighting");*/ + + addGroup("Reflection"); + addField("ReflectionMode", TypeReflectionModeEnum, Offset(mReflectionModeType, ReflectionProbe), + "The type of mesh data to use for collision queries."); + + addField("reflectionPath", TypeImageFilename, Offset(mReflectionPath, ReflectionProbe), + "The type of mesh data to use for collision queries."); + + addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, ReflectionProbe), "Cubemap used instead of reflection texture if fullReflect is off."); + + addProtectedField("Bake", TypeBool, Offset(mBake, ReflectionProbe), + &_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors); + endGroup("Reflection"); + + Con::addVariable("$Light::renderReflectionProbes", TypeBool, &ReflectionProbe::smRenderReflectionProbes, + "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, &ReflectionProbe::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"); + + /*addGroup("Internal"); + + addProtectedField("SHTerm", TypeRealString, NULL, &protectedSetSHTerms, &defaultProtectedGetFn, + "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors); + + addProtectedField("SHConsts", TypeRealString, NULL, &protectedSetSHConsts, &defaultProtectedGetFn, + "Do not modify, for internal use.", AbstractClassRep::FIELD_HideInInspectors); + + endGroup("Internal");*/ + + // SceneObject already handles exposing the transform + Parent::initPersistFields(); +} + +bool ReflectionProbe::protectedSetSHTerms(void *object, const char *index, const char *data) +{ + ReflectionProbe *probe = static_cast< ReflectionProbe* >(object); + + LinearColorF term; + U32 idx; + + dSscanf(data, "%i %g %g %g", &idx, &term.red, &term.green, &term.blue); + + probe->mProbeInfo->mSHTerms[idx] = term; + + return false; +} + +bool ReflectionProbe::protectedSetSHConsts(void *object, const char *index, const char *data) +{ + ReflectionProbe *probe = static_cast< ReflectionProbe* >(object); + + dSscanf(data, "%g %g %g %g %g", &probe->mProbeInfo->mSHConstants[0], + &probe->mProbeInfo->mSHConstants[1], &probe->mProbeInfo->mSHConstants[2], &probe->mProbeInfo->mSHConstants[3], &probe->mProbeInfo->mSHConstants[4]); + + return false; +} + +void ReflectionProbe::writeFields(Stream &stream, U32 tabStop) +{ + Parent::writeFields(stream, tabStop); + + if (mIndrectLightingModeType != SphericalHarmonics) + return; + + // Now write all planes. + + stream.write(2, "\r\n"); + + for (U32 i = 0; i < 9; i++) + { + const LinearColorF shTerm = mProbeInfo->mSHTerms[i]; + + stream.writeTabs(tabStop); + + char buffer[1024]; + dMemset(buffer, 0, 1024); + + dSprintf(buffer, 1024, "SHTerm = \"%i %g %g %g\";", i, shTerm.red, shTerm.green, shTerm.blue); + + stream.writeLine((const U8*)buffer); + } + + stream.writeTabs(tabStop); + + char buffer[1024]; + dMemset(buffer, 0, 1024); + + dSprintf(buffer, 1024, "SHConsts = \"%g %g %g %g %g\";", mProbeInfo->mSHConstants[0], + mProbeInfo->mSHConstants[1], mProbeInfo->mSHConstants[2], mProbeInfo->mSHConstants[3], mProbeInfo->mSHConstants[4]); + + stream.writeLine((const U8*)buffer); +} + +bool ReflectionProbe::writeField(StringTableEntry fieldname, const char *value) +{ + if (fieldname == StringTable->insert("SHTerm") || fieldname == StringTable->insert("SHConsts")) + return false; + + return Parent::writeField(fieldname, value); +} + +void ReflectionProbe::inspectPostApply() +{ + Parent::inspectPostApply(); + + mDirty = true; + + // Flag the network mask to send the updates + // to the client object + setMaskBits(-1); +} + +bool ReflectionProbe::_setEnabled(void *object, const char *index, const char *data) +{ + ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object); + + probe->mEnabled = dAtob(data); + probe->setMaskBits(-1); + + return true; +} + +bool ReflectionProbe::_doBake(void *object, const char *index, const char *data) +{ + ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object); + + if (probe->mDirty) + probe->bake(probe->mReflectionPath, 256); + + return false; +} + +bool ReflectionProbe::onAdd() +{ + if (!Parent::onAdd()) + return false; + + mObjBox.minExtents.set(-1, -1, -1); + mObjBox.maxExtents.set(1, 1, 1); + mObjScale.set(mRadius/2, mRadius/2, mRadius/2); + + // 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 ReflectionProbe::onRemove() +{ + // Remove this object from the scene + removeFromScene(); + + Parent::onRemove(); +} + +void ReflectionProbe::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 ReflectionProbe::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); + + // Write our transform information + if (stream->writeFlag(mask & TransformMask)) + { + mathWrite(*stream, getTransform()); + mathWrite(*stream, getScale()); + } + + if (stream->writeFlag(mask & ShapeTypeMask)) + { + stream->write((U32)mProbeShapeType); + } + + if (stream->writeFlag(mask & UpdateMask)) + { + stream->write(mAmbientColor); + stream->write(mRadius); + } + + 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)mIndrectLightingModeType); + stream->write((U32)mReflectionModeType); + } + + if (stream->writeFlag(mask & CubemapMask)) + { + stream->writeFlag(mUseCubemap); + stream->write(mCubemapName); + } + + return retMask; +} + +void ReflectionProbe::unpackUpdate(NetConnection *conn, BitStream *stream) +{ + // Let the Parent read any info it sent + Parent::unpackUpdate(conn, stream); + + if (stream->readFlag()) // TransformMask + { + mathRead(*stream, &mObjToWorld); + mathRead(*stream, &mObjScale); + + setTransform(mObjToWorld); + } + + if (stream->readFlag()) // ShapeTypeMask + { + U32 shapeType = ProbeInfo::Sphere; + stream->read(&shapeType); + + mProbeShapeType = (ProbeInfo::ProbeShapeType)shapeType; + createGeometry(); + } + + if (stream->readFlag()) // UpdateMask + { + stream->read(&mAmbientColor); + stream->read(&mRadius); + } + + 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 indirectModeType = AmbientColor; + stream->read(&indirectModeType); + mIndrectLightingModeType = (IndrectLightingModeType)indirectModeType; + + U32 reflectModeType = BakedCubemap; + stream->read(&reflectModeType); + mReflectionModeType = (ReflectionModeType)reflectModeType; + + isMaterialDirty = true; + } + + if (stream->readFlag()) // CubemapMask + { + mUseCubemap = stream->readFlag(); + + stream->read(&mCubemapName); + + isMaterialDirty = true; + } + + updateProbeParams(); + + if(isMaterialDirty) + updateMaterial(); +} + +void ReflectionProbe::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 ReflectionProbe::updateProbeParams() +{ + if (mProbeInfo == nullptr) + return; + + if (mIndrectLightingModeType == AmbientColor) + { + mProbeInfo->mAmbient = mAmbientColor; + } + else + { + mProbeInfo->mAmbient = LinearColorF(0, 0, 0, 0); + } + + mProbeInfo->mProbeShapeType = mProbeShapeType; + + mProbeInfo->setPosition(getPosition()); + + //Update the bounds + mObjBox.minExtents.set(-1, -1, -1); + mObjBox.maxExtents.set(1, 1, 1); + + mObjScale.set(mRadius / 2, mRadius / 2, mRadius / 2); + + // Skip our transform... it just dirties mask bits. + Parent::setTransform(mObjToWorld); + + resetWorldBox(); + + mProbeInfo->mBounds = mWorldBox; + mProbeInfo->mRadius = mRadius; + + mProbeInfo->mIsSkylight = false; +} + +void ReflectionProbe::updateMaterial() +{ + if (mReflectionModeType != DynamicCubemap) + { + if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty()) + { + bool validCubemap = true; + + char fileName[256]; + dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str()); + + Vector 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; + } + } + else if (mReflectionModeType == StaticCubemap && !mCubemapName.isEmpty()) + { + Sim::findObject(mCubemapName, mCubemap); + + mProbeInfo->mCubemap = &mCubemap->mCubemap; + } + } + else if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull()) + { + mProbeInfo->mCubemap = &mDynamicCubemap; + } + + generateTextures(); + + if (mPrefilterMap.isValid()) + { + mProbeInfo->mCubemap = &mPrefilterMap; + mProbeInfo->mIrradianceCubemap = &mIrridianceMap; + mProbeInfo->mBRDFTexture = &mBrdfTexture; + } + //calculateSHTerms(); +} + +bool ReflectionProbe::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 ReflectionProbe::generateTextures() +{ + if (!mCubemap) + return; + + if (!mResourcesCreated) + { + if (!createClientResources()) + { + Con::errorf("SkyLight::createIrridianceMap: Failed to create resources"); + return; + } + } + + GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false); + + //create irridiance cubemap + IBLUtilities::GenerateIrradianceMap(renderTarget, mCubemap->mCubemap, mIrridianceMap); + + //create prefilter cubemap (radiance) + IBLUtilities::GeneratePrefilterMap(renderTarget, mCubemap->mCubemap, mPrefilterMipLevels, mPrefilterMap); + + //create brdf lookup + IBLUtilities::GenerateBRDFTexture(mBrdfTexture); +} + +void ReflectionProbe::prepRenderImage(SceneRenderState *state) +{ + if (!mEnabled || !ReflectionProbe::smRenderReflectionProbes) + return; + + Point3F distVec = getRenderPosition() - state->getCameraPosition(); + F32 dist = distVec.len(); + + //Culling distance. Can be adjusted for performance options considerations via the scalar + if (dist > mMaxDrawDistance * Con::getFloatVariable("$pref::GI::ProbeDrawDistScale", 1.0)) + return; + + if (mReflectionModeType == DynamicCubemap && mRefreshRateMS < (Platform::getRealMilliseconds() - mDynamicLastBakeMS)) + { + bake("", 32); + mDynamicLastBakeMS = Platform::getRealMilliseconds(); + } + + //Submit our probe to actually do the probe action + // Get a handy pointer to our RenderPassmanager + //RenderPassManager *renderPass = state->getRenderPass(); + + //Update our score based on our radius, distance + mProbeInfo->mScore = mProbeInfo->mRadius/mMax(dist,1.0f); + + Point3F vect = distVec; + vect.normalizeSafe(); + + mProbeInfo->mScore *= mMax(mAbs(mDot(vect, state->getCameraTransform().getForwardVector())),0.001f); + + //Register + PROBEMGR->registerProbe(mProbeInfo, this); + + if (ReflectionProbe::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); + + if(mReflectionModeType != DynamicCubemap) + rdata.setCubemap(mCubemap->mCubemap); + else + rdata.setCubemap(mDynamicCubemap); + + // 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) + { + ObjectRenderInst *ri = state->getRenderPass()->allocInst(); + ri->renderDelegate.bind(this, &ReflectionProbe::_onRenderViz); + ri->type = RenderPassManager::RIT_Editor; + state->getRenderPass()->addInst(ri); + } +} + +void ReflectionProbe::_onRenderViz(ObjectRenderInst *ri, + SceneRenderState *state, + BaseMatInstance *overrideMat) +{ + if (!ReflectionProbe::smRenderReflectionProbes) + return; + + GFXDrawUtil *draw = GFX->getDrawUtil(); + + GFXStateBlockDesc desc; + desc.setZReadWrite(true, false); + desc.setCullMode(GFXCullNone); + desc.setBlend(true); + + // Base the sphere color on the light color. + ColorI color = ColorI::WHITE; + color.alpha = 50; + + if (mProbeShapeType == ProbeInfo::Sphere) + { + draw->drawSphere(desc, mRadius, getPosition(), color); + } + else + { + Box3F cube(mRadius); + cube.setCenter(getPosition()); + draw->drawCube(desc, cube, color); + } +} + +void ReflectionProbe::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); +} + +LinearColorF ReflectionProbe::decodeSH(Point3F normal) +{ + float x = normal.x; + float y = normal.y; + float z = normal.z; + + LinearColorF l00 = mProbeInfo->mSHTerms[0]; + + LinearColorF l10 = mProbeInfo->mSHTerms[1]; + LinearColorF l11 = mProbeInfo->mSHTerms[2]; + LinearColorF l12 = mProbeInfo->mSHTerms[3]; + + LinearColorF l20 = mProbeInfo->mSHTerms[4]; + LinearColorF l21 = mProbeInfo->mSHTerms[5]; + LinearColorF l22 = mProbeInfo->mSHTerms[6]; + LinearColorF l23 = mProbeInfo->mSHTerms[7]; + LinearColorF l24 = mProbeInfo->mSHTerms[8]; + + LinearColorF result = ( + l00 * mProbeInfo->mSHConstants[0] + + + l12 * mProbeInfo->mSHConstants[1] * x + + l10 * mProbeInfo->mSHConstants[1] * y + + l11 * mProbeInfo->mSHConstants[1] * z + + + l20 * mProbeInfo->mSHConstants[2] * x*y + + l21 * mProbeInfo->mSHConstants[2] * y*z + + l22 * mProbeInfo->mSHConstants[3] * (3.0*z*z - 1.0) + + l23 * mProbeInfo->mSHConstants[2] * x*z + + l24 * mProbeInfo->mSHConstants[4] * (x*x - y*y) + ); + + return LinearColorF(mMax(result.red, 0), mMax(result.green, 0), mMax(result.blue, 0)); +} + +MatrixF ReflectionProbe::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 ReflectionProbe::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 ReflectionProbe::sampleSide(U32 termindex, U32 sideIndex) +{ + MatrixF sideRot = getSideMatrix(sideIndex); + + LinearColorF result = LinearColorF::ZERO; + F32 divider = 0; + + for (int y = 0; ysampleTexel(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 ReflectionProbe::calculateSHTerms() +{ + if (!mCubemap || !mCubemap->mCubemap) + 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), + }; + + mCubemapResolution = mCubemap->mCubemap->getSize(); + + for (U32 i = 0; i < 6; i++) + { + mCubeFaceBitmaps[i] = new GBitmap(mCubemapResolution, mCubemapResolution, false, GFXFormatR8G8B8); + } + + //If we fail to parse the cubemap for whatever reason, we really can't continue + if (!CubemapSaver::getBitmaps(mCubemap->mCubemap, GFXFormatR8G8B8, mCubeFaceBitmaps)) + 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); + + mProbeInfo->mSHConstants[0] = L0; + mProbeInfo->mSHConstants[1] = L1; + mProbeInfo->mSHConstants[2] = L2 * L2m2_L2m1_L21; + mProbeInfo->mSHConstants[3] = L2 * L20; + mProbeInfo->mSHConstants[4] = L2 * L22; + + for (U32 i = 0; i < 9; i++) + { + //Clear it, just to be sure + mProbeInfo->mSHTerms[i] = LinearColorF(0.f, 0.f, 0.f); + + //Now, encode for each side + mProbeInfo->mSHTerms[i] = sampleSide(i, 0); //POS_X + mProbeInfo->mSHTerms[i] += sampleSide(i, 1); //NEG_X + mProbeInfo->mSHTerms[i] += sampleSide(i, 2); //POS_Y + mProbeInfo->mSHTerms[i] += sampleSide(i, 3); //NEG_Y + mProbeInfo->mSHTerms[i] += sampleSide(i, 4); //POS_Z + mProbeInfo->mSHTerms[i] += sampleSide(i, 5); //NEG_Z + + //Average + mProbeInfo->mSHTerms[i] /= 6; + } + + for (U32 i = 0; i < 6; i++) + SAFE_DELETE(mCubeFaceBitmaps[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->mSHTerms[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 ReflectionProbe::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; +} + +F32 ReflectionProbe::areaElement(F32 x, F32 y) +{ + return mAtan2(x * y, (F32)mSqrt(x * x + y * y + 1.0)); +} + +DefineEngineMethod(ReflectionProbe, postApply, void, (), , + "A utility method for forcing a network update.\n") +{ + object->inspectPostApply(); +} + +void ReflectionProbe::bake(String outputPath, S32 resolution) +{ + GFXDEBUGEVENT_SCOPE(ReflectionProbe_Bake, ColorI::WHITE); + + PostEffect *preCapture = dynamic_cast(Sim::findObject("AL_PreCapture")); + PostEffect *deferredShading = dynamic_cast(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) + { + 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; + + bitmap.deleteImage(); + } + }*/ + + 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(); +} + +DefineEngineMethod(ReflectionProbe, Bake, void, (String outputPath, S32 resolution), ("", 256), + "@brief returns true if control object is inside the fog\n\n.") +{ + object->bake(outputPath, resolution); +} \ No newline at end of file diff --git a/Engine/source/T3D/lighting/reflectionProbe.h b/Engine/source/T3D/lighting/reflectionProbe.h new file mode 100644 index 000000000..1fa3fad8a --- /dev/null +++ b/Engine/source/T3D/lighting/reflectionProbe.h @@ -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 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_ \ No newline at end of file diff --git a/Engine/source/T3D/lighting/skylight.cpp b/Engine/source/T3D/lighting/skylight.cpp new file mode 100644 index 000000000..b6ca9120f --- /dev/null +++ b/Engine/source/T3D/lighting/skylight.cpp @@ -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 +#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 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(Sim::findObject("AL_PreCapture")); + PostEffect *deferredShading = dynamic_cast(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); +} \ No newline at end of file diff --git a/Engine/source/T3D/lighting/skylight.h b/Engine/source/T3D/lighting/skylight.h new file mode 100644 index 000000000..f71c2eeeb --- /dev/null +++ b/Engine/source/T3D/lighting/skylight.h @@ -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 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_ \ No newline at end of file diff --git a/Engine/source/gfx/gfxEnums.h b/Engine/source/gfx/gfxEnums.h index 12a7337b8..464e5fc59 100644 --- a/Engine/source/gfx/gfxEnums.h +++ b/Engine/source/gfx/gfxEnums.h @@ -497,7 +497,6 @@ enum GFXTextureTransformFlags // 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] #define TEXTURE_STAGE_COUNT 32 -#define TEXTURE_STAGE_COUNT 16 enum GFXSamplerState { diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index 6cfb8510d..eb7a44bd4 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -40,9 +40,10 @@ #include "gfx/gfxDebugEvent.h" #include "math/util/matrixSet.h" #include "console/consoleTypes.h" +#include "gfx/gfxTextureManager.h" -const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "directLighting" ); -const String AdvancedLightBinManager::smBufferName( "directLighting" ); +const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "specularLighting" ); +const String AdvancedLightBinManager::smBufferName( "specularLighting" ); ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality; bool AdvancedLightBinManager::smPSSMDebugRender = false; @@ -180,6 +181,26 @@ bool AdvancedLightBinManager::setTargetSize(const Point2I &newTargetSize) 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 ) { // Get the light type. diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.h b/Engine/source/lighting/advanced/advancedLightBinManager.h index 1e13665f5..3ef926928 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.h +++ b/Engine/source/lighting/advanced/advancedLightBinManager.h @@ -90,6 +90,9 @@ public: // registered buffer name static const String smBufferName; + NamedTexTargetRef mDiffuseLightingTarget; + GFXTexHandle mDiffuseLightingTex; + /// The shadow filter mode to use on shadowed light materials. static ShadowFilterMode smShadowFilterMode; @@ -128,6 +131,7 @@ public: bool MRTLightmapsDuringDeferred() const { return mMRTLightmapsDuringDeferred; } void MRTLightmapsDuringDeferred(bool val); + bool _updateTargets(); typedef Signal RenderSignal; static RenderSignal &getRenderSignal(); diff --git a/Engine/source/lighting/advanced/advancedLightingFeatures.cpp b/Engine/source/lighting/advanced/advancedLightingFeatures.cpp index ae29f1c81..1a58c3431 100644 --- a/Engine/source/lighting/advanced/advancedLightingFeatures.cpp +++ b/Engine/source/lighting/advanced/advancedLightingFeatures.cpp @@ -63,6 +63,7 @@ void AdvancedLightingFeatures::registerFeatures( const GFXFormat &deferredTarget FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularGLSL()); FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertGLSL()); FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceGLSL()); + FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL); #endif } else @@ -75,6 +76,7 @@ void AdvancedLightingFeatures::registerFeatures( const GFXFormat &deferredTarget FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularHLSL()); FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertHLSL()); FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceHLSL()); + FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL); #endif } diff --git a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp index 70207bafe..f10be1b7c 100644 --- a/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp +++ b/Engine/source/lighting/advanced/glsl/advancedLightingFeaturesGLSL.cpp @@ -98,7 +98,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component uvScene->setName( "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 ); if( !rtParams ) { @@ -121,7 +121,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector &component // create texture var Var *lightInfoBuffer = new Var; lightInfoBuffer->setType( "sampler2D" ); - lightInfoBuffer->setName( "directLightingBuffer" ); + lightInfoBuffer->setName( "diffuseLightingBuffer" ); lightInfoBuffer->uniform = true; lightInfoBuffer->sampler = true; lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here @@ -207,7 +207,7 @@ void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat, mLastTexIndex = texIndex; passData.mTexType[ texIndex ] = Material::TexTarget; - passData.mSamplerNames[ texIndex ]= "directLightingBuffer"; + passData.mSamplerNames[ texIndex ]= "diffuseLightingBuffer"; passData.mTexSlot[ texIndex++ ].texTarget = texTarget; } } diff --git a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp index e4731df6c..ad426499e 100644 --- a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp @@ -99,7 +99,7 @@ void DeferredRTLightingFeatHLSL::processPix( Vector &component uvScene->setName("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); if (!rtParams) { @@ -215,7 +215,7 @@ void DeferredRTLightingFeatHLSL::setTexData( Material::StageData &stageDat, mLastTexIndex = texIndex; passData.mTexType[ texIndex ] = Material::TexTarget; - passData.mSamplerNames[ texIndex ]= "directLightingBuffer"; + passData.mSamplerNames[ texIndex ]= "diffuseLightingBuffer"; passData.mTexSlot[ texIndex++ ].texTarget = texTarget; } } diff --git a/Engine/source/lighting/basic/basicLightManager.cpp b/Engine/source/lighting/basic/basicLightManager.cpp index d3385dfe8..903121fcc 100644 --- a/Engine/source/lighting/basic/basicLightManager.cpp +++ b/Engine/source/lighting/basic/basicLightManager.cpp @@ -168,6 +168,7 @@ void BasicLightManager::activate( SceneManager *sceneManager ) FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL ); FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL ); FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularGLSL ); + FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL); #endif } else @@ -178,6 +179,7 @@ void BasicLightManager::activate( SceneManager *sceneManager ) FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL ); FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL ); FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL ); + FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL); #endif } diff --git a/Engine/source/lighting/probeManager.cpp b/Engine/source/lighting/probeManager.cpp new file mode 100644 index 000000000..d3cc41f5e --- /dev/null +++ b/Engine/source/lighting/probeManager.cpp @@ -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 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; igetReloadSignal().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 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( 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(); + + 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(); + + 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 *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 probePositions(4, sizeof(Point3F)); + static AlignedArray probeRadius(4, sizeof(F32)); + static AlignedArray probeBoxMins(4, sizeof(Point3F)); + static AlignedArray probeBoxMaxs(4, sizeof(Point3F)); + static AlignedArray probeLocalPositions(4, sizeof(Point3F)); + static AlignedArray probeIsSphere(4, sizeof(F32)); + //static AlignedArray 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 );*/ +} diff --git a/Engine/source/lighting/probeManager.h b/Engine/source/lighting/probeManager.h new file mode 100644 index 000000000..587af580b --- /dev/null +++ b/Engine/source/lighting/probeManager.h @@ -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 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 +{ +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 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 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 *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 diff --git a/Engine/source/materials/materialFeatureTypes.cpp b/Engine/source/materials/materialFeatureTypes.cpp index f0407e543..fd6134381 100644 --- a/Engine/source/materials/materialFeatureTypes.cpp +++ b/Engine/source/materials/materialFeatureTypes.cpp @@ -62,6 +62,8 @@ ImplementFeatureType( MFT_SubSurface, MFG_Lighting, 8.0f, true ); ImplementFeatureType( MFT_VertLit, MFG_Lighting, 9.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_Visibility, MFG_PostLighting, 2.0f, true ); ImplementFeatureType( MFT_Fog, MFG_PostProcess, 3.0f, true ); diff --git a/Engine/source/materials/materialFeatureTypes.h b/Engine/source/materials/materialFeatureTypes.h index e38cdc31a..89640292b 100644 --- a/Engine/source/materials/materialFeatureTypes.h +++ b/Engine/source/materials/materialFeatureTypes.h @@ -129,6 +129,8 @@ DeclareFeatureType( MFT_InvertSmoothness ); DeclareFeatureType( MFT_SpecularMap ); DeclareFeatureType( MFT_GlossMap ); +DeclareFeatureType( MFT_ReflectionProbes ); + /// This feature is only used to detect alpha transparency /// and does not have any code associtated with it. DeclareFeatureType( MFT_IsTranslucent ); diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 365676d44..df68780b6 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/Engine/source/materials/processedCustomMaterial.cpp @@ -40,6 +40,7 @@ #include "console/propertyParsing.h" #include "gfx/util/screenspace.h" #include "scene/reflectionManager.h" +#include "lighting/probeManager.h" ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat) @@ -322,6 +323,10 @@ bool ProcessedCustomMaterial::setupPass( SceneRenderState *state, const SceneDat if (lm) 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()); return true; diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index afee72800..a171e5c13 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -41,6 +41,8 @@ #include "gfx/util/screenspace.h" #include "math/util/matrixSet.h" +#include "lighting/probeManager.h" + // We need to include customMaterialDefinition for ShaderConstHandles::init #include "materials/customMaterialDefinition.h" @@ -343,10 +345,16 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, if ( mMaterial->mAlphaTest ) fd.features.addFeature( MFT_AlphaTest ); - if ( mMaterial->mEmissive[stageNum] ) - fd.features.addFeature( MFT_IsEmissive ); + if (mMaterial->mEmissive[stageNum]) + { + fd.features.addFeature(MFT_IsEmissive); + } else - fd.features.addFeature( MFT_RTLighting ); + { + fd.features.addFeature(MFT_RTLighting); + if (mMaterial->isTranslucent()) + fd.features.addFeature(MFT_ReflectionProbes); + } if ( mMaterial->mAnimFlags[stageNum] ) fd.features.addFeature( MFT_TexAnim ); @@ -357,7 +365,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, // cubemaps only available on stage 0 for now - bramage if ( stageNum < 1 && mMaterial->isTranslucent() && ( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) || - mMaterial->mDynamicCubemap ) ) + mMaterial->mDynamicCubemap ) && !features.hasFeature(MFT_ReflectionProbes)) { fd.features.addFeature( MFT_CubeMap ); } @@ -367,6 +375,8 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, fd.features.addFeature(MFT_StaticCubemap); fd.features.addFeature(MFT_CubeMap); fd.features.addFeature(MFT_SkyBox); + + fd.features.removeFeature(MFT_ReflectionProbes); } fd.features.addFeature( MFT_Visibility ); @@ -1296,13 +1306,15 @@ void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const Scene shaderConsts->set(handles->mEyePosSC, eyepos); } - shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform()); + shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform()); - ShaderRenderPassData *rpd = _getRPD( pass ); - for ( U32 i=0; i < rpd->featureShaderHandles.size(); i++ ) - rpd->featureShaderHandles[i]->setConsts( state, sgData, shaderConsts ); + ShaderRenderPassData *rpd = _getRPD(pass); + for (U32 i = 0; i < rpd->featureShaderHandles.size(); i++) + 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 ) diff --git a/Engine/source/renderInstance/renderBinManager.h b/Engine/source/renderInstance/renderBinManager.h index 2a1a4cbb5..4097aa7bb 100644 --- a/Engine/source/renderInstance/renderBinManager.h +++ b/Engine/source/renderInstance/renderBinManager.h @@ -86,8 +86,6 @@ public: MaterialOverrideDelegate& getMatOverrideDelegate() { return mMatOverrideDelegate; } -protected: - struct MainSortElem { RenderInst *inst; @@ -95,6 +93,7 @@ protected: U32 key2; }; +protected: void setRenderPass( RenderPassManager *rpm ); /// Called from derived bins to add additional diff --git a/Engine/source/renderInstance/renderDeferredMgr.cpp b/Engine/source/renderInstance/renderDeferredMgr.cpp index 346a5ee76..4ceac2aca 100644 --- a/Engine/source/renderInstance/renderDeferredMgr.cpp +++ b/Engine/source/renderInstance/renderDeferredMgr.cpp @@ -56,7 +56,7 @@ const String RenderDeferredMgr::BufferName("deferred"); const RenderInstType RenderDeferredMgr::RIT_Deferred("Deferred"); const String RenderDeferredMgr::ColorBufferName("color"); const String RenderDeferredMgr::MatInfoBufferName("matinfo"); -const String RenderDeferredMgr::LightMapBufferName("indirectLighting"); +const String RenderDeferredMgr::LightMapBufferName("diffuseLighting"); IMPLEMENT_CONOBJECT(RenderDeferredMgr); @@ -92,6 +92,7 @@ RenderDeferredMgr::RenderDeferredMgr( bool gatherDepth, notifyType( RenderPassManager::RIT_Mesh ); notifyType( RenderPassManager::RIT_Terrain ); notifyType( RenderPassManager::RIT_Object ); + notifyType( RenderPassManager::RIT_Probes ); // We want a full-resolution buffer mTargetSizeType = RenderTexTargetBinManager::WindowSize; @@ -186,10 +187,10 @@ bool RenderDeferredMgr::_updateTargets() 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(); - mLightMapTex.set(mTargetSize.x, mTargetSize.y, mTargetFormat, + mLightMapTex.set(mTargetSize.x, mTargetSize.y, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, avar("%s() - (line %d)", __FUNCTION__, __LINE__), 1, GFXTextureManager::AA_MATCH_BACKBUFFER); mLightMapTarget.setTexture(mLightMapTex); @@ -238,6 +239,8 @@ void RenderDeferredMgr::addElement( RenderInst *inst ) const bool isTerrainInst = inst->type == RenderPassManager::RIT_Terrain; + const bool isProbeInst = inst->type == RenderPassManager::RIT_Probes; + // Get the material if its a mesh. BaseMatInstance* matInst = NULL; if ( isMeshInst || isDecalMeshInst ) @@ -262,6 +265,8 @@ void RenderDeferredMgr::addElement( RenderInst *inst ) elementList = &mElementList; else if ( isTerrainInst ) elementList = &mTerrainElementList; + else if (isProbeInst) + elementList = &mProbeElementList; else elementList = &mObjectElementList; @@ -294,6 +299,7 @@ void RenderDeferredMgr::sort() void RenderDeferredMgr::clear() { Parent::clear(); + mProbeElementList.clear(); mTerrainElementList.clear(); mObjectElementList.clear(); } diff --git a/Engine/source/renderInstance/renderDeferredMgr.h b/Engine/source/renderInstance/renderDeferredMgr.h index ef4e1ada9..35ff93406 100644 --- a/Engine/source/renderInstance/renderDeferredMgr.h +++ b/Engine/source/renderInstance/renderDeferredMgr.h @@ -92,6 +92,9 @@ protected: DeferredMatInstance *mDeferredMatInstance; + /// + Vector< MainSortElem > mProbeElementList; + virtual void _registerFeatures(); virtual void _unregisterFeatures(); virtual bool _updateTargets(); diff --git a/Engine/source/renderInstance/renderPassManager.cpp b/Engine/source/renderInstance/renderPassManager.cpp index d4d5ad568..33e5f48b5 100644 --- a/Engine/source/renderInstance/renderPassManager.cpp +++ b/Engine/source/renderInstance/renderPassManager.cpp @@ -61,6 +61,7 @@ const RenderInstType RenderPassManager::RIT_Custom("Custom"); const RenderInstType RenderPassManager::RIT_Particle("Particle"); const RenderInstType RenderPassManager::RIT_Occluder("Occluder"); const RenderInstType RenderPassManager::RIT_Editor("Editor"); +const RenderInstType RenderPassManager::RIT_Probes("Probes"); //***************************************************************************** @@ -102,6 +103,11 @@ void OccluderRenderInst::clear() dMemset( this, 0, sizeof(OccluderRenderInst) ); } +void ProbeRenderInst::clear() +{ + dMemset(this, 0, sizeof(ProbeRenderInst)); + //mCubemap); +} IMPLEMENT_CONOBJECT(RenderPassManager); diff --git a/Engine/source/renderInstance/renderPassManager.h b/Engine/source/renderInstance/renderPassManager.h index 98080365b..85498e37c 100644 --- a/Engine/source/renderInstance/renderPassManager.h +++ b/Engine/source/renderInstance/renderPassManager.h @@ -37,6 +37,18 @@ #ifndef _SCENEMANAGER_H_ #include "scene/sceneManager.h" #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 ISceneObject; @@ -48,6 +60,7 @@ class LightInfo; struct RenderInst; class MatrixSet; class GFXPrimitiveBufferHandle; +class CubemapData; /// A RenderInstType hash value. typedef U32 RenderInstTypeHash; @@ -118,6 +131,7 @@ public: static const RenderInstType RIT_Particle; static const RenderInstType RIT_Occluder; static const RenderInstType RIT_Editor; + static const RenderInstType RIT_Probes; public: @@ -463,4 +477,85 @@ struct OccluderRenderInst : public RenderInst 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 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_ diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp new file mode 100644 index 000000000..120c4df00 --- /dev/null +++ b/Engine/source/renderInstance/renderProbeMgr.cpp @@ -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(((RenderBinManager::MainSortElem*)(a))->inst); + const ProbeRenderInst* pReflectProbeB = static_cast(((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(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 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; ipoly[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[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 ¯os = Vector(); + + 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 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()); + + 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 ¯os = Vector(); + + 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()); + + 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(); +} diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h new file mode 100644 index 000000000..fe1d196c2 --- /dev/null +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -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 mFarFrustumQuadVerts; + + GFXVertexBufferHandle getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBufferHandle &outPrimitives); + + // Convex geometry for lights + GFXVertexBufferHandle 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 \ No newline at end of file diff --git a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h index 057be5191..d6ef4772a 100644 --- a/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h +++ b/Engine/source/shaderGen/GLSL/shaderFeatureGLSL.h @@ -670,4 +670,29 @@ public: virtual String getName() { return "Hardware Skinning"; } }; +/// Reflection Probes +class ReflectionProbeFeatGLSL : public ShaderFeatureGLSL +{ +public: + virtual void processVert(Vector &componentList, + const MaterialFeatureData &fd) {} + + virtual void processPix(Vector &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_ diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 142eab703..aa856d503 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -2933,3 +2933,225 @@ void HardwareSkinningFeatureHLSL::processVert( Vector &compo output = meta; } + +//**************************************************************************** +// ReflectionProbeFeatHLSL +//**************************************************************************** + +ReflectionProbeFeatHLSL::ReflectionProbeFeatHLSL() + : mDep(String(Con::getVariable("$Core::CommonShaderPath")) + String("/lighting.hlsl")) +{ + addDependency(&mDep); +} + +void ReflectionProbeFeatHLSL::processPix(Vector &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(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; + } +} diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h index b4739c42c..6303ae641 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.h @@ -672,4 +672,30 @@ public: virtual String getName() { return "Hardware Skinning"; } }; +/// Reflection Probes +class ReflectionProbeFeatHLSL : public ShaderFeatureHLSL +{ +protected: + ShaderIncludeDependency mDep; + +public: + ReflectionProbeFeatHLSL(); + + virtual void processPix(Vector &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_ diff --git a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp index 03a867948..3c1512613 100644 --- a/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp +++ b/Engine/source/shaderGen/HLSL/shaderGenHLSLInit.cpp @@ -64,6 +64,7 @@ void _initShaderGenHLSL( ShaderGen *shaderGen ) FEATUREMGR->registerFeature( MFT_DetailMap, new DetailFeatHLSL ); FEATUREMGR->registerFeature( MFT_StaticCubemap, new NamedFeatureHLSL( "Static Cubemap" ) ); FEATUREMGR->registerFeature( MFT_CubeMap, new ReflectCubeFeatHLSL ); + FEATUREMGR->registerFeature( MFT_ReflectionProbes, new ReflectionProbeFeatHLSL); FEATUREMGR->registerFeature( MFT_PixSpecular, new PixelSpecularHLSL ); FEATUREMGR->registerFeature( MFT_InvertSmoothness, new NamedFeatureHLSL( "Roughest = 1.0" ) ); FEATUREMGR->registerFeature( MFT_IsTranslucent, new NamedFeatureHLSL( "Translucent" ) ); diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index 3682e9120..fc6b6f853 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/Engine/source/shaderGen/shaderGenVars.cpp @@ -68,6 +68,15 @@ const String ShaderGenVars::specularColor("$specularColor"); const String ShaderGenVars::smoothness("$smoothness"); const String ShaderGenVars::metalness("$metalness"); +//Reflection Probes +const String ShaderGenVars::probePosition("$inProbePos"); +const String ShaderGenVars::probeRadius("$inProbeRadius"); +const String ShaderGenVars::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. const String ShaderGenVars::fogMap("$fogMap"); const String ShaderGenVars::dlightMap("$dlightMap"); diff --git a/Engine/source/shaderGen/shaderGenVars.h b/Engine/source/shaderGen/shaderGenVars.h index fa8da875b..0b5e606e6 100644 --- a/Engine/source/shaderGen/shaderGenVars.h +++ b/Engine/source/shaderGen/shaderGenVars.h @@ -80,6 +80,15 @@ struct ShaderGenVars const static String specularColor; const static String smoothness; 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 const static String fogMap; diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp index 3a330df3f..faeca2d46 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.cpp +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.cpp @@ -49,6 +49,7 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureGLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatGLSL ); + FEATUREMGR->registerFeature( MFT_TerrainCompositeMap, new TerrainCompositeMapFeatGLSL ); FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatGLSL ); } @@ -141,6 +142,24 @@ Var* TerrainFeatGLSL::_getNormalMapTex() 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() { String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) ); @@ -203,7 +222,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis // So instead i fixed this by flipping the base and detail // 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 ) ); } @@ -223,7 +242,7 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis { Var *inNormal = (Var*)LangElement::find( "normal" ); 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 ) ); } else @@ -239,8 +258,8 @@ void TerrainBaseMapFeatGLSL::processVert( Vector &componentLis Var *inTangentZ = getVertTexCoord( "tcTangentZ" ); Var *inTanget = new Var( "T", "vec3" ); Var *squareSize = _getUniformVar( "squareSize", "float", cspPass ); - meta->addStatement( new GenOp( " @ = normalize( float3( @, 0, @ ) );\r\n", - new DecOp( inTanget ), squareSize, inTangentZ ) ); + meta->addStatement( new GenOp( " @ = normalize( vec3( @, 0, @ ) );\r\n", + new DecOp( inTanget ), squareSize, inTangentZ ) ); } void TerrainBaseMapFeatGLSL::processPix( Vector &componentList, @@ -334,7 +353,7 @@ void TerrainDetailMapFeatGLSL::processVert( Vector &component outNegViewTS->setName( "outNegViewTS" ); outNegViewTS->setStructName( "OUT" ); 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 ) ); } @@ -490,7 +509,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component { // create color var outColor = new Var; - outColor->setType("float4"); + outColor->setType("vec4"); outColor->setName("col"); outColor->setStructName("OUT"); meta->addStatement(new GenOp(" @;\r\n", outColor)); @@ -500,7 +519,7 @@ void TerrainDetailMapFeatGLSL::processPix( Vector &component if (!detailColor) { detailColor = new Var; - detailColor->setType("float4"); + detailColor->setType("vec4"); detailColor->setName("detailColor"); meta->addStatement(new GenOp(" @;\r\n", new DecOp(detailColor))); } @@ -1106,6 +1125,176 @@ void TerrainAdditiveFeatGLSL::processPix( Vector &componentLis //standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), //.b = specular strength, a= spec power. + + +void TerrainCompositeMapFeatGLSL::processVert(Vector &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(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(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 &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. //we'll most likely revisit that later. possibly several ways... @@ -1136,7 +1325,7 @@ void TerrainBlankInfoMapFeatGLSL::processPix(Vector &component 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; } diff --git a/Engine/source/terrain/glsl/terrFeatureGLSL.h b/Engine/source/terrain/glsl/terrFeatureGLSL.h index 7839558b1..fa024c609 100644 --- a/Engine/source/terrain/glsl/terrFeatureGLSL.h +++ b/Engine/source/terrain/glsl/terrFeatureGLSL.h @@ -45,7 +45,9 @@ public: Var* _getInMacroCoord(Vector &componentList ); Var* _getNormalMapTex(); - + + Var* _getCompositeMapTex(); + static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp ); Var* _getDetailIdStrengthParallax(); @@ -160,6 +162,22 @@ public: virtual String getName() { return "Terrain Additive"; } }; +class TerrainCompositeMapFeatGLSL : public TerrainFeatGLSL +{ +public: + + virtual void processVert(Vector &componentList, + const MaterialFeatureData &fd); + + virtual void processPix(Vector &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 { public: diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp index 0afe113df..62dd629a1 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.cpp @@ -49,6 +49,7 @@ namespace FEATUREMGR->registerFeature( MFT_TerrainLightMap, new TerrainLightMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainSideProject, new NamedFeatureHLSL( "Terrain Side Projection" ) ); FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL ); + FEATUREMGR->registerFeature( MFT_TerrainCompositeMap, new TerrainCompositeMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_DeferredTerrainBlankInfoMap, new TerrainBlankInfoMapFeatHLSL ); } }; @@ -140,6 +141,24 @@ Var* TerrainFeatHLSL::_getNormalMapTex() 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() { String name( String::ToString( "detailIdStrengthParallax%d", getProcessIndex() ) ); @@ -1116,6 +1135,183 @@ void TerrainAdditiveFeatHLSL::processPix( Vector &componentLis //standard matInfo map contains data of the form .r = bitflags, .g = (will contain AO), //.b = specular strength, a= spec power. + +void TerrainCompositeMapFeatHLSL::processVert(Vector &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(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(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 &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. //we'll most likely revisit that later. possibly several ways... diff --git a/Engine/source/terrain/hlsl/terrFeatureHLSL.h b/Engine/source/terrain/hlsl/terrFeatureHLSL.h index 2effbdc36..d825512c8 100644 --- a/Engine/source/terrain/hlsl/terrFeatureHLSL.h +++ b/Engine/source/terrain/hlsl/terrFeatureHLSL.h @@ -46,6 +46,7 @@ public: Var* _getInMacroCoord(Vector &componentList ); Var* _getNormalMapTex(); + Var* _getCompositeMapTex(); static Var* _getUniformVar( const char *name, const char *type, ConstantSortPosition csp ); @@ -161,6 +162,22 @@ public: virtual String getName() { return "Terrain Additive"; } }; +class TerrainCompositeMapFeatHLSL : public TerrainFeatHLSL +{ +public: + + virtual void processVert(Vector &componentList, + const MaterialFeatureData &fd); + + virtual void processPix(Vector &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 { public: diff --git a/Engine/source/terrain/terrCellMaterial.cpp b/Engine/source/terrain/terrCellMaterial.cpp index 7bf1324d8..8a022eebf 100644 --- a/Engine/source/terrain/terrCellMaterial.cpp +++ b/Engine/source/terrain/terrCellMaterial.cpp @@ -59,7 +59,8 @@ Vector _initSamplerNames() { samplerNames.push_back(avar("$normalMap%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; @@ -149,6 +150,19 @@ void TerrainCellMaterial::_updateDefaultAnisotropy() 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++ ) // Set the updated stateblock. @@ -424,6 +438,14 @@ bool TerrainCellMaterial::_createPass( Vector *materials, features.addFeature(MFT_isDeferred, 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] ); normalMaps.increment(); @@ -496,7 +518,7 @@ bool TerrainCellMaterial::_createPass( Vector *materials, // 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 // 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 ); pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat(), NULL, mSamplerNames ); @@ -613,6 +635,27 @@ bool TerrainCellMaterial::_createPass( Vector *materials, &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->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 ); if ( matInfo->normalTexConst->isValid() ) 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() ); @@ -837,7 +882,7 @@ bool TerrainCellMaterial::setupPass( const SceneRenderState *state, pass.lightParamsConst->isValid() ) { if ( !mLightInfoTarget ) - mLightInfoTarget = NamedTexTarget::find( "directLighting" ); + mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" ); GFXTextureObject *texObject = mLightInfoTarget->getTexture(); diff --git a/Engine/source/terrain/terrCellMaterial.h b/Engine/source/terrain/terrCellMaterial.h index 465cd5fc0..d762dd4d5 100644 --- a/Engine/source/terrain/terrCellMaterial.h +++ b/Engine/source/terrain/terrCellMaterial.h @@ -77,6 +77,9 @@ protected: GFXShaderConstHandle *normalTexConst; GFXTexHandle normalTex; + GFXShaderConstHandle *compositeTexConst; + GFXTexHandle compositeTex; + GFXShaderConstHandle *detailInfoVConst; GFXShaderConstHandle *detailInfoPConst; diff --git a/Engine/source/terrain/terrFeatureTypes.cpp b/Engine/source/terrain/terrFeatureTypes.cpp index 7a4f2e9b3..87ad84323 100644 --- a/Engine/source/terrain/terrFeatureTypes.cpp +++ b/Engine/source/terrain/terrFeatureTypes.cpp @@ -36,3 +36,4 @@ ImplementFeatureType( MFT_TerrainSideProject, MFG_Texture, 106.0f, false ); ImplementFeatureType( MFT_TerrainAdditive, MFG_PostProcess, 999.0f, false ); //Deferred Shading ImplementFeatureType( MFT_DeferredTerrainBlankInfoMap, MFG_Texture, 104.1f, false); +ImplementFeatureType( MFT_TerrainCompositeMap, MFG_Texture, 104.2f, false); diff --git a/Engine/source/terrain/terrFeatureTypes.h b/Engine/source/terrain/terrFeatureTypes.h index c8323ba8a..930d3fbc3 100644 --- a/Engine/source/terrain/terrFeatureTypes.h +++ b/Engine/source/terrain/terrFeatureTypes.h @@ -36,6 +36,7 @@ DeclareFeatureType( MFT_TerrainLightMap ); DeclareFeatureType( MFT_TerrainSideProject ); DeclareFeatureType( MFT_TerrainAdditive ); //Deferred Shading +DeclareFeatureType( MFT_TerrainCompositeMap ); DeclareFeatureType( MFT_DeferredTerrainBlankInfoMap ); diff --git a/Engine/source/terrain/terrMaterial.cpp b/Engine/source/terrain/terrMaterial.cpp index edfc826ff..ecbf8d822 100644 --- a/Engine/source/terrain/terrMaterial.cpp +++ b/Engine/source/terrain/terrMaterial.cpp @@ -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 " "occlusion effect (aka parallax) to the terrain material" ); + addField("compositeMap", TypeStringFilename, Offset(mCompositeMap, TerrainMaterial), "Composite map for the material"); Parent::initPersistFields(); // Gotta call this at least once or it won't get created! diff --git a/Engine/source/terrain/terrMaterial.h b/Engine/source/terrain/terrMaterial.h index de2cb47d1..923eca950 100644 --- a/Engine/source/terrain/terrMaterial.h +++ b/Engine/source/terrain/terrMaterial.h @@ -49,6 +49,9 @@ protected: /// FileName mDetailMap; + /// + FileName mCompositeMap; + /// The size of the detail map in meters used /// to generate the texture coordinates for the /// detail and normal maps. @@ -103,6 +106,8 @@ public: const String& getMacroMap() const { return mMacroMap; } + const String& getCompositeMap() const { return mCompositeMap; } + F32 getDetailSize() const { return mDetailSize; } F32 getDetailStrength() const { return mDetailStrength; } diff --git a/Templates/Full/game/art/shapes/Cheetah/materials.cs b/Templates/Full/game/art/shapes/Cheetah/materials.cs index a8eed41be..b874f86d9 100644 --- a/Templates/Full/game/art/shapes/Cheetah/materials.cs +++ b/Templates/Full/game/art/shapes/Cheetah/materials.cs @@ -28,8 +28,10 @@ singleton Material(Cheetah_Main) specularPower[0] = "10"; translucentBlendOp = "None"; normalMap[0] = "art/shapes/Cheetah/Cheetah_N"; - specularMap[0] = "art/shapes/Cheetah/Cheetah_S"; castDynamicShadows = true; + diffuseColor[3] = "1 1 1 1"; + specular0 = "0.9 0.9 0.9 1"; + specularPower0 = "10"; }; singleton Material(Cheetah_TailLights) diff --git a/Templates/Full/game/art/shapes/actors/Soldier/materials.cs b/Templates/Full/game/art/shapes/actors/Soldier/materials.cs index 6eb3eb806..f9d45da31 100644 --- a/Templates/Full/game/art/shapes/actors/Soldier/materials.cs +++ b/Templates/Full/game/art/shapes/actors/Soldier/materials.cs @@ -24,19 +24,18 @@ singleton Material(Mat_Soldier_Main) { mapTo = "base_Soldier_Main"; - diffuseMap[0] = "Soldier_Dif.dds"; - normalMap[0] = "Soldier_N.dds"; - specularMap[0] = "Soldier_Spec.dds"; - - diffuseColor[0] = "1 1 1 1"; - specular[0] = "0.9 0.9 0.9 1"; - specularPower[0] = 10; - - doubleSided = false; - translucent = false; - showFootprints = "0"; + diffuseMap[0] = "art/shapes/actors/Soldier/Soldier_Dif.dds"; + normalMap[0] = "art/shapes/actors/Soldier/Soldier_N.dds"; + specularMap[0] = "art/shapes/actors/Soldier/Soldier_c"; + FlipRB[0] = "1"; castDynamicShadows = true; 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) @@ -110,7 +109,8 @@ singleton Material(Mat_Orange_Soldier_Main : Mat_Soldier_Main) singleton Material(Mat_Red_Soldier_Main : Mat_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) diff --git a/Templates/Full/game/art/shapes/cube/materials.cs b/Templates/Full/game/art/shapes/cube/materials.cs index bf5e3c940..56e223c1f 100644 --- a/Templates/Full/game/art/shapes/cube/materials.cs +++ b/Templates/Full/game/art/shapes/cube/materials.cs @@ -25,9 +25,6 @@ singleton Material(cube_GridMaterial) { mapTo = "GridMaterial"; - diffuseMap[0] = "grid"; - normalMap[0] = ""; - specularMap[0] = ""; diffuseColor[0] = "1 1 1 1"; specular[0] = "0.9 0.9 0.9 1"; @@ -38,6 +35,12 @@ singleton Material(cube_GridMaterial) doubleSided = false; translucent = false; 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 --- diff --git a/Templates/Full/game/art/shapes/station/materials.cs b/Templates/Full/game/art/shapes/station/materials.cs index 35195578a..d63d4f303 100644 --- a/Templates/Full/game/art/shapes/station/materials.cs +++ b/Templates/Full/game/art/shapes/station/materials.cs @@ -24,14 +24,11 @@ new Material(Structure_wall) { mapTo = "building01walls"; diffuseMap[0] = "art/shapes/station/building01walls"; - //emissive[0] = true; -}; - - -new Material(Structure_grid) -{ - mapTo = "grid"; - diffuseMap[0] = "art/shapes/station/grid"; + normalMap[0] = "art/shapes/station/building01walls_n.dds"; + specularMap[0] = "art/shapes/station/building01walls_c.dds"; + effectColor[0] = "InvisibleBlack"; + materialTag0 = "Miscellaneous"; + pixelSpecular0 = "0"; //emissive[0] = true; }; @@ -40,6 +37,20 @@ new Material(Structure_plate) { mapTo = "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; }; diff --git a/Templates/Full/game/art/terrains/materials.cs b/Templates/Full/game/art/terrains/materials.cs index c13ab564f..2dcdbdf34 100644 --- a/Templates/Full/game/art/terrains/materials.cs +++ b/Templates/Full/game/art/terrains/materials.cs @@ -151,6 +151,7 @@ new TerrainMaterial() detailBrightness = "1"; Enabled = "1"; diffuseSize = "400"; + compositeMap = "art/terrains/Example/snowtop"; }; // ---------------------------------------------------------------------------- diff --git a/Templates/Full/game/core/art/grids/materials.cs b/Templates/Full/game/core/art/grids/materials.cs index ea05af987..c573019ce 100644 --- a/Templates/Full/game/core/art/grids/materials.cs +++ b/Templates/Full/game/core/art/grids/materials.cs @@ -51,8 +51,12 @@ singleton Material( Grid512_ForestGreenLines_Mat ) singleton Material( Grid512_Green_Mat ) { mapTo = "Grid512_Green_Mat"; - diffuseMap[0] = "512_green"; + diffuseMap[0] = "core/art/grids/512_green"; materialTag0 = "TestMaterial"; + smoothness[0] = "1"; + metalness[0] = "1"; + translucent = "0"; + translucentBlendOp = "Add"; }; singleton Material( Grid512_Grey_Mat ) @@ -65,8 +69,10 @@ singleton Material( Grid512_Grey_Mat ) singleton Material( Grid512_GreyBase_Mat ) { mapTo = "Grid512_GreyBase_Mat"; - diffuseMap[0] = "512_grey_base"; + diffuseMap[0] = "core/art/grids/512_grey_base"; materialTag0 = "TestMaterial"; + smoothness[0] = "1"; + metalness[0] = "1"; }; singleton Material( Grid512_Orange_Mat ) diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs index 08a956521..26940f47c 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/deferredShading.cs @@ -47,23 +47,56 @@ new ShaderData( AL_DeferredShader ) OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/deferredShadingP.glsl"; samplerNames[0] = "colorBufferTex"; - samplerNames[1] = "directLightingBuffer"; + samplerNames[1] = "diffuseLightingBuffer"; samplerNames[2] = "matInfoTex"; - samplerNames[3] = "indirectLightingBuffer"; + samplerNames[3] = "specularLightingBuffer"; samplerNames[4] = "deferredTex"; 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 ) { renderTime = "PFXAfterBin"; - renderBin = "SkyBin"; + renderBin = "ProbeBin"; shader = AL_DeferredShader; stateBlock = AL_DeferredShadingState; texture[0] = "#color"; - texture[1] = "#directLighting"; + texture[1] = "#diffuseLighting"; texture[2] = "#matinfo"; - texture[3] = "#indirectLighting"; + texture[3] = "#specularLighting"; texture[4] = "#deferred"; target = "$backBuffer"; @@ -192,7 +225,7 @@ new ShaderData( AL_LightMapShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl"; - samplerNames[0] = "indirectLightingBuffer"; + samplerNames[0] = "specularLightingBuffer"; pixVersion = 2.0; }; @@ -200,7 +233,7 @@ singleton PostEffect( AL_LightMapVisualize ) { shader = AL_LightMapShader; stateBlock = AL_DefaultVisualizeState; - texture[0] = "#indirectLighting"; + texture[0] = "#specularLighting"; target = "$backBuffer"; renderPriority = 9999; }; diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs index 8e6b00d43..19318d508 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/lightViz.cs @@ -149,7 +149,7 @@ new ShaderData( AL_LightColorVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightColorVisualizeP.glsl"; - samplerNames[0] = "directLightingBuffer"; + samplerNames[0] = "diffuseLightingBuffer"; pixVersion = 2.0; }; @@ -158,7 +158,7 @@ singleton PostEffect( AL_LightColorVisualize ) { shader = AL_LightColorVisualizeShader; stateBlock = AL_DefaultVisualizeState; - texture[0] = "#directLighting"; + texture[0] = "#diffuseLighting"; target = "$backBuffer"; renderPriority = 9999; }; @@ -184,16 +184,16 @@ new ShaderData( AL_LightSpecularVisualizeShader ) OGLVertexShaderFile = "shaders/common/postFx/gl/postFxV.glsl"; OGLPixelShaderFile = "shaders/common/lighting/advanced/gl/dbgLightSpecularVisualizeP.glsl"; - samplerNames[0] = "directLightingBuffer"; + samplerNames[0] = "diffuseLightingBuffer"; pixVersion = 2.0; }; singleton PostEffect( AL_LightSpecularVisualize ) { - shader = AL_LightSpecularVisualizeShader; + shader = AL_LightColorVisualizeShader; stateBlock = AL_DefaultVisualizeState; - texture[0] = "#directLighting"; + texture[0] = "#specularLighting"; target = "$backBuffer"; renderPriority = 9999; }; diff --git a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs index 88125b864..5ec7375d9 100644 --- a/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs +++ b/Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs @@ -86,11 +86,11 @@ new CustomMaterial( AL_VectorLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["ssaoMask"] = "#ssaoMask"; - sampler["lightBuffer"] = "#indirectLighting"; + sampler["lightBuffer"] = "#specularLighting"; sampler["colorBuffer"] = "#color"; sampler["matInfoBuffer"] = "#matinfo"; - target = "directLighting"; + target = "diffuseLighting"; pixVersion = 3.0; }; @@ -163,11 +163,11 @@ new CustomMaterial( AL_PointLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; - sampler["lightBuffer"] = "#indirectLighting"; + sampler["lightBuffer"] = "#specularLighting"; sampler["colorBuffer"] = "#color"; sampler["matInfoBuffer"] = "#matinfo"; - target = "directLighting"; + target = "diffuseLighting"; pixVersion = 3.0; }; @@ -202,11 +202,11 @@ new CustomMaterial( AL_SpotLightMaterial ) sampler["shadowMap"] = "$dynamiclight"; sampler["dynamicShadowMap"] = "$dynamicShadowMap"; sampler["cookieMap"] = "$dynamiclightmask"; - sampler["lightBuffer"] = "#indirectLighting"; + sampler["lightBuffer"] = "#specularLighting"; sampler["colorBuffer"] = "#color"; sampler["matInfoBuffer"] = "#matinfo"; - target = "directLighting"; + target = "diffuseLighting"; pixVersion = 3.0; }; @@ -269,7 +269,124 @@ new CustomMaterial( AL_ParticlePointLightMaterial ) stateBlock = AL_ConvexLightState; sampler["deferredBuffer"] = "#deferred"; - target = "directLighting"; + target = "diffuseLighting"; 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; +}; \ No newline at end of file diff --git a/Templates/Full/game/core/scripts/client/lighting/basic/init.cs b/Templates/Full/game/core/scripts/client/lighting/basic/init.cs index ed2972c11..3f7e7679a 100644 --- a/Templates/Full/game/core/scripts/client/lighting/basic/init.cs +++ b/Templates/Full/game/core/scripts/client/lighting/basic/init.cs @@ -64,7 +64,7 @@ singleton CustomMaterial( BL_ProjectedShadowMaterial ) function onActivateBasicLM() { // If HDR is enabled... enable the special format token. - if ( $platform !$= "macos" && HDRPostFx.isEnabled ) + if ( HDRPostFx.isEnabled ) AL_FormatToken.enable(); // Create render pass for projected shadow. diff --git a/Templates/Full/game/core/scripts/client/renderManager.cs b/Templates/Full/game/core/scripts/client/renderManager.cs index b52143918..da40a3378 100644 --- a/Templates/Full/game/core/scripts/client/renderManager.cs +++ b/Templates/Full/game/core/scripts/client/renderManager.cs @@ -51,7 +51,8 @@ function initRenderManager() // meshes... but that causes issues in reflections. 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; } ); // Normal mesh rendering. diff --git a/Templates/Full/game/levels/AProbeTest.mis b/Templates/Full/game/levels/AProbeTest.mis index 5c5a8a8f9..65d58f5e2 100644 --- a/Templates/Full/game/levels/AProbeTest.mis +++ b/Templates/Full/game/levels/AProbeTest.mis @@ -28,7 +28,7 @@ new SimGroup(MissionGroup) { levelName = "A Probe Test"; }; new SkyBox(theSky) { - Material = "DesertSkyMat"; + Material = "sky_day_hdr"; drawBottom = "0"; fogBandHeight = "0"; position = "0 0 0"; @@ -37,48 +37,16 @@ new SimGroup(MissionGroup) { canSave = "1"; canSaveDynamicFields = "1"; }; - new Sun(theSun) { - azimuth = "290"; - elevation = "50"; - 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"; + new Skylight() { + enabled = "1"; + StaticCubemap = "sky_day_hdr_cubemap"; position = "0 0 0"; rotation = "1 0 0 0"; scale = "1 1 1"; canSave = "1"; canSaveDynamicFields = "1"; - bias = "0.1"; - Blur = "1"; - 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"; + persistentId = "e4c73467-4089-11e8-b478-cd227cd60b8b"; + reflectionPath = "levels/AProbeTest/probes/"; }; new SimGroup(PlayerDropPoints) { canSave = "1"; @@ -117,13 +85,46 @@ new SimGroup(MissionGroup) { rotation = "1 0 0 0"; 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() { - enabled = "1"; + enabled = "0"; ProbeShape = "Sphere"; radius = "10"; - Intensity = "1"; - IndirectLightMode = "Ambient Color"; - IndirectLight = "1 1 1 1"; ReflectionMode = "Baked Cubemap"; reflectionPath = "levels/probeTest/probes/"; Bake = "0"; @@ -134,6 +135,9 @@ new SimGroup(MissionGroup) { canSaveDynamicFields = "1"; persistentId = "8072e1be-2846-11e7-9f56-abd46b190c60"; 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"; }; new ConvexShape() { @@ -243,7 +247,7 @@ new SimGroup(MissionGroup) { }; new PointLight() { radius = "10"; - isEnabled = "1"; + isEnabled = "0"; color = "0.887923 1 0.008023 1"; brightness = "1"; castShadows = "0"; @@ -272,5 +276,24 @@ new SimGroup(MissionGroup) { canSave = "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 --- diff --git a/Templates/Full/game/levels/Empty Room.mis b/Templates/Full/game/levels/Empty Room.mis index c3ba059a4..d20a6cd16 100644 --- a/Templates/Full/game/levels/Empty Room.mis +++ b/Templates/Full/game/levels/Empty Room.mis @@ -1,82 +1,1539 @@ //--- OBJECT WRITE BEGIN --- new SimGroup(MissionGroup) { + canSave = "1"; canSaveDynamicFields = "1"; - Enabled = "1"; + enabled = "1"; new LevelInfo(theLevelInfo) { + nearClip = "0.1"; visibleDistance = "1000"; + visibleGhostDistance = "0"; + decalBias = "0.0015"; fogColor = "0.6 0.6 0.7 1"; fogDensity = "0"; fogDensityOffset = "700"; fogAtmosphereHeight = "0"; canvasClearColor = "0 0 0 255"; - canSaveDynamicFields = "1"; - levelName = "Empty Room"; + ambientLightBlendPhase = "1"; + ambientLightBlendCurve = "0 0 -1 -1"; + LevelEnvMap = "BlueSkyCubemap"; + soundAmbience = "AudioAmbienceDefault"; + soundDistanceModel = "Linear"; + canSave = "1"; + canSaveDynamicFields = "1"; desc0 = "An empty room ready to be populated with Torque objects."; - Enabled = "1"; + enabled = "1"; + levelName = "Empty Room"; }; - new SkyBox(theSky) { - canSaveDynamicFields = "1"; - Position = "0 0 0"; - rotation = "1 0 0 0"; - scale = "1 1 1"; - Material = "BlackSkyMat"; - drawBottom = "0"; - fogBandHeight = "0"; - }; - new Sun(theSun) { - canSaveDynamicFields = "1"; - Position = "0 0 0"; - rotation = "1 0 0 0"; - scale = "1 1 1"; - azimuth = "230.396"; - elevation = "45"; - color = "0.968628 0.901961 0.901961 1"; - ambient = "0.078431 0.113725 0.156863 1"; + new ScatterSky() { + skyBrightness = "25"; + sunSize = "1"; + colorizeAmount = "0"; + colorize = "0 0 0 1"; + rayleighScattering = "0.0035"; + sunScale = "1 1 1 1"; + ambientScale = "1 1 1 1"; + fogScale = "1 1 1 1"; + exposure = "1"; + zOffset = "0"; + azimuth = "0"; + elevation = "90"; + moonAzimuth = "0"; + moonElevation = "45"; castShadows = "1"; + staticRefreshFreq = "8"; + dynamicRefreshFreq = "8"; + brightness = "1"; + flareScale = "1"; + nightColor = "0.0196078 0.0117647 0.109804 1"; + nightFogColor = "0.0196078 0.0117647 0.109804 1"; + moonEnabled = "1"; + moonMat = "Moon_Glow_Mat"; + moonScale = "0.2"; + moonLightColor = "0.192157 0.192157 0.192157 1"; + useNightCubemap = "1"; + nightCubemap = "NightCubemap"; attenuationRatio = "0 1 1"; shadowType = "PSSM"; texSize = "1024"; - overDarkFactor = "3000 2000 1000 250"; - shadowDistance = "400"; - shadowSoftness = "0.25"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "200"; + shadowSoftness = "0.15"; numSplits = "4"; - logWeight = "0.96"; - fadeStartDistance = "325"; + logWeight = "0.91"; + fadeStartDistance = "0"; lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "171.065 195.399 -1.10657"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + mieScattering = "0.0045"; }; new SimGroup(PlayerDropPoints) { + canSave = "1"; canSaveDynamicFields = "1"; - Enabled = "1"; + enabled = "1"; new SpawnSphere() { - canSaveDynamicFields = "1"; - Position = "0 0 2"; - rotation = "1 0 0 0"; - scale = "1 1 1"; - dataBlock = "SpawnSphereMarker"; - radius = "5"; - spawnClass = ""; - spawnDatablock = ""; autoSpawn = "0"; + spawnTransform = "0"; + radius = "5"; sphereWeight = "1"; indoorWeight = "1"; outdoorWeight = "1"; - Enabled = "1"; + isAIControlled = "0"; + dataBlock = "SpawnSphereMarker"; + position = "0 0 2"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; homingCount = "0"; lockCount = "0"; }; }; - new GroundPlane() { + new SimGroup(CameraBookmarks) { + canSave = "1"; canSaveDynamicFields = "1"; - Position = "0 0 0"; - rotation = "1 0 0 0"; - scale = "1 1 1"; + + new CameraBookmark() { + isAIControlled = "0"; + dataBlock = "CameraBookmarkMarker"; + position = "12.4869 4.10897 4.58326"; + rotation = "-0.0713349 -0.106471 -0.991754 112.795"; + scale = "1 1 1"; + internalName = "CryEngine_Sponza_Compare"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new CameraBookmark() { + isAIControlled = "0"; + dataBlock = "CameraBookmarkMarker"; + position = "-17.8058 0.291567 6.37798"; + rotation = "0.214026 0.125288 -0.96876 62.2862"; + scale = "1 1 1"; + internalName = "mirrorTest"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new CameraBookmark() { + isAIControlled = "0"; + dataBlock = "CameraBookmarkMarker"; + position = "15.8629 -8.35756 4.69165"; + rotation = "0.0151395 -0.00460125 0.999875 33.8145"; + scale = "1 1 1"; + internalName = "NewCamera_0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + }; + new GroundPlane() { squareSize = "128"; scaleU = "12"; scaleV = "12"; - Material = "BlankWhite"; - Enabled = "1"; + Material = "Grid512_Grey_Mat"; + canSave = "1"; + canSaveDynamicFields = "1"; + enabled = "1"; + position = "0 0 0"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + }; + new TSStatic() { + shapeName = "art/shapes/sponza/sponza.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Visible Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "-8.91623 -0.551134 0.392056"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + bricks = "bricks_mat"; + flagpole = "flagpole_mat"; + }; + new TSStatic() { + shapeName = "art/shapes/sponza/sponza_extra_curtains.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "-8.91623 -0.551134 0.392056"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + hidden = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new SimGroup(Probes) { + canSave = "1"; + canSaveDynamicFields = "1"; + + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 0.5"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + Bake = "0"; + position = "-11.4607 0.712664 16.8264"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "c04383f9-2147-11e7-9298-9a7d9c6feabe"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "19.0392 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6ab2beca-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.19861 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6ab8d961-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.368001 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6abfde5c-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.2042 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6ac869fc-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.4857 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6acef9c4-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.2419 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6ad5145b-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-38.8665 11.1366 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6adb7d13-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "18.8673 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6ae25afd-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.02669 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6aea4a5b-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.53992 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6af0da23-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.3761 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6af769ec-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.6576 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6afdf9b4-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.4138 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6b05c202-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-39.0384 -10.4486 16.5257"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "6b0dd870-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.00455975 0.00455975 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "19.0392 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25d6efbe-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "1 0.00455975 0.00455975 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.201096 0.00775103 0.00775103 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.19861 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25de1bc8-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.0356144 0.0315514 0.00604059 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.368001 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25e4365f-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.0356144 0.0315514 0.00604059 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.2042 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25eaed38-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.532"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.4857 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25f17d01-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.201096 0.00775103 0.00775103 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.2419 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "25fa7dd3-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.00455975 0.00455975 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-38.8665 11.1366 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "26021f0f-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "1 0.00455975 0.00455975 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.00455975 0.00455975 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "18.8673 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "ac3fe3f0-1ff5-11e7-b852-d5bab2d8fbcc"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "1 0.00455975 0.00455975 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.201096 0.00775103 0.00775103 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.02669 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "f41bf404-209f-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.0461488 0.113921 0.0915184 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.53992 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "fa446dc9-209f-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.499505 1 0.687031 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.3761 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "fe03f4d6-209f-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.0461488 0.113921 0.0915184 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.6576 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "02bbe946-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.201096 0.00775103 0.00775103 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.4138 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "072e6f42-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.119264 0.334458 0.554227 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.19861 0.0539651 26.7401"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "afa9693c-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.119264 0.334458 0.554227 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.368001 0.0539651 26.7401"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "afa1c7ff-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.119264 0.334458 0.554227 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.2042 0.0539651 26.7401"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "af993c5f-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.119264 0.334458 0.554227 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.4857 0.0539651 26.7401"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "af919b23-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.119264 0.334458 0.554227 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.2419 0.0539651 26.7401"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "af8a4807-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "19.0392 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1f5851f-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 0.5"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.19861 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1eef556-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 0.5"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.368001 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1e8658e-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.1 0.005 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-9.37523 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1e13983-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 0.5"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.4857 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1d8ade3-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 0.5"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.2419 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1d133b7-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.036 0.032 0.006 0.505"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-38.8665 0.0539651 16.5406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1cacaff-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.89 0.39 0.148 0.949"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "19.0392 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1c43b36-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "8.19861 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1bdf98f-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.1 0.005 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-0.368001 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1b71ba5-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-10.2042 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1afef9a-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-19.4857 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1a9fc14-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.618686 0.45908 0.147998 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-29.2419 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a1a3e17d-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "0.89 0.39 0.148 0.949"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-38.8665 0.0539651 5.01901"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "a19dedf6-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new ReflectionProbe() { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "10"; + Intensity = "1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 0.00455975 0.00455975 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "-39.0384 -10.4486 5.00406"; + rotation = "1 0 0 0"; + scale = "5 5 5"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "0b06aecb-20a0-11e7-9c9c-8cefe314de25"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "1 0.00455975 0.00455975 1"; + }; + }; + new ReflectionProbe(Skylight) { + enabled = "1"; + ProbeShape = "Sphere"; + radius = "200"; + Intensity = "0.1"; + IndirectLightMode = "Ambient Color"; + IndirectLight = "1 1 1 1"; + ReflectionMode = "Baked Cubemap"; + reflectionPath = "levels/Empty Room/probes/"; + StaticCubemap = "DesertSkyCubemap"; + Bake = "0"; + position = "0 0 50"; + rotation = "1 0 0 0"; + scale = "100 100 100"; + canSave = "1"; + canSaveDynamicFields = "1"; + persistentId = "0039b2a6-20c2-11e7-b558-91c869a431e1"; + GroundColor = "0.8 0.7 0.5 1"; + ProbeMode = "Baked Cubemap"; + SkyColor = "0.5 0.5 1 1"; + }; + new TSStatic() { + shapeName = "art/shapes/textures/pbrGrid.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "-26.8371 -4.49793 0.284616"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/textures/PBRTEST.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "23.1539 0.397566 1.22924"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "15"; + isEnabled = "1"; + color = "1 0.275833 0.00455975 1"; + brightness = "1"; + castShadows = "0"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "-38.6032 -10.4171 3.87317"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "15"; + isEnabled = "1"; + color = "1 0.275833 0.00455975 1"; + brightness = "1"; + castShadows = "0"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "-38.8136 10.7957 3.87317"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "15"; + isEnabled = "1"; + color = "1 0.275833 0.00455975 1"; + brightness = "1"; + castShadows = "0"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "19.1024 10.5955 3.87317"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "15"; + isEnabled = "1"; + color = "1 0.275833 0.00455975 1"; + brightness = "1"; + castShadows = "0"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "19.2761 -10.4968 3.87317"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new PointLight() { + radius = "15"; + isEnabled = "1"; + color = "0.0802193 0.804559 0.7593 1"; + brightness = "1"; + castShadows = "0"; + staticRefreshFreq = "250"; + dynamicRefreshFreq = "8"; + priority = "1"; + animate = "1"; + animationPeriod = "1"; + animationPhase = "1"; + flareScale = "1"; + attenuationRatio = "0 1 1"; + shadowType = "DualParaboloidSinglePass"; + texSize = "512"; + overDarkFactor = "2000 1000 500 100"; + shadowDistance = "400"; + shadowSoftness = "0.15"; + numSplits = "1"; + logWeight = "0.91"; + fadeStartDistance = "0"; + lastSplitTerrainOnly = "0"; + representedInLightmap = "0"; + shadowDarkenColor = "0 0 0 -1"; + includeLightmappedGeometryInShadow = "0"; + position = "-9.85153 -12.8646 7.06711"; + rotation = "1 0 0 0"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/cube/cube.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "-19.6187 2.45554 4.946"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new Prefab() { + fileName = "art/prefabs/vaseFlame.prefab"; + position = "3.24204 4.91314 3.64629"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new Prefab() { + fileName = "art/prefabs/vaseFlame.prefab"; + position = "3.27432 -4.14598 3.64629"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new Prefab() { + fileName = "art/prefabs/vaseFlame.prefab"; + position = "-24.3409 -4.14598 3.64629"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new Prefab() { + fileName = "art/prefabs/vaseFlame.prefab"; + position = "-24.378 4.92861 3.5101"; + rotation = "1 0 0 0"; + scale = "1 1 1"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/cube/cube.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "24.1149 10.5531 0.125195"; + rotation = "1 0 0 0"; + scale = "1 10 10"; + canSave = "1"; + canSaveDynamicFields = "1"; + }; + new TSStatic() { + shapeName = "art/shapes/cube/cube.dae"; + playAmbient = "1"; + meshCulling = "0"; + originSort = "0"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; + allowPlayerStep = "0"; + alphaFadeEnable = "0"; + alphaFadeStart = "100"; + alphaFadeEnd = "150"; + alphaFadeInverse = "0"; + renderNormals = "0"; + forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; + position = "12.7735 12.0238 0.464151"; + rotation = "1 0 0 0"; + scale = "1 10 10"; + canSave = "1"; + canSaveDynamicFields = "1"; }; }; //--- OBJECT WRITE END --- diff --git a/Templates/Full/game/levels/Empty Terrain.mis b/Templates/Full/game/levels/Empty Terrain.mis index 243ad4962..5553698fa 100644 --- a/Templates/Full/game/levels/Empty Terrain.mis +++ b/Templates/Full/game/levels/Empty Terrain.mis @@ -16,7 +16,6 @@ new SimGroup(MissionGroup) { canvasClearColor = "0 0 0 255"; ambientLightBlendPhase = "1"; ambientLightBlendCurve = "0 0 -1 -1"; - LevelEnvMap = "DesertSkyCubemap"; soundAmbience = "AudioAmbienceDefault"; soundDistanceModel = "Linear"; canSave = "1"; @@ -33,6 +32,7 @@ new SimGroup(MissionGroup) { baseTexFormat = "DDS"; lightMapSize = "256"; screenError = "16"; + ignoreZodiacs = "0"; position = "-1024 -1024 179.978"; rotation = "1 0 0 0"; canSave = "1"; @@ -67,8 +67,8 @@ new SimGroup(MissionGroup) { playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "1"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -76,6 +76,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "9.42739 27.7428 241.767"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -133,8 +137,8 @@ new SimGroup(MissionGroup) { playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "1"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -142,6 +146,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "17.8995 16.1596 241.136"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -158,27 +166,18 @@ new SimGroup(MissionGroup) { surface = "0 0 0 1 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 0.707107 -0.707107 0 1.29457 -6.60907 -4.54747e-013"; - 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 5.94063 -0.42643 -1.28542e-008"; - }; - 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"; + 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-13"; + 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-08"; }; new TSStatic() { shapeName = "art/shapes/textures/PBRTEST2.dae"; playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "1"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -186,6 +185,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "5.60579 18.8689 241.462"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -198,8 +201,8 @@ new SimGroup(MissionGroup) { meshCulling = "0"; originSort = "0"; cubeReflectorDesc = "DefaultCubeDesc"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "1"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -207,6 +210,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "22.1653 4.41543 241.364"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -218,8 +225,8 @@ new SimGroup(MissionGroup) { playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "1"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -227,6 +234,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "15.72 5.9186 241.191"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -246,8 +257,8 @@ new SimGroup(MissionGroup) { playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "0"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -255,6 +266,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "12.8895 -2.18239 238.765"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -266,8 +281,8 @@ new SimGroup(MissionGroup) { playAmbient = "1"; meshCulling = "0"; originSort = "0"; - collisionType = "Collision Mesh"; - decalType = "Collision Mesh"; + CollisionType = "Collision Mesh"; + DecalType = "Collision Mesh"; allowPlayerStep = "0"; alphaFadeEnable = "0"; alphaFadeStart = "100"; @@ -275,6 +290,10 @@ new SimGroup(MissionGroup) { alphaFadeInverse = "0"; renderNormals = "0"; forceDetail = "-1"; + ignoreZodiacs = "0"; + useGradientRange = "0"; + gradientRange = "0 180"; + invertGradientRange = "0"; position = "10.406 10.0939 240.551"; rotation = "1 0 0 0"; scale = "1 1 1"; @@ -300,9 +319,6 @@ new SimGroup(MissionGroup) { enabled = "1"; ProbeShape = "Sphere"; radius = "10"; - Intensity = "1"; - IndirectLightMode = "Ambient Color"; - IndirectLight = "1 1 1 1"; ReflectionMode = "Baked Cubemap"; reflectionPath = "levels/empty terrain/"; Bake = "0"; @@ -312,14 +328,14 @@ new SimGroup(MissionGroup) { canSave = "1"; canSaveDynamicFields = "1"; persistentId = "fc28816f-65a6-11e7-b9a1-b6f5317ad553"; + IndirectLight = "1 1 1 1"; + IndirectLightMode = "Ambient Color"; + Intensity = "1"; }; new ReflectionProbe() { enabled = "1"; ProbeShape = "Sphere"; radius = "10"; - Intensity = "1"; - IndirectLightMode = "Ambient Color"; - IndirectLight = "1 1 1 1"; ReflectionMode = "Baked Cubemap"; reflectionPath = "levels/empty terrain/"; Bake = "0"; @@ -329,6 +345,20 @@ new SimGroup(MissionGroup) { canSave = "1"; canSaveDynamicFields = "1"; 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 --- diff --git a/Templates/Full/game/shaders/common/gl/lighting.glsl b/Templates/Full/game/shaders/common/gl/lighting.glsl index 804ab1e3b..9ebe2e4a0 100644 --- a/Templates/Full/game/shaders/common/gl/lighting.glsl +++ b/Templates/Full/game/shaders/common/gl/lighting.glsl @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC -// +// Portions Copyright Zefiros // 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 @@ -38,12 +38,140 @@ uniform vec4 inLightColor[4]; uniform vec4 ambient; #define ambientCameraFactor 0.3 -uniform float specularPower; -uniform vec4 specularColor; +uniform float smoothness; +uniform float metalness; +uniform vec4 albedo; #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, vec3 wsPosition, vec3 wsNormal, @@ -57,8 +185,9 @@ void compute4Lights( vec3 wsView, vec4 inLightSpotDir[3], vec4 inLightSpotAngle, vec4 inLightSpotFalloff, - float specularPower, - vec4 specularColor, + float smoothness, + float metalness, + vec4 albedo, #endif // TORQUE_SHADERGEN @@ -81,9 +210,6 @@ void compute4Lights( vec3 wsView, for ( i = 0; i < 3; 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 // vector and the normal. @@ -99,40 +225,12 @@ void compute4Lights( vec3 wsView, vec4 nDotL = vec4(0); for ( i = 0; i < 3; 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. - // - // Notice we're using the half type here to get a - // 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. - // + vec4 squareDists = vec4(0); + for ( i = 0; i < 3; i++ ) + squareDists += lightVectors[i] * lightVectors[i]; half4 correction = half4(inversesqrt( squareDists )); nDotL = saturate( nDotL * correction ); - rDotL = clamp( rDotL * correction, 0.00001, 1.0 ); // First calculate a simple point light linear // attenuation factor. @@ -157,93 +255,18 @@ void compute4Lights( vec3 wsView, #endif - // Finally apply the shadow masking on the attenuation. - atten *= shadowMask; - // Get the final light intensity. 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. - vec4 specular = vec4(0,0,0,1); + // Combine the light colors for output. + vec4 lightColor = vec4(0); for ( i = 0; i < 4; i++ ) - specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 ); - - // 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 += intensity[i] * inLightColor[i]; - lightColor *= vec3(shadowAttenuation); - lightColor += ambient.rgb; - return vec4(lightColor.rgb, specularOut); -} + vec3 toLight = vec3(0); + for ( i = 0; i < 3; i++ ) + 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 ); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/gl/torque.glsl b/Templates/Full/game/shaders/common/gl/torque.glsl index 6e369bd5e..ee885af98 100644 --- a/Templates/Full/game/shaders/common/gl/torque.glsl +++ b/Templates/Full/game/shaders/common/gl/torque.glsl @@ -336,4 +336,20 @@ vec3 toGamma(vec3 tex) } #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_ diff --git a/Templates/Full/game/shaders/common/lighting.hlsl b/Templates/Full/game/shaders/common/lighting.hlsl index bda21795f..a32de2b1c 100644 --- a/Templates/Full/game/shaders/common/lighting.hlsl +++ b/Templates/Full/game/shaders/common/lighting.hlsl @@ -70,7 +70,7 @@ float Fr_DisneyDiffuse ( float NdotV , float NdotL , float LdotH , float linearR float lightScatter = F_schlick( f0 , fd90 , NdotL ).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 ) @@ -268,4 +268,41 @@ void compute4Lights( float3 wsView, 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 ); +} + +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); } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/brdfLookupP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/brdfLookupP.hlsl new file mode 100644 index 000000000..8dd093870 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/brdfLookupP.hlsl @@ -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); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/cubemapV.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/cubemapV.hlsl new file mode 100644 index 000000000..4defd5eb7 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/cubemapV.hlsl @@ -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; +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightMapVisualizeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightMapVisualizeP.hlsl index bca44159f..5cdd4945d 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/dbgLightMapVisualizeP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/dbgLightMapVisualizeP.hlsl @@ -23,11 +23,11 @@ #include "shadergen:/autogenConditioners.h" #include "../../postfx/postFx.hlsl" -TORQUE_UNIFORM_SAMPLER2D(indirectLightingBuffer,0); +TORQUE_UNIFORM_SAMPLER2D(specularLightingBuffer,0); float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 { - float4 directlighting = float4(TORQUE_TEX2D( indirectLightingBuffer, IN.uv0 ).rgb,1.0); - return directlighting; + float4 diffuseLighting = float4(TORQUE_TEX2D( specularLightingBuffer, IN.uv0 ).rgb,1.0); + return diffuseLighting; } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl index d04c34ad8..e23bb0ce0 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/deferredShadingP.hlsl @@ -25,9 +25,9 @@ #include "shaders/common/torque.hlsl" TORQUE_UNIFORM_SAMPLER2D(colorBufferTex,0); -TORQUE_UNIFORM_SAMPLER2D(directLightingBuffer,1); +TORQUE_UNIFORM_SAMPLER2D(diffuseLightingBuffer,1); TORQUE_UNIFORM_SAMPLER2D(matInfoTex,2); -TORQUE_UNIFORM_SAMPLER2D(indirectLightingBuffer,3); +TORQUE_UNIFORM_SAMPLER2D(specularLightingBuffer,3); TORQUE_UNIFORM_SAMPLER2D(deferredTex,4); float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 @@ -37,25 +37,27 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0 if (depth>0.9999) 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 bool emissive = getFlag(matInfo.r, 0); if (emissive) { - return float4(colorBuffer, 1.0); + return float4(albedo, 1.0); } - float4 directLighting = TORQUE_TEX2D( directLightingBuffer, IN.uv0 ); //shadowmap*specular - float3 indirectLighting = TORQUE_TEX2D( indirectLightingBuffer, IN.uv0 ).rgb; //environment mapping*lightmaps + float4 diffuse = TORQUE_TEX2D( diffuseLightingBuffer, IN.uv0 ); //shadowmap*specular + float4 specular = TORQUE_TEX2D( specularLightingBuffer, IN.uv0 ); //environment mapping*lightmaps + float metalness = matInfo.a; - - float frez = directLighting.a; - float3 diffuseColor = colorBuffer - (colorBuffer * metalness); - float3 reflectColor = indirectLighting*colorBuffer; - colorBuffer = diffuseColor+lerp(reflectColor,indirectLighting,frez); - colorBuffer *= max(directLighting.rgb,float3(0,0,0)); + float3 diffuseColor = albedo - (albedo * metalness); + float3 specularColor = lerp(float3(0.04,0.04,0.04), albedo, metalness); + + 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); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/cubemapV.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/cubemapV.glsl new file mode 100644 index 000000000..dadbb526e --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/cubemapV.glsl @@ -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); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl index 934097b41..15ca04700 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/dbgLightMapVisualizeP.glsl @@ -24,12 +24,12 @@ #include "shadergen:/autogenConditioners.h" in vec2 uv0; -uniform sampler2D directLightingBuffer; +uniform sampler2D diffuseLightingBuffer; out vec4 OUT_col; void main() { - vec4 directLighting = vec4(texture( directLightingBuffer, uv0 ).rgb,1.0); - OUT_col = directLighting; + vec4 diffuseLighting = vec4(texture( diffuseLightingBuffer, uv0 ).rgb,1.0); + OUT_col = diffuseLighting; } \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl index b58f347bb..eab8fc136 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredClearGBufferP.glsl @@ -23,6 +23,7 @@ out vec4 OUT_col; out vec4 OUT_col1; out vec4 OUT_col2; +out vec4 OUT_col3; //----------------------------------------------------------------------------- // Main @@ -33,8 +34,11 @@ void main() OUT_col = vec4(1.0, 1.0, 1.0, 1.0); // 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. - 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); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl index 0234d5fd1..3d6a79ee8 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/deferredShadingP.glsl @@ -26,8 +26,9 @@ #include "../../../gl/torque.glsl" uniform sampler2D colorBufferTex; -uniform sampler2D lightDeferredTex; +uniform sampler2D diffuseLightingBuffer; uniform sampler2D matInfoTex; +uniform sampler2D specularLightingBuffer; uniform sampler2D deferredTex; out vec4 OUT_col; @@ -40,20 +41,27 @@ void main() OUT_col = vec4(0.0); return; } - vec4 lightBuffer = texture( lightDeferredTex, uv0 ); - vec4 colorBuffer = texture( colorBufferTex, uv0 ); - vec4 matInfo = texture( matInfoTex, uv0 ); - float specular = clamp(lightBuffer.a,0.0,1.0); - - // Diffuse Color Altered by Metalness - bool metalness = getFlag(matInfo.r, 3); - if ( metalness ) + + vec3 colorBuffer = texture( colorBufferTex, uv0 ).rgb; //albedo + vec4 matInfo = texture( matInfoTex, uv0 ); //flags|smoothness|ao|metallic + bool emissive = getFlag(matInfo.r, 0); + if (emissive) { - colorBuffer *= (1.0 - colorBuffer.a); + OUT_col = float4(colorBuffer, 1.0); + return; } - - colorBuffer += vec4(specular, specular, specular, 1.0); - colorBuffer *= vec4(lightBuffer.rgb, 1.0); - - OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) ); + + vec4 diffuseLighting = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular + + vec3 specularLighting = texture( specularLightingBuffer, uv0 ).rgb; //environment mapping*lightmaps + 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)); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/irradianceP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/irradianceP.glsl new file mode 100644 index 000000000..bb70f1cab --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/irradianceP.glsl @@ -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); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl index 80869de25..d1b0ee39b 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl @@ -138,8 +138,9 @@ void main() vec3 ssPos = ssPos.xyz / ssPos.w; vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - // Emissive. + // Matinfo flags vec4 matInfo = texture( matInfoBuffer, uvScene ); + //early out if emissive bool emissive = getFlag( matInfo.r, 0 ); if ( emissive ) { @@ -245,12 +246,17 @@ void main() // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = AL_CalcSpecular( lightVec, - normal, - normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + float specular = 0; + 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; - vec3 lightColorOut = lightMapParams.rgb * lightcol; vec4 addToResult = vec4(0.0); // TODO: This needs to be removed when lightmapping is disabled @@ -269,5 +275,5 @@ void main() 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); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/probeShadingP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/probeShadingP.glsl new file mode 100644 index 000000000..5e8581fd1 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/probeShadingP.glsl @@ -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)); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeP.glsl new file mode 100644 index 000000000..1a75f9a4b --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeP.glsl @@ -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); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeV.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeV.glsl new file mode 100644 index 000000000..5d48e6613 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/reflectionProbeV.glsl @@ -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; +} + diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl index 5fcf1b19c..b088ae9b2 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl @@ -80,12 +80,13 @@ void main() vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w; vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - // Emissive. + // Matinfo flags vec4 matInfo = texture( matInfoBuffer, uvScene ); + //early out if emissive bool emissive = getFlag( matInfo.r, 0 ); 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; } @@ -182,12 +183,19 @@ void main() // cause the hardware occlusion query to disable the shadow. // Specular term - float specular = AL_CalcSpecular( -lightToPxlVec, - normal, - normalize( -eyeRay ) ) * lightBrightness * atten * shadowed; + float specular = 0; + 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; - vec3 lightColorOut = lightMapParams.rgb * lightcol; vec4 addToResult = vec4(0.0); // TODO: This needs to be removed when lightmapping is disabled @@ -206,5 +214,5 @@ void main() 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); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl index 142e58b10..6623a0226 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl @@ -193,12 +193,13 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap, out vec4 OUT_col; void main() { - // Emissive. + // Matinfo flags float4 matInfo = texture( matInfoBuffer, uv0 ); + //early out if emissive bool emissive = getFlag( matInfo.r, 0 ); 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; } @@ -289,29 +290,20 @@ void main() #endif // !NO_SHADOW - // Specular term - float specular = AL_CalcSpecular( -lightDirection, - normal, - normalize(-vsEyeRay) ) * lightBrightness * shadowed; + // Specular term + vec3 viewSpacePos = vsEyeRay * depth; + vec4 real_specular = EvalBDRF( colorSample.rgb, + 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; - vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb; - vec4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-vsEyeRay), normal)) ); - - // 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); - } + float Sat_NdotV = saturate(dot(normalize(-vsEyeRay), normal)); + vec4 addToResult = ( lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * Sat_NdotV ); // Sample the AO texture. #ifdef USE_SSAO_MASK @@ -323,5 +315,5 @@ void main() lightColorOut = debugColor; #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); } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/irradianceP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/irradianceP.hlsl new file mode 100644 index 000000000..8edf5c3e6 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/irradianceP.hlsl @@ -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); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl index 76fb4db70..b14e90cb0 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl @@ -136,48 +136,58 @@ uniform float2 lightAttenuation; uniform float3x3 viewToLightProj; 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 float3 ssPos = IN.ssPos.xyz / IN.ssPos.w; - float2 uvScene = getUVFromSSPos( ssPos, rtParams0 ); - + float2 uvScene = getUVFromSSPos(ssPos, rtParams0); + // Matinfo flags - float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene ); + float4 matInfo = TORQUE_TEX2D(matInfoBuffer, uvScene); //early out if emissive bool emissive = getFlag(matInfo.r, 0); 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); - if (getFlag( matInfo.r, 1 )) + + float4 colorSample = TORQUE_TEX2D(colorBuffer, uvScene); + float3 subsurface = float3(0.0, 0.0, 0.0); + if (getFlag(matInfo.r, 1)) { subsurface = colorSample.rgb; - if (colorSample.r>colorSample.g) + if (colorSample.r > colorSample.g) subsurface = float3(0.772549, 0.337255, 0.262745); else subsurface = float3(0.337255, 0.772549, 0.262745); } // Sample/unpack the normal/z data - float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene ); + float4 deferredSample = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene); float3 normal = deferredSample.rgb; float depth = deferredSample.a; // 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; // Build light vec, get length, clip pixel if needed float3 lightVec = lightPosition - viewSpacePos; - float lenLightV = length( lightVec ); - clip( lightRange - lenLightV ); + float lenLightV = length(lightVec); + clip(lightRange - lenLightV); // Get the attenuated falloff. - float atten = attenuate( lightColor, lightAttenuation, lenLightV ); - clip( atten - 1e-6 ); + float atten = attenuate(lightColor, lightAttenuation, lenLightV); + clip(atten - 1e-6); // Normalize lightVec lightVec /= lenLightV; @@ -187,97 +197,93 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0 float nDotL = dot( lightVec, normal ); //DB_CLIP( nDotL < 0 ); - #ifdef NO_SHADOW - - float shadowed = 1.0; - - #else +#ifdef NO_SHADOW - // Get a linear depth from the light source. - float distToLight = lenLightV / lightRange; + float shadowed = 1.0; - #ifdef SHADOW_CUBE - - // 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 +#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 ); + // Get a linear depth from the light source. + float distToLight = lenLightV / lightRange; - // 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 ); +#ifdef SHADOW_CUBE - 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; - #ifdef USE_COOKIE_TEX +#ifdef USE_COOKIE_TEX - // Lookup the cookie sample. - float4 cookie = TORQUE_TEXCUBE( cookieMap, mul( viewToLightProj, -lightVec ) ); + // Lookup the cookie sample. + float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(viewToLightProj, -lightVec)); - // Multiply the light with the cookie tex. - lightcol *= cookie.rgb; + // Multiply the light with the cookie tex. + lightcol *= cookie.rgb; - // Use a maximum channel luminance to attenuate - // the lighting else we get specular in the dark - // regions of the cookie texture. - atten *= max( cookie.r, max( cookie.g, cookie.b ) ); + // Use a maximum channel luminance to attenuate + // the lighting else we get specular in the dark + // regions of the cookie texture. + atten *= max(cookie.r, max(cookie.g, cookie.b)); - #endif +#endif // NOTE: Do not clip on fully shadowed pixels as it would // cause the hardware occlusion query to disable the shadow. - // Specular term - float specular = 0; - - 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; + float3 l = lightVec;// normalize(-lightDirection); + float3 v = eyeRay;// normalize(eyePosWorld - worldPos.xyz); - Sat_NL_Att = 1.0f; - shadowed = lerp( 1.0f, shadowed, atten ); - lightColorOut = shadowed; - specular *= lightBrightness; - addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); - } - return float4((lightColorOut*Sat_NL_Att+subsurface*(1.0-Sat_NL_Att)+addToResult.rgb),real_specular.a); + 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 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; } diff --git a/Templates/Full/game/shaders/common/lighting/advanced/prefilterP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/prefilterP.hlsl new file mode 100644 index 000000000..17dfac8d2 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/prefilterP.hlsl @@ -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); +} \ No newline at end of file diff --git a/Templates/Full/game/shaders/common/lighting/advanced/probeShadingP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/probeShadingP.hlsl new file mode 100644 index 000000000..3007819c5 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/probeShadingP.hlsl @@ -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) ); +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl new file mode 100644 index 000000000..f18020639 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeP.hlsl @@ -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; + } +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl new file mode 100644 index 000000000..bf78c2815 --- /dev/null +++ b/Templates/Full/game/shaders/common/lighting/advanced/skylightP.hlsl @@ -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; + +} diff --git a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl index 32ae68580..2a6b04ecf 100644 --- a/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl +++ b/Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl @@ -192,23 +192,24 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap), 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 - float4 matInfo = TORQUE_TEX2D( matInfoBuffer, IN.uv0 ); - //early out if emissive - bool emissive = getFlag(matInfo.r, 0); - if (emissive) - { - 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 )) + float4 matInfo = TORQUE_TEX2D(matInfoBuffer, IN.uv0); + + float4 colorSample = TORQUE_TEX2D(colorBuffer, IN.uv0); + float3 subsurface = float3(0.0, 0.0, 0.0); + if (getFlag(matInfo.r, 1)) { subsurface = colorSample.rgb; - if (colorSample.r>colorSample.g) + if (colorSample.r > colorSample.g) subsurface = float3(0.772549, 0.337255, 0.262745); else subsurface = float3(0.337255, 0.772549, 0.262745); @@ -224,96 +225,97 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0 // Get the light attenuation. float dotNL = dot(-lightDirection, normal); - #ifdef PSSM_DEBUG_RENDER - float3 debugColor = float3(0,0,0); - #endif +#ifdef PSSM_DEBUG_RENDER + float3 debugColor = float3(0, 0, 0); +#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. - float shadowed = 1.0; +//output + Output.diffuse = float4(diffuse * (lightBrightness*shadowed), dotNLa); + Output.spec = float4(specular * (lightBrightness*shadowed), dotNLa); - #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 - - // 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); + return Output; } diff --git a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl index ab0e9b56f..54c4bf9b7 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/finalPassCombineP.hlsl @@ -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; } -float3 tonemap(float3 c) +float3 tonemap(float3 color) { const float W = 11.2; float ExposureBias = 2.0f; - float ExposureAdjust = 1.5f; - c *= ExposureAdjust; - float3 curr = Uncharted2Tonemap(ExposureBias*c); - float3 whiteScale = 1.0f / Uncharted2Tonemap(W); - return curr*whiteScale; + //float ExposureAdjust = 1.5f; + //c *= ExposureAdjust; + color = Uncharted2Tonemap(ExposureBias*color); + color = color * (1.0f / Uncharted2Tonemap(W)); + + return color; } 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.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b; + sample = float4(tonemap(sample.rgb),1); + return sample; } diff --git a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl index 4b173d4d3..aa04a1b71 100644 --- a/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl +++ b/Templates/Full/game/shaders/common/postFx/hdr/gl/finalPassCombineP.glsl @@ -48,6 +48,29 @@ uniform float Contrast; 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() { vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) ); @@ -76,17 +99,6 @@ void main() // Add the bloom effect. _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. _sample.r = texture( colorCorrectionTex, _sample.r ).r; diff --git a/Templates/Full/game/shaders/common/torque.hlsl b/Templates/Full/game/shaders/common/torque.hlsl index 35b67bf02..f7ac8de03 100644 --- a/Templates/Full/game/shaders/common/torque.hlsl +++ b/Templates/Full/game/shaders/common/torque.hlsl @@ -310,4 +310,38 @@ float3 simpleFresnel(float3 diffuseColor, float3 reflectColor, float metalness, 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_ diff --git a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl index aba0cfa7e..91bdb4137 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterBasicP.glsl @@ -120,7 +120,6 @@ void main() { // Modulate baseColor by the ambientColor. vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 ); - waterBaseColor = waterBaseColor; // Get the bumpNorm... vec3 bumpNorm = ( texture( bumpMap, IN_rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x; diff --git a/Templates/Full/game/shaders/common/water/gl/waterP.glsl b/Templates/Full/game/shaders/common/water/gl/waterP.glsl index 98fab6a33..d4804245a 100644 --- a/Templates/Full/game/shaders/common/water/gl/waterP.glsl +++ b/Templates/Full/game/shaders/common/water/gl/waterP.glsl @@ -324,7 +324,6 @@ void main() // Calculate the water "base" color based on depth. vec4 waterBaseColor = baseColor * texture( depthGradMap, saturate( delta / depthGradMax ) ); - waterBaseColor = waterBaseColor; // Modulate baseColor by the ambientColor. waterBaseColor *= vec4( ambientColor.rgb, 1 ); diff --git a/Templates/Full/game/shaders/procedural/.gitignore b/Templates/Full/game/shaders/procedural/.gitignore new file mode 100644 index 000000000..5baa4d384 --- /dev/null +++ b/Templates/Full/game/shaders/procedural/.gitignore @@ -0,0 +1 @@ +/procedural/ diff --git a/Templates/Full/game/tools/resources/ReflectProbeSphere.dae b/Templates/Full/game/tools/resources/ReflectProbeSphere.dae new file mode 100644 index 000000000..b488de77a --- /dev/null +++ b/Templates/Full/game/tools/resources/ReflectProbeSphere.dae @@ -0,0 +1,115 @@ + + + + + Anonymous + Collada Exporter for Blender 2.6+, by Juan Linietsky (juan@codenix.com) + + 2016-09-06T21:59:07Z + 2016-09-06T21:59:07Z + + Z_UP + + + + + + + + + + 0.0 0.0 0.0 1.0 + + + 0.0 0.0 0.0 1.0 + + + 0.3737608488464481 0.3737608488464481 0.3737608488464481 1.0 + + + 0.0 0.0 0.0 1.0 + + + 50 + + + 1.0 1.0 1.0 1.0 + + + 4.0 + + + + + + + 0 + + + + + + + + + + + + + + + + -0.49039262533187866 0.0 0.09754517674446106 -0.49039262533187866 0.09754519164562225 3.774895063202166e-08 -0.5 0.0 3.774895063202166e-08 -0.09754516184329987 0.0 0.49039262533187866 1.2401747184753731e-08 -6.234699867491145e-08 0.5 -0.09567085653543472 0.019030148163437843 0.49039262533187866 1.6292068494294654e-07 0.0 -0.5 -0.09754504263401031 0.0 -0.49039265513420105 -0.09567073732614517 0.019030125811696053 -0.49039265513420105 -0.4809698760509491 0.09567089378833771 -0.09754510223865509 -0.49039265513420105 0.0 -0.09754510223865509 -0.1876651495695114 0.03732895478606224 0.4619397521018982 -0.19134172797203064 0.0 0.4619397521018982 -0.4619397819042206 0.0 -0.19134163856506348 -0.4530637264251709 0.09012001007795334 -0.19134163856506348 -0.27778512239456177 0.0 0.41573479771614075 -0.2724475562572479 0.054193224757909775 0.41573479771614075 -0.4077465832233429 0.08110587298870087 -0.2777850925922394 -0.41573482751846313 0.0 -0.2777850925922394 -0.34675994515419006 0.06897487491369247 0.3535533845424652 -0.3535533845424652 0.0 0.3535533845424652 -0.3535533845424652 0.0 -0.3535533845424652 -0.34675994515419006 0.06897487491369247 -0.3535533845424652 -0.4077465832233429 0.08110587298870087 0.2777850925922394 -0.41573482751846313 0.0 0.2777850925922394 -0.27244752645492554 0.05419321730732918 -0.41573482751846313 -0.2777850925922394 0.0 -0.41573482751846313 -0.4530636966228485 0.09012000262737274 0.19134171307086945 -0.4619397521018982 0.0 0.19134171307086945 -0.18766506016254425 0.03732893615961075 -0.46193981170654297 -0.19134163856506348 0.0 -0.46193981170654297 -0.4809698462486267 0.09567088633775711 0.09754517674446106 -0.17677661776542664 0.07322333753108978 -0.46193981170654297 -0.4530636668205261 0.187665194272995 0.09754517674446106 -0.0901198536157608 0.03732893243432045 -0.49039265513420105 -0.4619397222995758 0.19134177267551422 3.774895063202166e-08 -0.09011997282505035 0.03732898086309433 0.49039262533187866 -0.4530636668205261 0.187665194272995 -0.09754510223865509 -0.1767767071723938 0.07322336733341217 0.4619397521018982 -0.4267766773700714 0.17677675187587738 -0.19134163856506348 -0.2566399574279785 0.10630382597446442 0.41573479771614075 -0.3840888440608978 0.1590948849916458 -0.2777850925922394 -0.32664069533348083 0.13529908657073975 0.3535533845424652 -0.32664069533348083 0.13529908657073975 -0.3535533845424652 -0.3840888440608978 0.1590948849916458 0.2777850925922394 -0.25663992762565613 0.10630381107330322 -0.41573482751846313 -0.426776647567749 0.1767767369747162 0.19134171307086945 -0.3840888440608978 0.2566400468349457 -0.19134163856506348 -0.34567081928253174 0.23096996545791626 -0.2777850925922394 -0.2939688563346863 0.19642382860183716 0.3535533845424652 -0.2939688563346863 0.19642382860183716 -0.3535533845424652 -0.34567081928253174 0.23096996545791626 0.2777850925922394 -0.23096981644630432 0.15432921051979065 -0.41573482751846313 -0.38408881425857544 0.2566400468349457 0.19134171307086945 -0.15909473598003387 0.10630381107330322 -0.46193981170654297 -0.40774649381637573 0.2724476158618927 0.09754517674446106 -0.08110571652650833 0.05419320985674858 -0.49039265513420105 -0.41573473811149597 0.27778521180152893 3.774895063202166e-08 -0.08110581338405609 0.05419328436255455 0.49039262533187866 -0.40774649381637573 0.2724476158618927 -0.09754510223865509 -0.15909481048583984 0.1063038557767868 0.4619397521018982 -0.2309698462486267 0.15432922542095184 0.41573479771614075 -0.06897471845149994 0.06897486746311188 -0.49039265513420105 -0.3467598557472229 0.3467600345611572 0.09754517674446106 -0.35355329513549805 0.35355350375175476 3.774895063202166e-08 -0.0689748004078865 0.06897496432065964 0.49039262533187866 -0.3467598557472229 0.3467600345611572 -0.09754510223865509 -0.1352989822626114 0.13529914617538452 0.4619397521018982 -0.32664069533348083 0.3266408145427704 -0.19134163856506348 -0.19642367959022522 0.19642384350299835 0.41573479771614075 -0.2939688265323639 0.2939690053462982 -0.2777850925922394 -0.24999994039535522 0.25000008940696716 0.3535533845424652 -0.24999994039535522 0.25000008940696716 -0.3535533845424652 -0.2939688265323639 0.2939690053462982 0.2777850925922394 -0.19642364978790283 0.19642382860183716 -0.41573482751846313 -0.32664066553115845 0.3266408145427704 0.19134171307086945 -0.1352989375591278 0.13529908657073975 -0.46193981170654297 -0.19642364978790283 0.2939690053462982 0.3535533845424652 -0.19642364978790283 0.2939690053462982 -0.3535533845424652 -0.23096978664398193 0.3456709682941437 0.2777850925922394 -0.15432903170585632 0.23096996545791626 -0.41573482751846313 -0.25663989782333374 0.3840889632701874 0.19134171307086945 -0.10630366206169128 0.159094899892807 -0.46193981170654297 -0.272447407245636 0.40774664282798767 0.09754517674446106 -0.054193053394556046 0.08110586553812027 -0.49039265513420105 -0.2777850031852722 0.4157349169254303 3.774895063202166e-08 -0.05419311672449112 0.08110596984624863 0.49039262533187866 -0.272447407245636 0.40774664282798767 -0.09754510223865509 -0.10630369931459427 0.15909495949745178 0.4619397521018982 -0.25663992762565613 0.3840889632701874 -0.19134163856506348 -0.1543290615081787 0.23096999526023865 0.41573479771614075 -0.23096978664398193 0.3456709682941437 -0.2777850925922394 -0.1913415789604187 0.46193987131118774 3.774895063202166e-08 -0.0373288132250309 0.09012012183666229 0.49039262533187866 -0.037328775972127914 0.09012000262737274 -0.49039265513420105 -0.1876649558544159 0.4530637562274933 -0.09754510223865509 -0.07322321087121964 0.17677684128284454 0.4619397521018982 -0.17677661776542664 0.4267767667770386 -0.19134163856506348 -0.10630366206169128 0.25664010643959045 0.41573479771614075 -0.1590946912765503 0.38408899307250977 -0.2777850925922394 -0.13529890775680542 0.3266408443450928 0.3535533845424652 -0.13529890775680542 0.3266408443450928 -0.3535533845424652 -0.1590946912765503 0.38408899307250977 0.2777850925922394 -0.1063036322593689 0.25664007663726807 -0.41573482751846313 -0.17677658796310425 0.4267767667770386 0.19134171307086945 -0.07322318851947784 0.17677676677703857 -0.46193981170654297 -0.1876649558544159 0.4530637562274933 0.09754517674446106 -0.08110568672418594 0.40774667263031006 -0.2777850925922394 -0.06897471100091934 0.3467600643634796 -0.3535533845424652 -0.08110568672418594 0.40774667263031006 0.2777850925922394 -0.05419303476810455 0.2724476456642151 -0.41573482751846313 -0.0901198536157608 0.4530637860298157 0.19134171307086945 -0.03732877969741821 0.1876652091741562 -0.46193981170654297 -0.0956706702709198 0.4809699058532715 0.09754517674446106 -0.019029967486858368 0.09567087888717651 -0.49039265513420105 -0.09754499793052673 0.4903927445411682 3.774895063202166e-08 -0.019029982388019562 0.09567100554704666 0.49039262533187866 -0.0956706702709198 0.4809699058532715 -0.09754510223865509 -0.03732878714799881 0.18766528367996216 0.4619397521018982 -0.09011988341808319 0.4530637860298157 -0.19134163856506348 -0.054193057119846344 0.2724476754665375 0.41573479771614075 -0.06897471100091934 0.3467600643634796 0.3535533845424652 1.6331796359736472e-07 0.09754530340433121 0.49039262533187866 1.5400473785120994e-07 0.09754518419504166 -0.49039265513420105 1.8939499568659812e-07 0.5000001192092896 3.774895063202166e-08 1.9684557628352195e-07 0.49039262533187866 -0.09754510223865509 1.595926732989028e-07 0.1913418471813202 0.4619397521018982 1.1488918971735984e-07 0.46193984150886536 -0.19134163856506348 1.558673830004409e-07 0.2777852416038513 0.41573479771614075 1.6704325389582664e-07 0.4157348871231079 -0.2777850925922394 1.595926732989028e-07 0.3535534739494324 0.3535533845424652 1.595926732989028e-07 0.3535534739494324 -0.3535533845424652 1.6704325389582664e-07 0.4157348871231079 0.2777850925922394 1.7076854419428855e-07 0.27778518199920654 -0.41573482751846313 1.3724093150813133e-07 0.46193984150886536 0.19134171307086945 1.5214209270197898e-07 0.19134177267551422 -0.46193981170654297 1.9684557628352195e-07 0.49039262533187866 0.09754517674446106 0.06897501647472382 0.3467600345611572 0.3535533845424652 0.08110601454973221 0.40774664282798767 0.2777850925922394 0.06897501647472382 0.3467600345611572 -0.3535533845424652 0.05419337376952171 0.2724476158618927 -0.41573482751846313 0.09012012928724289 0.4530637860298157 0.19134171307086945 0.03732908144593239 0.187665194272995 -0.46193981170654297 0.09567105025053024 0.4809698462486267 0.09754517674446106 0.01903027668595314 0.09567087888717651 -0.49039265513420105 0.09754537045955658 0.4903927445411682 3.774895063202166e-08 0.019030308350920677 0.09567099809646606 0.49039262533187866 0.09567105025053024 0.4809698462486267 -0.09754510223865509 0.03732910379767418 0.18766526877880096 0.4619397521018982 0.0901201069355011 0.4530637860298157 -0.19134163856506348 0.054193370044231415 0.2724476754665375 0.41573479771614075 0.08110601454973221 0.40774664282798767 -0.2777850925922394 0.18766531348228455 0.4530636668205261 -0.09754510223865509 0.07322350889444351 0.17677681148052216 0.4619397521018982 0.17677682638168335 0.4267767667770386 -0.19134163856506348 0.10630396008491516 0.25664007663726807 0.41573479771614075 0.15909501910209656 0.3840889036655426 -0.2777850925922394 0.1352992057800293 0.3266408145427704 0.3535533845424652 0.1352992057800293 0.3266408145427704 -0.3535533845424652 0.15909501910209656 0.3840889036655426 0.2777850925922394 0.10630396008491516 0.2566400170326233 -0.41573482751846313 0.17677685618400574 0.4267767667770386 0.19134171307086945 0.07322347909212112 0.1767767369747162 -0.46193981170654297 0.18766531348228455 0.4530636668205261 0.09754517674446106 0.03732908144593239 0.09011999517679214 -0.49039265513420105 0.19134193658828735 0.46193984150886536 3.774895063202166e-08 0.03732913359999657 0.0901200994849205 0.49039262533187866 0.19642391800880432 0.29396897554397583 -0.3535533845424652 0.1543293297290802 0.23096990585327148 -0.41573482751846313 0.25664013624191284 0.384088933467865 0.19134171307086945 0.10630394518375397 0.15909485518932343 -0.46193981170654297 0.27244770526885986 0.4077465236186981 0.09754517674446106 0.05419335886836052 0.08110585063695908 -0.49039265513420105 0.2777853310108185 0.4157348573207855 3.774895063202166e-08 0.05419342592358589 0.08110594004392624 0.49039262533187866 0.27244770526885986 0.4077465236186981 -0.09754510223865509 0.10630397498607635 0.1590949296951294 0.4619397521018982 0.25664013624191284 0.384088933467865 -0.19134163856506348 0.1543293446302414 0.23096996545791626 0.41573479771614075 0.2309700846672058 0.3456708788871765 -0.2777850925922394 0.19642391800880432 0.29396897554397583 0.3535533845424652 0.2309700846672058 0.3456708788871765 0.2777850925922394 0.32664090394973755 0.3266408145427704 -0.19134163856506348 0.1964239478111267 0.19642379879951477 0.41573479771614075 0.2939690947532654 0.29396888613700867 -0.2777850925922394 0.2500001788139343 0.2500000298023224 0.3535533845424652 0.2500001788139343 0.2500000298023224 -0.3535533845424652 0.2939690947532654 0.29396888613700867 0.2777850925922394 0.19642391800880432 0.1964237540960312 -0.41573482751846313 0.32664090394973755 0.3266408145427704 0.19134171307086945 0.1352992057800293 0.13529904186725616 -0.46193981170654297 0.346760094165802 0.3467599153518677 0.09754517674446106 0.06897501647472382 0.06897485256195068 -0.49039265513420105 0.3535536229610443 0.3535534143447876 3.774895063202166e-08 0.06897509843111038 0.06897492706775665 0.49039262533187866 0.346760094165802 0.3467599153518677 -0.09754510223865509 0.13529925048351288 0.13529911637306213 0.4619397521018982 0.15909498929977417 0.10630377382040024 -0.46193981170654297 0.38408905267715454 0.2566400468349457 0.19134171307086945 0.40774670243263245 0.27244749665260315 0.09754517674446106 0.08110600709915161 0.05419319495558739 -0.49039265513420105 0.41573503613471985 0.27778512239456177 3.774895063202166e-08 0.08110609650611877 0.054193247109651566 0.49039262533187866 0.40774670243263245 0.27244749665260315 -0.09754510223865509 0.15909504890441895 0.10630382597446442 0.4619397521018982 0.38408905267715454 0.2566400468349457 -0.19134163856506348 0.2309700846672058 0.15432918071746826 0.41573479771614075 0.34567102789878845 0.2309698611497879 -0.2777850925922394 0.2939690947532654 0.1964237540960312 0.3535533845424652 0.2939690947532654 0.1964237540960312 -0.3535533845424652 0.34567102789878845 0.2309698611497879 0.2777850925922394 0.23097005486488342 0.15432913601398468 -0.41573482751846313 0.1767769157886505 0.07322335243225098 0.4619397521018982 0.2566401958465576 0.10630379617214203 0.41573479771614075 0.42677685618400574 0.1767767369747162 -0.19134163856506348 0.38408902287483215 0.15909478068351746 -0.2777850925922394 0.32664090394973755 0.13529901206493378 0.3535533845424652 0.32664090394973755 0.13529901206493378 -0.3535533845424652 0.38408902287483215 0.15909478068351746 0.2777850925922394 0.25664013624191284 0.10630375146865845 -0.41573482751846313 0.42677685618400574 0.1767767369747162 0.19134171307086945 0.17677685618400574 0.0732233077287674 -0.46193981170654297 0.45306381583213806 0.18766507506370544 0.09754517674446106 0.09012014418840408 0.03732892498373985 -0.49039265513420105 0.4619399905204773 0.19134169816970825 3.774895063202166e-08 0.09012024104595184 0.03732895851135254 0.49039262533187866 0.45306381583213806 0.18766507506370544 -0.09754510223865509 0.45306387543678284 0.09012001007795334 0.19134171307086945 0.48096996545791626 0.09567080438137054 0.09754517674446106 0.18766529858112335 0.037328921258449554 -0.46193981170654297 0.09567102044820786 0.019030120223760605 -0.49039265513420105 0.49039286375045776 0.09754512459039688 3.774895063202166e-08 0.09567112475633621 0.0190301351249218 0.49039262533187866 0.48096996545791626 0.09567080438137054 -0.09754510223865509 0.18766535818576813 0.03732895106077194 0.4619397521018982 0.45306387543678284 0.09012001007795334 -0.19134163856506348 0.27244776487350464 0.05419321358203888 0.41573479771614075 0.40774667263031006 0.0811057835817337 -0.2777850925922394 0.3467601239681244 0.06897483021020889 0.3535533845424652 0.3467601239681244 0.06897483021020889 -0.3535533845424652 0.40774667263031006 0.0811057835817337 0.2777850925922394 0.27244770526885986 0.05419318005442619 -0.41573482751846313 0.4619399309158325 3.1784249898691996e-08 -0.19134163856506348 0.4157348573207855 -4.2721556070546285e-08 -0.2777850925922394 0.2777853310108185 1.3157798406382426e-08 0.41573479771614075 0.35355353355407715 -1.2919233682850972e-08 0.3535533845424652 0.35355353355407715 -1.2919233682850972e-08 -0.3535533845424652 0.4157348573207855 -4.2721556070546285e-08 0.2777850925922394 0.2777852416038513 -5.468653085927144e-09 -0.41573482751846313 0.4619399309158325 3.1784249898691996e-08 0.19134171307086945 0.19134186208248138 1.981927510996684e-09 -0.46193981170654297 0.49039268493652344 -4.2721556070546285e-08 0.09754517674446106 0.0975453183054924 1.981927510996684e-09 -0.49039265513420105 0.5000001788139343 -5.017213666747011e-08 3.774895063202166e-08 0.09754542261362076 -3.6060079366961872e-09 0.49039262533187866 0.49039268493652344 -4.2721556070546285e-08 -0.09754510223865509 0.19134192168712616 2.0608379003306254e-08 0.4619397521018982 0.09567101299762726 -0.019030114635825157 -0.49039265513420105 0.490392804145813 -0.09754522144794464 3.774895063202166e-08 0.09567110985517502 -0.019030140712857246 0.49039262533187866 0.4809699058532715 -0.09567087888717651 -0.09754510223865509 0.18766532838344574 -0.03732890635728836 0.4619397521018982 0.45306387543678284 -0.09011995047330856 -0.19134163856506348 0.27244776487350464 -0.05419318377971649 0.41573479771614075 0.4077466130256653 -0.08110586553812027 -0.2777850925922394 0.346760094165802 -0.06897486001253128 0.3535533845424652 0.346760094165802 -0.06897486001253128 -0.3535533845424652 0.4077466130256653 -0.08110586553812027 0.2777850925922394 0.2724476754665375 -0.05419318377971649 -0.41573482751846313 0.45306387543678284 -0.09011995047330856 0.19134171307086945 0.18766526877880096 -0.03732891008257866 -0.46193981170654297 0.4809699058532715 -0.09567087888717651 0.09754517674446106 0.2566401958465576 -0.10630376636981964 0.41573479771614075 0.32664087414741516 -0.13529902696609497 0.3535533845424652 0.32664087414741516 -0.13529902696609497 -0.3535533845424652 0.3840888738632202 -0.15909482538700104 0.2777850925922394 0.25664010643959045 -0.10630375146865845 -0.41573482751846313 0.42677685618400574 -0.17677666246891022 0.19134171307086945 0.17677681148052216 -0.0732232928276062 -0.46193981170654297 0.4530637264251709 -0.18766513466835022 0.09754517674446106 0.09012012183666229 -0.03732891008257866 -0.49039265513420105 0.46193990111351013 -0.19134178757667542 3.774895063202166e-08 0.09012021869421005 -0.03732895478606224 0.49039262533187866 0.4530637264251709 -0.18766513466835022 -0.09754510223865509 0.17677687108516693 -0.0732233002781868 0.4619397521018982 0.42677685618400574 -0.17677666246891022 -0.19134163856506348 0.3840888738632202 -0.15909482538700104 -0.2777850925922394 0.4157349169254303 -0.27778518199920654 3.774895063202166e-08 0.08110606670379639 -0.05419323593378067 0.49039262533187866 0.08110597729682922 -0.054193172603845596 -0.49039265513420105 0.4077465832233429 -0.27244752645492554 -0.09754510223865509 0.15909498929977417 -0.10630375891923904 0.4619397521018982 0.38408902287483215 -0.2566399574279785 -0.19134163856506348 0.2309700846672058 -0.15432915091514587 0.41573479771614075 0.3456708490848541 -0.2309698462486267 -0.2777850925922394 0.2939690351486206 -0.19642373919487 0.3535533845424652 0.2939690351486206 -0.19642373919487 -0.3535533845424652 0.3456708490848541 -0.2309698462486267 0.2777850925922394 0.23096999526023865 -0.1543291211128235 -0.41573482751846313 0.38408902287483215 -0.2566399574279785 0.19134171307086945 0.1590949296951294 -0.10630373656749725 -0.46193981170654297 0.4077465832233429 -0.27244752645492554 0.09754517674446106 0.25000011920928955 -0.25 -0.3535533845424652 0.25000011920928955 -0.25 0.3535533845424652 0.29396888613700867 -0.2939688265323639 0.2777850925922394 0.19642384350299835 -0.1964237093925476 -0.41573482751846313 0.32664087414741516 -0.32664069533348083 0.19134171307086945 0.13529913127422333 -0.13529899716377258 -0.46193981170654297 0.34675994515419006 -0.3467598855495453 0.09754517674446106 0.06897498667240143 -0.0689748227596283 -0.49039265513420105 0.3535534739494324 -0.35355344414711 3.774895063202166e-08 0.0689750611782074 -0.06897490471601486 0.49039262533187866 0.34675994515419006 -0.3467598855495453 -0.09754510223865509 0.1352991759777069 -0.13529902696609497 0.4619397521018982 0.32664087414741516 -0.32664069533348083 -0.19134163856506348 0.19642393290996552 -0.1964237540960312 0.41573479771614075 0.29396888613700867 -0.2939688265323639 -0.2777850925922394 0.05419332906603813 -0.08110581338405609 -0.49039265513420105 0.27244752645492554 -0.40774646401405334 -0.09754510223865509 0.10630390048027039 -0.15909482538700104 0.4619397521018982 0.25664013624191284 -0.3840888440608978 -0.19134163856506348 0.154329314827919 -0.2309698909521103 0.41573479771614075 0.2309698909521103 -0.34567075967788696 -0.2777850925922394 0.19642385840415955 -0.29396888613700867 0.3535533845424652 0.19642385840415955 -0.29396888613700867 -0.3535533845424652 0.2309698909521103 -0.34567075967788696 0.2777850925922394 0.15432924032211304 -0.2309698462486267 -0.41573482751846313 0.25664013624191284 -0.3840888440608978 0.19134171307086945 0.1063038557767868 -0.15909478068351746 -0.46193981170654297 0.27244752645492554 -0.40774646401405334 0.09754517674446106 0.27778518199920654 -0.41573482751846313 3.774895063202166e-08 0.05419338867068291 -0.08110590279102325 0.49039262533187866 0.106303870677948 -0.25663992762565613 -0.41573482751846313 0.17677685618400574 -0.4267766773700714 0.19134171307086945 0.07322340458631516 -0.17677663266658783 -0.46193981170654297 0.18766511976718903 -0.45306357741355896 0.09754517674446106 0.0373290590941906 -0.09011994302272797 -0.49039265513420105 0.19134177267551422 -0.4619397521018982 3.774895063202166e-08 0.03732910379767418 -0.09012004733085632 0.49039262533187866 0.18766511976718903 -0.45306357741355896 -0.09754510223865509 0.07322343438863754 -0.1767766773700714 0.4619397521018982 0.17677685618400574 -0.4267766773700714 -0.19134163856506348 0.10630391538143158 -0.2566399872303009 0.41573479771614075 0.15909484028816223 -0.3840887248516083 -0.2777850925922394 0.13529913127422333 -0.3266407251358032 0.3535533845424652 0.13529913127422333 -0.3266407251358032 -0.3535533845424652 0.15909484028816223 -0.3840887248516083 0.2777850925922394 0.019030287861824036 -0.09567093104124069 0.49039262533187866 0.03732905164361 -0.18766510486602783 0.4619397521018982 0.09012013673782349 -0.4530636966228485 -0.19134163856506348 0.05419333279132843 -0.2724475562572479 0.41573479771614075 0.08110587298870087 -0.40774640440940857 -0.2777850925922394 0.06897494196891785 -0.34675994515419006 0.3535533845424652 0.06897494196891785 -0.34675994515419006 -0.3535533845424652 0.08110587298870087 -0.40774640440940857 0.2777850925922394 0.05419331043958664 -0.27244749665260315 -0.41573482751846313 0.09012013673782349 -0.4530636966228485 0.19134171307086945 0.03732902929186821 -0.18766506016254425 -0.46193981170654297 0.09567087143659592 -0.48096969723701477 0.09754517674446106 0.019030267372727394 -0.09567081928253174 -0.49039265513420105 0.09754522144794464 -0.4903925955295563 3.774895063202166e-08 0.09567087143659592 -0.48096969723701477 -0.09754510223865509 1.595926732989028e-07 -0.4619397222995758 0.19134171307086945 1.297903509112075e-07 -0.2777850329875946 -0.41573482751846313 1.2606506061274558e-07 -0.19134162366390228 -0.46193981170654297 4.783396434504539e-08 -0.49039241671562195 0.09754517674446106 1.5773002814967185e-07 -0.09754512459039688 -0.49039265513420105 7.018570613581687e-08 -0.49999991059303284 3.774895063202166e-08 1.558673830004409e-07 -0.09754522889852524 0.49039262533187866 4.783396434504539e-08 -0.49039241671562195 -0.09754510223865509 1.4096622180659324e-07 -0.19134168326854706 0.4619397521018982 1.595926732989028e-07 -0.4619397222995758 -0.19134163856506348 1.4096622180659324e-07 -0.2777850925922394 0.41573479771614075 7.018570613581687e-08 -0.4157346189022064 -0.2777850925922394 9.253744792658836e-08 -0.3535533547401428 0.3535533845424652 9.253744792658836e-08 -0.3535533547401428 -0.3535533845424652 7.018570613581687e-08 -0.4157346189022064 0.2777850925922394 -0.09011981636285782 -0.4530636668205261 -0.19134163856506348 -0.05419304221868515 -0.27244752645492554 0.41573479771614075 -0.08110573142766953 -0.4077463448047638 -0.2777850925922394 -0.06897474825382233 -0.3467599153518677 0.3535533845424652 -0.06897474825382233 -0.3467599153518677 -0.3535533845424652 -0.08110573142766953 -0.4077463448047638 0.2777850925922394 -0.05419304221868515 -0.27244746685028076 -0.41573482751846313 -0.09011981636285782 -0.4530636668205261 0.19134171307086945 -0.037328772246837616 -0.18766504526138306 -0.46193981170654297 -0.09567076712846756 -0.4809696078300476 0.09754517674446106 -0.019029950723052025 -0.09567081928253174 -0.49039265513420105 -0.0975450798869133 -0.4903925061225891 3.774895063202166e-08 -0.019029973074793816 -0.0956709235906601 0.49039262533187866 -0.09567076712846756 -0.4809696078300476 -0.09754510223865509 -0.03732876852154732 -0.18766510486602783 0.4619397521018982 -0.10630360245704651 -0.25663986802101135 -0.41573482751846313 -0.07322314381599426 -0.17677660286426544 -0.46193981170654297 -0.17677652835845947 -0.426776647567749 0.19134171307086945 -0.18766498565673828 -0.453063428401947 0.09754517674446106 -0.03732874244451523 -0.09011994302272797 -0.49039265513420105 -0.1913416087627411 -0.46193960309028625 3.774895063202166e-08 -0.03732878342270851 -0.09012003988027573 0.49039262533187866 -0.18766498565673828 -0.453063428401947 -0.09754510223865509 -0.07322315126657486 -0.17677666246891022 0.4619397521018982 -0.17677652835845947 -0.426776647567749 -0.19134163856506348 -0.1063036173582077 -0.25663992762565613 0.41573479771614075 -0.1590946763753891 -0.3840886354446411 -0.2777850925922394 -0.1352989226579666 -0.32664066553115845 0.3535533845424652 -0.1352989226579666 -0.32664066553115845 -0.3535533845424652 -0.1590946763753891 -0.3840886354446411 0.2777850925922394 -0.10630360245704651 -0.15909478068351746 0.4619397521018982 -0.15432898700237274 -0.23096981644630432 0.41573479771614075 -0.2566398084163666 -0.38408881425857544 -0.19134163856506348 -0.23096969723701477 -0.345670610666275 -0.2777850925922394 -0.19642361998558044 -0.2939688265323639 0.3535533845424652 -0.19642361998558044 -0.2939688265323639 -0.3535533845424652 -0.23096969723701477 -0.345670610666275 0.2777850925922394 -0.15432895720005035 -0.23096975684165955 -0.41573482751846313 -0.2566398084163666 -0.38408881425857544 0.19134171307086945 -0.10630358010530472 -0.15909472107887268 -0.46193981170654297 -0.2724473476409912 -0.407746285200119 0.09754517674446106 -0.05419300124049187 -0.0811058059334755 -0.49039265513420105 -0.27778497338294983 -0.4157346189022064 3.774895063202166e-08 -0.05419306457042694 -0.08110588788986206 0.49039262533187866 -0.2724473476409912 -0.407746285200119 -0.09754510223865509 -0.3266405463218689 -0.32664069533348083 0.19134171307086945 -0.3467596769332886 -0.3467596769332886 0.09754517674446106 -0.06897465884685516 -0.0689748153090477 -0.49039265513420105 -0.3535532057285309 -0.3535531759262085 3.774895063202166e-08 -0.06897473335266113 -0.06897488236427307 0.49039262533187866 -0.3467596769332886 -0.3467596769332886 -0.09754510223865509 -0.13529884815216064 -0.1352989673614502 0.4619397521018982 -0.3266405463218689 -0.32664069533348083 -0.19134163856506348 -0.19642357528209686 -0.19642366468906403 0.41573479771614075 -0.29396867752075195 -0.29396864771842957 -0.2777850925922394 -0.24999986588954926 -0.24999992549419403 0.3535533845424652 -0.24999986588954926 -0.24999992549419403 -0.3535533845424652 -0.29396867752075195 -0.29396864771842957 0.2777850925922394 -0.19642353057861328 -0.19642361998558044 -0.41573482751846313 -0.13529881834983826 -0.1352989375591278 -0.46193981170654297 -0.3840886652469635 -0.25663992762565613 -0.19134163856506348 -0.34567058086395264 -0.2309696525335312 -0.2777850925922394 -0.29396873712539673 -0.19642364978790283 0.3535533845424652 -0.29396873712539673 -0.19642364978790283 -0.3535533845424652 -0.34567058086395264 -0.2309696525335312 0.2777850925922394 -0.2309696525335312 -0.15432903170585632 -0.41573482751846313 -0.3840886652469635 -0.25663992762565613 0.19134171307086945 -0.15909460186958313 -0.10630368441343307 -0.46193981170654297 -0.40774622559547424 -0.27244728803634644 0.09754517674446106 -0.08110564947128296 -0.0541931614279747 -0.49039265513420105 -0.41573455929756165 -0.27778491377830505 3.774895063202166e-08 -0.08110573142766953 -0.05419321358203888 0.49039262533187866 -0.40774622559547424 -0.27244728803634644 -0.09754510223865509 -0.15909463167190552 -0.10630370676517487 0.4619397521018982 -0.23096969723701477 -0.1543290615081787 0.41573479771614075 -0.09011978656053543 -0.037328895181417465 -0.49039265513420105 -0.4619394540786743 -0.19134151935577393 3.774895063202166e-08 -0.09011988341808319 -0.03732892870903015 0.49039262533187866 -0.45306330919265747 -0.18766489624977112 -0.09754510223865509 -0.17677649855613708 -0.07322325557470322 0.4619397521018982 -0.4267764687538147 -0.17677664756774902 -0.19134163856506348 -0.2566397786140442 -0.10630369186401367 0.41573479771614075 -0.38408854603767395 -0.15909460186958313 -0.2777850925922394 -0.3266405761241913 -0.1352989375591278 0.3535533845424652 -0.3266405761241913 -0.1352989375591278 -0.3535533845424652 -0.38408854603767395 -0.15909460186958313 0.2777850925922394 -0.2566397190093994 -0.10630366206169128 -0.41573482751846313 -0.4267764687538147 -0.17677664756774902 0.19134171307086945 -0.1767764687538147 -0.07322324067354202 -0.46193981170654297 -0.45306330919265747 -0.18766489624977112 0.09754517674446106 -0.34675976634025574 -0.06897476315498352 -0.3535533845424652 -0.34675976634025574 -0.06897476315498352 0.3535533845424652 -0.40774619579315186 -0.08110565692186356 0.2777850925922394 -0.27244725823402405 -0.054193101823329926 -0.41573482751846313 -0.4530634880065918 -0.09011993557214737 0.19134171307086945 -0.18766489624977112 -0.03732886165380478 -0.46193981170654297 -0.4809694290161133 -0.0956706702709198 0.09754517674446106 -0.0956706628203392 -0.019030101597309113 -0.49039265513420105 -0.49039226770401 -0.09754499047994614 3.774895063202166e-08 -0.09567075967788696 -0.019030112773180008 0.49039262533187866 -0.4809694290161133 -0.0956706702709198 -0.09754510223865509 -0.1876649260520935 -0.037328869104385376 0.4619397521018982 -0.4530634880065918 -0.09011993557214737 -0.19134163856506348 -0.2724473178386688 -0.05419312044978142 0.41573479771614075 -0.40774619579315186 -0.08110565692186356 -0.2777850925922394 + + + + + + + + + + -0.9809869527816772 0.0 0.19391460716724396 -0.9807733297348022 0.19507431983947754 0.0 -1.0 0.0 0.0 -0.20096439123153687 0.0 0.9795831441879272 0.0 0.0 1.0 -0.19708853960037231 0.039185766130685806 0.9795831441879272 0.0 0.0 -1.0 -0.20096439123153687 0.0 -0.9795831441879272 -0.19708853960037231 0.039185766130685806 -0.9795831441879272 -0.9621570706367493 0.191381573677063 -0.19391460716724396 -0.9809869527816772 0.0 -0.19391460716724396 -0.3804132342338562 0.07565538585186005 0.921689510345459 -0.3878597319126129 0.0 0.921689510345459 -0.9247413277626038 0.0 -0.3805353045463562 -0.9069795608520508 0.18039490282535553 -0.3805353045463562 -0.5597705245018005 0.0 0.8286385536193848 -0.5489974617958069 0.10919522494077682 0.8286385536193848 -0.8173161745071411 0.16257210075855255 -0.5527512431144714 -0.8333384394645691 0.0 -0.5527512431144714 -0.6964934468269348 0.13852351903915405 0.7040314674377441 -0.7101352214813232 0.0 0.7040314674377441 -0.7101352214813232 0.0 -0.7040314674377441 -0.6964934468269348 0.13852351903915405 -0.7040314674377441 -0.8173161745071411 0.16257210075855255 0.5527512431144714 -0.8333384394645691 0.0 0.5527512431144714 -0.5489974617958069 0.10919522494077682 -0.8286385536193848 -0.5597705245018005 0.0 -0.8286385536193848 -0.9069795608520508 0.18039490282535553 0.3805353045463562 -0.9247413277626038 0.0 0.3805353045463562 -0.3804132342338562 0.07565538585186005 -0.921689510345459 -0.3878597319126129 0.0 -0.921689510345459 -0.9621570706367493 0.191381573677063 0.19391460716724396 -0.3583483397960663 0.14841151237487793 -0.921689510345459 -0.9063386917114258 0.3754081726074219 0.19391460716724396 -0.18564409017562866 0.07690664380788803 -0.9795831441879272 -0.9238563179969788 0.382671594619751 0.0 -0.18564409017562866 0.07690664380788803 0.9795831441879272 -0.9063386917114258 0.3754081726074219 -0.19391460716724396 -0.3583483397960663 0.14841151237487793 0.921689510345459 -0.8543656468391418 0.35389262437820435 -0.3805353045463562 -0.5171361565589905 0.2142094224691391 0.8286385536193848 -0.7698904275894165 0.3188879191875458 -0.5527512431144714 -0.6560564041137695 0.2717368006706238 0.7040314674377441 -0.6560564041137695 0.2717368006706238 -0.7040314674377441 -0.7698904275894165 0.3188879191875458 0.5527512431144714 -0.5171361565589905 0.2142094224691391 -0.8286385536193848 -0.8543656468391418 0.35386210680007935 0.3805353045463562 -0.7689138650894165 0.5137485861778259 -0.3805353045463562 -0.6928922533988953 0.46296578645706177 -0.5527512431144714 -0.5904415845870972 0.39451277256011963 0.7040314674377441 -0.5904415845870972 0.39451277256011963 -0.7040314674377441 -0.6928922533988953 0.46296578645706177 0.5527512431144714 -0.46540728211402893 0.3109835982322693 -0.8286385536193848 -0.7689138650894165 0.5137485861778259 0.3805353045463562 -0.32248908281326294 0.2154911905527115 -0.921689510345459 -0.8156682252883911 0.5449995398521423 0.19391460716724396 -0.1670888364315033 0.1116367056965828 -0.9795831441879272 -0.8314462900161743 0.5555589199066162 0.0 -0.1670888364315033 0.1116367056965828 0.9795831441879272 -0.8156682252883911 0.5449995398521423 -0.19391460716724396 -0.32248908281326294 0.2154911905527115 0.921689510345459 -0.46540728211402893 0.3109835982322693 0.8286385536193848 -0.1420941799879074 0.1420941799879074 -0.9795831441879272 -0.6936551928520203 0.6936551928520203 0.19391460716724396 -0.7070833444595337 0.7070833444595337 0.0 -0.1420941799879074 0.1420941799879074 0.9795831441879272 -0.6936551928520203 0.6936551928520203 -0.19391460716724396 -0.27426984906196594 0.27426984906196594 0.921689510345459 -0.6538895964622498 0.6538895964622498 -0.3805353045463562 -0.395794540643692 0.395794540643692 0.8286385536193848 -0.5892513990402222 0.5892513990402222 -0.5527512431144714 -0.5021210312843323 0.5021210312843323 0.7040314674377441 -0.5021210312843323 0.5021210312843323 -0.7040314674377441 -0.5892513990402222 0.5892513990402222 0.5527512431144714 -0.395794540643692 0.395794540643692 -0.8286385536193848 -0.6538895964622498 0.6538895964622498 0.3805353045463562 -0.27426984906196594 0.27426984906196594 -0.921689510345459 -0.39451277256011963 0.5904415845870972 0.7040314674377441 -0.39451277256011963 0.5904415845870972 -0.7040314674377441 -0.46296578645706177 0.6928922533988953 0.5527512431144714 -0.3109835982322693 0.46540728211402893 -0.8286385536193848 -0.5137485861778259 0.7689138650894165 0.3805353045463562 -0.2154911905527115 0.32248908281326294 -0.921689510345459 -0.5449995398521423 0.8156682252883911 0.19391460716724396 -0.1116367056965828 0.1670888364315033 -0.9795831441879272 -0.5555589199066162 0.8314462900161743 0.0 -0.1116367056965828 0.1670888364315033 0.9795831441879272 -0.5449995398521423 0.8156682252883911 -0.19391460716724396 -0.2154911905527115 0.32248908281326294 0.921689510345459 -0.5137485861778259 0.7689138650894165 -0.3805353045463562 -0.3109835982322693 0.46540728211402893 0.8286385536193848 -0.46296578645706177 0.6928922533988953 -0.5527512431144714 -0.382671594619751 0.9238563179969788 0.0 -0.07690664380788803 0.18564409017562866 0.9795831441879272 -0.07690664380788803 0.18564409017562866 -0.9795831441879272 -0.3754081726074219 0.9063386917114258 -0.19391460716724396 -0.14841151237487793 0.3583483397960663 0.921689510345459 -0.35386210680007935 0.8543656468391418 -0.3805353045463562 -0.2142094224691391 0.5171361565589905 0.8286385536193848 -0.3188879191875458 0.7698904275894165 -0.5527512431144714 -0.2717368006706238 0.6560564041137695 0.7040314674377441 -0.2717368006706238 0.6560564041137695 -0.7040314674377441 -0.3188879191875458 0.7698904275894165 0.5527512431144714 -0.2142094224691391 0.5171361565589905 -0.8286385536193848 -0.35386210680007935 0.8543656468391418 0.3805353045463562 -0.14841151237487793 0.3583483397960663 -0.921689510345459 -0.3754081726074219 0.9063386917114258 0.19391460716724396 -0.16257210075855255 0.8173161745071411 -0.5527512431144714 -0.13852351903915405 0.6964934468269348 -0.7040314674377441 -0.16257210075855255 0.8173161745071411 0.5527512431144714 -0.10919522494077682 0.5489974617958069 -0.8286385536193848 -0.18039490282535553 0.9069795608520508 0.3805353045463562 -0.07565538585186005 0.3804132342338562 -0.921689510345459 -0.191381573677063 0.9621570706367493 0.19391460716724396 -0.039185766130685806 0.19708853960037231 -0.9795831441879272 -0.19507431983947754 0.9807733297348022 0.0 -0.039185766130685806 0.19708853960037231 0.9795831441879272 -0.191381573677063 0.9621570706367493 -0.19391460716724396 -0.07565538585186005 0.3804132342338562 0.921689510345459 -0.18039490282535553 0.9069795608520508 -0.3805353045463562 -0.10919522494077682 0.5489974617958069 0.8286385536193848 -0.13852351903915405 0.6964934468269348 0.7040314674377441 0.0 0.20096439123153687 0.9795831441879272 0.0 0.20096439123153687 -0.9795831441879272 0.0 1.0 0.0 0.0 0.9809869527816772 -0.19391460716724396 0.0 0.3878597319126129 0.921689510345459 0.0 0.9247413277626038 -0.3805353045463562 0.0 0.5597705245018005 0.8286385536193848 0.0 0.8333384394645691 -0.5527512431144714 0.0 0.7101352214813232 0.7040314674377441 0.0 0.7101352214813232 -0.7040314674377441 0.0 0.8333384394645691 0.5527512431144714 0.0 0.5597705245018005 -0.8286385536193848 0.0 0.9247413277626038 0.3805353045463562 0.0 0.3878597319126129 -0.921689510345459 0.0 0.9809869527816772 0.19391460716724396 0.13852351903915405 0.6964934468269348 0.7040314674377441 0.16257210075855255 0.8173161745071411 0.5527512431144714 0.13852351903915405 0.6964934468269348 -0.7040314674377441 0.10919522494077682 0.5489974617958069 -0.8286385536193848 0.18039490282535553 0.9069795608520508 0.3805353045463562 0.07565538585186005 0.3804132342338562 -0.921689510345459 0.191381573677063 0.9621570706367493 0.19391460716724396 0.039185766130685806 0.19708853960037231 -0.9795831441879272 0.19507431983947754 0.9807733297348022 0.0 0.039185766130685806 0.19708853960037231 0.9795831441879272 0.191381573677063 0.9621570706367493 -0.19391460716724396 0.07565538585186005 0.3804132342338562 0.921689510345459 0.18039490282535553 0.9069795608520508 -0.3805353045463562 0.10919522494077682 0.5489974617958069 0.8286385536193848 0.16257210075855255 0.8173161745071411 -0.5527512431144714 0.3754081726074219 0.9063386917114258 -0.19391460716724396 0.14841151237487793 0.3583483397960663 0.921689510345459 0.35386210680007935 0.8543656468391418 -0.3805353045463562 0.2142094224691391 0.5171361565589905 0.8286385536193848 0.3188879191875458 0.7698904275894165 -0.5527512431144714 0.2717368006706238 0.6560564041137695 0.7040314674377441 0.2717368006706238 0.6560564041137695 -0.7040314674377441 0.3188879191875458 0.7698904275894165 0.5527512431144714 0.2142094224691391 0.5171361565589905 -0.8286385536193848 0.35386210680007935 0.8543656468391418 0.3805353045463562 0.14841151237487793 0.3583483397960663 -0.921689510345459 0.3754081726074219 0.9063386917114258 0.19391460716724396 0.07690664380788803 0.18564409017562866 -0.9795831441879272 0.382671594619751 0.9238563179969788 0.0 0.07690664380788803 0.18564409017562866 0.9795831441879272 0.39451277256011963 0.5904415845870972 -0.7040314674377441 0.3109835982322693 0.46540728211402893 -0.8286385536193848 0.5137485861778259 0.7689138650894165 0.3805353045463562 0.2154911905527115 0.32248908281326294 -0.921689510345459 0.5449995398521423 0.8156682252883911 0.19391460716724396 0.1116367056965828 0.1670888364315033 -0.9795831441879272 0.5555589199066162 0.8314462900161743 0.0 0.1116367056965828 0.1670888364315033 0.9795831441879272 0.5449995398521423 0.8156682252883911 -0.19391460716724396 0.2154911905527115 0.32248908281326294 0.921689510345459 0.5137485861778259 0.7689138650894165 -0.3805353045463562 0.3109835982322693 0.46540728211402893 0.8286385536193848 0.46296578645706177 0.6928922533988953 -0.5527512431144714 0.39451277256011963 0.5904415845870972 0.7040314674377441 0.46296578645706177 0.6928922533988953 0.5527512431144714 0.6538895964622498 0.6538895964622498 -0.3805353045463562 0.395794540643692 0.395794540643692 0.8286385536193848 0.5892513990402222 0.5892513990402222 -0.5527512431144714 0.5021210312843323 0.5021210312843323 0.7040314674377441 0.5021210312843323 0.5021210312843323 -0.7040314674377441 0.5892513990402222 0.5892513990402222 0.5527512431144714 0.395794540643692 0.395794540643692 -0.8286385536193848 0.6538895964622498 0.6538895964622498 0.3805353045463562 0.27426984906196594 0.27426984906196594 -0.921689510345459 0.6936551928520203 0.6936551928520203 0.19391460716724396 0.1420941799879074 0.1420941799879074 -0.9795831441879272 0.7070833444595337 0.7070833444595337 0.0 0.1420941799879074 0.1420941799879074 0.9795831441879272 0.6936551928520203 0.6936551928520203 -0.19391460716724396 0.27426984906196594 0.27426984906196594 0.921689510345459 0.32248908281326294 0.2154911905527115 -0.921689510345459 0.7689138650894165 0.5137485861778259 0.3805353045463562 0.8156682252883911 0.5449995398521423 0.19391460716724396 0.1670888364315033 0.1116367056965828 -0.9795831441879272 0.8314462900161743 0.5555589199066162 0.0 0.1670888364315033 0.1116367056965828 0.9795831441879272 0.8156682252883911 0.5449995398521423 -0.19391460716724396 0.32248908281326294 0.2154911905527115 0.921689510345459 0.7689138650894165 0.5137485861778259 -0.3805353045463562 0.46540728211402893 0.3109835982322693 0.8286385536193848 0.6928922533988953 0.46296578645706177 -0.5527512431144714 0.5904415845870972 0.39451277256011963 0.7040314674377441 0.5904415845870972 0.39451277256011963 -0.7040314674377441 0.6928922533988953 0.46296578645706177 0.5527512431144714 0.46540728211402893 0.3109835982322693 -0.8286385536193848 0.3583483397960663 0.14841151237487793 0.921689510345459 0.5171361565589905 0.2142094224691391 0.8286385536193848 0.8543656468391418 0.35386210680007935 -0.3805353045463562 0.7698904275894165 0.3188879191875458 -0.5527512431144714 0.6560564041137695 0.2717368006706238 0.7040314674377441 0.6560564041137695 0.2717368006706238 -0.7040314674377441 0.7698904275894165 0.3188879191875458 0.5527512431144714 0.5171361565589905 0.2142094224691391 -0.8286385536193848 0.8543656468391418 0.35386210680007935 0.3805353045463562 0.3583483397960663 0.14841151237487793 -0.921689510345459 0.9063386917114258 0.3754081726074219 0.19391460716724396 0.18564409017562866 0.07690664380788803 -0.9795831441879272 0.9238563179969788 0.382671594619751 0.0 0.18564409017562866 0.07690664380788803 0.9795831441879272 0.9063386917114258 0.3754081726074219 -0.19391460716724396 0.9069795608520508 0.18039490282535553 0.3805353045463562 0.9621570706367493 0.191381573677063 0.19391460716724396 0.3804132342338562 0.07565538585186005 -0.921689510345459 0.19708853960037231 0.039185766130685806 -0.9795831441879272 0.9807733297348022 0.19507431983947754 0.0 0.19708853960037231 0.039185766130685806 0.9795831441879272 0.9621570706367493 0.191381573677063 -0.19391460716724396 0.3804132342338562 0.07565538585186005 0.921689510345459 0.9069795608520508 0.18039490282535553 -0.3805353045463562 0.5489974617958069 0.10919522494077682 0.8286385536193848 0.8173161745071411 0.16257210075855255 -0.5527512431144714 0.6964934468269348 0.13852351903915405 0.7040314674377441 0.6964934468269348 0.13852351903915405 -0.7040314674377441 0.8173161745071411 0.16257210075855255 0.5527512431144714 0.5489974617958069 0.10919522494077682 -0.8286385536193848 0.9247413277626038 0.0 -0.3805353045463562 0.8333384394645691 0.0 -0.5527512431144714 0.5597705245018005 0.0 0.8286385536193848 0.7101352214813232 0.0 0.7040314674377441 0.7101352214813232 0.0 -0.7040314674377441 0.8333384394645691 0.0 0.5527512431144714 0.5597705245018005 0.0 -0.8286385536193848 0.9247413277626038 0.0 0.3805353045463562 0.3878597319126129 0.0 -0.921689510345459 0.9809869527816772 0.0 0.19391460716724396 0.20096439123153687 0.0 -0.9795831441879272 1.0 0.0 0.0 0.20096439123153687 0.0 0.9795831441879272 0.9809869527816772 0.0 -0.19391460716724396 0.3878597319126129 0.0 0.921689510345459 0.19708853960037231 -0.039185766130685806 -0.9795831441879272 0.9807733297348022 -0.19507431983947754 0.0 0.19708853960037231 -0.039185766130685806 0.9795831441879272 0.9621570706367493 -0.191381573677063 -0.19391460716724396 0.3804132342338562 -0.07565538585186005 0.921689510345459 0.9069795608520508 -0.18039490282535553 -0.3805353045463562 0.5489974617958069 -0.10919522494077682 0.8286385536193848 0.8173161745071411 -0.16257210075855255 -0.5527512431144714 0.6964934468269348 -0.13852351903915405 0.7040314674377441 0.6964934468269348 -0.13852351903915405 -0.7040314674377441 0.8173161745071411 -0.16257210075855255 0.5527512431144714 0.5489974617958069 -0.10919522494077682 -0.8286385536193848 0.9069795608520508 -0.18039490282535553 0.3805353045463562 0.3804132342338562 -0.07565538585186005 -0.921689510345459 0.9621570706367493 -0.191381573677063 0.19391460716724396 0.5171361565589905 -0.2142094224691391 0.8286385536193848 0.6560564041137695 -0.2717368006706238 0.7040314674377441 0.6560564041137695 -0.2717368006706238 -0.7040314674377441 0.7698904275894165 -0.3188879191875458 0.5527512431144714 0.5171361565589905 -0.2142094224691391 -0.8286385536193848 0.8543656468391418 -0.35389262437820435 0.3805353045463562 0.3583483397960663 -0.14841151237487793 -0.921689510345459 0.9063386917114258 -0.3754081726074219 0.19391460716724396 0.18564409017562866 -0.07690664380788803 -0.9795831441879272 0.9238563179969788 -0.382671594619751 0.0 0.18564409017562866 -0.07690664380788803 0.9795831441879272 0.9063386917114258 -0.3754081726074219 -0.19391460716724396 0.3583483397960663 -0.14841151237487793 0.921689510345459 0.8543656468391418 -0.35386210680007935 -0.3805353045463562 0.7698904275894165 -0.3188879191875458 -0.5527512431144714 0.8314462900161743 -0.5555589199066162 0.0 0.1670888364315033 -0.1116367056965828 0.9795831441879272 0.1670888364315033 -0.1116367056965828 -0.9795831441879272 0.8156682252883911 -0.5449995398521423 -0.19391460716724396 0.32248908281326294 -0.2154911905527115 0.921689510345459 0.7689138650894165 -0.5137485861778259 -0.3805353045463562 0.46540728211402893 -0.3109835982322693 0.8286385536193848 0.6928922533988953 -0.46296578645706177 -0.5527512431144714 0.5904415845870972 -0.39451277256011963 0.7040314674377441 0.5904415845870972 -0.39451277256011963 -0.7040314674377441 0.6928922533988953 -0.46296578645706177 0.5527512431144714 0.46540728211402893 -0.3109835982322693 -0.8286385536193848 0.7689138650894165 -0.5137485861778259 0.3805353045463562 0.32248908281326294 -0.2154911905527115 -0.921689510345459 0.8156682252883911 -0.5449995398521423 0.19391460716724396 0.5021210312843323 -0.5021210312843323 -0.7040314674377441 0.5021210312843323 -0.5021210312843323 0.7040314674377441 0.5892513990402222 -0.5892513990402222 0.5527512431144714 0.395794540643692 -0.395794540643692 -0.8286385536193848 0.6538895964622498 -0.6538895964622498 0.3805353045463562 0.27426984906196594 -0.27426984906196594 -0.921689510345459 0.6936551928520203 -0.6936551928520203 0.19391460716724396 0.1420941799879074 -0.1420941799879074 -0.9795831441879272 0.7070833444595337 -0.7070833444595337 0.0 0.1420941799879074 -0.1420941799879074 0.9795831441879272 0.6936551928520203 -0.6936551928520203 -0.19391460716724396 0.27426984906196594 -0.27426984906196594 0.921689510345459 0.6538895964622498 -0.6538895964622498 -0.3805353045463562 0.395794540643692 -0.395794540643692 0.8286385536193848 0.5892513990402222 -0.5892513990402222 -0.5527512431144714 0.1116367056965828 -0.1670888364315033 -0.9795831441879272 0.5449995398521423 -0.8156682252883911 -0.19391460716724396 0.2154911905527115 -0.32248908281326294 0.921689510345459 0.5137485861778259 -0.7689138650894165 -0.3805353045463562 0.3109835982322693 -0.46540728211402893 0.8286385536193848 0.46296578645706177 -0.6928922533988953 -0.5527512431144714 0.39451277256011963 -0.5904415845870972 0.7040314674377441 0.39451277256011963 -0.5904415845870972 -0.7040314674377441 0.46296578645706177 -0.6928922533988953 0.5527512431144714 0.3109835982322693 -0.46540728211402893 -0.8286385536193848 0.5137485861778259 -0.7689138650894165 0.3805353045463562 0.2154911905527115 -0.32248908281326294 -0.921689510345459 0.5449995398521423 -0.8156682252883911 0.19391460716724396 0.5555589199066162 -0.8314462900161743 0.0 0.1116367056965828 -0.1670888364315033 0.9795831441879272 0.2142094224691391 -0.5171361565589905 -0.8286385536193848 0.35386210680007935 -0.8543656468391418 0.3805353045463562 0.14841151237487793 -0.3583483397960663 -0.921689510345459 0.3754081726074219 -0.9063386917114258 0.19391460716724396 0.07690664380788803 -0.18564409017562866 -0.9795831441879272 0.382671594619751 -0.9238563179969788 0.0 0.07687612622976303 -0.18564409017562866 0.9795831441879272 0.3754081726074219 -0.9063386917114258 -0.19391460716724396 0.14841151237487793 -0.3583483397960663 0.921689510345459 0.35386210680007935 -0.8543656468391418 -0.3805353045463562 0.2142094224691391 -0.5171361565589905 0.8286385536193848 0.3188879191875458 -0.7698904275894165 -0.5527512431144714 0.2717368006706238 -0.6560564041137695 0.7040314674377441 0.2717368006706238 -0.6560564041137695 -0.7040314674377441 0.3188879191875458 -0.7698904275894165 0.5527512431144714 0.039185766130685806 -0.19708853960037231 0.9795831441879272 0.07565538585186005 -0.3804132342338562 0.921689510345459 0.18039490282535553 -0.9069795608520508 -0.3805353045463562 0.10919522494077682 -0.5489974617958069 0.8286385536193848 0.16257210075855255 -0.8173161745071411 -0.5527512431144714 0.13852351903915405 -0.6964934468269348 0.7040314674377441 0.13852351903915405 -0.6964934468269348 -0.7040314674377441 0.16257210075855255 -0.8173161745071411 0.5527512431144714 0.10919522494077682 -0.5489974617958069 -0.8286385536193848 0.18039490282535553 -0.9069795608520508 0.3805353045463562 0.07565538585186005 -0.3804132342338562 -0.921689510345459 0.191381573677063 -0.9621570706367493 0.19391460716724396 0.039185766130685806 -0.19708853960037231 -0.9795831441879272 0.19507431983947754 -0.9807733297348022 0.0 0.191381573677063 -0.9621570706367493 -0.19391460716724396 0.0 -0.9247413277626038 0.3805353045463562 0.0 -0.5597705245018005 -0.8286385536193848 0.0 -0.3878597319126129 -0.921689510345459 0.0 -0.9809869527816772 0.19391460716724396 0.0 -0.20096439123153687 -0.9795831441879272 0.0 -1.0 0.0 0.0 -0.20096439123153687 0.9795831441879272 0.0 -0.9809869527816772 -0.19391460716724396 0.0 -0.3878597319126129 0.921689510345459 0.0 -0.9247413277626038 -0.3805353045463562 0.0 -0.5597705245018005 0.8286385536193848 0.0 -0.8333384394645691 -0.5527512431144714 0.0 -0.7101352214813232 0.7040314674377441 0.0 -0.7101352214813232 -0.7040314674377441 0.0 -0.8333384394645691 0.5527512431144714 -0.18039490282535553 -0.9069795608520508 -0.3805353045463562 -0.10919522494077682 -0.5489974617958069 0.8286385536193848 -0.16257210075855255 -0.8173161745071411 -0.5527512431144714 -0.13852351903915405 -0.6964934468269348 0.7040314674377441 -0.13852351903915405 -0.6964934468269348 -0.7040314674377441 -0.16257210075855255 -0.8173161745071411 0.5527512431144714 -0.10919522494077682 -0.5489974617958069 -0.8286385536193848 -0.18039490282535553 -0.9069795608520508 0.3805353045463562 -0.07565538585186005 -0.3804132342338562 -0.921689510345459 -0.191381573677063 -0.9621570706367493 0.19391460716724396 -0.039185766130685806 -0.19708853960037231 -0.9795831441879272 -0.19507431983947754 -0.9807733297348022 0.0 -0.039185766130685806 -0.19708853960037231 0.9795831441879272 -0.191381573677063 -0.9621570706367493 -0.19391460716724396 -0.07565538585186005 -0.3804132342338562 0.921689510345459 -0.2142094224691391 -0.5171361565589905 -0.8286385536193848 -0.14841151237487793 -0.3583483397960663 -0.921689510345459 -0.35389262437820435 -0.8543656468391418 0.3805353045463562 -0.3754081726074219 -0.9063386917114258 0.19391460716724396 -0.07690664380788803 -0.18564409017562866 -0.9795831441879272 -0.382671594619751 -0.9238563179969788 0.0 -0.07687612622976303 -0.18564409017562866 0.9795831441879272 -0.3754081726074219 -0.9063386917114258 -0.19391460716724396 -0.14841151237487793 -0.3583483397960663 0.921689510345459 -0.35386210680007935 -0.8543656468391418 -0.3805353045463562 -0.2142094224691391 -0.5171361565589905 0.8286385536193848 -0.3188879191875458 -0.7698904275894165 -0.5527512431144714 -0.2717368006706238 -0.6560564041137695 0.7040314674377441 -0.2717368006706238 -0.6560564041137695 -0.7040314674377441 -0.3188879191875458 -0.7698904275894165 0.5527512431144714 -0.2154911905527115 -0.32248908281326294 0.921689510345459 -0.3109835982322693 -0.46540728211402893 0.8286385536193848 -0.5137485861778259 -0.7689138650894165 -0.3805353045463562 -0.46296578645706177 -0.6928922533988953 -0.5527512431144714 -0.39451277256011963 -0.5904415845870972 0.7040314674377441 -0.39451277256011963 -0.5904415845870972 -0.7040314674377441 -0.46296578645706177 -0.6928922533988953 0.5527512431144714 -0.3109835982322693 -0.46540728211402893 -0.8286385536193848 -0.5137485861778259 -0.7689138650894165 0.3805353045463562 -0.2154911905527115 -0.32248908281326294 -0.921689510345459 -0.5449995398521423 -0.8156682252883911 0.19391460716724396 -0.1116367056965828 -0.1670888364315033 -0.9795831441879272 -0.5555589199066162 -0.8314462900161743 0.0 -0.1116367056965828 -0.1670888364315033 0.9795831441879272 -0.5449995398521423 -0.8156682252883911 -0.19391460716724396 -0.6538895964622498 -0.6538895964622498 0.3805353045463562 -0.6936551928520203 -0.6936551928520203 0.19391460716724396 -0.1420941799879074 -0.1420941799879074 -0.9795831441879272 -0.7070833444595337 -0.7070833444595337 0.0 -0.1420941799879074 -0.1420941799879074 0.9795831441879272 -0.6936551928520203 -0.6936551928520203 -0.19391460716724396 -0.27426984906196594 -0.27426984906196594 0.921689510345459 -0.6538895964622498 -0.6538895964622498 -0.3805353045463562 -0.395794540643692 -0.395794540643692 0.8286385536193848 -0.5892513990402222 -0.5892513990402222 -0.5527512431144714 -0.5021210312843323 -0.5021210312843323 0.7040314674377441 -0.5021210312843323 -0.5021210312843323 -0.7040314674377441 -0.5892513990402222 -0.5892513990402222 0.5527512431144714 -0.395794540643692 -0.395794540643692 -0.8286385536193848 -0.27426984906196594 -0.27426984906196594 -0.921689510345459 -0.7689138650894165 -0.5137485861778259 -0.3805353045463562 -0.6928922533988953 -0.46296578645706177 -0.5527512431144714 -0.5904415845870972 -0.39451277256011963 0.7040314674377441 -0.5904415845870972 -0.39451277256011963 -0.7040314674377441 -0.6928922533988953 -0.46296578645706177 0.5527512431144714 -0.46540728211402893 -0.3109835982322693 -0.8286385536193848 -0.7689138650894165 -0.5137485861778259 0.3805353045463562 -0.32248908281326294 -0.2154911905527115 -0.921689510345459 -0.8156682252883911 -0.5449995398521423 0.19391460716724396 -0.1670888364315033 -0.1116367056965828 -0.9795831441879272 -0.8314462900161743 -0.5555589199066162 0.0 -0.1670888364315033 -0.1116367056965828 0.9795831441879272 -0.8156682252883911 -0.5449995398521423 -0.19391460716724396 -0.32248908281326294 -0.2154911905527115 0.921689510345459 -0.46540728211402893 -0.3109835982322693 0.8286385536193848 -0.18564409017562866 -0.07690664380788803 -0.9795831441879272 -0.9238563179969788 -0.382671594619751 0.0 -0.18564409017562866 -0.07690664380788803 0.9795831441879272 -0.9063386917114258 -0.3754081726074219 -0.19391460716724396 -0.3583483397960663 -0.14841151237487793 0.921689510345459 -0.8543656468391418 -0.35386210680007935 -0.3805353045463562 -0.5171361565589905 -0.2142094224691391 0.8286385536193848 -0.7698904275894165 -0.3188879191875458 -0.5527512431144714 -0.6560564041137695 -0.2717368006706238 0.7040314674377441 -0.6560564041137695 -0.2717368006706238 -0.7040314674377441 -0.7698904275894165 -0.3188879191875458 0.5527512431144714 -0.5171361565589905 -0.2142094224691391 -0.8286385536193848 -0.8543656468391418 -0.35386210680007935 0.3805353045463562 -0.3583483397960663 -0.14841151237487793 -0.921689510345459 -0.9063386917114258 -0.3754081726074219 0.19391460716724396 -0.6964934468269348 -0.13852351903915405 -0.7040314674377441 -0.6964934468269348 -0.13852351903915405 0.7040314674377441 -0.8173161745071411 -0.16257210075855255 0.5527512431144714 -0.5489974617958069 -0.10919522494077682 -0.8286385536193848 -0.9069795608520508 -0.18039490282535553 0.3805353045463562 -0.3804132342338562 -0.07565538585186005 -0.921689510345459 -0.9621570706367493 -0.191381573677063 0.19391460716724396 -0.19708853960037231 -0.039185766130685806 -0.9795831441879272 -0.9807733297348022 -0.19507431983947754 0.0 -0.19708853960037231 -0.039185766130685806 0.9795831441879272 -0.9621570706367493 -0.191381573677063 -0.19391460716724396 -0.3804132342338562 -0.07565538585186005 0.921689510345459 -0.9069795608520508 -0.18039490282535553 -0.3805353045463562 -0.5489974617958069 -0.10919522494077682 0.8286385536193848 -0.8173161745071411 -0.16257210075855255 -0.5527512431144714 + + + + + + + + + + + + + + +

0 1 2 3 4 5 6 7 8 2 9 10 3 11 12 13 9 14 15 11 16 13 17 18 15 19 20 21 17 22 20 23 24 21 25 26 24 27 28 26 29 30 28 31 0 30 8 7 25 32 29 27 33 31 29 34 8 31 35 1 5 4 36 6 8 34 9 35 37 5 38 11 14 37 39 11 40 16 14 41 17 16 42 19 22 41 43 19 44 23 22 45 25 23 46 27 41 47 48 40 49 42 43 48 50 42 51 44 43 52 45 44 53 46 45 54 32 33 53 55 32 56 34 33 57 35 36 4 58 6 34 56 35 59 37 36 60 38 37 47 39 38 61 40 54 62 56 57 63 64 58 4 65 6 56 62 57 66 59 58 67 60 59 68 47 60 69 61 48 68 70 61 71 49 48 72 50 49 73 51 50 74 52 51 75 53 52 76 54 53 63 55 69 77 71 70 78 72 73 77 79 74 78 80 73 81 75 76 80 82 75 83 63 76 84 62 64 83 85 65 4 86 6 62 84 64 87 66 65 88 67 66 89 68 67 90 69 70 89 91 83 92 85 86 4 93 6 84 94 85 95 87 86 96 88 87 97 89 88 98 90 91 97 99 90 100 77 78 99 101 79 100 102 78 103 80 79 104 81 82 103 105 83 104 106 82 94 84 101 107 108 100 109 102 101 110 103 102 111 104 103 112 105 106 111 113 94 112 114 106 115 92 93 4 116 6 94 114 92 117 95 93 118 96 95 119 97 96 120 98 99 119 107 100 120 121 116 4 122 6 114 123 117 124 125 116 126 118 117 127 119 118 128 120 107 127 129 120 130 121 107 131 108 121 132 109 110 131 133 109 134 111 112 133 135 113 134 136 114 135 123 113 124 115 132 137 138 133 139 140 132 141 134 133 142 135 136 141 143 123 142 144 136 145 124 122 4 146 6 123 144 124 147 125 126 146 148 125 149 127 126 150 128 129 149 151 128 137 130 129 139 131 145 152 147 146 153 148 147 154 149 150 153 155 151 154 156 150 157 137 151 158 139 137 159 138 139 160 140 138 161 141 142 160 162 143 161 163 142 164 144 143 165 145 146 4 166 6 144 164 160 167 168 159 169 161 160 170 162 163 169 171 162 172 164 163 173 165 166 4 174 6 164 172 152 173 175 166 176 153 152 177 154 153 178 155 156 177 179 155 180 157 156 167 158 159 180 181 175 182 177 176 183 178 177 184 179 178 185 180 179 186 167 180 187 181 168 186 188 181 189 169 168 190 170 171 189 191 172 190 192 171 193 173 174 4 194 6 172 192 173 195 175 174 196 176 188 197 190 191 198 199 192 197 200 191 201 193 194 4 202 6 192 200 195 201 203 194 204 196 195 205 182 196 206 183 184 205 207 185 206 208 184 209 186 187 208 210 188 209 211 187 198 189 206 212 213 207 214 215 206 216 208 207 217 209 208 218 210 211 217 219 210 220 198 211 221 197 199 220 222 197 223 200 199 224 201 202 4 225 6 200 223 201 226 203 202 212 204 203 214 205 222 227 228 223 229 230 222 231 224 225 4 232 6 223 230 224 233 226 225 234 212 226 235 214 212 236 213 215 235 237 213 238 216 215 239 217 216 240 218 217 241 219 218 227 220 219 229 221 237 242 243 238 244 245 237 246 239 238 247 240 241 246 248 240 249 227 241 250 229 228 249 251 230 250 252 228 253 231 232 4 254 6 230 252 231 255 233 232 256 234 233 242 235 236 256 244 250 257 252 251 258 253 254 4 259 6 252 257 253 260 255 254 261 256 255 262 242 256 263 244 243 262 264 245 263 265 243 266 246 247 265 267 246 268 248 247 269 249 248 270 250 251 269 271 265 272 273 264 274 266 267 273 275 266 276 268 267 277 269 270 276 278 271 277 279 257 278 280 271 281 258 259 4 282 6 257 280 260 281 283 259 284 261 260 285 262 261 272 263 264 285 286 279 287 281 282 4 288 6 280 289 281 290 283 282 291 284 283 292 285 284 293 272 286 292 294 272 295 273 286 296 274 275 295 297 276 296 298 275 299 277 276 300 278 279 299 301 280 300 289 294 302 296 297 303 304 296 305 298 297 306 299 298 307 300 301 306 308 300 309 289 287 308 310 288 4 311 6 289 309 287 312 290 288 313 291 290 314 292 291 315 293 294 314 316 295 315 303 6 309 317 310 318 312 311 319 313 312 320 314 313 321 315 316 320 322 303 321 323 316 324 302 304 323 325 302 326 305 304 327 306 307 326 328 308 327 329 307 317 309 308 330 310 311 4 331 324 332 326 325 333 327 328 332 334 329 333 335 317 334 336 329 337 330 331 4 338 6 317 336 330 339 318 331 340 319 318 341 320 319 342 321 322 341 343 323 342 344 324 343 345 325 344 346 340 347 348 339 349 341 340 350 342 343 349 351 344 350 352 343 353 345 346 352 354 345 355 332 346 356 333 334 355 357 335 356 358 334 359 336 335 360 337 338 4 347 6 336 359 337 361 339 354 362 356 357 363 364 358 362 365 357 366 359 358 367 360 347 4 368 6 359 366 361 367 369 348 368 370 361 371 349 348 372 350 351 371 373 352 372 374 351 375 353 352 376 354 355 375 363 369 377 371 370 378 372 373 377 379 374 378 380 373 381 375 376 380 382 375 383 363 376 384 362 364 383 385 365 384 386 364 387 366 365 388 367 368 4 389 6 366 387 369 388 390 370 389 391 385 392 393 386 394 395 385 396 387 386 397 388 389 4 398 6 387 396 388 399 390 389 400 391 390 401 377 391 402 378 379 401 403 380 402 404 379 405 381 380 406 382 381 392 383 382 394 384 402 407 408 403 409 410 404 408 411 403 412 405 406 411 413 405 414 392 406 415 394 393 414 416 395 415 417 393 418 396 395 419 397 398 4 420 6 396 418 399 419 421 398 407 400 399 409 401 417 422 423 416 424 418 417 425 419 420 4 426 6 418 424 421 425 427 420 428 407 421 429 409 407 430 408 410 429 431 408 432 411 410 433 412 413 432 434 412 435 414 413 422 415 414 436 416 431 437 438 430 439 432 431 440 433 434 439 441 435 440 442 434 443 422 435 444 436 423 443 445 436 446 424 425 445 447 426 4 448 6 424 446 425 449 427 426 450 428 427 437 429 428 451 430 444 452 446 445 453 447 448 4 454 6 446 452 447 455 449 450 454 456 449 457 437 451 456 458 438 457 459 439 458 460 438 461 440 441 460 462 440 463 442 441 464 443 442 465 444 445 464 466 459 467 461 462 468 469 461 470 463 462 471 464 463 472 465 466 471 473 452 472 474 466 475 453 454 4 476 6 452 474 453 477 455 454 478 456 455 479 457 456 480 458 459 479 481 458 468 460 476 4 3 6 474 7 475 10 477 478 3 12 477 13 479 480 12 15 479 18 481 468 15 20 481 21 467 469 20 24 467 26 470 471 24 28 470 30 472 473 28 0 472 7 474 475 0 2 0 31 1 2 1 9 3 5 11 13 10 9 15 12 11 13 14 17 15 16 19 21 18 17 20 19 23 21 22 25 24 23 27 26 25 29 28 27 31 30 29 8 25 45 32 27 46 33 29 32 34 31 33 35 9 1 35 5 36 38 14 9 37 11 38 40 14 39 41 16 40 42 22 17 41 19 42 44 22 43 45 23 44 46 41 39 47 40 61 49 43 41 48 42 49 51 43 50 52 44 51 53 45 52 54 33 46 53 32 54 56 33 55 57 35 57 59 36 58 60 37 59 47 38 60 61 54 76 62 57 55 63 57 64 66 58 65 67 59 66 68 60 67 69 48 47 68 61 69 71 48 70 72 49 71 73 50 72 74 51 73 75 52 74 76 53 75 63 69 90 77 70 91 78 73 71 77 74 72 78 73 79 81 76 74 80 75 81 83 76 82 84 64 63 83 64 85 87 65 86 88 66 87 89 67 88 90 70 68 89 83 106 92 85 92 95 86 93 96 87 95 97 88 96 98 91 89 97 90 98 100 78 91 99 79 77 100 78 101 103 79 102 104 82 80 103 83 81 104 82 105 94 101 99 107 100 121 109 101 108 110 102 109 111 103 110 112 106 104 111 94 105 112 106 113 115 92 115 117 93 116 118 95 117 119 96 118 120 99 97 119 100 98 120 117 115 124 116 122 126 117 125 127 118 126 128 107 119 127 120 128 130 107 129 131 121 130 132 110 108 131 109 132 134 112 110 133 113 111 134 114 112 135 113 136 124 132 130 137 133 131 139 132 138 141 133 140 142 136 134 141 123 135 142 136 143 145 124 145 147 126 122 146 125 147 149 126 148 150 129 127 149 128 150 137 129 151 139 145 165 152 146 166 153 147 152 154 150 148 153 151 149 154 150 155 157 151 156 158 137 157 159 139 158 160 138 159 161 142 140 160 143 141 161 142 162 164 143 163 165 160 158 167 159 181 169 160 168 170 163 161 169 162 170 172 163 171 173 152 165 173 166 174 176 152 175 177 153 176 178 156 154 177 155 178 180 156 179 167 159 157 180 175 195 182 176 196 183 177 182 184 178 183 185 179 184 186 180 185 187 168 167 186 181 187 189 168 188 190 171 169 189 172 170 190 171 191 193 173 193 195 174 194 196 188 211 197 191 189 198 192 190 197 191 199 201 195 193 201 194 202 204 195 203 205 196 204 206 184 182 205 185 183 206 184 207 209 187 185 208 188 186 209 187 210 198 206 204 212 207 205 214 206 213 216 207 215 217 208 216 218 211 209 217 210 218 220 211 219 221 199 198 220 197 221 223 199 222 224 201 224 226 202 225 212 203 226 214 222 220 227 223 221 229 222 228 231 224 231 233 225 232 234 226 233 235 212 234 236 215 214 235 213 236 238 215 237 239 216 238 240 217 239 241 218 240 227 219 241 229 237 235 242 238 236 244 237 243 246 238 245 247 241 239 246 240 247 249 241 248 250 228 227 249 230 229 250 228 251 253 231 253 255 232 254 256 233 255 242 236 234 256 250 270 257 251 271 258 253 258 260 254 259 261 255 260 262 256 261 263 243 242 262 245 244 263 243 264 266 247 245 265 246 266 268 247 267 269 248 268 270 251 249 269 265 263 272 264 286 274 267 265 273 266 274 276 267 275 277 270 268 276 271 269 277 257 270 278 271 279 281 260 258 281 259 282 284 260 283 285 261 284 272 264 262 285 279 301 287 281 287 290 282 288 291 283 290 292 284 291 293 286 285 292 272 293 295 286 294 296 275 273 295 276 274 296 275 297 299 276 298 300 279 277 299 280 278 300 294 316 302 297 295 303 296 302 305 297 304 306 298 305 307 301 299 306 300 307 309 287 301 308 287 310 312 288 311 313 290 312 314 291 313 315 294 292 314 295 293 315 310 330 318 311 331 319 312 318 320 313 319 321 316 314 320 303 315 321 316 322 324 304 303 323 302 324 326 304 325 327 307 305 326 308 306 327 307 328 317 308 329 330 324 345 332 325 346 333 328 326 332 329 327 333 317 328 334 329 335 337 330 337 339 331 338 340 318 339 341 319 340 342 322 320 341 323 321 342 324 322 343 325 323 344 340 338 347 339 361 349 340 348 350 343 341 349 344 342 350 343 351 353 346 344 352 345 353 355 346 354 356 334 332 355 335 333 356 334 357 359 335 358 360 337 360 361 354 376 362 357 355 363 358 356 362 357 364 366 358 365 367 361 360 367 348 347 368 361 369 371 348 370 372 351 349 371 352 350 372 351 373 375 352 374 376 355 353 375 369 390 377 370 391 378 373 371 377 374 372 378 373 379 381 376 374 380 375 381 383 376 382 384 364 363 383 365 362 384 364 385 387 365 386 388 369 367 388 370 368 389 385 383 392 386 384 394 385 393 396 386 395 397 388 397 399 389 398 400 390 399 401 391 400 402 379 377 401 380 378 402 379 403 405 380 404 406 381 405 392 382 406 394 402 400 407 403 401 409 404 402 408 403 410 412 406 404 411 405 412 414 406 413 415 393 392 414 395 394 415 393 416 418 395 417 419 399 397 419 398 420 407 399 421 409 417 415 422 416 436 424 417 423 425 421 419 425 420 426 428 421 427 429 407 428 430 410 409 429 408 430 432 410 431 433 413 411 432 412 433 435 413 434 422 414 435 436 431 429 437 430 451 439 431 438 440 434 432 439 435 433 440 434 441 443 435 442 444 423 422 443 436 444 446 425 423 445 425 447 449 426 448 450 427 449 437 428 450 451 444 465 452 445 466 453 447 453 455 450 448 454 449 455 457 451 450 456 438 437 457 439 451 458 438 459 461 441 439 460 440 461 463 441 462 464 442 463 465 445 443 464 459 481 467 462 460 468 461 467 470 462 469 471 463 470 472 466 464 471 452 465 472 466 473 475 453 475 477 454 476 478 455 477 479 456 478 480 459 457 479 458 480 468 475 2 10 478 476 3 477 10 13 480 478 12 479 13 18 468 480 15 481 18 21 469 468 20 467 21 26 471 469 24 470 26 30 473 471 28 472 30 7 475 473 0

+
+
+
+
+ + + + + + + + + + 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 + + + + + + + + + + + + + +
diff --git a/Templates/Full/game/tools/resources/materials.cs b/Templates/Full/game/tools/resources/materials.cs new file mode 100644 index 000000000..d9c7ea97f --- /dev/null +++ b/Templates/Full/game/tools/resources/materials.cs @@ -0,0 +1,8 @@ +singleton Material(ReflectProbePreviewMat) +{ + mapTo = "ReflectProbePreviewMat"; + diffuseColor[0] = "1 1 1 1"; + smoothness[0] = "1"; + metalness[0] = "1"; + translucentBlendOp = "None"; +}; diff --git a/Templates/Full/game/tools/resources/reflectionProbePreviewP.hlsl b/Templates/Full/game/tools/resources/reflectionProbePreviewP.hlsl new file mode 100644 index 000000000..5eb32ffc7 --- /dev/null +++ b/Templates/Full/game/tools/resources/reflectionProbePreviewP.hlsl @@ -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); +} diff --git a/Templates/Full/game/tools/resources/reflectionProbePreviewV.hlsl b/Templates/Full/game/tools/resources/reflectionProbePreviewV.hlsl new file mode 100644 index 000000000..5c571d9e8 --- /dev/null +++ b/Templates/Full/game/tools/resources/reflectionProbePreviewV.hlsl @@ -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; +} diff --git a/Templates/Full/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui b/Templates/Full/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui index 09a90ef26..5530dcbd0 100644 --- a/Templates/Full/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui +++ b/Templates/Full/game/tools/worldEditor/gui/guiTerrainMaterialDlg.ed.gui @@ -1,1390 +1,1743 @@ //--- OBJECT WRITE BEGIN --- -%guiContent = new GuiControl(TerrainMaterialDlg, EditorGuiGroup) { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; +%guiContent = new GuiControl(TerrainMaterialDlg,EditorGuiGroup) { position = "0 0"; - Extent = "800 768"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; + extent = "1024 768"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "1"; + activeMat = "17411"; + matIndex = "0"; + onApplyCallback = "EPainter_TerrainMaterialUpdateCallback"; new GuiWindowCtrl() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiWindowProfile"; - HorizSizing = "center"; - VertSizing = "center"; - position = "221 151"; - Extent = "394 432"; - MinExtent = "358 432"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Docking = "None"; - Margin = "4 4 4 4"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; + text = "Terrain Materials Editor"; resizeWidth = "1"; resizeHeight = "1"; canMove = "1"; canClose = "1"; canMinimize = "0"; canMaximize = "0"; - minSize = "50 50"; + canCollapse = "0"; closeCommand = "TerrainMaterialDlg.dialogCancel();"; - EdgeSnap = "0"; - text = "Terrain Materials Editor"; - new GuiContainer(){ //Node Properties - isContainer = "1"; - Profile = "inspectorStyleRolloutDarkProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - Position = "6 25"; - Extent = "189 64"; - - new GuiTextCtrl(){ - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - Position = "5 0"; - Extent = "91 18"; - text = "Terrain Materials"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "top"; - position = "160 2"; - Extent = "15 15"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.newMat();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/new"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "top"; - position = "173 2"; - Extent = "15 15"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.deleteMat();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - }; + edgeSnap = "0"; + docking = "None"; + margin = "4 4 4 4"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "315 168"; + extent = "394 432"; + minExtent = "358 432"; + horizSizing = "center"; + vertSizing = "center"; + profile = "ToolsGuiWindowProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + new GuiContainer() { - canSaveDynamicFields = "0"; - internalName = "matSettingsParent"; - isContainer = "1"; - Profile = "inspectorStyleRolloutProfile"; - HorizSizing = "left"; - VertSizing = "height"; - position = "202 26"; - Extent = "185 363"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 25"; + extent = "189 64"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "inspectorStyleRolloutDarkProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; - new GuiBitmapCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "1 0"; - Extent = "183 2"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "core/art/gui/images/separator-v"; - wrap = "0"; - }; new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "8 22"; - Extent = "44 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiDefaultProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Name"; + text = "Terrain Materials"; maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "matNameCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "39 21"; - Extent = "143 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; - altCommand = "TerrainMaterialDlg.setMaterialName( $ThisControl.getText() );"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiInspectorTitleTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "8 0"; - Extent = "117 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Material Properties"; - maxLength = "1024"; - }; - new GuiContainer() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "6 43"; - Extent = "185 75"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - - new GuiCheckBoxCtrl() { - internalName = "sideProjectionCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiCheckBoxProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "55 54"; - Extent = "119 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - text = " Use Side Projection"; - groupNum = "-1"; - buttonType = "ToggleButton"; - useMouseEvents = "0"; - useInactiveState = "0"; - }; - new GuiBitmapCtrl() { - internalName = "baseTexCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "47 47"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "tools/materialEditor/gui/unknownImage"; - wrap = "0"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeBase();"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Change the Active Diffuse Map for this layer"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "EditorTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "56 -3"; - Extent = "39 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Diffuse"; - maxLength = "1024"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "56 16"; - Extent = "116 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "None"; - maxLength = "1024"; - }; - new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "116 0"; - Extent = "40 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeBase();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - text = "Edit"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "159 0"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg-->baseTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "132 35"; - Extent = "39 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - text = "Size"; - maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "baseSizeCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "94 34"; - Extent = "34 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; - }; - }; - new GuiBitmapCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "6 116"; - Extent = "175 2"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "tools/gui/images/separator-v"; - wrap = "0"; - }; - new GuiContainer() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "6 295"; - Extent = "185 50"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - - new GuiBitmapCtrl() { - internalName = "normTexCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "47 47"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "tools/materialEditor/gui/unknownImage"; - wrap = "0"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "EditorTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "56 -3"; - Extent = "39 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Normal"; - maxLength = "1024"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeNormal();"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Change the active Normal Map for this layer."; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "56 15"; - Extent = "116 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "None"; - maxLength = "1024"; - }; - new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "116 0"; - Extent = "40 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeNormal();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - text = "Edit"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "159 0"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg-->normTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "92 34"; - Extent = "77 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Parallax Scale"; - maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "parallaxScaleCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "55 33"; - Extent = "34 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - text = "0.00"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; - }; - }; - - new GuiBitmapCtrl() { - bitmap = "tools/gui/images/separator-v"; - wrap = "0"; - position = "6 288"; - extent = "175 2"; - minExtent = "8 2"; - horizSizing = "width"; - vertSizing = "bottom"; - profile = "ToolsGuiDefaultProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiContainer() { margin = "0 0 0 0"; padding = "0 0 0 0"; anchorTop = "1"; anchorBottom = "0"; anchorLeft = "1"; anchorRight = "0"; - position = "6 122"; - extent = "185 72"; + position = "5 0"; + extent = "91 18"; minExtent = "8 2"; - horizSizing = "width"; + horizSizing = "right"; vertSizing = "bottom"; profile = "ToolsGuiDefaultProfile"; visible = "1"; active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/new"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "160 2"; + extent = "15 15"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "top"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.newMat();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "173 2"; + extent = "15 15"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "top"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.deleteMat();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + }; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "202 26"; + extent = "185 363"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "height"; + profile = "inspectorStyleRolloutProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "matSettingsParent"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { + text = "Name"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "8 22"; + extent = "44 17"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiDefaultProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "sand"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "39 21"; + extent = "143 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + altCommand = "TerrainMaterialDlg.setMaterialName( $ThisControl.getText() );"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "matNameCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Material Properties"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "8 0"; + extent = "117 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiInspectorTitleTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiScrollCtrl() { + willFirstRespond = "1"; + hScrollBar = "dynamic"; + vScrollBar = "dynamic"; + lockHorizScroll = "1"; + lockVertScroll = "0"; + constantThumbHeight = "0"; + childMargin = "0 0"; + mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 45"; + extent = "189 329"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiScrollProfile"; + visible = "1"; + active = "1"; tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; isContainer = "1"; canSave = "1"; canSaveDynamicFields = "0"; - new GuiBitmapCtrl() { - bitmap = "tools/materialEditor/gui/unknownImage"; - wrap = "0"; - position = "1 1"; - extent = "47 47"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiDefaultProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - internalName = "macroTexCtrl"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiBitmapButtonCtrl() { - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; - bitmapMode = "Stretched"; - autoFitExtents = "0"; - useModifiers = "0"; - useStates = "1"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - position = "1 1"; - extent = "48 48"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiDefaultProfile"; - visible = "1"; - active = "1"; - command = "TerrainMaterialDlg.changeMacro();"; - tooltipProfile = "ToolsGuiDefaultProfile"; - tooltip = "Change the active Macro Map for this layer."; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Macro"; - maxLength = "1024"; + new GuiContainer() { margin = "0 0 0 0"; padding = "0 0 0 0"; anchorTop = "1"; anchorBottom = "0"; anchorLeft = "1"; anchorRight = "0"; - position = "56 -3"; - extent = "34 18"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "EditorTextProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "None"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "1"; - anchorBottom = "0"; - anchorLeft = "1"; - anchorRight = "0"; - position = "56 17"; - extent = "116 17"; + position = "1 1"; + extent = "174 73"; minExtent = "8 2"; horizSizing = "width"; vertSizing = "bottom"; - profile = "ToolsGuiTextProfile"; + profile = "ToolsGuiDefaultProfile"; visible = "1"; active = "1"; tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; - isContainer = "0"; + isContainer = "1"; canSave = "1"; canSaveDynamicFields = "0"; + + new GuiCheckBoxCtrl() { + text = " Use Side Projection"; + groupNum = "-1"; + buttonType = "ToggleButton"; + useMouseEvents = "0"; + position = "55 54"; + extent = "119 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiCheckBoxProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "sideProjectionCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "art/terrains/Example/sand"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 1"; + extent = "47 47"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "baseTexCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "1 1"; + extent = "48 48"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeBase();"; + tooltipProfile = "ToolsGuiDefaultProfile"; + tooltip = "Change the Active Diffuse Map for this layer"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Diffuse"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 -3"; + extent = "39 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "EditorTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "None"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 16"; + extent = "79 17"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Edit"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "110 0"; + extent = "40 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeBase();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "153 0"; + extent = "16 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg-->baseTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Size"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "132 35"; + extent = "39 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "200"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "94 34"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "baseSizeCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "tools/gui/images/separator-v"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 71"; + extent = "148 2"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; - new GuiButtonCtrl() { - text = "Edit"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - position = "116 0"; - extent = "40 16"; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "4 78"; + extent = "174 76"; minExtent = "8 2"; - horizSizing = "left"; - vertSizing = "bottom"; - profile = "ToolsGuiButtonProfile"; - visible = "1"; - active = "1"; - command = "TerrainMaterialDlg.changeMacro();"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiBitmapButtonCtrl() { - bitmap = "tools/gui/images/delete"; - bitmapMode = "Stretched"; - autoFitExtents = "0"; - useModifiers = "0"; - useStates = "1"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - position = "159 0"; - extent = "16 16"; - minExtent = "8 2"; - horizSizing = "left"; + horizSizing = "width"; vertSizing = "bottom"; profile = "ToolsGuiDefaultProfile"; visible = "1"; active = "1"; - command = "TerrainMaterialDlg-->macroTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; - isContainer = "0"; + isContainer = "1"; canSave = "1"; canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Size"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "132 33"; - extent = "39 16"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextEditCtrl() { - historySize = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - password = "0"; - passwordMask = "*"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "94 32"; - extent = "34 18"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextEditProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - internalName = "macroSizeCtrl"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Strength"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "39 54"; - extent = "46 16"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextEditCtrl() { - historySize = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - password = "0"; - passwordMask = "*"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "1 53"; - extent = "34 18"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextEditProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - internalName = "macroStrengthCtrl"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl() { - text = "Distance"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "132 54"; - extent = "45 16"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - new GuiTextEditCtrl() { - historySize = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - password = "0"; - passwordMask = "*"; - maxLength = "1024"; - margin = "0 0 0 0"; - padding = "0 0 0 0"; - anchorTop = "0"; - anchorBottom = "0"; - anchorLeft = "0"; - anchorRight = "0"; - position = "94 53"; - extent = "34 18"; - minExtent = "8 2"; - horizSizing = "right"; - vertSizing = "bottom"; - profile = "ToolsGuiTextEditProfile"; - visible = "1"; - active = "1"; - tooltipProfile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - isContainer = "0"; - internalName = "macroDistanceCtrl"; - canSave = "1"; - canSaveDynamicFields = "0"; - }; - }; - - new GuiBitmapCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "6 200"; - Extent = "175 2"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "tools/gui/images/separator-v"; - wrap = "0"; - }; - new GuiContainer() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "6 206"; - Extent = "185 72"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - new GuiBitmapCtrl() { - internalName = "detailTexCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "47 47"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - bitmap = "tools/materialEditor/gui/unknownImage"; - wrap = "0"; + new GuiBitmapCtrl() { + bitmap = "art/terrains/Example/sand_d"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 1"; + extent = "47 47"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "detailTexCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "1 1"; + extent = "48 48"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeDetail();"; + tooltipProfile = "ToolsGuiDefaultProfile"; + tooltip = "Change the active Detail Map for this layer."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Detail"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 -3"; + extent = "30 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "EditorTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "None"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 16"; + extent = "79 17"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Edit"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "111 0"; + extent = "40 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeDetail();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "154 0"; + extent = "16 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg-->detailTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Size"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "132 33"; + extent = "39 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "10"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "94 32"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "detSizeCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Strength"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "39 54"; + extent = "46 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "1"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "1 53"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "detStrengthCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Distance"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "132 54"; + extent = "45 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "100"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "94 53"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "detDistanceCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "core/art/gui/images/separator-v"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 73"; + extent = "148 2"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; - new GuiBitmapButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "48 48"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeDetail();"; - tooltipprofile = "ToolsGuiDefaultProfile"; - ToolTip = "Change the active Detail Map for this layer."; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 158"; + extent = "174 54"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "tools/materialEditor/gui/unknownImage"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 1"; + extent = "47 47"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "normTexCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Normal"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 -3"; + extent = "39 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "EditorTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "1 1"; + extent = "48 48"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeNormal();"; + tooltipProfile = "ToolsGuiDefaultProfile"; + tooltip = "Change the active Normal Map for this layer."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "None"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 15"; + extent = "79 17"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Edit"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "111 0"; + extent = "40 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeNormal();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "154 0"; + extent = "16 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg-->normTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Parallax Scale"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "92 34"; + extent = "77 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "55 33"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "parallaxScaleCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "tools/gui/images/separator-v"; + color = "255 255 255 255"; + wrap = "0"; + position = "-10 53"; + extent = "148 2"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "EditorTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "56 -3"; - Extent = "30 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 216"; + extent = "174 53"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "Detail"; - maxLength = "1024"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiBitmapCtrl() { + bitmap = "tools/materialEditor/gui/unknownImage"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 1"; + extent = "47 47"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "compositeTexCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "1 1"; + extent = "48 48"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changecomposite();"; + tooltipProfile = "ToolsGuiDefaultProfile"; + tooltip = "Change the active composite Map for this layer."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Composite"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 -3"; + extent = "61 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "EditorTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "None"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 17"; + extent = "79 17"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Edit"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "111 0"; + extent = "40 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changecomposite();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "154 0"; + extent = "16 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg-->compositeTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapCtrl() { + bitmap = "tools/gui/images/separator-v"; + color = "255 255 255 255"; + wrap = "0"; + position = "4 51"; + extent = "148 2"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "width"; - VertSizing = "bottom"; - position = "56 16"; - Extent = "116 17"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; + new GuiContainer() { + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "6 272"; + extent = "174 71"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; - text = "None"; - maxLength = "1024"; - }; - new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "116 0"; - Extent = "40 16"; - MinExtent = "8 2"; + isContainer = "1"; canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.changeDetail();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - text = "Edit"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - }; - new GuiBitmapButtonCtrl() { canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "bottom"; - position = "159 0"; - Extent = "16 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg-->detailTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - groupNum = "-1"; - buttonType = "PushButton"; - useMouseEvents = "0"; - bitmap = "tools/gui/images/delete"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "132 33"; - Extent = "39 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - text = "Size"; - maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "detSizeCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "94 32"; - Extent = "34 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "39 54"; - Extent = "46 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - text = "Strength"; - maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "detStrengthCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 53"; - Extent = "34 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; - }; - new GuiTextCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "132 54"; - Extent = "45 16"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - text = "Distance"; - maxLength = "1024"; - }; - new GuiTextEditCtrl() { - internalName = "detDistanceCtrl"; - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiTextEditProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "94 53"; - Extent = "34 18"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - maxLength = "1024"; - historySize = "0"; - password = "0"; - tabComplete = "0"; - sinkAllKeyEvents = "0"; - passwordMask = "*"; + + new GuiBitmapCtrl() { + bitmap = "tools/materialEditor/gui/unknownImage"; + color = "255 255 255 255"; + wrap = "0"; + position = "1 1"; + extent = "47 47"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "macroTexCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/materialEditor/gui/cubemapBtnBorder"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "1 1"; + extent = "48 48"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeMacro();"; + tooltipProfile = "ToolsGuiDefaultProfile"; + tooltip = "Change the active Macro Map for this layer."; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Macro"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 -3"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "EditorTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "None"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "56 17"; + extent = "111 17"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiButtonCtrl() { + text = "Edit"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "111 0"; + extent = "40 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.changeMacro();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiBitmapButtonCtrl() { + bitmap = "tools/gui/images/delete"; + bitmapMode = "Stretched"; + autoFitExtents = "0"; + useModifiers = "0"; + useStates = "1"; + masked = "0"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + position = "154 0"; + extent = "16 16"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "bottom"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg-->macroTexCtrl.setBitmap(\"tools/materialEditor/gui/unknownImage\");"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Size"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "132 33"; + extent = "39 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "200"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "94 32"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "macroSizeCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Strength"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "39 54"; + extent = "46 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "0.7"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "1 53"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "macroStrengthCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextCtrl() { + text = "Distance"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "132 54"; + extent = "45 16"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; + new GuiTextEditCtrl() { + historySize = "0"; + tabComplete = "0"; + sinkAllKeyEvents = "0"; + password = "0"; + passwordMask = "*"; + text = "500"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "0"; + anchorBottom = "0"; + anchorLeft = "0"; + anchorRight = "0"; + position = "94 53"; + extent = "34 18"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTextEditProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + internalName = "macroDistanceCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; + }; }; }; }; new GuiControl() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "height"; position = "6 42"; - Extent = "189 373"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; + extent = "189 373"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiDefaultProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; new GuiScrollCtrl() { - canSaveDynamicFields = "0"; - isContainer = "1"; - Profile = "ToolsGuiScrollProfile"; - HorizSizing = "width"; - VertSizing = "height"; - position = "0 0"; - Extent = "189 374"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "1"; - AnchorBottom = "0"; - AnchorLeft = "1"; - AnchorRight = "0"; willFirstRespond = "1"; hScrollBar = "dynamic"; vScrollBar = "dynamic"; - lockHorizScroll = "false"; - lockVertScroll = "false"; + lockHorizScroll = "0"; + lockVertScroll = "0"; constantThumbHeight = "0"; childMargin = "0 0"; mouseWheelScrollSpeed = "-1"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 -1"; + extent = "189 374"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "height"; + profile = "ToolsGuiScrollProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; new GuiTreeViewCtrl() { - internalName = "matLibTree"; - canSaveDynamicFields = "0"; - class = "TerrainMaterialTreeCtrl"; - className = "TerrainMaterialTreeCtrl"; - isContainer = "1"; - Profile = "ToolsGuiTreeViewProfile"; - HorizSizing = "right"; - VertSizing = "bottom"; - position = "1 1"; - Extent = "125 84"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; tabSize = "16"; textOffset = "2"; fullRowSelect = "0"; itemHeight = "21"; destroyTreeOnSleep = "1"; - MouseDragging = "0"; - MultipleSelections = "0"; - DeleteObjectAllowed = "0"; - DragToItemAllowed = "0"; - ClearAllOnSingleSelection = "1"; + mouseDragging = "0"; + multipleSelections = "0"; + deleteObjectAllowed = "0"; + dragToItemAllowed = "0"; + clearAllOnSingleSelection = "1"; showRoot = "0"; - internalNamesOnly = "1"; - objectNamesOnly = "0"; + useInspectorTooltips = "0"; + tooltipOnWidthOnly = "0"; + showObjectIds = "0"; + showClassNames = "0"; + showObjectNames = "0"; + showInternalNames = "1"; + showClassNameForUnnamedObjects = "0"; + compareToObjectID = "1"; + canRenameObjects = "1"; + renameInternal = "0"; + position = "1 1"; + extent = "109 147"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "bottom"; + profile = "ToolsGuiTreeViewProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "matLibTree"; + class = "TerrainMaterialTreeCtrl"; + canSave = "1"; + canSaveDynamicFields = "0"; }; }; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "top"; - position = "202 394"; - Extent = "98 22"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.dialogApply();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; text = "Apply&Select"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "202 394"; + extent = "98 22"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "top"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.dialogApply();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; new GuiButtonCtrl() { - canSaveDynamicFields = "0"; - isContainer = "0"; - Profile = "ToolsGuiButtonProfile"; - HorizSizing = "left"; - VertSizing = "top"; - position = "307 394"; - Extent = "80 22"; - MinExtent = "8 2"; - canSave = "1"; - Visible = "1"; - Command = "TerrainMaterialDlg.dialogCancel();"; - tooltipprofile = "ToolsGuiToolTipProfile"; - hovertime = "1000"; text = "Cancel"; groupNum = "-1"; buttonType = "PushButton"; useMouseEvents = "0"; + position = "307 394"; + extent = "80 22"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "top"; + profile = "ToolsGuiButtonProfile"; + visible = "1"; + active = "1"; + command = "TerrainMaterialDlg.dialogCancel();"; + tooltipProfile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + isContainer = "0"; + canSave = "1"; + canSaveDynamicFields = "0"; }; - - new GuiBitmapCtrl() { // inactive overlay - internalName = "inactiveOverlay"; - Profile = "ToolsGuiDefaultProfile"; - HorizSizing = "left"; - VertSizing = "height"; - position = "199 23"; - Extent = "190 267"; - isContainer = true; - Visible = false; + new GuiBitmapCtrl() { bitmap = "tools/gui/images/inactive-overlay"; - - new GuiTextCtrl(){ - internalName = "inactiveOverlayDlg"; - Profile = "ToolsGuiTextCenterProfile"; - HorizSizing = "width"; - VertSizing = "center"; - position = "0 104"; - Extent = "190 64"; + color = "255 255 255 255"; + wrap = "0"; + position = "199 23"; + extent = "190 267"; + minExtent = "8 2"; + horizSizing = "left"; + vertSizing = "height"; + profile = "ToolsGuiDefaultProfile"; + visible = "0"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "inactiveOverlay"; + hidden = "1"; + canSave = "1"; + canSaveDynamicFields = "0"; + + new GuiTextCtrl() { text = "Inactive"; + maxLength = "1024"; + margin = "0 0 0 0"; + padding = "0 0 0 0"; + anchorTop = "1"; + anchorBottom = "0"; + anchorLeft = "1"; + anchorRight = "0"; + position = "0 104"; + extent = "190 64"; + minExtent = "8 2"; + horizSizing = "width"; + vertSizing = "center"; + profile = "ToolsGuiTextCenterProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; + isContainer = "1"; + internalName = "inactiveOverlayDlg"; + canSave = "1"; + canSaveDynamicFields = "0"; }; }; }; diff --git a/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui b/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui index 74f1200c6..129e5988c 100644 --- a/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui +++ b/Templates/Full/game/tools/worldEditor/gui/objectBuilderGui.ed.gui @@ -877,6 +877,24 @@ function ObjectBuilderGui::buildParticleSimulation(%this) %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 //------------------------------------------------------------------------------ diff --git a/Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui b/Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui new file mode 100644 index 000000000..6f4c10d77 --- /dev/null +++ b/Templates/Full/game/tools/worldEditor/gui/probeBakeDlg.gui @@ -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 --- diff --git a/Templates/Full/game/tools/worldEditor/main.cs b/Templates/Full/game/tools/worldEditor/main.cs index 3610a26db..28d6937f4 100644 --- a/Templates/Full/game/tools/worldEditor/main.cs +++ b/Templates/Full/game/tools/worldEditor/main.cs @@ -43,6 +43,7 @@ function initializeWorldEditor() exec("./gui/AddFMODProjectDlg.ed.gui"); exec("./gui/SelectObjectsWindow.ed.gui"); exec("./gui/ProceduralTerrainPainterGui.gui" ); + exec("./gui/probeBakeDlg.gui" ); // Load Scripts. exec("./scripts/menus.ed.cs"); @@ -61,6 +62,7 @@ function initializeWorldEditor() exec("./scripts/ManageSFXParametersWindow.ed.cs"); exec("./scripts/AddFMODProjectDlg.ed.cs"); exec("./scripts/SelectObjectsWindow.ed.cs"); + exec("./scripts/probeBake.ed.cs"); // Load Custom Editors loadDirectory(expandFilename("./scripts/editors")); @@ -115,10 +117,11 @@ function initializeWorldEditor() EVisibility.addOption( "Debug Render: Light Frustums", "$Light::renderLightFrustums", "" ); EVisibility.addOption( "Debug Render: Bounding Boxes", "$Scene::renderBoundingBoxes", "" ); 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: Light Color Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" ); - EVisibility.addOption( "AL: Environment Light", "$AL_LightMapShaderVar", "toggleLightMapViz" ); - EVisibility.addOption( "AL: Light Specular Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" ); + EVisibility.addOption( "AL: Diffuse Lighting Viz", "$AL_LightColorVisualizeVar", "toggleLightColorViz" ); + EVisibility.addOption( "AL: Specular Lighting Viz", "$AL_LightSpecularVisualizeVar", "toggleLightSpecularViz" ); EVisibility.addOption( "AL: Normals Viz", "$AL_NormalsVisualizeVar", "toggleNormalsViz" ); EVisibility.addOption( "AL: Depth Viz", "$AL_DepthVisualizeVar", "toggleDepthViz" ); EVisibility.addOption( "AL: Color Buffer", "$AL_ColorBufferShaderVar", "toggleColorBufferViz" ); diff --git a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs index 66f2304ec..712986e38 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs @@ -55,6 +55,10 @@ function EWCreatorWindow::init( %this ) %this.registerMissionObject( "PointLight", "Point Light" ); %this.registerMissionObject( "SpotLight", "Spot Light" ); + + %this.registerMissionObject( "ReflectionProbe", "Reflection Probe" ); + %this.registerMissionObject( "Skylight", "Skylight" ); + %this.registerMissionObject( "GroundCover", "Ground Cover" ); %this.registerMissionObject( "TerrainBlock", "Terrain Block" ); %this.registerMissionObject( "GroundPlane", "Ground Plane" ); diff --git a/Templates/Full/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs index 2ec8e17f3..2a5f12a5c 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/interfaces/terrainMaterialDlg.ed.cs @@ -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 ) { // Create a unique material name. @@ -394,7 +416,12 @@ function TerrainMaterialDlg::setActiveMaterial( %this, %mat ) %this-->normTexCtrl.setBitmap( "tools/materialEditor/gui/unknownImage" ); }else{ %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-->baseSizeCtrl.setText( %mat.diffuseSize ); %this-->detStrengthCtrl.setText( %mat.detailStrength ); @@ -448,6 +475,11 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat ) }else{ %newMacro = %this-->macroTexCtrl.bitmap; } + if (%this-->compositeTexCtrl.bitmap $= "tools/materialEditor/gui/unknownImage"){ + %newComposite = ""; + }else{ + %newComposite = %this-->compositeTexCtrl.bitmap; + } %detailSize = %this-->detSizeCtrl.getText(); %diffuseSize = %this-->baseSizeCtrl.getText(); %detailStrength = %this-->detStrengthCtrl.getText(); @@ -466,6 +498,7 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat ) %mat.diffuseMap $= %newDiffuse && %mat.normalMap $= %newNormal && %mat.detailMap $= %newDetail && + %mat.compositeMap $= %newComposite && %mat.macroMap $= %newMacro && %mat.detailSize == %detailSize && %mat.diffuseSize == %diffuseSize && @@ -497,7 +530,8 @@ function TerrainMaterialDlg::saveDirtyMaterial( %this, %mat ) } %mat.diffuseMap = %newDiffuse; - %mat.normalMap = %newNormal; + %mat.normalMap = %newNormal; + %mat.compositeMap = %newComposite; %mat.detailMap = %newDetail; %mat.macroMap = %newMacro; %mat.detailSize = %detailSize; @@ -544,6 +578,7 @@ function TerrainMaterialDlg::snapshotMaterials( %this ) diffuseMap = %mat.diffuseMap; normalMap = %mat.normalMap; detailMap = %mat.detailMap; + compositeMap = %mat.compositeMap; macroMap = %mat.macroMap; detailSize = %mat.detailSize; diffuseSize = %mat.diffuseSize; @@ -578,6 +613,7 @@ function TerrainMaterialDlg::restoreMaterials( %this ) %mat.diffuseMap = %obj.diffuseMap; %mat.normalMap = %obj.normalMap; %mat.detailMap = %obj.detailMap; + %mat.compositeMap = %obj.compositeMap; %mat.macroMap = %obj.macroMap; %mat.detailSize = %obj.detailSize; %mat.diffuseSize = %obj.diffuseSize; diff --git a/Templates/Full/game/tools/worldEditor/scripts/lighting.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/lighting.ed.cs index 8886b8eb9..f9afcaad4 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/lighting.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/lighting.ed.cs @@ -61,3 +61,21 @@ function EditorLightingMenu::onMenuSelect( %this ) //%selSize = EWorldEditor.getSelectionSize(); %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); +} diff --git a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs index b225d3534..9f8a24e58 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs @@ -263,6 +263,8 @@ function EditorGui::buildMenus(%this) item[0] = "Full Relight" TAB "Alt L" TAB "Editor.lightScene(\"\", forceAlways);"; item[1] = "Toggle ShadowViz" TAB "" TAB "toggleShadowViz();"; item[2] = "-"; + item[3] = "Update Reflection Probes" TAB "" TAB "updateReflectionProbes();"; + item[4] = "-"; // NOTE: The light managers will be inserted as the // last menu items in EditorLightingMenu::onAdd(). diff --git a/Templates/Full/game/tools/worldEditor/scripts/probeBake.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/probeBake.ed.cs new file mode 100644 index 000000000..765a2bed0 --- /dev/null +++ b/Templates/Full/game/tools/worldEditor/scripts/probeBake.ed.cs @@ -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; +} \ No newline at end of file diff --git a/Tools/CMake/torque3d.cmake b/Tools/CMake/torque3d.cmake index 751c908d8..4819ebe9d 100644 --- a/Tools/CMake/torque3d.cmake +++ b/Tools/CMake/torque3d.cmake @@ -333,6 +333,7 @@ addPath("${srcDir}/T3D/decal") addPath("${srcDir}/T3D/sfx") addPath("${srcDir}/T3D/gameBase") addPath("${srcDir}/T3D/turret") +addPath("${srcDir}/T3D/lighting") addPathRec("${srcDir}/T3D/components/") addPathRec("${srcDir}/T3D/systems") diff --git a/Tools/CMake/torqueConfig.h.in b/Tools/CMake/torqueConfig.h.in index 886195e06..92a01536f 100644 --- a/Tools/CMake/torqueConfig.h.in +++ b/Tools/CMake/torqueConfig.h.in @@ -195,17 +195,3 @@ #else # define TORQUE_INSTANCE_EXCLUSION "TorqueTest" #endif - -// Someday, it might make sense to do some pragma magic here so we error -// on inconsistent flags. - -// The Xbox360 has it's own profiling tools, the Torque Profiler should not be used -#ifdef TORQUE_OS_XENON -# ifdef TORQUE_ENABLE_PROFILER -# undef TORQUE_ENABLE_PROFILER -# endif -# -# ifdef TORQUE_ENABLE_PROFILE_PATH -# undef TORQUE_ENABLE_PROFILE_PATH -#endif -#endif