| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "T3D/lighting/Skylight.h"
- #include "math/mathIO.h"
- #include "scene/sceneRenderState.h"
- #include "console/consoleTypes.h"
- #include "core/stream/bitStream.h"
- #include "materials/baseMatInstance.h"
- #include "console/engineAPI.h"
- #include "gfx/gfxDrawUtil.h"
- #include "gfx/gfxDebugEvent.h"
- #include "gfx/gfxTransformSaver.h"
- #include "math/mathUtils.h"
- #include "gfx/bitmap/gBitmap.h"
- #include "core/stream/fileStream.h"
- #include "core/fileObject.h"
- #include "core/resourceManager.h"
- #include "console/simPersistId.h"
- #include <string>
- #include "T3D/gameFunctions.h"
- #include "postFx/postEffect.h"
- #include "renderInstance/renderProbeMgr.h"
- #include "lighting/probeManager.h"
- #include "math/util/sphereMesh.h"
- #include "materials/materialManager.h"
- #include "math/util/matrixSet.h"
- #include "gfx/bitmap/cubemapSaver.h"
- #include "materials/materialFeatureTypes.h"
- #include "materials/shaderData.h"
- #include "gfx/gfxTextureManager.h"
- #include "gfx/bitmap/imageUtils.h"
- #include "T3D/lighting/IBLUtilities.h"
- extern bool gEditingMission;
- extern ColorI gCanvasClearColor;
- bool Skylight::smRenderSkylights = true;
- bool Skylight::smRenderPreviewProbes = true;
- IMPLEMENT_CO_NETOBJECT_V1(Skylight);
- ConsoleDocClass(Skylight,
- "@brief An example scene object which renders a mesh.\n\n"
- "This class implements a basic SceneObject that can exist in the world at a "
- "3D position and render itself. There are several valid ways to render an "
- "object in Torque. This class implements the preferred rendering method which "
- "is to submit a MeshRenderInst along with a Material, vertex buffer, "
- "primitive buffer, and transform and allow the RenderMeshMgr handle the "
- "actual setup and rendering for you.\n\n"
- "See the C++ code for implementation details.\n\n"
- "@ingroup Examples\n");
- ImplementEnumType(SkylightReflectionModeEnum,
- "Type of mesh data available in a shape.\n"
- "@ingroup gameObjects")
- { Skylight::StaticCubemap, "Static Cubemap", "Uses a static CubemapData" },
- { Skylight::BakedCubemap, "Baked Cubemap", "Uses a cubemap baked from the probe's current position" },
- EndImplementEnumType;
- //-----------------------------------------------------------------------------
- // Object setup and teardown
- //-----------------------------------------------------------------------------
- Skylight::Skylight()
- {
- // Flag this object so that it will always
- // be sent across the network to clients
- mNetFlags.set(Ghostable | ScopeAlways);
- mTypeMask = LightObjectType | MarkerObjectType;
- mReflectionModeType = StaticCubemap;
- mEnabled = true;
- mBake = false;
- mDirty = false;
- mCubemap = NULL;
- mReflectionPath = "";
- mProbeUniqueID = "";
- mEditorShapeInst = NULL;
- mEditorShape = NULL;
- mIrridianceMap = NULL;
- mPrefilterMap = NULL;
- mBrdfTexture = NULL;
- mResourcesCreated = false;
- mPrefilterSize = 512;
- mPrefilterMipLevels = 6;
- mProbeInfo = new ProbeInfo();
- }
- Skylight::~Skylight()
- {
- if (mEditorShapeInst)
- SAFE_DELETE(mEditorShapeInst);
- if (mReflectionModeType != StaticCubemap && mCubemap)
- mCubemap->deleteObject();
- }
- //-----------------------------------------------------------------------------
- // Object Editing
- //-----------------------------------------------------------------------------
- void Skylight::initPersistFields()
- {
- addGroup("Rendering");
- addProtectedField("enabled", TypeBool, Offset(mEnabled, Skylight),
- &_setEnabled, &defaultProtectedGetFn, "Regenerate Voxel Grid");
- endGroup("Rendering");
- addGroup("Reflection");
- //addField("ReflectionMode", TypeSkylightReflectionModeEnum, Offset(mReflectionModeType, Skylight),
- // "The type of mesh data to use for collision queries.");
- //addField("reflectionPath", TypeImageFilename, Offset(mReflectionPath, Skylight),
- // "The type of mesh data to use for collision queries.");
- addField("StaticCubemap", TypeCubemapName, Offset(mCubemapName, Skylight), "Cubemap used instead of reflection texture if fullReflect is off.");
- //addProtectedField("Bake", TypeBool, Offset(mBake, Skylight),
- // &_doBake, &defaultProtectedGetFn, "Regenerate Voxel Grid", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
- endGroup("Reflection");
- Con::addVariable("$Light::renderSkylights", TypeBool, &Skylight::smRenderSkylights,
- "Toggles rendering of light frustums when the light is selected in the editor.\n\n"
- "@note Only works for shadow mapped lights.\n\n"
- "@ingroup Lighting");
- Con::addVariable("$Light::renderPreviewProbes", TypeBool, &Skylight::smRenderPreviewProbes,
- "Toggles rendering of light frustums when the light is selected in the editor.\n\n"
- "@note Only works for shadow mapped lights.\n\n"
- "@ingroup Lighting");
- // SceneObject already handles exposing the transform
- Parent::initPersistFields();
- }
- void Skylight::inspectPostApply()
- {
- Parent::inspectPostApply();
- mDirty = true;
- // Flag the network mask to send the updates
- // to the client object
- setMaskBits(-1);
- }
- bool Skylight::_setEnabled(void *object, const char *index, const char *data)
- {
- Skylight* probe = reinterpret_cast< Skylight* >(object);
- probe->mEnabled = dAtob(data);
- probe->setMaskBits(-1);
- return true;
- }
- bool Skylight::_doBake(void *object, const char *index, const char *data)
- {
- Skylight* probe = reinterpret_cast< Skylight* >(object);
- if (probe->mDirty)
- probe->bake(probe->mReflectionPath, 256);
- return false;
- }
- bool Skylight::onAdd()
- {
- if (!Parent::onAdd())
- return false;
- mObjBox.minExtents.set(-1, -1, -1);
- mObjBox.maxExtents.set(1, 1, 1);
- // Skip our transform... it just dirties mask bits.
- Parent::setTransform(mObjToWorld);
- resetWorldBox();
- // Add this object to the scene
- addToScene();
- if (isServerObject())
- {
- if (!mPersistentId)
- mPersistentId = getOrCreatePersistentId();
- mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
- }
- // Refresh this object's material (if any)
- if (isClientObject())
- updateMaterial();
-
- setMaskBits(-1);
- return true;
- }
- void Skylight::onRemove()
- {
- // Remove this object from the scene
- removeFromScene();
- Parent::onRemove();
- }
- void Skylight::setTransform(const MatrixF & mat)
- {
- // Let SceneObject handle all of the matrix manipulation
- Parent::setTransform(mat);
- mDirty = true;
- // Dirty our network mask so that the new transform gets
- // transmitted to the client object
- setMaskBits(TransformMask);
- }
- U32 Skylight::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
- {
- // Allow the Parent to get a crack at writing its info
- U32 retMask = Parent::packUpdate(conn, mask, stream);
- if (stream->writeFlag(mask & InitialUpdateMask))
- {
- //initial work, just in case?
- }
- // Write our transform information
- if (stream->writeFlag(mask & TransformMask))
- {
- mathWrite(*stream, getTransform());
- mathWrite(*stream, getScale());
- }
- /*if (stream->writeFlag(mask & BakeInfoMask))
- {
- stream->write(mReflectionPath);
- stream->write(mProbeUniqueID);
- }*/
- if (stream->writeFlag(mask & EnabledMask))
- {
- stream->writeFlag(mEnabled);
- }
- /*if (stream->writeFlag(mask & ModeMask))
- {
- stream->write((U32)mReflectionModeType);
- }*/
- if (stream->writeFlag(mask & CubemapMask))
- {
- stream->write(mCubemapName);
- }
- return retMask;
- }
- void Skylight::unpackUpdate(NetConnection *conn, BitStream *stream)
- {
- // Let the Parent read any info it sent
- Parent::unpackUpdate(conn, stream);
- if (stream->readFlag())
- {
- //some initial work?
- createGeometry();
- }
- if (stream->readFlag()) // TransformMask
- {
- mathRead(*stream, &mObjToWorld);
- mathRead(*stream, &mObjScale);
- setTransform(mObjToWorld);
- }
- /*if (stream->readFlag()) // BakeInfoMask
- {
- stream->read(&mReflectionPath);
- stream->read(&mProbeUniqueID);
- }*/
- if (stream->readFlag()) // EnabledMask
- {
- mEnabled = stream->readFlag();
- }
- bool isMaterialDirty = false;
- /*if (stream->readFlag()) // ModeMask
- {
- U32 reflectModeType = StaticCubemap;
- stream->read(&reflectModeType);
- mReflectionModeType = (ReflectionModeType)reflectModeType;
- isMaterialDirty = true;
- }*/
- if (stream->readFlag()) // CubemapMask
- {
- stream->read(&mCubemapName);
- isMaterialDirty = true;
- }
- updateProbeParams();
- if(isMaterialDirty)
- updateMaterial();
- }
- void Skylight::createGeometry()
- {
- // Clean up our previous shape
- if (mEditorShapeInst)
- SAFE_DELETE(mEditorShapeInst);
-
- mEditorShape = NULL;
-
- String shapeFile = "tools/resources/ReflectProbeSphere.dae";
-
- // Attempt to get the resource from the ResourceManager
- mEditorShape = ResourceManager::get().load(shapeFile);
- if (mEditorShape)
- {
- mEditorShapeInst = new TSShapeInstance(mEditorShape, isClientObject());
- }
- }
- //-----------------------------------------------------------------------------
- // Object Rendering
- //-----------------------------------------------------------------------------
- void Skylight::updateProbeParams()
- {
- if (mProbeInfo == nullptr)
- return;
- mProbeInfo->mIntensity = 1;
- mProbeInfo->mAmbient = LinearColorF(0, 0, 0, 0);
- mProbeInfo->mProbeShapeType = ProbeInfo::Sphere;
- mProbeInfo->setPosition(getPosition());
- //Update the bounds
- mObjBox.minExtents.set(-1, -1, -1);
- mObjBox.maxExtents.set(1, 1, 1);
- // Skip our transform... it just dirties mask bits.
- Parent::setTransform(mObjToWorld);
- resetWorldBox();
- F32 visDist = gClientSceneGraph->getVisibleDistance();
- Box3F skylightBounds = Box3F(visDist * 2);
- skylightBounds.setCenter(Point3F::Zero);
- mProbeInfo->setPosition(Point3F::Zero);
- mProbeInfo->mBounds = skylightBounds;
- setGlobalBounds();
- mProbeInfo->mIsSkylight = true;
- mProbeInfo->mScore = -1.0f; //sky comes first
- }
- bool Skylight::createClientResources()
- {
- //irridiance resources
- mIrridianceMap = GFX->createCubemap();
- mIrridianceMap->initDynamic(128, GFXFormatR16G16B16A16F, 1);
- //prefilter resources - we share the irridiance stateblock
- mPrefilterMap = GFX->createCubemap();
- mPrefilterMap->initDynamic(mPrefilterSize, GFXFormatR16G16B16A16F, mPrefilterMipLevels);
- //brdf lookup resources
- //make the brdf lookup texture the same size as the prefilter texture
- mBrdfTexture = TEXMGR->createTexture(mPrefilterSize, mPrefilterSize, GFXFormatR16G16B16A16F, &GFXRenderTargetProfile, 1, 0);
- mResourcesCreated = true;
- return true;
- }
- void Skylight::updateMaterial()
- {
- if ((mReflectionModeType == BakedCubemap) && !mProbeUniqueID.isEmpty())
- {
- bool validCubemap = true;
- char fileName[256];
- dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str());
- Vector<FileName> fileNames;
- if (Platform::isFile(fileName))
- {
- if (!mCubemap)
- {
- mCubemap = new CubemapData();
- mCubemap->registerObject();
- }
- mCubemap->setCubemapFile(FileName(fileName));
- }
- else
- {
- validCubemap = false;
- }
- if (validCubemap)
- {
- if (mCubemap->mCubemap)
- mCubemap->updateFaces();
- else
- mCubemap->createMap();
- mDirty = false;
- mProbeInfo->mCubemap = &mCubemap->mCubemap;
- }
- /*for (U32 i = 0; i < 6; ++i)
- {
- char faceFile[256];
- dSprintf(faceFile, sizeof(faceFile), "%s%s_%i.png", mReflectionPath.c_str(),
- mProbeUniqueID.c_str(), i);
- if (Platform::isFile(faceFile))
- {
- fileNames.push_back(FileName(faceFile));
- }
- else
- {
- validCubemap = false;
- break;
- }
- }
- if (validCubemap)
- {
- if (!mCubemap)
- {
- mCubemap = new CubemapData();
- mCubemap->registerObject();
- }
- for(U32 i=0; i < 6; i++)
- mCubemap->setCubeFaceFile(i, fileNames[i]);
- mCubemap->createMap();
- mCubemap->updateFaces();
- mProbeInfo->mCubemap = &mCubemap->mCubemap;
- }*/
- }
- else if (mReflectionModeType == StaticCubemap && !mCubemapName.isEmpty())
- {
- Sim::findObject(mCubemapName, mCubemap);
- if (!mCubemap)
- return;
- if (mCubemap->mCubemap)
- mCubemap->updateFaces();
- else
- mCubemap->createMap();
- mProbeInfo->mCubemap = &mCubemap->mCubemap;
- }
- //calculateSHTerms();
- generateTextures();
- //Now that the work is done, assign the relevent maps
- if (mPrefilterMap.isValid())
- {
- mProbeInfo->mCubemap = &mPrefilterMap;
- mProbeInfo->mIrradianceCubemap = &mIrridianceMap;
- mProbeInfo->mBRDFTexture = &mBrdfTexture;
- }
- }
- void Skylight::generateTextures()
- {
- if (!mCubemap)
- return;
- if (!mResourcesCreated)
- {
- if (!createClientResources())
- {
- Con::errorf("SkyLight::createIrridianceMap: Failed to create resources");
- return;
- }
- }
- //GFXTransformSaver saver;
- GFXTextureTargetRef renderTarget = GFX->allocRenderToTextureTarget(false);
- IBLUtilities::GenerateIrradianceMap(renderTarget, mCubemap->mCubemap, mIrridianceMap);
- //Write it out
- char fileName[256];
- dSprintf(fileName, 256, "levels/test/irradiance.DDS");
- CubemapSaver::save(mIrridianceMap, fileName);
- if (!Platform::isFile(fileName))
- {
- Con::errorf("Failed to properly save out the skylight baked irradiance!");
- }
- //create prefilter cubemap (radiance)
- IBLUtilities::GeneratePrefilterMap(renderTarget, mCubemap->mCubemap, mPrefilterMipLevels, mPrefilterMap);
- //Write it out
- fileName[256];
- dSprintf(fileName, 256, "levels/test/prefilter.DDS");
- CubemapSaver::save(mPrefilterMap, fileName);
- if (!Platform::isFile(fileName))
- {
- Con::errorf("Failed to properly save out the skylight baked irradiance!");
- }
- //create brdf lookup
- IBLUtilities::GenerateBRDFTexture(mBrdfTexture);
- /*FileStream fs;
- if (fs.open("levels/test/brdf.DDS", Torque::FS::File::Write))
- {
- // Read back the render target, dxt compress it, and write it to disk.
- GBitmap brdfBmp(mBrdfTexture.getHeight(), mBrdfTexture.getWidth(), false, GFXFormatR8G8B8A8);
- mBrdfTexture.copyToBmp(&brdfBmp);
- brdfBmp.extrudeMipLevels();
- DDSFile *brdfDDS = DDSFile::createDDSFileFromGBitmap(&brdfBmp);
- ImageUtil::ddsCompress(brdfDDS, GFXFormatBC1);
- // Write result to file stream
- brdfDDS->write(fs);
- delete brdfDDS;
- }
- fs.close();*/
- }
- void Skylight::prepRenderImage(SceneRenderState *state)
- {
- if (!mEnabled || !Skylight::smRenderSkylights)
- return;
- Point3F distVec = getPosition() - state->getCameraPosition();
- F32 dist = distVec.len();
- //special hook-in for skylights
- Point3F camPos = state->getCameraPosition();
- mProbeInfo->mBounds.setCenter(camPos);
- mProbeInfo->setPosition(camPos);
- //Submit our probe to actually do the probe action
- // Get a handy pointer to our RenderPassmanager
- //RenderPassManager *renderPass = state->getRenderPass();
- PROBEMGR->registerSkylight(mProbeInfo, this);
- if (Skylight::smRenderPreviewProbes && gEditingMission && mEditorShapeInst && mCubemap != nullptr)
- {
- GFXTransformSaver saver;
- // Calculate the distance of this object from the camera
- Point3F cameraOffset;
- getRenderTransform().getColumn(3, &cameraOffset);
- cameraOffset -= state->getDiffuseCameraPosition();
- F32 dist = cameraOffset.len();
- if (dist < 0.01f)
- dist = 0.01f;
- // Set up the LOD for the shape
- F32 invScale = (1.0f / getMax(getMax(mObjScale.x, mObjScale.y), mObjScale.z));
- mEditorShapeInst->setDetailFromDistance(state, dist * invScale);
- // Make sure we have a valid level of detail
- if (mEditorShapeInst->getCurrentDetail() < 0)
- return;
- BaseMatInstance* probePrevMat = mEditorShapeInst->getMaterialList()->getMaterialInst(0);
- setPreviewMatParameters(state, probePrevMat);
- // GFXTransformSaver is a handy helper class that restores
- // the current GFX matrices to their original values when
- // it goes out of scope at the end of the function
- // Set up our TS render state
- TSRenderState rdata;
- rdata.setSceneState(state);
- rdata.setFadeOverride(1.0f);
- // We might have some forward lit materials
- // so pass down a query to gather lights.
- LightQuery query;
- query.init(getWorldSphere());
- rdata.setLightQuery(&query);
- // Set the world matrix to the objects render transform
- MatrixF mat = getRenderTransform();
- mat.scale(Point3F(1, 1, 1));
- GFX->setWorldMatrix(mat);
- // Animate the the shape
- mEditorShapeInst->animate();
- // Allow the shape to submit the RenderInst(s) for itself
- mEditorShapeInst->render(rdata);
- saver.restore();
- }
- // If the light is selected or light visualization
- // is enabled then register the callback.
- const bool isSelectedInEditor = (gEditingMission && isSelected());
- if (isSelectedInEditor)
- {
- }
- }
- void Skylight::setPreviewMatParameters(SceneRenderState* renderState, BaseMatInstance* mat)
- {
- if (!mat->getFeatures().hasFeature(MFT_isDeferred))
- return;
- //Set up the params
- MaterialParameters *matParams = mat->getMaterialParameters();
- //Get the deferred render target
- NamedTexTarget* deferredTexTarget = NamedTexTarget::find("deferred");
- GFXTextureObject *deferredTexObject = deferredTexTarget->getTexture();
- if (!deferredTexObject)
- return;
- GFX->setTexture(0, deferredTexObject);
- //Set the cubemap
- GFX->setCubeTexture(1, mCubemap->mCubemap);
- //Set the invViewMat
- MatrixSet &matrixSet = renderState->getRenderPass()->getMatrixSet();
- const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
- MaterialParameterHandle *invViewMat = mat->getMaterialParameterHandle("$invViewMat");
- matParams->setSafe(invViewMat, worldToCameraXfm);
- }
- DefineEngineMethod(Skylight, postApply, void, (), ,
- "A utility method for forcing a network update.\n")
- {
- object->inspectPostApply();
- }
- void Skylight::bake(String outputPath, S32 resolution)
- {
- GFXDEBUGEVENT_SCOPE(Skylight_Bake, ColorI::WHITE);
- PostEffect *preCapture = dynamic_cast<PostEffect*>(Sim::findObject("AL_PreCapture"));
- PostEffect *deferredShading = dynamic_cast<PostEffect*>(Sim::findObject("AL_DeferredShading"));
- if (preCapture)
- preCapture->enable();
- if (deferredShading)
- deferredShading->disable();
- //if (mReflectionModeType == StaticCubemap || mReflectionModeType == BakedCubemap || mReflectionModeType == SkyLight)
- {
- if (!mCubemap)
- {
- mCubemap = new CubemapData();
- mCubemap->registerObject();
- }
- }
- if (mReflectionModeType == BakedCubemap)
- {
- if (mReflectionPath.isEmpty() || !mPersistentId)
- {
- if (!mPersistentId)
- mPersistentId = getOrCreatePersistentId();
- mReflectionPath = outputPath.c_str();
- mProbeUniqueID = std::to_string(mPersistentId->getUUID().getHash()).c_str();
- }
- }
- bool validCubemap = true;
- // Save the current transforms so we can restore
- // it for child control rendering below.
- GFXTransformSaver saver;
- //bool saveEditingMission = gEditingMission;
- //gEditingMission = false;
- //Set this to true to use the prior method where it goes through the SPT_Reflect path for the bake
- bool probeRenderState = Skylight::smRenderSkylights;
- Skylight::smRenderSkylights = false;
- for (U32 i = 0; i < 6; ++i)
- {
- GFXTexHandle blendTex;
- blendTex.set(resolution, resolution, GFXFormatR8G8B8A8, &GFXRenderTargetProfile, "");
- GFXTextureTargetRef mBaseTarget = GFX->allocRenderToTextureTarget();
- GFX->clearTextureStateImmediate(0);
- mBaseTarget->attachTexture(GFXTextureTarget::Color0, blendTex);
- // Standard view that will be overridden below.
- VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f);
- switch (i)
- {
- case 0: // D3DCUBEMAP_FACE_POSITIVE_X:
- vLookatPt = VectorF(1.0f, 0.0f, 0.0f);
- vUpVec = VectorF(0.0f, 1.0f, 0.0f);
- break;
- case 1: // D3DCUBEMAP_FACE_NEGATIVE_X:
- vLookatPt = VectorF(-1.0f, 0.0f, 0.0f);
- vUpVec = VectorF(0.0f, 1.0f, 0.0f);
- break;
- case 2: // D3DCUBEMAP_FACE_POSITIVE_Y:
- vLookatPt = VectorF(0.0f, 1.0f, 0.0f);
- vUpVec = VectorF(0.0f, 0.0f, -1.0f);
- break;
- case 3: // D3DCUBEMAP_FACE_NEGATIVE_Y:
- vLookatPt = VectorF(0.0f, -1.0f, 0.0f);
- vUpVec = VectorF(0.0f, 0.0f, 1.0f);
- break;
- case 4: // D3DCUBEMAP_FACE_POSITIVE_Z:
- vLookatPt = VectorF(0.0f, 0.0f, 1.0f);
- vUpVec = VectorF(0.0f, 1.0f, 0.0f);
- break;
- case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z:
- vLookatPt = VectorF(0.0f, 0.0f, -1.0f);
- vUpVec = VectorF(0.0f, 1.0f, 0.0f);
- break;
- }
- // create camera matrix
- VectorF cross = mCross(vUpVec, vLookatPt);
- cross.normalizeSafe();
- MatrixF matView(true);
- matView.setColumn(0, cross);
- matView.setColumn(1, vLookatPt);
- matView.setColumn(2, vUpVec);
- matView.setPosition(getPosition());
- matView.inverse();
- // set projection to 90 degrees vertical and horizontal
- F32 left, right, top, bottom;
- F32 nearPlane = 100.f;
- F32 farDist = 10000.f;
- MathUtils::makeFrustum(&left, &right, &top, &bottom, M_HALFPI_F, 1.0f, nearPlane);
- Frustum frustum(false, left, right, top, bottom, nearPlane, farDist);
- renderFrame(&mBaseTarget, matView, frustum, StaticObjectType | StaticShapeObjectType & EDITOR_RENDER_TYPEMASK, ColorI::RED);
- mBaseTarget->resolve();
- mCubemap->setCubeFaceTexture(i, blendTex);
- char fileName[256];
- dSprintf(fileName, 256, "%s%s_%i.png", mReflectionPath.c_str(),
- mProbeUniqueID.c_str(), i);
- FileStream stream;
- if (!stream.open(fileName, Torque::FS::File::Write))
- {
- Con::errorf("ReflectionProbe::bake(): Couldn't open cubemap face file fo writing " + String(fileName));
- if (preCapture)
- preCapture->disable();
- if (deferredShading)
- deferredShading->enable();
- return;
- }
- GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8);
- blendTex->copyToBmp(&bitmap);
- bitmap.writeBitmap("png", stream);
- if (Platform::isFile(fileName) && mCubemap)
- {
- mCubemap->setCubeFaceFile(i, FileName(fileName));
- }
- else
- {
- validCubemap = false;
- break;
- }
- bitmap.deleteImage();
- }
- if (validCubemap)
- {
- if (mCubemap->mCubemap)
- mCubemap->updateFaces();
- else
- mCubemap->createMap();
- char fileName[256];
- dSprintf(fileName, 256, "%s%s.DDS", mReflectionPath.c_str(), mProbeUniqueID.c_str());
- CubemapSaver::save(mCubemap->mCubemap, fileName);
- if (!Platform::isFile(fileName))
- {
- validCubemap = false; //if we didn't save right, just
- Con::errorf("Failed to properly save out the skylight baked cubemap!");
- }
- }
- if (validCubemap)
- {
- mDirty = false;
- //remove the temp files
- for (U32 i = 0; i < 6; i++)
- {
- char fileName[256];
- dSprintf(fileName, 256, "%s%s_%i.png", mReflectionPath.c_str(),
- mProbeUniqueID.c_str(), i);
- Platform::fileDelete(fileName);
- }
- }
- //calculateSHTerms();
- Skylight::smRenderSkylights = probeRenderState;
- setMaskBits(-1);
- if (preCapture)
- preCapture->disable();
- if (deferredShading)
- deferredShading->enable();
- }
- DefineEngineMethod(Skylight, Bake, void, (String outputPath, S32 resolution), ("", 256),
- "@brief returns true if control object is inside the fog\n\n.")
- {
- object->bake(outputPath, resolution);
- }
|