mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Includes a fix to get lights to render more correctly in the reflection pass. Also includes a helper function to force a render from a passed in transform and frustum.
This commit is contained in:
parent
412c0380f4
commit
212fc80dfc
|
|
@ -33,6 +33,8 @@
|
|||
#include "core/module.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "platform/output/IDisplayDevice.h"
|
||||
#include "postFx/postEffectManager.h"
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
|
||||
static void RegisterGameFunctions();
|
||||
static void Process3D();
|
||||
|
|
@ -432,7 +434,197 @@ void GameRenderWorld()
|
|||
PROFILE_END();
|
||||
}
|
||||
|
||||
//================================================================================================
|
||||
//Render a full frame from a given transform and frustum, and render out to a target
|
||||
//================================================================================================
|
||||
void renderFrame(GFXTextureTargetRef* target, MatrixF transform, Frustum frustum, U32 typeMask, ColorI canvasClearColor)
|
||||
{
|
||||
if (!GFX->allowRender() || GFX->canCurrentlyRender())
|
||||
return;
|
||||
|
||||
PROFILE_START(GameFunctions_RenderFrame);
|
||||
|
||||
GFX->setActiveRenderTarget(*target);
|
||||
if (!GFX->getActiveRenderTarget())
|
||||
return;
|
||||
|
||||
GFXTarget* renderTarget = GFX->getActiveRenderTarget();
|
||||
if (renderTarget == NULL)
|
||||
return;
|
||||
|
||||
// Make sure the root control is the size of the canvas.
|
||||
Point2I size = renderTarget->getSize();
|
||||
if (size.x == 0 || size.y == 0)
|
||||
return;
|
||||
|
||||
//Now, getting to the meat of it!
|
||||
#ifdef TORQUE_GFX_STATE_DEBUG
|
||||
GFX->getDebugStateManager()->startFrame();
|
||||
#endif
|
||||
RectI targetRect(0, 0, size.x, size.y);
|
||||
|
||||
// Signal the interested parties.
|
||||
GuiCanvas::getGuiCanvasFrameSignal().trigger(true);
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
||||
// Gross hack to make sure we don't end up with advanced lighting and msaa
|
||||
// at the same time, which causes artifacts. At the same time we don't
|
||||
// want to just throw the settings the user has chosen if the light manager
|
||||
// changes at a later time.
|
||||
/*GFXVideoMode mode = mPlatformWindow->getVideoMode();
|
||||
if (dStricmp(LIGHTMGR->getId(), "ADVLM") == 0 && mode.antialiasLevel > 0)
|
||||
{
|
||||
const char *pref = Con::getVariable("$pref::Video::mode");
|
||||
mode.parseFromString(pref);
|
||||
mode.antialiasLevel = 0;
|
||||
mPlatformWindow->setVideoMode(mode);
|
||||
|
||||
Con::printf("AntiAliasing has been disabled; it is not compatible with AdvancedLighting.");
|
||||
}
|
||||
else if (dStricmp(LIGHTMGR->getId(), "BLM") == 0)
|
||||
{
|
||||
const char *pref = Con::getVariable("$pref::Video::mode");
|
||||
|
||||
U32 prefAA = dAtoi(StringUnit::getUnit(pref, 5, " "));
|
||||
if (prefAA != mode.antialiasLevel)
|
||||
{
|
||||
mode.parseFromString(pref);
|
||||
mPlatformWindow->setVideoMode(mode);
|
||||
|
||||
Con::printf("AntiAliasing has been enabled while running BasicLighting.");
|
||||
}
|
||||
}*/
|
||||
|
||||
// Begin GFX
|
||||
PROFILE_START(GameFunctions_RenderFrame_GFXBeginScene);
|
||||
bool beginSceneRes = GFX->beginScene();
|
||||
PROFILE_END();
|
||||
|
||||
PROFILE_START(GameFunctions_RenderFrame_OffscreenCanvases);
|
||||
|
||||
// Render all offscreen canvas objects here since we may need them in the render loop
|
||||
if (GuiOffscreenCanvas::sList.size() != 0)
|
||||
{
|
||||
// Reset the entire state since oculus shit will have barfed it.
|
||||
GFX->updateStates(true);
|
||||
|
||||
for (Vector<GuiOffscreenCanvas*>::iterator itr = GuiOffscreenCanvas::sList.begin(); itr != GuiOffscreenCanvas::sList.end(); itr++)
|
||||
{
|
||||
(*itr)->renderFrame(false, false);
|
||||
}
|
||||
|
||||
GFX->setActiveRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
PROFILE_END();
|
||||
|
||||
// Can't render if waiting for device to reset.
|
||||
if (!beginSceneRes)
|
||||
{
|
||||
// Since we already triggered the signal once for begin-of-frame,
|
||||
// we should be consistent and trigger it again for end-of-frame.
|
||||
GuiCanvas::getGuiCanvasFrameSignal().trigger(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the current viewport area
|
||||
GFX->setViewport(targetRect);
|
||||
GFX->clear(GFXClearZBuffer | GFXClearStencil | GFXClearTarget, canvasClearColor, 1.0f, 0);
|
||||
|
||||
// Make sure we have a clean matrix state
|
||||
// before we start rendering anything!
|
||||
GFX->setWorldMatrix(MatrixF::Identity);
|
||||
GFX->setViewMatrix(MatrixF::Identity);
|
||||
GFX->setProjectionMatrix(MatrixF::Identity);
|
||||
|
||||
{
|
||||
GFXStateBlockDesc d;
|
||||
|
||||
d.cullDefined = true;
|
||||
d.cullMode = GFXCullNone;
|
||||
d.zDefined = true;
|
||||
d.zEnable = false;
|
||||
|
||||
GFXStateBlockRef mDefaultGuiSB = GFX->createStateBlock(d);
|
||||
|
||||
GFX->setClipRect(targetRect);
|
||||
GFX->setStateBlock(mDefaultGuiSB);
|
||||
|
||||
GFXTargetRef origTarget = GFX->getActiveRenderTarget();
|
||||
U32 origStyle = GFX->getCurrentRenderStyle();
|
||||
|
||||
// Clear the zBuffer so GUI doesn't hose object rendering accidentally
|
||||
GFX->clear(GFXClearZBuffer, ColorI(20, 20, 20), 1.0f, 0);
|
||||
|
||||
GFX->setFrustum(frustum);
|
||||
MatrixF mSaveProjection = GFX->getProjectionMatrix();
|
||||
|
||||
// We're going to be displaying this render at size of this control in
|
||||
// pixels - let the scene know so that it can calculate e.g. reflections
|
||||
// correctly for that final display result.
|
||||
gClientSceneGraph->setDisplayTargetResolution(size);
|
||||
|
||||
// Set the GFX world matrix to the world-to-camera transform, but don't
|
||||
// change the cameraMatrix in mLastCameraQuery. This is because
|
||||
// mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world
|
||||
// transform. In-place invert would save a copy but mess up any GUIs that
|
||||
// depend on that value.
|
||||
CameraQuery camera;
|
||||
GameProcessCameraQuery(&camera);
|
||||
|
||||
MatrixF worldToCamera = transform;
|
||||
|
||||
RotationF tranRot = RotationF(transform);
|
||||
EulerF trf = tranRot.asEulerF(RotationF::Degrees);
|
||||
Point3F pos = transform.getPosition();
|
||||
|
||||
GFX->setWorldMatrix(worldToCamera);
|
||||
|
||||
mSaveProjection = GFX->getProjectionMatrix();
|
||||
MatrixF mSaveModelview = GFX->getWorldMatrix();
|
||||
|
||||
Point2F mSaveWorldToScreenScale = GFX->getWorldToScreenScale();
|
||||
Frustum mSaveFrustum = GFX->getFrustum();
|
||||
mSaveFrustum.setTransform(transform);
|
||||
|
||||
// Set the default non-clip projection as some
|
||||
// objects depend on this even in non-reflect cases.
|
||||
gClientSceneGraph->setNonClipProjection(mSaveProjection);
|
||||
|
||||
// Give the post effect manager the worldToCamera, and cameraToScreen matrices
|
||||
PFXMGR->setFrameMatrices(mSaveModelview, mSaveProjection);
|
||||
|
||||
//renderWorld(guiViewport);
|
||||
PROFILE_START(GameFunctions_RenderFrame_RenderWorld);
|
||||
FrameAllocator::setWaterMark(0);
|
||||
|
||||
gClientSceneGraph->renderScene(SPT_Reflect, typeMask);
|
||||
|
||||
// renderScene leaves some states dirty, which causes problems if GameTSCtrl is the last Gui object rendered
|
||||
GFX->updateStates();
|
||||
|
||||
AssertFatal(FrameAllocator::getWaterMark() == 0,
|
||||
"Error, someone didn't reset the water mark on the frame allocator!");
|
||||
FrameAllocator::setWaterMark(0);
|
||||
PROFILE_END();
|
||||
}
|
||||
|
||||
PROFILE_START(GameFunctions_RenderFrame_GFXEndScene);
|
||||
GFX->endScene();
|
||||
PROFILE_END();
|
||||
|
||||
#ifdef TORQUE_GFX_STATE_DEBUG
|
||||
GFX->getDebugStateManager()->endFrame();
|
||||
#endif
|
||||
|
||||
saver.restore();
|
||||
|
||||
PROFILE_END();
|
||||
}
|
||||
|
||||
//================================================================================================
|
||||
static void Process3D()
|
||||
{
|
||||
MATMGR->updateTime();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,15 @@
|
|||
#ifndef _MMATRIX_H_
|
||||
#include "math/mMatrix.h"
|
||||
#endif
|
||||
#ifndef _GFXTARGET_H_
|
||||
#include "gfx/gfxTarget.h"
|
||||
#endif
|
||||
#ifndef _MATHUTIL_FRUSTUM_H_
|
||||
#include "math/util/frustum.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
|
||||
struct CameraQuery;
|
||||
|
||||
|
|
@ -37,6 +46,10 @@ struct CameraQuery;
|
|||
/// scene ONLY - new guis, no damage flashes.
|
||||
void GameRenderWorld();
|
||||
|
||||
/// Does a full, top-to-bottom call to render a frame. This does all the setup to make a render happen
|
||||
/// Allowing setting of a intended render target, a view transform, the view frustum, resolution, objects-to-render typemask, and the clear color
|
||||
void renderFrame(GFXTextureTargetRef* target, MatrixF transform, Frustum frustum, U32 typeMask, ColorI canvasClearColor);
|
||||
|
||||
/// Renders overlays such as damage flashes, white outs, and water masks.
|
||||
/// These are usually a color applied over the entire screen.
|
||||
void GameRenderFilters(const CameraQuery& camq);
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
|
|||
sgData.init( state );
|
||||
|
||||
// There are cases where shadow rendering is disabled.
|
||||
const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;
|
||||
const bool disableShadows = /*state->isReflectPass() || */ShadowMapPass::smDisableShadows;
|
||||
|
||||
// Pick the right material for rendering the sunlight... we only
|
||||
// cast shadows when its enabled and we're not in a reflection.
|
||||
|
|
@ -300,6 +300,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
|
|||
GFX->setVertexBuffer( mFarFrustumQuadVerts );
|
||||
GFX->setPrimitiveBuffer( NULL );
|
||||
|
||||
vectorMatInfo->matInstance->mSpecialLight = true;
|
||||
|
||||
// Render the material passes
|
||||
while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
|
||||
{
|
||||
|
|
@ -337,6 +339,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
|
|||
|
||||
lsp->getOcclusionQuery()->begin();
|
||||
|
||||
curLightMat->matInstance->mSpecialLight = false;
|
||||
|
||||
// Render the material passes
|
||||
while( curLightMat->matInstance->setupPass( state, sgData ) )
|
||||
{
|
||||
|
|
@ -497,6 +501,17 @@ void AdvancedLightBinManager::_setupPerFrameParameters( const SceneRenderState *
|
|||
farPlane,
|
||||
vsFarPlane);
|
||||
}
|
||||
|
||||
MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
|
||||
//matrixSet.restoreSceneViewProjection();
|
||||
|
||||
const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
|
||||
|
||||
MatrixF inverseViewMatrix = worldToCameraXfm;
|
||||
//inverseViewMatrix.fullInverse();
|
||||
//inverseViewMatrix.transpose();
|
||||
|
||||
//MatrixF inverseViewMatrix = MatrixF::Identity;
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light )
|
||||
|
|
@ -747,6 +762,10 @@ bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgDa
|
|||
mProcessedMaterial->getNumPasses() == 0 )
|
||||
return false;
|
||||
|
||||
U32 reflectStatus = Base;
|
||||
if (state->isReflectPass())
|
||||
reflectStatus = Reflecting;
|
||||
|
||||
// Fetch the lightmap params
|
||||
const LightMapParams *lmParams = sgData.lights[0]->getExtended<LightMapParams>();
|
||||
|
||||
|
|
@ -795,14 +814,21 @@ bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgDa
|
|||
{
|
||||
// If this is not an internal pass, and this light is represented in lightmaps
|
||||
// than only effect non-lightmapped geometry for this pass
|
||||
if(lmParams->representedInLightmap)
|
||||
GFX->setStateBlock(mLitState[StaticLightNonLMGeometry]);
|
||||
if (lmParams->representedInLightmap)
|
||||
{
|
||||
GFX->setStateBlock(mLitState[StaticLightNonLMGeometry][reflectStatus]);
|
||||
}
|
||||
else // This is a normal, dynamic light.
|
||||
GFX->setStateBlock(mLitState[DynamicLight]);
|
||||
|
||||
{
|
||||
if (mSpecialLight)
|
||||
GFX->setStateBlock(mLitState[SunLight][reflectStatus]);
|
||||
else
|
||||
GFX->setStateBlock(mLitState[DynamicLight][reflectStatus]);
|
||||
}
|
||||
|
||||
}
|
||||
else // Internal pass, this is the add-specular/multiply-darken-color pass
|
||||
GFX->setStateBlock(mLitState[StaticLightLMGeometry]);
|
||||
GFX->setStateBlock(mLitState[StaticLightLMGeometry][reflectStatus]);
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
|
@ -832,17 +858,32 @@ bool LightMatInstance::init( const FeatureSet &features, const GFXVertexFormat *
|
|||
|
||||
//DynamicLight State: This will effect lightmapped and non-lightmapped geometry
|
||||
// in the same way.
|
||||
|
||||
litState.separateAlphaBlendDefined = true;
|
||||
litState.separateAlphaBlendEnable = false;
|
||||
litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask | RenderDeferredMgr::OpaqueStaticLitMask;
|
||||
mLitState[DynamicLight] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCW);
|
||||
mLitState[DynamicLight][Base] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCCW);
|
||||
mLitState[DynamicLight][Reflecting] = GFX->createStateBlock(litState);
|
||||
|
||||
litState.separateAlphaBlendDefined = true;
|
||||
litState.separateAlphaBlendEnable = false;
|
||||
litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask | RenderDeferredMgr::OpaqueStaticLitMask;
|
||||
litState.setCullMode(GFXCullCCW);
|
||||
mLitState[SunLight][Base] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCCW);
|
||||
mLitState[SunLight][Reflecting] = GFX->createStateBlock(litState);
|
||||
|
||||
// StaticLightNonLMGeometry State: This will treat non-lightmapped geometry
|
||||
// in the usual way, but will not effect lightmapped geometry.
|
||||
litState.separateAlphaBlendDefined = true;
|
||||
litState.separateAlphaBlendEnable = false;
|
||||
litState.stencilMask = RenderDeferredMgr::OpaqueDynamicLitMask;
|
||||
mLitState[StaticLightNonLMGeometry] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCW);
|
||||
mLitState[StaticLightNonLMGeometry][Base] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCCW);
|
||||
mLitState[StaticLightNonLMGeometry][Reflecting] = GFX->createStateBlock(litState);
|
||||
|
||||
// StaticLightLMGeometry State: This will add specular information (alpha) but
|
||||
// multiply-darken color information.
|
||||
|
|
@ -854,7 +895,10 @@ bool LightMatInstance::init( const FeatureSet &features, const GFXVertexFormat *
|
|||
litState.separateAlphaBlendSrc = GFXBlendOne;
|
||||
litState.separateAlphaBlendDest = GFXBlendOne;
|
||||
litState.separateAlphaBlendOp = GFXBlendOpAdd;
|
||||
mLitState[StaticLightLMGeometry] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCW);
|
||||
mLitState[StaticLightLMGeometry][Base] = GFX->createStateBlock(litState);
|
||||
litState.setCullMode(GFXCullCCW);
|
||||
mLitState[StaticLightLMGeometry][Reflecting] = GFX->createStateBlock(litState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,19 +60,23 @@ protected:
|
|||
enum
|
||||
{
|
||||
DynamicLight = 0,
|
||||
SunLight,
|
||||
StaticLightNonLMGeometry,
|
||||
StaticLightLMGeometry,
|
||||
NUM_LIT_STATES
|
||||
NUM_LIT_STATES,
|
||||
Base = 0,
|
||||
Reflecting = 1
|
||||
};
|
||||
GFXStateBlockRef mLitState[NUM_LIT_STATES];
|
||||
GFXStateBlockRef mLitState[NUM_LIT_STATES][2];
|
||||
|
||||
public:
|
||||
LightMatInstance(Material &mat) : Parent(mat), mLightMapParamsSC(NULL), mInternalPass(false) {}
|
||||
|
||||
virtual bool init( const FeatureSet &features, const GFXVertexFormat *vertexFormat );
|
||||
virtual bool setupPass( SceneRenderState *state, const SceneData &sgData );
|
||||
};
|
||||
|
||||
bool mSpecialLight;
|
||||
};
|
||||
|
||||
class AdvancedLightBinManager : public RenderTexTargetBinManager
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue