1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084 |
- //-----------------------------------------------------------------------------
- // 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 "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::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")
- { ProbeRenderInst::Sphere, "Sphere", "Sphere shaped" },
- { ProbeRenderInst::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 = ProbeRenderInst::Box;
- mIndrectLightingModeType = NoIndirect;
- mReflectionModeType = BakedCubemap;
- mEnabled = true;
- mBake = false;
- mDirty = false;
- mRadius = 10;
- mUseCubemap = false;
- mUseHDRCaptures = true;
- mStaticCubemap = NULL;
- mReflectionPath = "";
- mProbeUniqueID = "";
- mEditorShapeInst = NULL;
- mEditorShape = NULL;
- mRefreshRateMS = 200;
- mDynamicLastBakeMS = 0;
- mMaxDrawDistance = 75;
- mResourcesCreated = false;
- mProbeInfo = nullptr;
- mPrefilterSize = 64;
- mPrefilterMipLevels = mLog2(F32(mPrefilterSize));
- mPrefilterMap = nullptr;
- mIrridianceMap = nullptr;
- mProbePosOffset = Point3F::Zero;
- mEditPosOffset = false;
- mProbeInfoIdx = -1;
- mCaptureMask = REFLECTION_PROBE_CAPTURE_TYPEMASK;
- }
- ReflectionProbe::~ReflectionProbe()
- {
- if (mEditorShapeInst)
- SAFE_DELETE(mEditorShapeInst);
- if (mProbeInfo)
- SAFE_DELETE(mProbeInfo);
- if (mReflectionModeType != StaticCubemap && mStaticCubemap)
- mStaticCubemap->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.");
- addField("posOffset", TypePoint3F, Offset(mProbePosOffset, ReflectionProbe), "");
- //addProtectedField("EditPosOffset", TypeBool, Offset(mEditPosOffset, ReflectionProbe),
- // &_toggleEditPosOffset, &defaultProtectedGetFn, "Toggle Edit Pos Offset Mode", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
- endGroup("Rendering");
- 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, &ProbeManager::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");
- // SceneObject already handles exposing the transform
- Parent::initPersistFields();
- }
- 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);
- ReflectionProbe *clientProbe = (ReflectionProbe*)probe->getClientObject();
- if (clientProbe)
- {
- clientProbe->bake(clientProbe->mReflectionPath, 64);
- }
- return false;
- }
- bool ReflectionProbe::_toggleEditPosOffset(void *object, const char *index, const char *data)
- {
- ReflectionProbe* probe = reinterpret_cast< ReflectionProbe* >(object);
- probe->mEditPosOffset = !probe->mEditPosOffset;
- //if (probe->mDirty)
- // probe->bake(probe->mReflectionPath, 256);
- return false;
- }
- bool ReflectionProbe::onAdd()
- {
- if (!Parent::onAdd())
- return false;
- mEditPosOffset = 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())
- {
- createGeometry();
- updateProbeParams();
- }
-
- setMaskBits(-1);
- return true;
- }
- void ReflectionProbe::onRemove()
- {
- // Remove this object from the scene
- removeFromScene();
- Parent::onRemove();
- }
- void ReflectionProbe::deleteObject()
- {
- //we're deleting it?
- //Then we need to clear out the processed cubemaps(if we have them)
- String prefilPath = getPrefilterMapPath();
- if (Platform::isFile(prefilPath))
- {
- Platform::fileDelete(prefilPath);
- }
- String irrPath = getIrradianceMapPath();
- if (Platform::isFile(irrPath))
- {
- Platform::fileDelete(irrPath);
- }
- Parent::deleteObject();
- }
- void ReflectionProbe::setTransform(const MatrixF & mat)
- {
- // Let SceneObject handle all of the matrix manipulation
- if (!mEditPosOffset)
- Parent::setTransform(mat);
- else
- mProbePosOffset = mat.getPosition();
- 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());
- mathWrite(*stream, mProbePosOffset);
- }
- if (stream->writeFlag(mask & ShapeTypeMask))
- {
- stream->write((U32)mProbeShapeType);
- }
- if (stream->writeFlag(mask & UpdateMask))
- {
- 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);
- mathRead(*stream, &mProbePosOffset);
- }
- if (stream->readFlag()) // ShapeTypeMask
- {
- U32 shapeType = ProbeRenderInst::Sphere;
- stream->read(&shapeType);
- mProbeShapeType = (ProbeRenderInst::ProbeShapeType)shapeType;
- createGeometry();
- }
- if (stream->readFlag()) // UpdateMask
- {
- 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();
- String newCubemapName;
- stream->read(&mCubemapName);
- //if (newCubemapName != mCubemapName)
- {
- processStaticCubemap();
- }
- 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)
- {
- mProbeInfo = new ProbeRenderInst();
- mProbeInfoIdx = ProbeRenderInst::all.size() - 1;
- mProbeInfo->mIsEnabled = false;
- }
- updateMaterial();
- mProbeInfo->mAmbient = LinearColorF(0, 0, 0, 0);
- mProbeInfo->mProbeShapeType = mProbeShapeType;
- mProbeInfo->mTransform = getWorldTransform();
- mProbeInfo->mTransform.inverse();
- mProbeInfo->setPosition(getPosition());
- //Point3F pos = mProbeInfo->mTransform.getPosition();
- //Update the bounds
- //mObjBox.minExtents.set(-1, -1, -1);
- //mObjBox.maxExtents.set(1, 1, 1);
- mObjScale.set(mRadius, mRadius, mRadius);
- // Skip our transform... it just dirties mask bits.
- Parent::setTransform(mObjToWorld);
- resetWorldBox();
- mProbeInfo->mBounds = mWorldBox;
- mProbeInfo->mRadius = mRadius;
- mProbeInfo->mIsSkylight = false;
- mProbeInfo->mProbePosOffset = mProbePosOffset;
- mProbeInfo->mDirty = true;
- mProbeInfo->mScore = mMaxDrawDistance;
- }
- void ReflectionProbe::processStaticCubemap()
- {
- createClientResources();
- Sim::findObject(mCubemapName, mStaticCubemap);
- if (!mStaticCubemap)
- {
- Con::errorf("ReflectionProbe::updateMaterial() - unable to find static cubemap file!");
- return;
- }
- if (mStaticCubemap->mCubemap == nullptr)
- {
- mStaticCubemap->createMap();
- mStaticCubemap->updateFaces();
- }
- String prefilPath = getPrefilterMapPath();
- String irrPath = getIrradianceMapPath();
- //if (!Platform::isFile(irrPath) || !Platform::isFile(prefilPath))
- {
- GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
- /*IBLUtilities::GenerateIrradianceMap(renderTarget, mStaticCubemap->mCubemap, mIrridianceMap->mCubemap);
- IBLUtilities::GeneratePrefilterMap(renderTarget, mStaticCubemap->mCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
- IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
- IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);*/
- }
- mProbeInfo->mCubemap = &mPrefilterMap->mCubemap;
- mProbeInfo->mIrradianceCubemap = &mIrridianceMap->mCubemap;
- }
- void ReflectionProbe::updateMaterial()
- {
- createClientResources();
- if (mReflectionModeType != DynamicCubemap)
- {
- if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty())
- {
- if (mPrefilterMap != nullptr && mPrefilterMap->mCubemap.isValid())
- {
- mProbeInfo->mCubemap = &mPrefilterMap->mCubemap;
- }
- if (mIrridianceMap != nullptr && mIrridianceMap->mCubemap.isValid())
- {
- mProbeInfo->mIrradianceCubemap = &mIrridianceMap->mCubemap;
- }
- }
- }
- else if (mReflectionModeType == DynamicCubemap && !mDynamicCubemap.isNull())
- {
- mProbeInfo->mCubemap = &mDynamicCubemap;
- }
- if (mBrdfTexture.isValid())
- {
- mProbeInfo->mBRDFTexture = &mBrdfTexture;
- }
- //Make us ready to render
- if (mEnabled)
- mProbeInfo->mIsEnabled = true;
- else
- mProbeInfo->mIsEnabled = false;
- }
- bool ReflectionProbe::createClientResources()
- {
- //irridiance resources
- if (!mIrridianceMap)
- {
- mIrridianceMap = new CubemapData();
- mIrridianceMap->registerObject();
- mIrridianceMap->createMap();
- }
- String irrPath = getIrradianceMapPath();
- if (Platform::isFile(irrPath))
- {
- mIrridianceMap->setCubemapFile(FileName(irrPath));
- mIrridianceMap->updateFaces();
- }
- if (mIrridianceMap->mCubemap.isNull())
- Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked irradiance map at %s", getIrradianceMapPath().c_str());
- //
- if (!mPrefilterMap)
- {
- mPrefilterMap = new CubemapData();
- mPrefilterMap->registerObject();
- mPrefilterMap->createMap();
- }
- String prefilPath = getPrefilterMapPath();
- if (Platform::isFile(prefilPath))
- {
- mPrefilterMap->setCubemapFile(FileName(prefilPath));
- mPrefilterMap->updateFaces();
- }
- if (mPrefilterMap->mCubemap.isNull())
- Con::errorf("ReflectionProbe::createClientResources() - Unable to load baked prefilter map at %s", getPrefilterMapPath().c_str());
- //brdf lookup texture
- String brdfPath = Con::getVariable("$Core::BRDFTexture", "core/art/pbr/brdfTexture.dds");
- mBrdfTexture = TEXMGR->createTexture(brdfPath, &GFXTexturePersistentProfile);
- if (!mBrdfTexture)
- {
- return false;
- }
- mResourcesCreated = true;
- return true;
- }
- void ReflectionProbe::generateTextures()
- {
- }
- void ReflectionProbe::prepRenderImage(SceneRenderState *state)
- {
- if (!mEnabled || !ProbeManager::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))
- {
- mProbeInfo->mScore = mMaxDrawDistance;
- 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(mProbeInfoIdx);
- if (ReflectionProbe::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mPrefilterMap != nullptr)
- {
- GFXTransformSaver saver;
- // Calculate the distance of this object from the camera
- Point3F cameraOffset;
- getRenderTransform().getColumn(3, &cameraOffset);
- cameraOffset -= state->getDiffuseCameraPosition();
- 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(mPrefilterMap->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));
-
- Point3F centerPos = mat.getPosition();
- centerPos += mProbePosOffset;
- mat.setPosition(centerPos);
- 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<ObjectRenderInst>();
- 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 (!ProbeManager::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 = 25;
- if (mProbeShapeType == ProbeRenderInst::Sphere)
- {
- draw->drawSphere(desc, mRadius, getPosition(), color);
- }
- else
- {
- const MatrixF worldToObjectXfm = getTransform();
- Box3F cube(-Point3F(mRadius, mRadius, mRadius),Point3F(mRadius, mRadius, mRadius));
- Box3F wb = getWorldBox();
- cube.setCenter(getPosition()+mProbePosOffset);
- wb.setCenter(getPosition() + mProbePosOffset);
- draw->drawCube(desc, cube, color, &worldToObjectXfm);
- draw->drawCube(desc, wb, color, &worldToObjectXfm);
- }
- }
- 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, mPrefilterMap->mCubemap);
- //Set the invViewMat
- MatrixSet &matrixSet = renderState->getRenderPass()->getMatrixSet();
- const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
- MaterialParameterHandle *invViewMat = mat->getMaterialParameterHandle("$invViewMat");
- matParams->setSafe(invViewMat, worldToCameraXfm);
- }
- DefineEngineMethod(ReflectionProbe, postApply, void, (), ,
- "A utility method for forcing a network update.\n")
- {
- object->inspectPostApply();
- }
- String ReflectionProbe::getPrefilterMapPath()
- {
- if (mReflectionPath.isEmpty() || mProbeUniqueID.isEmpty())
- {
- Con::errorf("ReflectionProbe::getPrefilterMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
- return "";
- }
- char fileName[256];
- dSprintf(fileName, 256, "%s%s_Prefilter.dds", mReflectionPath.c_str(), mProbeUniqueID.c_str());
- return fileName;
- }
- String ReflectionProbe::getIrradianceMapPath()
- {
- if (mReflectionPath.isEmpty() || mProbeUniqueID.isEmpty())
- {
- Con::errorf("ReflectionProbe::getIrradianceMapPath() - We don't have a set output path or persistant id, so no valid path can be provided!");
- return "";
- }
- char fileName[256];
- dSprintf(fileName, 256, "%s%s_Irradiance.dds", mReflectionPath.c_str(), mProbeUniqueID.c_str());
- return fileName;
- }
- void ReflectionProbe::bake(String outputPath, S32 resolution, bool renderWithProbes)
- {
- GFXDEBUGEVENT_SCOPE(ReflectionProbe_Bake, ColorI::WHITE);
- Con::warnf("ReflectionProbe::bake() - Beginning bake!");
- U32 startMSTime = Platform::getRealMilliseconds();
- /*PostEffect *preCapture = dynamic_cast<PostEffect*>(Sim::findObject("AL_PreCapture"));
- PostEffect *deferredShading = dynamic_cast<PostEffect*>(Sim::findObject("AL_DeferredShading"));
- if (preCapture)
- {
- preCapture->setShaderConst("$radius",String::ToString(mRadius));
- preCapture->setShaderConst("$captureRez", String::ToString(F32(resolution)));
- preCapture->enable();
- }
- if (deferredShading)
- deferredShading->disable();*/
- GFXCubemapHandle sceneCaptureCubemap;
- if (mReflectionModeType == DynamicCubemap && mDynamicCubemap.isNull())
- {
- //mCubemap->createMap();
- mDynamicCubemap = GFX->createCubemap();
- if(mUseHDRCaptures)
- mDynamicCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
- else
- mDynamicCubemap->initDynamic(resolution, GFXFormatB8G8R8A8);
- sceneCaptureCubemap = mDynamicCubemap;
- }
- else if (mReflectionModeType != DynamicCubemap)
- {
- //Prep our bake path
- if (mReflectionPath.isEmpty())
- {
- Con::errorf("ReflectionProbe::bake() - Unable to bake our captures because probe doesn't have a path set");
- return;
- }
- if (mProbeUniqueID.isEmpty())
- {
- Con::errorf("ReflectionProbe::bake() - Unable to bake our captures because probe doesn't have a unique ID set");
- return;
- }
- sceneCaptureCubemap = GFX->createCubemap();
- if (mUseHDRCaptures)
- sceneCaptureCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
- else
- sceneCaptureCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
- }
- 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 = ProbeManager::smRenderReflectionProbes;
- if (!renderWithProbes)
- ProbeManager::smRenderReflectionProbes = false;
- for (U32 i = 0; i < 6; ++i)
- {
- GFXTexHandle blendTex;
- blendTex.set(resolution, resolution, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, "");
- GFXTextureTargetRef baseTarget = GFX->allocRenderToTextureTarget();
- GFX->clearTextureStateImmediate(0);
-
- baseTarget->attachTexture(GFXTextureTarget::Color0, sceneCaptureCubemap, i);
- // 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()+mProbePosOffset);
- 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);
- F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust;
- TSShapeInstance::smDetailAdjust *= getNextPow2(resolution);
- renderFrame(&baseTarget, matView, frustum, mCaptureMask & EDITOR_RENDER_TYPEMASK, gCanvasClearColor);
- TSShapeInstance::smDetailAdjust = detailAdjustBackup;
- baseTarget->resolve();
- }
- if (sceneCaptureCubemap.isValid())
- {
- validCubemap = true;
- mDirty = false;
- }
- else
- {
- validCubemap = false;
- }
- //Now, save out the maps
- //create irridiance cubemap
- if (validCubemap)
- {
- bool se = isServerObject();
- //Just to ensure we're prepped for the generation
- createClientResources();
- //Prep it with whatever resolution we've dictated for our bake
- if (mUseHDRCaptures)
- {
- mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
- mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR16G16B16A16F);
- }
- else
- {
- mIrridianceMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
- mPrefilterMap->mCubemap->initDynamic(resolution, GFXFormatR8G8B8A8);
- }
- //IBLUtilities::GenerateAndSaveIrradianceMap(getIrradianceMapPath(), resolution, sceneCaptureCubemap, mIrridianceMap->mCubemap);
- //IBLUtilities::GenerateAndSavePrefilterMap(getPrefilterMapPath(), resolution, sceneCaptureCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
- GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
- IBLUtilities::GenerateIrradianceMap(renderTarget, sceneCaptureCubemap, mIrridianceMap->mCubemap);
- IBLUtilities::GeneratePrefilterMap(renderTarget, sceneCaptureCubemap, mPrefilterMipLevels, mPrefilterMap->mCubemap);
- IBLUtilities::SaveCubeMap(getIrradianceMapPath(), mIrridianceMap->mCubemap);
- IBLUtilities::SaveCubeMap(getPrefilterMapPath(), mPrefilterMap->mCubemap);
- }
- else
- {
- Con::errorf("ReflectionProbe::bake() - Didn't generate a valid scene capture cubemap, unable to generate prefilter and irradiance maps!");
- }
- if(!renderWithProbes)
- ProbeManager::smRenderReflectionProbes = probeRenderState;
- setMaskBits(-1);
- /*if (preCapture)
- preCapture->disable();
- if (deferredShading)
- deferredShading->enable();*/
- U32 endMSTime = Platform::getRealMilliseconds();
- F32 diffTime = F32(endMSTime - startMSTime);
- Con::warnf("ReflectionProbe::bake() - Finished bake! Took %g milliseconds", diffTime);
- }
- DefineEngineMethod(ReflectionProbe, Bake, void, (String outputPath, S32 resolution, bool renderWithProbes), ("", 64, false),
- "@brief returns true if control object is inside the fog\n\n.")
- {
- ReflectionProbe *clientProbe = (ReflectionProbe*)object->getClientObject();
- if (clientProbe)
- {
- clientProbe->bake(outputPath, resolution, renderWithProbes);
- }
- //object->bake(outputPath, resolution);
- }
|