mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 15:14:35 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
855
Engine/source/lighting/advanced/advancedLightBinManager.cpp
Normal file
855
Engine/source/lighting/advanced/advancedLightBinManager.cpp
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/advancedLightBinManager.h"
|
||||
|
||||
#include "lighting/advanced/advancedLightManager.h"
|
||||
#include "lighting/advanced/advancedLightBufferConditioner.h"
|
||||
#include "lighting/shadowMap/shadowMapManager.h"
|
||||
#include "lighting/shadowMap/shadowMapPass.h"
|
||||
#include "lighting/shadowMap/lightShadowMap.h"
|
||||
#include "lighting/common/lightMapParams.h"
|
||||
#include "renderInstance/renderPrePassMgr.h"
|
||||
#include "gfx/gfxTransformSaver.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "materials/sceneData.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "core/util/rgb2luv.h"
|
||||
#include "gfx/gfxDebugEvent.h"
|
||||
#include "math/util/matrixSet.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
|
||||
const RenderInstType AdvancedLightBinManager::RIT_LightInfo( "LightInfo" );
|
||||
const String AdvancedLightBinManager::smBufferName( "lightinfo" );
|
||||
|
||||
ShadowFilterMode AdvancedLightBinManager::smShadowFilterMode = ShadowFilterMode_SoftShadowHighQuality;
|
||||
bool AdvancedLightBinManager::smPSSMDebugRender = false;
|
||||
bool AdvancedLightBinManager::smUseSSAOMask = false;
|
||||
|
||||
|
||||
ImplementEnumType( ShadowFilterMode,
|
||||
"The shadow filtering modes for Advanced Lighting shadows.\n"
|
||||
"@ingroup AdvancedLighting" )
|
||||
|
||||
{ ShadowFilterMode_None, "None",
|
||||
"@brief Simple point sampled filtering.\n"
|
||||
"This is the fastest and lowest quality mode." },
|
||||
|
||||
{ ShadowFilterMode_SoftShadow, "SoftShadow",
|
||||
"@brief A variable tap rotated poisson disk soft shadow filter.\n"
|
||||
"It performs 4 taps to classify the point as in shadow, out of shadow, or along a "
|
||||
"shadow edge. Samples on the edge get an additional 8 taps to soften them." },
|
||||
|
||||
{ ShadowFilterMode_SoftShadowHighQuality, "SoftShadowHighQuality",
|
||||
"@brief A 12 tap rotated poisson disk soft shadow filter.\n"
|
||||
"It performs all the taps for every point without any early rejection." },
|
||||
|
||||
EndImplementEnumType;
|
||||
|
||||
// NOTE: The order here matches that of the LightInfo::Type enum.
|
||||
const String AdvancedLightBinManager::smLightMatNames[] =
|
||||
{
|
||||
"AL_PointLightMaterial", // LightInfo::Point
|
||||
"AL_SpotLightMaterial", // LightInfo::Spot
|
||||
"AL_VectorLightMaterial", // LightInfo::Vector
|
||||
"", // LightInfo::Ambient
|
||||
};
|
||||
|
||||
// NOTE: The order here matches that of the LightInfo::Type enum.
|
||||
const GFXVertexFormat* AdvancedLightBinManager::smLightMatVertex[] =
|
||||
{
|
||||
getGFXVertexFormat<AdvancedLightManager::LightVertex>(), // LightInfo::Point
|
||||
getGFXVertexFormat<AdvancedLightManager::LightVertex>(), // LightInfo::Spot
|
||||
getGFXVertexFormat<FarFrustumQuadVert>(), // LightInfo::Vector
|
||||
NULL, // LightInfo::Ambient
|
||||
};
|
||||
|
||||
// NOTE: The order here matches that of the ShadowType enum.
|
||||
const String AdvancedLightBinManager::smShadowTypeMacro[] =
|
||||
{
|
||||
"", // ShadowType_Spot
|
||||
"", // ShadowType_PSSM,
|
||||
"SHADOW_PARABOLOID", // ShadowType_Paraboloid,
|
||||
"SHADOW_DUALPARABOLOID_SINGLE_PASS", // ShadowType_DualParaboloidSinglePass,
|
||||
"SHADOW_DUALPARABOLOID", // ShadowType_DualParaboloid,
|
||||
"SHADOW_CUBE", // ShadowType_CubeMap,
|
||||
};
|
||||
|
||||
AdvancedLightBinManager::RenderSignal &AdvancedLightBinManager::getRenderSignal()
|
||||
{
|
||||
static RenderSignal theSignal;
|
||||
return theSignal;
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(AdvancedLightBinManager);
|
||||
|
||||
ConsoleDocClass( AdvancedLightBinManager,
|
||||
"@brief Rendering Manager responsible for lighting, shadows, and global variables affecing both.\n\n"
|
||||
|
||||
"Should not be exposed to TorqueScript as a game object, meant for internal use only\n\n"
|
||||
|
||||
"@ingroup Lighting"
|
||||
);
|
||||
|
||||
AdvancedLightBinManager::AdvancedLightBinManager( AdvancedLightManager *lm /* = NULL */,
|
||||
ShadowMapManager *sm /* = NULL */,
|
||||
GFXFormat lightBufferFormat /* = GFXFormatR8G8B8A8 */ )
|
||||
: RenderTexTargetBinManager( RIT_LightInfo, 1.0f, 1.0f, lightBufferFormat ),
|
||||
mNumLightsCulled(0),
|
||||
mLightManager(lm),
|
||||
mShadowManager(sm),
|
||||
mConditioner(NULL)
|
||||
{
|
||||
// Create an RGB conditioner
|
||||
mConditioner = new AdvancedLightBufferConditioner( getTargetFormat(),
|
||||
AdvancedLightBufferConditioner::RGB );
|
||||
mNamedTarget.setConditioner( mConditioner );
|
||||
mNamedTarget.registerWithName( smBufferName );
|
||||
|
||||
// We want a full-resolution buffer
|
||||
mTargetSizeType = RenderTexTargetBinManager::WindowSize;
|
||||
|
||||
mMRTLightmapsDuringPrePass = false;
|
||||
|
||||
Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials );
|
||||
Con::addVariableNotify( "$pref::Shadows::filterMode", callback );
|
||||
Con::addVariableNotify( "$AL::PSSMDebugRender", callback );
|
||||
Con::addVariableNotify( "$AL::UseSSAOMask", callback );
|
||||
}
|
||||
|
||||
|
||||
AdvancedLightBinManager::~AdvancedLightBinManager()
|
||||
{
|
||||
_deleteLightMaterials();
|
||||
|
||||
SAFE_DELETE(mConditioner);
|
||||
|
||||
Con::NotifyDelegate callback( this, &AdvancedLightBinManager::_deleteLightMaterials );
|
||||
Con::removeVariableNotify( "$pref::shadows::filterMode", callback );
|
||||
Con::removeVariableNotify( "$AL::PSSMDebugRender", callback );
|
||||
Con::removeVariableNotify( "$AL::UseSSAOMask", callback );
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
Con::addVariable( "$pref::shadows::filterMode",
|
||||
TYPEID<ShadowFilterMode>(), &smShadowFilterMode,
|
||||
"The filter mode to use for shadows.\n"
|
||||
"@ingroup AdvancedLighting\n" );
|
||||
|
||||
Con::addVariable( "$AL::UseSSAOMask", TypeBool, &smUseSSAOMask,
|
||||
"Used by the SSAO PostEffect to toggle the sampling of ssaomask "
|
||||
"texture by the light shaders.\n"
|
||||
"@ingroup AdvancedLighting\n" );
|
||||
|
||||
Con::addVariable( "$AL::PSSMDebugRender", TypeBool, &smPSSMDebugRender,
|
||||
"Enables debug rendering of the PSSM shadows.\n"
|
||||
"@ingroup AdvancedLighting\n" );
|
||||
}
|
||||
|
||||
bool AdvancedLightBinManager::setTargetSize(const Point2I &newTargetSize)
|
||||
{
|
||||
bool ret = Parent::setTargetSize( newTargetSize );
|
||||
|
||||
// We require the viewport to match the default.
|
||||
mNamedTarget.setViewport( GFX->getViewport() );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::addLight( LightInfo *light )
|
||||
{
|
||||
// Get the light type.
|
||||
const LightInfo::Type lightType = light->getType();
|
||||
|
||||
AssertFatal( lightType == LightInfo::Point ||
|
||||
lightType == LightInfo::Spot, "Bogus light type." );
|
||||
|
||||
// Find a shadow map for this light, if it has one
|
||||
ShadowMapParams *lsp = light->getExtended<ShadowMapParams>();
|
||||
LightShadowMap *lsm = lsp->getShadowMap();
|
||||
|
||||
// Get the right shadow type.
|
||||
ShadowType shadowType = ShadowType_None;
|
||||
if ( light->getCastShadows() &&
|
||||
lsm && lsm->hasShadowTex() &&
|
||||
!ShadowMapPass::smDisableShadows )
|
||||
shadowType = lsm->getShadowType();
|
||||
|
||||
// Add the entry
|
||||
LightBinEntry lEntry;
|
||||
lEntry.lightInfo = light;
|
||||
lEntry.shadowMap = lsm;
|
||||
lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex() );
|
||||
|
||||
if( lightType == LightInfo::Spot )
|
||||
lEntry.vertBuffer = mLightManager->getConeMesh( lEntry.numPrims, lEntry.primBuffer );
|
||||
else
|
||||
lEntry.vertBuffer = mLightManager->getSphereMesh( lEntry.numPrims, lEntry.primBuffer );
|
||||
|
||||
// If it's a point light, push front, spot
|
||||
// light, push back. This helps batches.
|
||||
Vector<LightBinEntry> &curBin = mLightBin;
|
||||
if ( light->getType() == LightInfo::Point )
|
||||
curBin.push_front( lEntry );
|
||||
else
|
||||
curBin.push_back( lEntry );
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::clear()
|
||||
{
|
||||
Con::setIntVariable("lightMetrics::activeLights", mLightBin.size());
|
||||
Con::setIntVariable("lightMetrics::culledLights", mNumLightsCulled);
|
||||
|
||||
mLightBin.clear();
|
||||
mNumLightsCulled = 0;
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::render( SceneRenderState *state )
|
||||
{
|
||||
PROFILE_SCOPE( AdvancedLightManager_Render );
|
||||
|
||||
// Take a look at the SceneRenderState and see if we should skip drawing the pre-pass
|
||||
if( state->disableAdvancedLightingBins() )
|
||||
return;
|
||||
|
||||
// Automagically save & restore our viewport and transforms.
|
||||
GFXTransformSaver saver;
|
||||
|
||||
if( !mLightManager )
|
||||
return;
|
||||
|
||||
// Get the sunlight. If there's no sun, and no lights in the bins, no draw
|
||||
LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType );
|
||||
if( !sunLight && mLightBin.empty() )
|
||||
return;
|
||||
|
||||
GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render, ColorI::RED );
|
||||
|
||||
// Tell the superclass we're about to render
|
||||
if ( !_onPreRender( state ) )
|
||||
return;
|
||||
|
||||
// Clear as long as there isn't MRT population of light buffer with lightmap data
|
||||
if ( !MRTLightmapsDuringPrePass() )
|
||||
GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);
|
||||
|
||||
// Restore transforms
|
||||
MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
|
||||
matrixSet.restoreSceneViewProjection();
|
||||
|
||||
const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();
|
||||
|
||||
// Set up the SG Data
|
||||
SceneData sgData;
|
||||
sgData.init( state );
|
||||
|
||||
// There are cases where shadow rendering is disabled.
|
||||
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.
|
||||
LightMaterialInfo *vectorMatInfo;
|
||||
if ( sunLight &&
|
||||
sunLight->getCastShadows() &&
|
||||
!disableShadows &&
|
||||
sunLight->getExtended<ShadowMapParams>() )
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM, false );
|
||||
else
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None, false );
|
||||
|
||||
// Initialize and set the per-frame parameters after getting
|
||||
// the vector light material as we use lazy creation.
|
||||
_setupPerFrameParameters( state );
|
||||
|
||||
// Draw sunlight/ambient
|
||||
if ( sunLight && vectorMatInfo )
|
||||
{
|
||||
GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Sunlight, ColorI::RED );
|
||||
|
||||
// Set up SG data
|
||||
setupSGData( sgData, state, sunLight );
|
||||
vectorMatInfo->setLightParameters( sunLight, state, worldToCameraXfm );
|
||||
|
||||
// Set light holds the active shadow map.
|
||||
mShadowManager->setLightShadowMapForLight( sunLight );
|
||||
|
||||
// Set geometry
|
||||
GFX->setVertexBuffer( mFarFrustumQuadVerts );
|
||||
GFX->setPrimitiveBuffer( NULL );
|
||||
|
||||
// Render the material passes
|
||||
while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
|
||||
{
|
||||
vectorMatInfo->matInstance->setSceneInfo( state, sgData );
|
||||
vectorMatInfo->matInstance->setTransforms( matrixSet, state );
|
||||
GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
// Blend the lights in the bin to the light buffer
|
||||
for( LightBinIterator itr = mLightBin.begin(); itr != mLightBin.end(); itr++ )
|
||||
{
|
||||
LightBinEntry& curEntry = *itr;
|
||||
LightInfo *curLightInfo = curEntry.lightInfo;
|
||||
LightMaterialInfo *curLightMat = curEntry.lightMaterial;
|
||||
const U32 numPrims = curEntry.numPrims;
|
||||
const U32 numVerts = curEntry.vertBuffer->mNumVerts;
|
||||
|
||||
// Skip lights which won't affect the scene.
|
||||
if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f )
|
||||
continue;
|
||||
|
||||
GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Light, ColorI::RED );
|
||||
|
||||
setupSGData( sgData, state, curLightInfo );
|
||||
curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
|
||||
mShadowManager->setLightShadowMap( curEntry.shadowMap );
|
||||
|
||||
// Let the shadow know we're about to render from it.
|
||||
if ( curEntry.shadowMap )
|
||||
curEntry.shadowMap->preLightRender();
|
||||
|
||||
// Set geometry
|
||||
GFX->setVertexBuffer( curEntry.vertBuffer );
|
||||
GFX->setPrimitiveBuffer( curEntry.primBuffer );
|
||||
|
||||
// Render the material passes
|
||||
while( curLightMat->matInstance->setupPass( state, sgData ) )
|
||||
{
|
||||
// Set transforms
|
||||
matrixSet.setWorld(*sgData.objTrans);
|
||||
curLightMat->matInstance->setTransforms(matrixSet, state);
|
||||
curLightMat->matInstance->setSceneInfo(state, sgData);
|
||||
|
||||
if(curEntry.primBuffer)
|
||||
GFX->drawIndexedPrimitive(GFXTriangleList, 0, 0, numVerts, 0, numPrims);
|
||||
else
|
||||
GFX->drawPrimitive(GFXTriangleList, 0, numPrims);
|
||||
}
|
||||
|
||||
// Tell it we're done rendering.
|
||||
if ( curEntry.shadowMap )
|
||||
curEntry.shadowMap->postLightRender();
|
||||
}
|
||||
|
||||
// Set NULL for active shadow map (so nothing gets confused)
|
||||
mShadowManager->setLightShadowMap(NULL);
|
||||
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);
|
||||
|
||||
// Finish up the rendering
|
||||
_onPostRender();
|
||||
}
|
||||
|
||||
AdvancedLightBinManager::LightMaterialInfo* AdvancedLightBinManager::_getLightMaterial( LightInfo::Type lightType,
|
||||
ShadowType shadowType,
|
||||
bool useCookieTex )
|
||||
{
|
||||
PROFILE_SCOPE( AdvancedLightBinManager_GetLightMaterial );
|
||||
|
||||
// Build the key.
|
||||
const LightMatKey key( lightType, shadowType, useCookieTex );
|
||||
|
||||
// See if we've already built this one.
|
||||
LightMatTable::Iterator iter = mLightMaterials.find( key );
|
||||
if ( iter != mLightMaterials.end() )
|
||||
return iter->value;
|
||||
|
||||
// If we got here we need to build a material for
|
||||
// this light+shadow combination.
|
||||
|
||||
LightMaterialInfo *info = NULL;
|
||||
|
||||
// First get the light material name and make sure
|
||||
// this light has a material in the first place.
|
||||
const String &lightMatName = smLightMatNames[ lightType ];
|
||||
if ( lightMatName.isNotEmpty() )
|
||||
{
|
||||
Vector<GFXShaderMacro> shadowMacros;
|
||||
|
||||
// Setup the shadow type macros for this material.
|
||||
if ( shadowType == ShadowType_None )
|
||||
shadowMacros.push_back( GFXShaderMacro( "NO_SHADOW" ) );
|
||||
else
|
||||
{
|
||||
shadowMacros.push_back( GFXShaderMacro( smShadowTypeMacro[ shadowType ] ) );
|
||||
|
||||
// Do we need to do shadow filtering?
|
||||
if ( smShadowFilterMode != ShadowFilterMode_None )
|
||||
{
|
||||
shadowMacros.push_back( GFXShaderMacro( "SOFTSHADOW" ) );
|
||||
|
||||
const F32 SM = GFX->getPixelShaderVersion();
|
||||
if ( SM >= 3.0f && smShadowFilterMode == ShadowFilterMode_SoftShadowHighQuality )
|
||||
shadowMacros.push_back( GFXShaderMacro( "SOFTSHADOW_HIGH_QUALITY" ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( useCookieTex )
|
||||
shadowMacros.push_back( GFXShaderMacro( "USE_COOKIE_TEX" ) );
|
||||
|
||||
// Its safe to add the PSSM debug macro to all the materials.
|
||||
if ( smPSSMDebugRender )
|
||||
shadowMacros.push_back( GFXShaderMacro( "PSSM_DEBUG_RENDER" ) );
|
||||
|
||||
// If its a vector light see if we can enable SSAO.
|
||||
if ( lightType == LightInfo::Vector && smUseSSAOMask )
|
||||
shadowMacros.push_back( GFXShaderMacro( "USE_SSAO_MASK" ) );
|
||||
|
||||
// Now create the material info object.
|
||||
info = new LightMaterialInfo( lightMatName, smLightMatVertex[ lightType ], shadowMacros );
|
||||
}
|
||||
|
||||
// Push this into the map and return it.
|
||||
mLightMaterials.insertUnique( key, info );
|
||||
return info;
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::_deleteLightMaterials()
|
||||
{
|
||||
LightMatTable::Iterator iter = mLightMaterials.begin();
|
||||
for ( ; iter != mLightMaterials.end(); iter++ )
|
||||
delete iter->value;
|
||||
|
||||
mLightMaterials.clear();
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::_setupPerFrameParameters( const SceneRenderState *state )
|
||||
{
|
||||
PROFILE_SCOPE( AdvancedLightBinManager_SetupPerFrameParameters );
|
||||
const Frustum &frustum = state->getFrustum();
|
||||
|
||||
MatrixF invCam( frustum.getTransform() );
|
||||
invCam.inverse();
|
||||
|
||||
const Point3F *wsFrustumPoints = frustum.getPoints();
|
||||
const Point3F& cameraPos = frustum.getPosition();
|
||||
|
||||
// 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::FarBottomLeft] - cameraPos );
|
||||
invCam.mulP( wsFrustumPoints[Frustum::FarBottomLeft], &verts[0].normal );
|
||||
verts[0].texCoord.set( -1.0, -1.0 );
|
||||
|
||||
verts[1].point.set( wsFrustumPoints[Frustum::FarTopLeft] - cameraPos );
|
||||
invCam.mulP( wsFrustumPoints[Frustum::FarTopLeft], &verts[1].normal );
|
||||
verts[1].texCoord.set( -1.0, 1.0 );
|
||||
|
||||
verts[2].point.set( wsFrustumPoints[Frustum::FarTopRight] - cameraPos );
|
||||
invCam.mulP( wsFrustumPoints[Frustum::FarTopRight], &verts[2].normal );
|
||||
verts[2].texCoord.set( 1.0, 1.0 );
|
||||
|
||||
verts[3].point.set( wsFrustumPoints[Frustum::FarBottomRight] - cameraPos );
|
||||
invCam.mulP( wsFrustumPoints[Frustum::FarBottomRight], &verts[3].normal );
|
||||
verts[3].texCoord.set( 1.0, -1.0 );
|
||||
}
|
||||
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);
|
||||
|
||||
// Parameters calculated, assign them to the materials
|
||||
LightMatTable::Iterator iter = mLightMaterials.begin();
|
||||
for ( ; iter != mLightMaterials.end(); iter++ )
|
||||
{
|
||||
if ( iter->value )
|
||||
iter->value->setViewParameters( frustum.getNearDist(),
|
||||
frustum.getFarDist(),
|
||||
frustum.getPosition(),
|
||||
farPlane,
|
||||
vsFarPlane);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light )
|
||||
{
|
||||
PROFILE_SCOPE( AdvancedLightBinManager_setupSGData );
|
||||
|
||||
data.lights[0] = light;
|
||||
data.ambientLightColor = state->getAmbientLightColor();
|
||||
data.objTrans = &MatrixF::Identity;
|
||||
|
||||
if ( light )
|
||||
{
|
||||
if ( light->getType() == LightInfo::Point )
|
||||
{
|
||||
// The point light volume gets some flat spots along
|
||||
// the perimiter mostly visible in the constant and
|
||||
// quadradic falloff modes.
|
||||
//
|
||||
// To account for them slightly increase the scale
|
||||
// instead of greatly increasing the polycount.
|
||||
|
||||
mLightMat = light->getTransform();
|
||||
mLightMat.scale( light->getRange() * 1.01f );
|
||||
data.objTrans = &mLightMat;
|
||||
}
|
||||
else if ( light->getType() == LightInfo::Spot )
|
||||
{
|
||||
mLightMat = light->getTransform();
|
||||
|
||||
// Rotate it to face down the -y axis.
|
||||
MatrixF scaleRotateTranslate( EulerF( M_PI_F / -2.0f, 0.0f, 0.0f ) );
|
||||
|
||||
// Calculate the radius based on the range and angle.
|
||||
F32 range = light->getRange().x;
|
||||
F32 radius = range * mSin( mDegToRad( light->getOuterConeAngle() ) * 0.5f );
|
||||
|
||||
// NOTE: This fudge makes the cone a little bigger
|
||||
// to remove the facet egde of the cone geometry.
|
||||
radius *= 1.1f;
|
||||
|
||||
// Use the scale to distort the cone to
|
||||
// match our radius and range.
|
||||
scaleRotateTranslate.scale( Point3F( radius, radius, range ) );
|
||||
|
||||
// Apply the transform and set the position.
|
||||
mLightMat *= scaleRotateTranslate;
|
||||
mLightMat.setPosition( light->getPosition() );
|
||||
|
||||
data.objTrans = &mLightMat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::MRTLightmapsDuringPrePass( bool val )
|
||||
{
|
||||
// Do not enable if the GFX device can't do MRT's
|
||||
if ( GFX->getNumRenderTargets() < 2 )
|
||||
val = false;
|
||||
|
||||
if ( mMRTLightmapsDuringPrePass != val )
|
||||
{
|
||||
mMRTLightmapsDuringPrePass = val;
|
||||
|
||||
// Reload materials to cause a feature recalculation on prepass materials
|
||||
if(mLightManager->isActive())
|
||||
MATMGR->flushAndReInitInstances();
|
||||
|
||||
RenderPrePassMgr *prepass;
|
||||
if ( Sim::findObject( "AL_PrePassBin", prepass ) && prepass->getTargetTexture( 0 ) )
|
||||
prepass->updateTargets();
|
||||
}
|
||||
}
|
||||
|
||||
AdvancedLightBinManager::LightMaterialInfo::LightMaterialInfo( const String &matName,
|
||||
const GFXVertexFormat *vertexFormat,
|
||||
const Vector<GFXShaderMacro> ¯os )
|
||||
: matInstance(NULL),
|
||||
zNearFarInvNearFar(NULL),
|
||||
farPlane(NULL),
|
||||
vsFarPlane(NULL),
|
||||
negFarPlaneDotEye(NULL),
|
||||
lightPosition(NULL),
|
||||
lightDirection(NULL),
|
||||
lightColor(NULL),
|
||||
lightAttenuation(NULL),
|
||||
lightRange(NULL),
|
||||
lightAmbient(NULL),
|
||||
lightTrilight(NULL),
|
||||
lightSpotParams(NULL)
|
||||
{
|
||||
Material *mat = MATMGR->getMaterialDefinitionByName( matName );
|
||||
if ( !mat )
|
||||
return;
|
||||
|
||||
matInstance = new LightMatInstance( *mat );
|
||||
|
||||
for ( U32 i=0; i < macros.size(); i++ )
|
||||
matInstance->addShaderMacro( macros[i].name, macros[i].value );
|
||||
|
||||
matInstance->init( MATMGR->getDefaultFeatures(), vertexFormat );
|
||||
|
||||
lightDirection = matInstance->getMaterialParameterHandle("$lightDirection");
|
||||
lightAmbient = matInstance->getMaterialParameterHandle("$lightAmbient");
|
||||
lightTrilight = matInstance->getMaterialParameterHandle("$lightTrilight");
|
||||
lightSpotParams = matInstance->getMaterialParameterHandle("$lightSpotParams");
|
||||
lightAttenuation = matInstance->getMaterialParameterHandle("$lightAttenuation");
|
||||
lightRange = matInstance->getMaterialParameterHandle("$lightRange");
|
||||
lightPosition = matInstance->getMaterialParameterHandle("$lightPosition");
|
||||
farPlane = matInstance->getMaterialParameterHandle("$farPlane");
|
||||
vsFarPlane = matInstance->getMaterialParameterHandle("$vsFarPlane");
|
||||
negFarPlaneDotEye = matInstance->getMaterialParameterHandle("$negFarPlaneDotEye");
|
||||
zNearFarInvNearFar = matInstance->getMaterialParameterHandle("$zNearFarInvNearFar");
|
||||
lightColor = matInstance->getMaterialParameterHandle("$lightColor");
|
||||
lightBrightness = matInstance->getMaterialParameterHandle("$lightBrightness");
|
||||
}
|
||||
|
||||
AdvancedLightBinManager::LightMaterialInfo::~LightMaterialInfo()
|
||||
{
|
||||
SAFE_DELETE(matInstance);
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::LightMaterialInfo::setViewParameters( const F32 _zNear,
|
||||
const F32 _zFar,
|
||||
const Point3F &_eyePos,
|
||||
const PlaneF &_farPlane,
|
||||
const PlaneF &_vsFarPlane)
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
|
||||
void AdvancedLightBinManager::LightMaterialInfo::setLightParameters( const LightInfo *lightInfo, const SceneRenderState* renderState, const MatrixF &worldViewOnly )
|
||||
{
|
||||
MaterialParameters *matParams = matInstance->getMaterialParameters();
|
||||
|
||||
// Set color in the right format, set alpha to the luminance value for the color.
|
||||
ColorF col = lightInfo->getColor();
|
||||
|
||||
// TODO: The specularity control of the light
|
||||
// is being scaled by the overall lumiance.
|
||||
//
|
||||
// Not sure if this may be the source of our
|
||||
// bad specularity results maybe?
|
||||
//
|
||||
|
||||
const Point3F colorToLumiance( 0.3576f, 0.7152f, 0.1192f );
|
||||
F32 lumiance = mDot(*((const Point3F *)&lightInfo->getColor()), colorToLumiance );
|
||||
col.alpha *= lumiance;
|
||||
|
||||
matParams->setSafe( lightColor, col );
|
||||
matParams->setSafe( lightBrightness, lightInfo->getBrightness() );
|
||||
|
||||
switch( lightInfo->getType() )
|
||||
{
|
||||
case LightInfo::Vector:
|
||||
{
|
||||
VectorF lightDir = lightInfo->getDirection();
|
||||
worldViewOnly.mulV(lightDir);
|
||||
lightDir.normalize();
|
||||
matParams->setSafe( lightDirection, lightDir );
|
||||
|
||||
// Set small number for alpha since it represents existing specular in
|
||||
// the vector light. This prevents a divide by zero.
|
||||
ColorF ambientColor = renderState->getAmbientLightColor();
|
||||
ambientColor.alpha = 0.00001f;
|
||||
matParams->setSafe( lightAmbient, ambientColor );
|
||||
|
||||
// If no alt color is specified, set it to the average of
|
||||
// the ambient and main color to avoid artifacts.
|
||||
//
|
||||
// TODO: Trilight disabled until we properly implement it
|
||||
// in the light info!
|
||||
//
|
||||
//ColorF lightAlt = lightInfo->getAltColor();
|
||||
ColorF lightAlt( ColorF::BLACK ); // = lightInfo->getAltColor();
|
||||
if ( lightAlt.red == 0.0f && lightAlt.green == 0.0f && lightAlt.blue == 0.0f )
|
||||
lightAlt = (lightInfo->getColor() + renderState->getAmbientLightColor()) / 2.0f;
|
||||
|
||||
ColorF trilightColor = lightAlt;
|
||||
matParams->setSafe(lightTrilight, trilightColor);
|
||||
}
|
||||
break;
|
||||
|
||||
case LightInfo::Spot:
|
||||
{
|
||||
const F32 outerCone = lightInfo->getOuterConeAngle();
|
||||
const F32 innerCone = getMin( lightInfo->getInnerConeAngle(), outerCone );
|
||||
const F32 outerCos = mCos( mDegToRad( outerCone / 2.0f ) );
|
||||
const F32 innerCos = mCos( mDegToRad( innerCone / 2.0f ) );
|
||||
Point4F spotParams( outerCos,
|
||||
innerCos - outerCos,
|
||||
mCos( mDegToRad( outerCone ) ),
|
||||
0.0f );
|
||||
|
||||
matParams->setSafe( lightSpotParams, spotParams );
|
||||
|
||||
VectorF lightDir = lightInfo->getDirection();
|
||||
worldViewOnly.mulV(lightDir);
|
||||
lightDir.normalize();
|
||||
matParams->setSafe( lightDirection, lightDir );
|
||||
}
|
||||
// Fall through
|
||||
|
||||
case LightInfo::Point:
|
||||
{
|
||||
const F32 radius = lightInfo->getRange().x;
|
||||
matParams->setSafe( lightRange, radius );
|
||||
|
||||
Point3F lightPos;
|
||||
worldViewOnly.mulP(lightInfo->getPosition(), &lightPos);
|
||||
matParams->setSafe( lightPosition, lightPos );
|
||||
|
||||
// Get the attenuation falloff ratio and normalize it.
|
||||
Point3F attenRatio = lightInfo->getExtended<ShadowMapParams>()->attenuationRatio;
|
||||
F32 total = attenRatio.x + attenRatio.y + attenRatio.z;
|
||||
if ( total > 0.0f )
|
||||
attenRatio /= total;
|
||||
|
||||
Point2F attenParams( ( 1.0f / radius ) * attenRatio.y,
|
||||
( 1.0f / ( radius * radius ) ) * attenRatio.z );
|
||||
|
||||
matParams->setSafe( lightAttenuation, attenParams );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
AssertFatal( false, "Bad light type!" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool LightMatInstance::setupPass( SceneRenderState *state, const SceneData &sgData )
|
||||
{
|
||||
// Go no further if the material failed to initialize properly.
|
||||
if ( !mProcessedMaterial ||
|
||||
mProcessedMaterial->getNumPasses() == 0 )
|
||||
return false;
|
||||
|
||||
// Fetch the lightmap params
|
||||
const LightMapParams *lmParams = sgData.lights[0]->getExtended<LightMapParams>();
|
||||
|
||||
// If no Lightmap params, let parent handle it
|
||||
if(lmParams == NULL)
|
||||
return Parent::setupPass(state, sgData);
|
||||
|
||||
// Defaults
|
||||
bool bRetVal = true;
|
||||
|
||||
// What render pass is this...
|
||||
if(mCurPass == -1)
|
||||
{
|
||||
// First pass, reset this flag
|
||||
mInternalPass = false;
|
||||
|
||||
// Pass call to parent
|
||||
bRetVal = Parent::setupPass(state, sgData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this light is represented in a lightmap, it has already done it's
|
||||
// job for non-lightmapped geometry. Now render the lightmapped geometry
|
||||
// pass (specular + shadow-darkening)
|
||||
if(!mInternalPass && lmParams->representedInLightmap)
|
||||
mInternalPass = true;
|
||||
else
|
||||
return Parent::setupPass(state, sgData);
|
||||
}
|
||||
|
||||
// Set up the shader constants we need to...
|
||||
if(mLightMapParamsSC->isValid())
|
||||
{
|
||||
// If this is an internal pass, special case the parameters
|
||||
if(mInternalPass)
|
||||
{
|
||||
AssertFatal( lmParams->shadowDarkenColor.alpha == -1.0f, "Assumption failed, check unpack code!" );
|
||||
getMaterialParameters()->set( mLightMapParamsSC, lmParams->shadowDarkenColor );
|
||||
}
|
||||
else
|
||||
getMaterialParameters()->set( mLightMapParamsSC, ColorF::WHITE );
|
||||
}
|
||||
|
||||
// Now override stateblock with our own
|
||||
if(!mInternalPass)
|
||||
{
|
||||
// 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]);
|
||||
else // This is a normal, dynamic light.
|
||||
GFX->setStateBlock(mLitState[DynamicLight]);
|
||||
|
||||
}
|
||||
else // Internal pass, this is the add-specular/multiply-darken-color pass
|
||||
GFX->setStateBlock(mLitState[StaticLightLMGeometry]);
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
bool LightMatInstance::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;
|
||||
|
||||
mLightMapParamsSC = getMaterialParameterHandle("$lightMapParams");
|
||||
|
||||
// Grab the state block for the first render pass (since this mat instance
|
||||
// inserts a pass after the first pass)
|
||||
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!");
|
||||
|
||||
// Get state block desc for normal (not wireframe, not translucent, not glow, etc)
|
||||
// render state
|
||||
GFXStateBlockDesc litState = rpd->mRenderStates[0]->getDesc();
|
||||
|
||||
// Create state blocks for each of the 3 possible combos in setupPass
|
||||
|
||||
//DynamicLight State: This will effect lightmapped and non-lightmapped geometry
|
||||
// in the same way.
|
||||
litState.separateAlphaBlendDefined = true;
|
||||
litState.separateAlphaBlendEnable = false;
|
||||
litState.stencilMask = RenderPrePassMgr::OpaqueDynamicLitMask | RenderPrePassMgr::OpaqueStaticLitMask;
|
||||
mLitState[DynamicLight] = 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 = RenderPrePassMgr::OpaqueDynamicLitMask;
|
||||
mLitState[StaticLightNonLMGeometry] = GFX->createStateBlock(litState);
|
||||
|
||||
// StaticLightLMGeometry State: This will add specular information (alpha) but
|
||||
// multiply-darken color information.
|
||||
litState.blendDest = GFXBlendSrcColor;
|
||||
litState.blendSrc = GFXBlendZero;
|
||||
litState.stencilMask = RenderPrePassMgr::OpaqueStaticLitMask;
|
||||
litState.separateAlphaBlendDefined = true;
|
||||
litState.separateAlphaBlendEnable = true;
|
||||
litState.separateAlphaBlendSrc = GFXBlendOne;
|
||||
litState.separateAlphaBlendDest = GFXBlendOne;
|
||||
litState.separateAlphaBlendOp = GFXBlendOpAdd;
|
||||
mLitState[StaticLightLMGeometry] = GFX->createStateBlock(litState);
|
||||
|
||||
return true;
|
||||
}
|
||||
234
Engine/source/lighting/advanced/advancedLightBinManager.h
Normal file
234
Engine/source/lighting/advanced/advancedLightBinManager.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _ADVANCEDLIGHTBINMANAGER_H_
|
||||
#define _ADVANCEDLIGHTBINMANAGER_H_
|
||||
|
||||
#ifndef _TEXTARGETBIN_MGR_H_
|
||||
#include "renderInstance/renderTexTargetBinManager.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
#ifndef _LIGHTINFO_H_
|
||||
#include "lighting/lightInfo.h"
|
||||
#endif
|
||||
#ifndef _MATHUTIL_FRUSTUM_H_
|
||||
#include "math/util/frustum.h"
|
||||
#endif
|
||||
#ifndef _MATINSTANCE_H_
|
||||
#include "materials/matInstance.h"
|
||||
#endif
|
||||
#ifndef _SHADOW_COMMON_H_
|
||||
#include "lighting/shadowMap/shadowCommon.h"
|
||||
#endif
|
||||
|
||||
|
||||
class AdvancedLightManager;
|
||||
class ShadowMapManager;
|
||||
class LightShadowMap;
|
||||
class AdvancedLightBufferConditioner;
|
||||
class LightMapParams;
|
||||
|
||||
|
||||
class LightMatInstance : public MatInstance
|
||||
{
|
||||
typedef MatInstance Parent;
|
||||
protected:
|
||||
MaterialParameterHandle *mLightMapParamsSC;
|
||||
bool mInternalPass;
|
||||
|
||||
enum
|
||||
{
|
||||
DynamicLight = 0,
|
||||
StaticLightNonLMGeometry,
|
||||
StaticLightLMGeometry,
|
||||
NUM_LIT_STATES
|
||||
};
|
||||
GFXStateBlockRef mLitState[NUM_LIT_STATES];
|
||||
|
||||
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 );
|
||||
};
|
||||
|
||||
|
||||
class AdvancedLightBinManager : public RenderTexTargetBinManager
|
||||
{
|
||||
typedef RenderTexTargetBinManager Parent;
|
||||
|
||||
public:
|
||||
|
||||
// Light info Render Inst Type
|
||||
static const RenderInstType RIT_LightInfo;
|
||||
|
||||
// registered buffer name
|
||||
static const String smBufferName;
|
||||
|
||||
/// The shadow filter mode to use on shadowed light materials.
|
||||
static ShadowFilterMode smShadowFilterMode;
|
||||
|
||||
/// Used to toggle the PSSM debug rendering mode.
|
||||
static bool smPSSMDebugRender;
|
||||
|
||||
/// Set by the SSAO post effect to tell the vector
|
||||
/// light to compile in the SSAO mask.
|
||||
static bool smUseSSAOMask;
|
||||
|
||||
// Used for console init
|
||||
AdvancedLightBinManager( AdvancedLightManager *lm = NULL,
|
||||
ShadowMapManager *sm = NULL,
|
||||
GFXFormat lightBufferFormat = GFXFormatR8G8B8A8 );
|
||||
virtual ~AdvancedLightBinManager();
|
||||
|
||||
// ConsoleObject
|
||||
static void consoleInit();
|
||||
|
||||
// RenderBinManager
|
||||
virtual void render(SceneRenderState *);
|
||||
virtual void clear();
|
||||
virtual void sort() {}
|
||||
|
||||
// Add a light to the bins
|
||||
void addLight( LightInfo *light );
|
||||
|
||||
virtual bool setTargetSize(const Point2I &newTargetSize);
|
||||
|
||||
// ConsoleObject interface
|
||||
DECLARE_CONOBJECT(AdvancedLightBinManager);
|
||||
|
||||
bool MRTLightmapsDuringPrePass() const { return mMRTLightmapsDuringPrePass; }
|
||||
void MRTLightmapsDuringPrePass(bool val);
|
||||
|
||||
|
||||
typedef Signal<void(SceneRenderState *, AdvancedLightBinManager *)> RenderSignal;
|
||||
static RenderSignal &getRenderSignal();
|
||||
|
||||
AdvancedLightManager *getManager() { return mLightManager; }
|
||||
|
||||
protected:
|
||||
|
||||
/// Frees all the currently allocated light materials.
|
||||
void _deleteLightMaterials();
|
||||
|
||||
// Track a light material and associated data
|
||||
struct LightMaterialInfo
|
||||
{
|
||||
LightMatInstance *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;
|
||||
|
||||
// Light Parameters
|
||||
MaterialParameterHandle *lightPosition;
|
||||
MaterialParameterHandle *lightDirection;
|
||||
MaterialParameterHandle *lightColor;
|
||||
MaterialParameterHandle *lightBrightness;
|
||||
MaterialParameterHandle *lightAttenuation;
|
||||
MaterialParameterHandle *lightRange;
|
||||
MaterialParameterHandle *lightAmbient;
|
||||
MaterialParameterHandle *lightTrilight;
|
||||
MaterialParameterHandle *lightSpotParams;
|
||||
|
||||
LightMaterialInfo( const String &matName,
|
||||
const GFXVertexFormat *vertexFormat,
|
||||
const Vector<GFXShaderMacro> ¯os = Vector<GFXShaderMacro>() );
|
||||
|
||||
virtual ~LightMaterialInfo();
|
||||
|
||||
|
||||
void setViewParameters( const F32 zNear,
|
||||
const F32 zFar,
|
||||
const Point3F &eyePos,
|
||||
const PlaneF &farPlane,
|
||||
const PlaneF &_vsFarPlane );
|
||||
|
||||
void setLightParameters( const LightInfo *light, const SceneRenderState* renderState, const MatrixF &worldViewOnly );
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
struct LightBinEntry
|
||||
{
|
||||
LightInfo* lightInfo;
|
||||
LightShadowMap* shadowMap;
|
||||
LightMaterialInfo* lightMaterial;
|
||||
GFXPrimitiveBuffer* primBuffer;
|
||||
GFXVertexBuffer* vertBuffer;
|
||||
U32 numPrims;
|
||||
};
|
||||
|
||||
Vector<LightBinEntry> mLightBin;
|
||||
typedef Vector<LightBinEntry>::iterator LightBinIterator;
|
||||
|
||||
bool mMRTLightmapsDuringPrePass;
|
||||
|
||||
/// Used in setupSGData to set the object transform.
|
||||
MatrixF mLightMat;
|
||||
|
||||
U32 mNumLightsCulled;
|
||||
AdvancedLightManager *mLightManager;
|
||||
ShadowMapManager *mShadowManager;
|
||||
|
||||
static const String smLightMatNames[LightInfo::Count];
|
||||
|
||||
static const String smShadowTypeMacro[ShadowType_Count];
|
||||
|
||||
static const GFXVertexFormat* smLightMatVertex[LightInfo::Count];
|
||||
|
||||
typedef CompoundKey3<LightInfo::Type,ShadowType,bool> LightMatKey;
|
||||
|
||||
typedef HashTable<LightMatKey,LightMaterialInfo*> LightMatTable;
|
||||
|
||||
/// The fixed table of light material info.
|
||||
LightMatTable mLightMaterials;
|
||||
|
||||
LightMaterialInfo* _getLightMaterial( LightInfo::Type lightType, ShadowType shadowType, bool useCookieTex );
|
||||
|
||||
///
|
||||
void _onShadowFilterChanged();
|
||||
|
||||
AdvancedLightBufferConditioner *mConditioner;
|
||||
|
||||
typedef GFXVertexPNT FarFrustumQuadVert;
|
||||
GFXVertexBufferHandle<FarFrustumQuadVert> mFarFrustumQuadVerts;
|
||||
|
||||
|
||||
//void _createMaterials();
|
||||
|
||||
void _setupPerFrameParameters( const SceneRenderState *state );
|
||||
|
||||
void setupSGData( SceneData &data, const SceneRenderState* state, LightInfo *light );
|
||||
};
|
||||
|
||||
#endif // _ADVANCEDLIGHTBINMANAGER_H_
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/advancedLightBufferConditioner.h"
|
||||
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
|
||||
|
||||
AdvancedLightBufferConditioner::~AdvancedLightBufferConditioner()
|
||||
{
|
||||
}
|
||||
|
||||
Var *AdvancedLightBufferConditioner::_conditionOutput( Var *unconditionedOutput, MultiLine *meta )
|
||||
{
|
||||
Var *conditionedOutput = new Var;
|
||||
|
||||
if(GFX->getAdapterType() == OpenGL)
|
||||
conditionedOutput->setType("vec4");
|
||||
else
|
||||
conditionedOutput->setType("float4");
|
||||
|
||||
DecOp *outputDecl = new DecOp(conditionedOutput);
|
||||
if(mColorFormat == RGB)
|
||||
{
|
||||
conditionedOutput->setName("rgbLightInfoOut");
|
||||
|
||||
// If this is a 16 bit integer format, scale up/down the values. All other
|
||||
// formats just write out the full 0..1
|
||||
if(getBufferFormat() == GFXFormatR16G16B16A16)
|
||||
meta->addStatement( new GenOp( " @ = max(4.0, (float4(lightColor, specular) * NL_att + float4(bufferSample.rgb, 0.0)) / 4.0);\r\n", outputDecl ) );
|
||||
else
|
||||
meta->addStatement( new GenOp( " @ = float4(lightColor, specular) * NL_att + float4(bufferSample.rgb, 0.0);\r\n", outputDecl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Input u'v' assumed to be scaled
|
||||
conditionedOutput->setName("luvLightInfoOut");
|
||||
meta->addStatement( new GenOp( " @ = float4( lerp(bufferSample.xy, lightColor.xy, saturate(NL_att / bufferSample.z) * 0.5),\r\n", outputDecl ) );
|
||||
meta->addStatement( new GenOp( " bufferSample.z + NL_att, bufferSample.w + saturate(specular * NL_att) );\r\n" ) );
|
||||
}
|
||||
|
||||
return conditionedOutput;
|
||||
}
|
||||
|
||||
Var *AdvancedLightBufferConditioner::_unconditionInput( Var *conditionedInput, MultiLine *meta )
|
||||
{
|
||||
if(mColorFormat == RGB)
|
||||
{
|
||||
if(getBufferFormat() == GFXFormatR16G16B16A16)
|
||||
meta->addStatement( new GenOp( " lightColor = @.rgb * 4.0;\r\n", conditionedInput ) );
|
||||
else
|
||||
meta->addStatement( new GenOp( " lightColor = @.rgb;\r\n", conditionedInput ) );
|
||||
meta->addStatement( new GenOp( " NL_att = dot(@.rgb, float3(0.3576, 0.7152, 0.1192));\r\n", conditionedInput ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
meta->addStatement( new GenOp( " // TODO: This clamps HDR values.\r\n" ) );
|
||||
meta->addStatement( new GenOp( " NL_att = @.b;\r\n", conditionedInput ) );
|
||||
meta->addStatement( new GenOp( " lightColor = DecodeLuv(float3(saturate(NL_att), @.rg * 0.62));\r\n", conditionedInput ) );
|
||||
}
|
||||
meta->addStatement( new GenOp( " specular = max(@.a / NL_att, 0.00001f);\r\n", conditionedInput ) );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Var *AdvancedLightBufferConditioner::printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta )
|
||||
{
|
||||
Var *methodVar = new Var;
|
||||
methodVar->setName(methodName);
|
||||
DecOp *methodDecl = new DecOp(methodVar);
|
||||
|
||||
Var *lightColor = new Var;
|
||||
lightColor->setName("lightColor");
|
||||
DecOp *lightColorDecl = new DecOp(lightColor);
|
||||
|
||||
Var *NLAtt = new Var;
|
||||
NLAtt->setName("NL_att");
|
||||
DecOp *NLAttDecl = new DecOp(NLAtt);
|
||||
|
||||
Var *specular = new Var;
|
||||
specular->setName("specular");
|
||||
DecOp *specularDecl = new DecOp(specular);
|
||||
|
||||
Var *bufferSample = new Var;
|
||||
bufferSample->setName("bufferSample");
|
||||
DecOp *bufferSampleDecl = new DecOp(bufferSample);
|
||||
|
||||
const bool isCondition = ( methodType == ConditionerFeature::ConditionMethod );
|
||||
|
||||
if(GFX->getAdapterType() == OpenGL)
|
||||
{
|
||||
methodVar->setType(avar("%s", isCondition ? "vec4" : "void"));
|
||||
lightColor->setType(avar("%s vec3", isCondition ? "in" : "out"));
|
||||
NLAtt->setType(avar("%s float", isCondition ? "in" : "out"));
|
||||
specular->setType(avar("%s float", isCondition ? "in" : "out"));
|
||||
bufferSample->setType("in vec4");
|
||||
}
|
||||
else
|
||||
{
|
||||
methodVar->setType(avar("inline %s", isCondition ? "float4" : "void"));
|
||||
lightColor->setType(avar("%s float3", isCondition ? "in" : "out"));
|
||||
NLAtt->setType(avar("%s float", isCondition ? "in" : "out"));
|
||||
specular->setType(avar("%s float", isCondition ? "in" : "out"));
|
||||
bufferSample->setType("in float4");
|
||||
}
|
||||
|
||||
// If this is LUV, print methods to convert RGB<->LUV as needed
|
||||
if(mColorFormat == LUV)
|
||||
{
|
||||
if(!isCondition)
|
||||
{
|
||||
meta->addStatement( new GenOp( "float3 DecodeLuv(float3 Luv)\r\n{\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float2 xy = float2(9.0f, 4.0f) * Luv.yz / (dot(Luv.yz, float2(6.0f, -16.0f)) + 12.0f);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float Ld = Luv.x;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float3 XYZ = float3(xy.x, Ld, 1.0f - xy.x - xy.y);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " XYZ.xz = XYZ.xz * Ld / xy.y;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " const float3x3 XYZ2RGB =\r\n" ) );
|
||||
meta->addStatement( new GenOp( " {\r\n" ) );
|
||||
meta->addStatement( new GenOp( " 2.5651f, -1.1665f, -0.3986f,\r\n" ) );
|
||||
meta->addStatement( new GenOp( " -1.0217f, 1.9777f, 0.0439f,\r\n" ) );
|
||||
meta->addStatement( new GenOp( " 0.0753f, -0.2543f, 1.1892f\r\n" ) );
|
||||
meta->addStatement( new GenOp( " };\r\n" ) );
|
||||
meta->addStatement( new GenOp( " return mul(XYZ2RGB, XYZ);\r\n" ) );
|
||||
meta->addStatement( new GenOp( "}\r\n\r\n" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shouldn't need this
|
||||
}
|
||||
}
|
||||
|
||||
// Method header and opening bracket
|
||||
if(isCondition)
|
||||
{
|
||||
// All parameters are input parameters, and the return value is float4.
|
||||
// If this is an LUV buffer format, than the previous pixel value is needed
|
||||
// for interpolation.
|
||||
meta->addStatement( new GenOp( "@(@, @, @, @)\r\n", methodDecl, lightColorDecl, NLAttDecl, specularDecl, bufferSampleDecl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sample as input, parameters as output. Void return.
|
||||
meta->addStatement( new GenOp( "@(@, @, @, @)\r\n", methodDecl, bufferSampleDecl, lightColorDecl, NLAttDecl, specularDecl ) );
|
||||
}
|
||||
|
||||
meta->addStatement( new GenOp( "{\r\n" ) );
|
||||
|
||||
// We don't use this way of passing var's around, so this should cause a crash
|
||||
// if something uses this improperly
|
||||
return ( isCondition ? NULL : bufferSample );
|
||||
}
|
||||
|
||||
void AdvancedLightBufferConditioner::printMethodFooter( ConditionerFeature::MethodType methodType, Var *retVar, Stream &stream, MultiLine *meta )
|
||||
{
|
||||
// Return and closing bracket
|
||||
if(methodType == ConditionerFeature::ConditionMethod)
|
||||
meta->addStatement( new GenOp( "\r\n return @;\r\n", retVar ) );
|
||||
|
||||
// Uncondition will assign output parameters
|
||||
meta->addStatement( new GenOp( "}\r\n" ) );
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _ADVANCED_LIGHTBUFFER_CONDITIONER_H_
|
||||
#define _ADVANCED_LIGHTBUFFER_CONDITIONER_H_
|
||||
|
||||
#ifndef _CONDITIONER_BASE_H_
|
||||
#include "shaderGen/conditionerFeature.h"
|
||||
#endif
|
||||
|
||||
|
||||
class AdvancedLightBufferConditioner : public ConditionerFeature
|
||||
{
|
||||
typedef ConditionerFeature Parent;
|
||||
|
||||
public:
|
||||
enum ColorFormat
|
||||
{
|
||||
RGB,
|
||||
LUV
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
AdvancedLightBufferConditioner(const GFXFormat bufferFormat, const ColorFormat colorFormat)
|
||||
: Parent(bufferFormat), mColorFormat(colorFormat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~AdvancedLightBufferConditioner();
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return String("Light Buffer Conditioner ") + String( mColorFormat == RGB ? "[RGB]" : "[LUV]" );
|
||||
}
|
||||
|
||||
protected:
|
||||
ColorFormat mColorFormat;
|
||||
|
||||
virtual Var *_conditionOutput( Var *unconditionedOutput, MultiLine *meta );
|
||||
virtual Var *_unconditionInput( Var *conditionedInput, MultiLine *meta );
|
||||
virtual Var *printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta );
|
||||
virtual void printMethodFooter( MethodType methodType, Var *retVar, Stream &stream, MultiLine *meta );
|
||||
};
|
||||
|
||||
#endif // _ADVANCED_LIGHTBUFFER_CONDITIONER_H_
|
||||
671
Engine/source/lighting/advanced/advancedLightManager.cpp
Normal file
671
Engine/source/lighting/advanced/advancedLightManager.cpp
Normal file
|
|
@ -0,0 +1,671 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/advancedLightManager.h"
|
||||
|
||||
#include "lighting/advanced/advancedLightBinManager.h"
|
||||
#include "lighting/advanced/advancedLightingFeatures.h"
|
||||
#include "lighting/shadowMap/shadowMapManager.h"
|
||||
#include "lighting/shadowMap/lightShadowMap.h"
|
||||
#include "lighting/common/sceneLighting.h"
|
||||
#include "lighting/common/lightMapParams.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "renderInstance/renderPrePassMgr.h"
|
||||
#include "materials/materialManager.h"
|
||||
#include "math/util/sphereMesh.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "scene/sceneRenderState.h"
|
||||
|
||||
|
||||
ImplementEnumType( ShadowType,
|
||||
"\n\n"
|
||||
"@ingroup AdvancedLighting" )
|
||||
{ ShadowType_Spot, "Spot" },
|
||||
{ ShadowType_PSSM, "PSSM" },
|
||||
{ ShadowType_Paraboloid, "Paraboloid" },
|
||||
{ ShadowType_DualParaboloidSinglePass, "DualParaboloidSinglePass" },
|
||||
{ ShadowType_DualParaboloid, "DualParaboloid" },
|
||||
{ ShadowType_CubeMap, "CubeMap" },
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
AdvancedLightManager AdvancedLightManager::smSingleton;
|
||||
|
||||
|
||||
AdvancedLightManager::AdvancedLightManager()
|
||||
: LightManager( "Advanced Lighting", "ADVLM" )
|
||||
{
|
||||
mLightBinManager = NULL;
|
||||
mLastShader = NULL;
|
||||
mAvailableSLInterfaces = NULL;
|
||||
}
|
||||
|
||||
AdvancedLightManager::~AdvancedLightManager()
|
||||
{
|
||||
mLastShader = NULL;
|
||||
mLastConstants = NULL;
|
||||
|
||||
for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
|
||||
{
|
||||
if (i->value)
|
||||
SAFE_DELETE(i->value);
|
||||
}
|
||||
mConstantLookup.clear();
|
||||
}
|
||||
|
||||
bool AdvancedLightManager::isCompatible() const
|
||||
{
|
||||
// TODO: We need at least 3.0 shaders at the moment
|
||||
// but this should be relaxed to 2.0 soon.
|
||||
if ( GFX->getPixelShaderVersion() < 3.0 )
|
||||
return false;
|
||||
|
||||
// TODO: Test for the necessary texture formats!
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AdvancedLightManager::activate( SceneManager *sceneManager )
|
||||
{
|
||||
Parent::activate( sceneManager );
|
||||
|
||||
GFXShader::addGlobalMacro( "TORQUE_ADVANCED_LIGHTING" );
|
||||
|
||||
sceneManager->setPostEffectFog( true );
|
||||
|
||||
SHADOWMGR->activate();
|
||||
|
||||
// Find a target format that supports blending...
|
||||
// we prefer the floating point format if it works.
|
||||
Vector<GFXFormat> formats;
|
||||
formats.push_back( GFXFormatR16G16B16A16F );
|
||||
formats.push_back( GFXFormatR16G16B16A16 );
|
||||
GFXFormat blendTargetFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile,
|
||||
formats,
|
||||
true,
|
||||
true,
|
||||
false );
|
||||
|
||||
mLightBinManager = new AdvancedLightBinManager( this, SHADOWMGR, blendTargetFormat );
|
||||
mLightBinManager->assignName( "AL_LightBinMgr" );
|
||||
|
||||
// First look for the prepass bin...
|
||||
RenderPrePassMgr *prePassBin = _findPrePassRenderBin();
|
||||
|
||||
// If we didn't find the prepass bin then add one.
|
||||
if ( !prePassBin )
|
||||
{
|
||||
prePassBin = new RenderPrePassMgr( true, blendTargetFormat );
|
||||
prePassBin->assignName( "AL_PrePassBin" );
|
||||
prePassBin->registerObject();
|
||||
getSceneManager()->getDefaultRenderPass()->addManager( prePassBin );
|
||||
mPrePassRenderBin = prePassBin;
|
||||
}
|
||||
|
||||
// Tell the material manager that prepass is enabled.
|
||||
MATMGR->setPrePassEnabled( true );
|
||||
|
||||
// Insert our light bin manager.
|
||||
mLightBinManager->setRenderOrder( prePassBin->getRenderOrder() + 0.01f );
|
||||
getSceneManager()->getDefaultRenderPass()->addManager( mLightBinManager );
|
||||
|
||||
AdvancedLightingFeatures::registerFeatures(mPrePassRenderBin->getTargetFormat(), mLightBinManager->getTargetFormat());
|
||||
|
||||
// Last thing... let everyone know we're active.
|
||||
smActivateSignal.trigger( getId(), true );
|
||||
}
|
||||
|
||||
void AdvancedLightManager::deactivate()
|
||||
{
|
||||
Parent::deactivate();
|
||||
|
||||
GFXShader::removeGlobalMacro( "TORQUE_ADVANCED_LIGHTING" );
|
||||
|
||||
// Release our bin manager... it will take care of
|
||||
// removing itself from the render passes.
|
||||
if( mLightBinManager )
|
||||
{
|
||||
mLightBinManager->MRTLightmapsDuringPrePass(false);
|
||||
mLightBinManager->deleteObject();
|
||||
}
|
||||
mLightBinManager = NULL;
|
||||
|
||||
if ( mPrePassRenderBin )
|
||||
mPrePassRenderBin->deleteObject();
|
||||
mPrePassRenderBin = NULL;
|
||||
|
||||
SHADOWMGR->deactivate();
|
||||
|
||||
mLastShader = NULL;
|
||||
mLastConstants = NULL;
|
||||
|
||||
for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
|
||||
{
|
||||
if (i->value)
|
||||
SAFE_DELETE(i->value);
|
||||
}
|
||||
mConstantLookup.clear();
|
||||
|
||||
mSphereGeometry = NULL;
|
||||
mSphereIndices = NULL;
|
||||
mConeGeometry = NULL;
|
||||
mConeIndices = NULL;
|
||||
|
||||
AdvancedLightingFeatures::unregisterFeatures();
|
||||
|
||||
// Now let everyone know we've deactivated.
|
||||
smActivateSignal.trigger( getId(), false );
|
||||
}
|
||||
|
||||
void AdvancedLightManager::_addLightInfoEx( LightInfo *lightInfo )
|
||||
{
|
||||
lightInfo->addExtended( new ShadowMapParams( lightInfo ) );
|
||||
lightInfo->addExtended( new LightMapParams( lightInfo ) );
|
||||
}
|
||||
|
||||
|
||||
void AdvancedLightManager::_initLightFields()
|
||||
{
|
||||
#define DEFINE_LIGHT_FIELD( var, type, enum_ ) \
|
||||
static inline const char* _get##var##Field( void *obj, const char *data ) \
|
||||
{ \
|
||||
ShadowMapParams *p = _getShadowMapParams( obj ); \
|
||||
if ( p ) \
|
||||
return Con::getData( type, &p->var, 0, enum_ ); \
|
||||
else \
|
||||
return ""; \
|
||||
} \
|
||||
\
|
||||
static inline bool _set##var##Field( void *object, const char *index, const char *data ) \
|
||||
{ \
|
||||
ShadowMapParams *p = _getShadowMapParams( object ); \
|
||||
if ( p ) \
|
||||
{ \
|
||||
Con::setData( type, &p->var, 0, 1, &data, enum_ ); \
|
||||
p->_validate(); \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define DEFINE_LIGHTMAP_FIELD( var, type, enum_ ) \
|
||||
static inline const char* _get##var##Field( void *obj, const char *data ) \
|
||||
{ \
|
||||
LightMapParams *p = _getLightMapParams( obj ); \
|
||||
if ( p ) \
|
||||
return Con::getData( type, &p->var, 0, enum_ ); \
|
||||
else \
|
||||
return ""; \
|
||||
} \
|
||||
\
|
||||
static inline bool _set##var##Field( void *object, const char *index, const char *data ) \
|
||||
{ \
|
||||
LightMapParams *p = _getLightMapParams( object ); \
|
||||
if ( p ) \
|
||||
{ \
|
||||
Con::setData( type, &p->var, 0, 1, &data, enum_ ); \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define ADD_LIGHT_FIELD( field, type, var, desc ) \
|
||||
ConsoleObject::addProtectedField( field, type, 0, \
|
||||
&Dummy::_set##var##Field, &Dummy::_get##var##Field, desc )
|
||||
|
||||
// Our dummy adaptor class which we hide in here
|
||||
// to keep from poluting the global namespace.
|
||||
class Dummy
|
||||
{
|
||||
protected:
|
||||
|
||||
static inline ShadowMapParams* _getShadowMapParams( void *obj )
|
||||
{
|
||||
ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( (SimObject*)obj );
|
||||
if ( sceneLight )
|
||||
{
|
||||
LightInfo *lightInfo = sceneLight->getLight();
|
||||
if ( lightInfo )
|
||||
return lightInfo->getExtended<ShadowMapParams>();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline LightMapParams* _getLightMapParams( void *obj )
|
||||
{
|
||||
ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( (SimObject*)obj );
|
||||
if ( sceneLight )
|
||||
{
|
||||
LightInfo *lightInfo = sceneLight->getLight();
|
||||
if ( lightInfo )
|
||||
return lightInfo->getExtended<LightMapParams>();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
DEFINE_LIGHT_FIELD( attenuationRatio, TypePoint3F, NULL );
|
||||
DEFINE_LIGHT_FIELD( shadowType, TYPEID< ShadowType >(), ConsoleBaseType::getType( TYPEID< ShadowType >() )->getEnumTable() );
|
||||
DEFINE_LIGHT_FIELD( texSize, TypeS32, NULL );
|
||||
DEFINE_LIGHT_FIELD( cookie, TypeStringFilename, NULL );
|
||||
DEFINE_LIGHT_FIELD( numSplits, TypeS32, NULL );
|
||||
DEFINE_LIGHT_FIELD( logWeight, TypeF32, NULL );
|
||||
DEFINE_LIGHT_FIELD( overDarkFactor, TypePoint4F, NULL);
|
||||
DEFINE_LIGHT_FIELD( shadowDistance, TypeF32, NULL );
|
||||
DEFINE_LIGHT_FIELD( shadowSoftness, TypeF32, NULL );
|
||||
DEFINE_LIGHT_FIELD( fadeStartDist, TypeF32, NULL );
|
||||
DEFINE_LIGHT_FIELD( lastSplitTerrainOnly, TypeBool, NULL );
|
||||
|
||||
DEFINE_LIGHTMAP_FIELD( representedInLightmap, TypeBool, NULL );
|
||||
DEFINE_LIGHTMAP_FIELD( shadowDarkenColor, TypeColorF, NULL );
|
||||
DEFINE_LIGHTMAP_FIELD( includeLightmappedGeometryInShadow, TypeBool, NULL );
|
||||
};
|
||||
|
||||
ConsoleObject::addGroup( "Advanced Lighting" );
|
||||
|
||||
ADD_LIGHT_FIELD( "attenuationRatio", TypePoint3F, attenuationRatio,
|
||||
"The proportions of constant, linear, and quadratic attenuation to use for "
|
||||
"the falloff for point and spot lights." );
|
||||
|
||||
ADD_LIGHT_FIELD( "shadowType", TYPEID< ShadowType >(), shadowType,
|
||||
"The type of shadow to use on this light." );
|
||||
|
||||
ADD_LIGHT_FIELD( "cookie", TypeStringFilename, cookie,
|
||||
"A custom pattern texture which is projected from the light." );
|
||||
|
||||
ADD_LIGHT_FIELD( "texSize", TypeS32, texSize,
|
||||
"The texture size of the shadow map." );
|
||||
|
||||
ADD_LIGHT_FIELD( "overDarkFactor", TypePoint4F, overDarkFactor,
|
||||
"The ESM shadow darkening factor");
|
||||
|
||||
ADD_LIGHT_FIELD( "shadowDistance", TypeF32, shadowDistance,
|
||||
"The distance from the camera to extend the PSSM shadow." );
|
||||
|
||||
ADD_LIGHT_FIELD( "shadowSoftness", TypeF32, shadowSoftness,
|
||||
"" );
|
||||
|
||||
ADD_LIGHT_FIELD( "numSplits", TypeS32, numSplits,
|
||||
"The logrithmic PSSM split distance factor." );
|
||||
|
||||
ADD_LIGHT_FIELD( "logWeight", TypeF32, logWeight,
|
||||
"The logrithmic PSSM split distance factor." );
|
||||
|
||||
ADD_LIGHT_FIELD( "fadeStartDistance", TypeF32, fadeStartDist,
|
||||
"Start fading shadows out at this distance. 0 = auto calculate this distance.");
|
||||
|
||||
ADD_LIGHT_FIELD( "lastSplitTerrainOnly", TypeBool, lastSplitTerrainOnly,
|
||||
"This toggles only terrain being rendered to the last split of a PSSM shadow map.");
|
||||
|
||||
ConsoleObject::endGroup( "Advanced Lighting" );
|
||||
|
||||
ConsoleObject::addGroup( "Advanced Lighting Lightmap" );
|
||||
|
||||
ADD_LIGHT_FIELD( "representedInLightmap", TypeBool, representedInLightmap,
|
||||
"This light is represented in lightmaps (static light, default: false)");
|
||||
|
||||
ADD_LIGHT_FIELD( "shadowDarkenColor", TypeColorF, shadowDarkenColor,
|
||||
"The color that should be used to multiply-blend dynamic shadows onto lightmapped geometry (ignored if 'representedInLightmap' is false)");
|
||||
|
||||
ADD_LIGHT_FIELD( "includeLightmappedGeometryInShadow", TypeBool, includeLightmappedGeometryInShadow,
|
||||
"This light should render lightmapped geometry during its shadow-map update (ignored if 'representedInLightmap' is false)");
|
||||
|
||||
ConsoleObject::endGroup( "Advanced Lighting Lightmap" );
|
||||
|
||||
#undef DEFINE_LIGHT_FIELD
|
||||
#undef ADD_LIGHT_FIELD
|
||||
}
|
||||
|
||||
void AdvancedLightManager::setLightInfo( ProcessedMaterial *pmat,
|
||||
const Material *mat,
|
||||
const SceneData &sgData,
|
||||
const SceneRenderState *state,
|
||||
U32 pass,
|
||||
GFXShaderConstBuffer *shaderConsts)
|
||||
{
|
||||
// Skip this if we're rendering from the prepass bin.
|
||||
if ( sgData.binType == SceneData::PrePassBin )
|
||||
return;
|
||||
|
||||
PROFILE_SCOPE(AdvancedLightManager_setLightInfo);
|
||||
|
||||
LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);
|
||||
|
||||
LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();
|
||||
|
||||
LightInfo *light;
|
||||
if ( lsm )
|
||||
light = lsm->getLightInfo();
|
||||
else
|
||||
{
|
||||
light = sgData.lights[0];
|
||||
if ( !light )
|
||||
light = getDefaultLight();
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
// Update the forward shading light constants.
|
||||
_update4LightConsts( sgData,
|
||||
lsc->mLightPositionSC,
|
||||
lsc->mLightDiffuseSC,
|
||||
lsc->mLightAmbientSC,
|
||||
lsc->mLightInvRadiusSqSC,
|
||||
lsc->mLightSpotDirSC,
|
||||
lsc->mLightSpotAngleSC,
|
||||
lsc->mLightSpotFalloffSC,
|
||||
shaderConsts );
|
||||
|
||||
if ( lsm && light->getCastShadows() )
|
||||
{
|
||||
if ( lsc->mWorldToLightProjSC->isValid() )
|
||||
shaderConsts->set( lsc->mWorldToLightProjSC,
|
||||
lsm->getWorldToLightProj(),
|
||||
lsc->mWorldToLightProjSC->getType() );
|
||||
|
||||
if ( lsc->mViewToLightProjSC->isValid() )
|
||||
{
|
||||
// TODO: Should probably cache these results and
|
||||
// not do this mul here on every material that needs
|
||||
// this transform.
|
||||
|
||||
shaderConsts->set( lsc->mViewToLightProjSC,
|
||||
lsm->getWorldToLightProj() * state->getCameraTransform(),
|
||||
lsc->mViewToLightProjSC->getType() );
|
||||
}
|
||||
|
||||
shaderConsts->setSafe( lsc->mShadowMapSizeSC, 1.0f / (F32)lsm->getTexSize() );
|
||||
|
||||
// Do this last so that overrides can properly override parameters previously set
|
||||
lsm->setShaderParameters(shaderConsts, lsc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lsc->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( lsc->mViewToLightProjSC,
|
||||
proj * state->getCameraTransform(),
|
||||
lsc->mViewToLightProjSC->getType() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedLightManager::registerGlobalLight(LightInfo *light, SimObject *obj)
|
||||
{
|
||||
Parent::registerGlobalLight( light, obj );
|
||||
|
||||
// Pass the volume lights to the bin manager.
|
||||
if ( mLightBinManager &&
|
||||
( light->getType() == LightInfo::Point ||
|
||||
light->getType() == LightInfo::Spot ) )
|
||||
mLightBinManager->addLight( light );
|
||||
}
|
||||
|
||||
void AdvancedLightManager::unregisterAllLights()
|
||||
{
|
||||
Parent::unregisterAllLights();
|
||||
|
||||
if ( mLightBinManager )
|
||||
mLightBinManager->clear();
|
||||
}
|
||||
|
||||
bool AdvancedLightManager::setTextureStage( const SceneData &sgData,
|
||||
const U32 currTexFlag,
|
||||
const U32 textureSlot,
|
||||
GFXShaderConstBuffer *shaderConsts,
|
||||
ShaderConstHandles *handles )
|
||||
{
|
||||
LightShadowMap* lsm = SHADOWMGR->getCurrentShadowMap();
|
||||
|
||||
// Assign Shadowmap, if it exists
|
||||
LightingShaderConstants* lsc = getLightingShaderConstants(shaderConsts);
|
||||
if ( !lsc )
|
||||
return false;
|
||||
|
||||
if ( lsm && lsm->getLightInfo()->getCastShadows() )
|
||||
return lsm->setTextureStage( currTexFlag, lsc );
|
||||
|
||||
|
||||
if ( currTexFlag == Material::DynamicLight )
|
||||
{
|
||||
S32 reg = lsc->mShadowMapSC->getSamplerRegister();
|
||||
if ( reg != -1 )
|
||||
GFX->setTexture( reg, GFXTexHandle::ONE );
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( currTexFlag == Material::DynamicLightMask )
|
||||
{
|
||||
S32 reg = lsc->mCookieMapSC->getSamplerRegister();
|
||||
if ( reg != -1 && sgData.lights[0] )
|
||||
{
|
||||
ShadowMapParams *p = sgData.lights[0]->getExtended<ShadowMapParams>();
|
||||
|
||||
if ( lsc->mCookieMapSC->getType() == GFXSCT_SamplerCube )
|
||||
GFX->setCubeTexture( reg, p->getCookieCubeTex() );
|
||||
else
|
||||
GFX->setTexture( reg, p->getCookieTex() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LightingShaderConstants* AdvancedLightManager::getLightingShaderConstants(GFXShaderConstBuffer* buffer)
|
||||
{
|
||||
if ( !buffer )
|
||||
return NULL;
|
||||
|
||||
PROFILE_SCOPE( AdvancedLightManager_GetLightingShaderConstants );
|
||||
|
||||
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 )
|
||||
{
|
||||
LightConstantMap::Iterator iter = mConstantLookup.find(shader);
|
||||
if ( iter != mConstantLookup.end() )
|
||||
{
|
||||
mLastConstants = iter->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LightingShaderConstants* lsc = new LightingShaderConstants();
|
||||
mConstantLookup[shader] = lsc;
|
||||
|
||||
mLastConstants = lsc;
|
||||
}
|
||||
|
||||
// Set our new shader
|
||||
mLastShader = shader;
|
||||
}
|
||||
|
||||
// Make sure that our current lighting constants are initialized
|
||||
if (!mLastConstants->mInit)
|
||||
mLastConstants->init(shader);
|
||||
|
||||
return mLastConstants;
|
||||
}
|
||||
|
||||
GFXVertexBufferHandle<AdvancedLightManager::LightVertex> AdvancedLightManager::getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives)
|
||||
{
|
||||
static SphereMesh sSphereMesh;
|
||||
|
||||
if( mSphereGeometry.isNull() )
|
||||
{
|
||||
const SphereMesh::TriangleMesh * sphereMesh = sSphereMesh.getMesh(3);
|
||||
S32 numPoly = sphereMesh->numPoly;
|
||||
mSpherePrimitiveCount = 0;
|
||||
mSphereGeometry.set(GFX, numPoly*3, GFXBufferTypeStatic);
|
||||
mSphereGeometry.lock();
|
||||
S32 vertexIndex = 0;
|
||||
|
||||
for (S32 i=0; i<numPoly; i++)
|
||||
{
|
||||
mSpherePrimitiveCount++;
|
||||
|
||||
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[0];
|
||||
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||
vertexIndex++;
|
||||
|
||||
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[1];
|
||||
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||
vertexIndex++;
|
||||
|
||||
mSphereGeometry[vertexIndex].point = sphereMesh->poly[i].pnt[2];
|
||||
mSphereGeometry[vertexIndex].color = ColorI::WHITE;
|
||||
vertexIndex++;
|
||||
}
|
||||
mSphereGeometry.unlock();
|
||||
}
|
||||
|
||||
outNumPrimitives = mSpherePrimitiveCount;
|
||||
outPrimitives = NULL; // For now
|
||||
return mSphereGeometry;
|
||||
}
|
||||
|
||||
GFXVertexBufferHandle<AdvancedLightManager::LightVertex> AdvancedLightManager::getConeMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives )
|
||||
{
|
||||
static const Point2F circlePoints[] =
|
||||
{
|
||||
Point2F(0.707107f, 0.707107f),
|
||||
Point2F(0.923880f, 0.382683f),
|
||||
Point2F(1.000000f, 0.000000f),
|
||||
Point2F(0.923880f, -0.382684f),
|
||||
Point2F(0.707107f, -0.707107f),
|
||||
Point2F(0.382683f, -0.923880f),
|
||||
Point2F(0.000000f, -1.000000f),
|
||||
Point2F(-0.382683f, -0.923880f),
|
||||
Point2F(-0.707107f, -0.707107f),
|
||||
Point2F(-0.923880f, -0.382684f),
|
||||
Point2F(-1.000000f, 0.000000f),
|
||||
Point2F(-0.923879f, 0.382684f),
|
||||
Point2F(-0.707107f, 0.707107f),
|
||||
Point2F(-0.382683f, 0.923880f),
|
||||
Point2F(0.000000f, 1.000000f),
|
||||
Point2F(0.382684f, 0.923879f)
|
||||
};
|
||||
const S32 numPoints = sizeof(circlePoints)/sizeof(Point2F);
|
||||
|
||||
if ( mConeGeometry.isNull() )
|
||||
{
|
||||
mConeGeometry.set(GFX, numPoints + 1, GFXBufferTypeStatic);
|
||||
mConeGeometry.lock();
|
||||
|
||||
mConeGeometry[0].point = Point3F(0.0f,0.0f,0.0f);
|
||||
|
||||
for (S32 i=1; i<numPoints + 1; i++)
|
||||
{
|
||||
S32 imod = (i - 1) % numPoints;
|
||||
mConeGeometry[i].point = Point3F(circlePoints[imod].x,circlePoints[imod].y, -1.0f);
|
||||
mConeGeometry[i].color = ColorI::WHITE;
|
||||
}
|
||||
mConeGeometry.unlock();
|
||||
|
||||
mConePrimitiveCount = numPoints * 2 - 1;
|
||||
|
||||
// Now build the index buffer
|
||||
mConeIndices.set(GFX, mConePrimitiveCount * 3, mConePrimitiveCount, GFXBufferTypeStatic);
|
||||
|
||||
U16 *idx = NULL;
|
||||
mConeIndices.lock( &idx );
|
||||
// Build the cone
|
||||
U32 idxIdx = 0;
|
||||
for( int i = 1; i < numPoints + 1; i++ )
|
||||
{
|
||||
idx[idxIdx++] = 0; // Triangles on cone start at top point
|
||||
idx[idxIdx++] = i;
|
||||
idx[idxIdx++] = ( i + 1 > numPoints ) ? 1 : i + 1;
|
||||
}
|
||||
|
||||
// Build the bottom of the cone (reverse winding order)
|
||||
for( int i = 1; i < numPoints - 1; i++ )
|
||||
{
|
||||
idx[idxIdx++] = 1;
|
||||
idx[idxIdx++] = i + 2;
|
||||
idx[idxIdx++] = i + 1;
|
||||
}
|
||||
mConeIndices.unlock();
|
||||
}
|
||||
|
||||
outNumPrimitives = mConePrimitiveCount;
|
||||
outPrimitives = mConeIndices.getPointer();
|
||||
return mConeGeometry;
|
||||
}
|
||||
|
||||
LightShadowMap* AdvancedLightManager::findShadowMapForObject( SimObject *object )
|
||||
{
|
||||
if ( !object )
|
||||
return NULL;
|
||||
|
||||
ISceneLight *sceneLight = dynamic_cast<ISceneLight*>( object );
|
||||
if ( !sceneLight || !sceneLight->getLight() )
|
||||
return NULL;
|
||||
|
||||
return sceneLight->getLight()->getExtended<ShadowMapParams>()->getShadowMap();
|
||||
}
|
||||
|
||||
ConsoleFunction( setShadowVizLight, const char*, 2, 2, "" )
|
||||
{
|
||||
static const String DebugTargetName( "AL_ShadowVizTexture" );
|
||||
|
||||
NamedTexTarget *target = NamedTexTarget::find( DebugTargetName );
|
||||
if ( target )
|
||||
target->unregister();
|
||||
|
||||
AdvancedLightManager *lm = dynamic_cast<AdvancedLightManager*>( LIGHTMGR );
|
||||
if ( !lm )
|
||||
return 0;
|
||||
|
||||
SimObject *object;
|
||||
Sim::findObject( argv[1], object );
|
||||
LightShadowMap *lightShadowMap = lm->findShadowMapForObject( object );
|
||||
if ( !lightShadowMap || !lightShadowMap->getTexture() )
|
||||
return 0;
|
||||
|
||||
lightShadowMap->setDebugTarget( DebugTargetName );
|
||||
|
||||
GFXTextureObject *texObject = lightShadowMap->getTexture();
|
||||
const Point3I &size = texObject->getSize();
|
||||
F32 aspect = (F32)size.x / (F32)size.y;
|
||||
|
||||
char *result = Con::getReturnBuffer( 64 );
|
||||
dSprintf( result, 64, "%d %d %g", size.x, size.y, aspect );
|
||||
return result;
|
||||
}
|
||||
|
||||
143
Engine/source/lighting/advanced/advancedLightManager.h
Normal file
143
Engine/source/lighting/advanced/advancedLightManager.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _ADVANCEDLIGHTMANAGER_H_
|
||||
#define _ADVANCEDLIGHTMANAGER_H_
|
||||
|
||||
#ifndef _SIMOBJECT_H_
|
||||
#include "console/simObject.h"
|
||||
#endif
|
||||
#ifndef _LIGHTMANAGER_H_
|
||||
#include "lighting/lightManager.h"
|
||||
#endif
|
||||
#ifndef _LIGHTINFO_H_
|
||||
#include "lighting/lightInfo.h"
|
||||
#endif
|
||||
#ifndef _GFXTEXTUREHANDLE_H_
|
||||
#include "gfx/gfxTextureHandle.h"
|
||||
#endif
|
||||
#ifndef _GFXTARGET_H_
|
||||
#include "gfx/gfxTarget.h"
|
||||
#endif
|
||||
#ifndef _TDICTIONARY_H_
|
||||
#include "core/util/tDictionary.h"
|
||||
#endif
|
||||
#ifndef _LIGHTSHADOWMAP_H_
|
||||
#include "lighting/shadowMap/lightShadowMap.h"
|
||||
#endif
|
||||
#ifndef _GFXPRIMITIVEBUFFER_H_
|
||||
#include "gfx/gfxPrimitiveBuffer.h"
|
||||
#endif
|
||||
#ifndef _GFXVERTEXBUFFER_H_
|
||||
#include "gfx/gfxVertexBuffer.h"
|
||||
#endif
|
||||
|
||||
|
||||
class AvailableSLInterfaces;
|
||||
class AdvancedLightBinManager;
|
||||
class RenderPrePassMgr;
|
||||
class BaseMatInstance;
|
||||
class MaterialParameters;
|
||||
class MaterialParameterHandle;
|
||||
class GFXShader;
|
||||
class GFXShaderConstHandle;
|
||||
class ShadowMapManager;
|
||||
|
||||
|
||||
class AdvancedLightManager : public LightManager
|
||||
{
|
||||
typedef LightManager Parent;
|
||||
|
||||
public:
|
||||
|
||||
/// Return the lightBinManager for this light manager.
|
||||
AdvancedLightBinManager* getLightBinManager() { return mLightBinManager; }
|
||||
|
||||
// LightManager
|
||||
virtual bool isCompatible() const;
|
||||
virtual void activate( SceneManager *sceneManager );
|
||||
virtual void deactivate();
|
||||
virtual void registerGlobalLight(LightInfo *light, SimObject *obj);
|
||||
virtual void unregisterAllLights();
|
||||
virtual void setLightInfo( ProcessedMaterial *pmat,
|
||||
const Material *mat,
|
||||
const SceneData &sgData,
|
||||
const SceneRenderState *state,
|
||||
U32 pass,
|
||||
GFXShaderConstBuffer *shaderConsts );
|
||||
virtual bool setTextureStage( const SceneData &sgData,
|
||||
const U32 currTexFlag,
|
||||
const U32 textureSlot,
|
||||
GFXShaderConstBuffer *shaderConsts,
|
||||
ShaderConstHandles *handles );
|
||||
|
||||
typedef GFXVertexPC LightVertex;
|
||||
|
||||
GFXVertexBufferHandle<LightVertex> getSphereMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives );
|
||||
GFXVertexBufferHandle<LightVertex> getConeMesh(U32 &outNumPrimitives, GFXPrimitiveBuffer *&outPrimitives );
|
||||
|
||||
LightShadowMap* findShadowMapForObject( SimObject *object );
|
||||
|
||||
protected:
|
||||
|
||||
// LightManager
|
||||
virtual void _addLightInfoEx( LightInfo *lightInfo );
|
||||
virtual void _initLightFields();
|
||||
|
||||
/// A simple protected singleton. Use LightManager::findByName()
|
||||
/// to access this light manager.
|
||||
/// @see LightManager::findByName()
|
||||
static AdvancedLightManager smSingleton;
|
||||
|
||||
// These are protected because we're a singleton and
|
||||
// no one else should be creating us!
|
||||
AdvancedLightManager();
|
||||
virtual ~AdvancedLightManager();
|
||||
|
||||
SimObjectPtr<AdvancedLightBinManager> mLightBinManager;
|
||||
|
||||
SimObjectPtr<RenderPrePassMgr> mPrePassRenderBin;
|
||||
|
||||
LightConstantMap mConstantLookup;
|
||||
|
||||
GFXShaderRef mLastShader;
|
||||
|
||||
LightingShaderConstants* mLastConstants;
|
||||
|
||||
// Convex geometry for lights
|
||||
GFXVertexBufferHandle<LightVertex> mSphereGeometry;
|
||||
|
||||
GFXPrimitiveBufferHandle mSphereIndices;
|
||||
|
||||
U32 mSpherePrimitiveCount;
|
||||
|
||||
GFXVertexBufferHandle<LightVertex> mConeGeometry;
|
||||
|
||||
GFXPrimitiveBufferHandle mConeIndices;
|
||||
|
||||
U32 mConePrimitiveCount;
|
||||
|
||||
LightingShaderConstants* getLightingShaderConstants(GFXShaderConstBuffer* shader);
|
||||
|
||||
};
|
||||
|
||||
#endif // _ADVANCEDLIGHTMANAGER_H_
|
||||
101
Engine/source/lighting/advanced/advancedLightingFeatures.cpp
Normal file
101
Engine/source/lighting/advanced/advancedLightingFeatures.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/advancedLightingFeatures.h"
|
||||
|
||||
#include "shaderGen/featureMgr.h"
|
||||
#include "gfx/gfxStringEnumTranslate.h"
|
||||
#include "materials/materialParameters.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "materials/matTextureTarget.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
|
||||
#ifndef TORQUE_OS_MAC
|
||||
# include "lighting/advanced/hlsl/gBufferConditionerHLSL.h"
|
||||
# include "lighting/advanced/hlsl/advancedLightingFeaturesHLSL.h"
|
||||
#else
|
||||
# include "lighting/advanced/glsl/gBufferConditionerGLSL.h"
|
||||
# include "lighting/advanced/glsl/advancedLightingFeaturesGLSL.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
bool AdvancedLightingFeatures::smFeaturesRegistered = false;
|
||||
|
||||
void AdvancedLightingFeatures::registerFeatures( const GFXFormat &prepassTargetFormat, const GFXFormat &lightInfoTargetFormat )
|
||||
{
|
||||
AssertFatal( !smFeaturesRegistered, "AdvancedLightingFeatures::registerFeatures() - Features already registered. Bad!" );
|
||||
|
||||
// If we ever need this...
|
||||
TORQUE_UNUSED(lightInfoTargetFormat);
|
||||
|
||||
ConditionerFeature *cond = NULL;
|
||||
|
||||
if(GFX->getAdapterType() == OpenGL)
|
||||
{
|
||||
#ifdef TORQUE_OS_MAC
|
||||
cond = new GBufferConditionerGLSL( prepassTargetFormat );
|
||||
FEATUREMGR->registerFeature(MFT_PrePassConditioner, cond);
|
||||
FEATUREMGR->registerFeature(MFT_RTLighting, new DeferredRTLightingFeatGLSL());
|
||||
FEATUREMGR->registerFeature(MFT_NormalMap, new DeferredBumpFeatGLSL());
|
||||
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularGLSL());
|
||||
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertGLSL());
|
||||
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceGLSL());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef TORQUE_OS_MAC
|
||||
cond = new GBufferConditionerHLSL( prepassTargetFormat, GBufferConditionerHLSL::ViewSpace );
|
||||
FEATUREMGR->registerFeature(MFT_PrePassConditioner, cond);
|
||||
FEATUREMGR->registerFeature(MFT_RTLighting, new DeferredRTLightingFeatHLSL());
|
||||
FEATUREMGR->registerFeature(MFT_NormalMap, new DeferredBumpFeatHLSL());
|
||||
FEATUREMGR->registerFeature(MFT_PixSpecular, new DeferredPixelSpecularHLSL());
|
||||
FEATUREMGR->registerFeature(MFT_MinnaertShading, new DeferredMinnaertHLSL());
|
||||
FEATUREMGR->registerFeature(MFT_SubSurface, new DeferredSubSurfaceHLSL());
|
||||
#endif
|
||||
}
|
||||
|
||||
NamedTexTarget *target = NamedTexTarget::find( "prepass" );
|
||||
if ( target )
|
||||
target->setConditioner( cond );
|
||||
|
||||
smFeaturesRegistered = true;
|
||||
}
|
||||
|
||||
void AdvancedLightingFeatures::unregisterFeatures()
|
||||
{
|
||||
NamedTexTarget *target = NamedTexTarget::find( "prepass" );
|
||||
if ( target )
|
||||
target->setConditioner( NULL );
|
||||
|
||||
FEATUREMGR->unregisterFeature(MFT_PrePassConditioner);
|
||||
FEATUREMGR->unregisterFeature(MFT_RTLighting);
|
||||
FEATUREMGR->unregisterFeature(MFT_NormalMap);
|
||||
FEATUREMGR->unregisterFeature(MFT_PixSpecular);
|
||||
FEATUREMGR->unregisterFeature(MFT_MinnaertShading);
|
||||
FEATUREMGR->unregisterFeature(MFT_SubSurface);
|
||||
|
||||
smFeaturesRegistered = false;
|
||||
}
|
||||
42
Engine/source/lighting/advanced/advancedLightingFeatures.h
Normal file
42
Engine/source/lighting/advanced/advancedLightingFeatures.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _ADVANCEDLIGHTINGFEATURES_H_
|
||||
#define _ADVANCEDLIGHTINGFEATURES_H_
|
||||
|
||||
#ifndef _GFXENUMS_H_
|
||||
#include "gfx/gfxEnums.h"
|
||||
#endif
|
||||
|
||||
|
||||
class AdvancedLightingFeatures
|
||||
{
|
||||
public:
|
||||
|
||||
static void registerFeatures( const GFXFormat &prepassTargetFormat, const GFXFormat &lightInfoTargetFormat );
|
||||
static void unregisterFeatures();
|
||||
|
||||
private:
|
||||
|
||||
static bool smFeaturesRegistered;
|
||||
};
|
||||
|
||||
#endif // _ADVANCEDLIGHTINGFEATURES_H_
|
||||
|
|
@ -0,0 +1,725 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/glsl/advancedLightingFeaturesGLSL.h"
|
||||
|
||||
#include "lighting/advanced/advancedLightBinManager.h"
|
||||
#include "shaderGen/langElement.h"
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#include "shaderGen/conditionerFeature.h"
|
||||
#include "renderInstance/renderPrePassMgr.h"
|
||||
#include "materials/processedMaterial.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
|
||||
|
||||
void DeferredRTLightingFeatGLSL::processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
/// TODO: This needs to be done via some sort of material
|
||||
/// feature and not just allow all translucent elements to
|
||||
/// read from the light prepass.
|
||||
/*
|
||||
if ( fd.features[MFT_IsTranslucent] )
|
||||
{
|
||||
Parent::processPixMacros( macros, fd );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// Pull in the uncondition method for the light info buffer
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName );
|
||||
if ( texTarget && texTarget->getConditioner() )
|
||||
{
|
||||
ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod);
|
||||
unconditionMethod->createMethodMacro( String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition", macros );
|
||||
addDependency(unconditionMethod);
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
/// TODO: This needs to be done via some sort of material
|
||||
/// feature and not just allow all translucent elements to
|
||||
/// read from the light prepass.
|
||||
/*
|
||||
if ( fd.features[MFT_IsTranslucent] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// Pass screen space position to pixel shader to compute a full screen buffer uv
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *ssPos = connectComp->getElement( RT_TEXCOORD );
|
||||
ssPos->setName( "screenspacePos" );
|
||||
ssPos->setType( "vec4" );
|
||||
|
||||
// Var *outPosition = (Var*) LangElement::find( "hpos" );
|
||||
// AssertFatal( outPosition, "No hpos, ohnoes." );
|
||||
|
||||
output = new GenOp( " @ = gl_Position;\r\n", ssPos );
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
/// TODO: This needs to be done via some sort of material
|
||||
/// feature and not just allow all translucent elements to
|
||||
/// read from the light prepass.
|
||||
/*
|
||||
if ( fd.features[MFT_IsTranslucent] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *ssPos = connectComp->getElement( RT_TEXCOORD );
|
||||
ssPos->setName( "screenspacePos" );
|
||||
ssPos->setType( "vec4" );
|
||||
|
||||
Var *uvScene = new Var;
|
||||
uvScene->setType( "vec2" );
|
||||
uvScene->setName( "uvScene" );
|
||||
LangElement *uvSceneDecl = new DecOp( uvScene );
|
||||
|
||||
Var *rtParams = (Var*) LangElement::find( "renderTargetParams" );
|
||||
if( !rtParams )
|
||||
{
|
||||
rtParams = new Var;
|
||||
rtParams->setType( "vec4" );
|
||||
rtParams->setName( "renderTargetParams" );
|
||||
rtParams->uniform = true;
|
||||
rtParams->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", uvSceneDecl, ssPos, ssPos ) ); // get the screen coord... its -1 to +1
|
||||
meta->addStatement( new GenOp( " @ = ( @ + 1.0 ) / 2.0;\r\n", uvScene, uvScene ) ); // get the screen coord to 0 to 1
|
||||
meta->addStatement( new GenOp( " @ = ( @ * @.zw ) + @.xy;\r\n", uvScene, uvScene, rtParams, rtParams) ); // scale it down and offset it to the rt size
|
||||
|
||||
Var *lightInfoSamp = new Var;
|
||||
lightInfoSamp->setType( "vec4" );
|
||||
lightInfoSamp->setName( "lightInfoSample" );
|
||||
|
||||
// create texture var
|
||||
Var *lightInfoBuffer = new Var;
|
||||
lightInfoBuffer->setType( "sampler2D" );
|
||||
lightInfoBuffer->setName( "lightInfoBuffer" );
|
||||
lightInfoBuffer->uniform = true;
|
||||
lightInfoBuffer->sampler = true;
|
||||
lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition";
|
||||
|
||||
meta->addStatement( new GenOp( " vec3 d_lightcolor;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float d_NL_Att;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float d_specular;\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " %s(texture2D(@, @), d_lightcolor, d_NL_Att, d_specular);\r\n", unconditionLightInfo.c_str() ),
|
||||
lightInfoBuffer, uvScene ) );
|
||||
|
||||
Var *rtShading = new Var;
|
||||
rtShading->setType( "vec4" );
|
||||
rtShading->setName( "rtShading" );
|
||||
LangElement *rtShadingDecl = new DecOp( rtShading );
|
||||
meta->addStatement( new GenOp( " @ = vec4( d_lightcolor, 1.0 );\r\n", rtShadingDecl ) );
|
||||
|
||||
// This is kind of weak sauce
|
||||
if( !fd.features[MFT_SubSurface] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] )
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( rtShading, Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredRTLightingFeatGLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
/// TODO: This needs to be done via some sort of material
|
||||
/// feature and not just allow all translucent elements to
|
||||
/// read from the light prepass.
|
||||
/*
|
||||
if( fd.features[MFT_IsTranslucent] )
|
||||
return Parent::getResources( fd );
|
||||
*/
|
||||
|
||||
Resources res;
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatGLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
/// TODO: This needs to be done via some sort of material
|
||||
/// feature and not just allow all translucent elements to
|
||||
/// read from the light prepass.
|
||||
/*
|
||||
if( fd.features[MFT_IsTranslucent] )
|
||||
{
|
||||
Parent::setTexData( stageDat, fd, passData, texIndex );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName );
|
||||
if( texTarget )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeferredBumpFeatGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_PrePassConditioner] )
|
||||
{
|
||||
// There is an output conditioner active, so we need to supply a transform
|
||||
// to the pixel shader.
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// setup texture space matrix
|
||||
Var *texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" );
|
||||
if( !texSpaceMat )
|
||||
{
|
||||
LangElement * texSpaceSetup = setupTexSpaceMat( componentList, &texSpaceMat );
|
||||
meta->addStatement( texSpaceSetup );
|
||||
texSpaceMat = (Var*) LangElement::find( "objToTangentSpace" );
|
||||
}
|
||||
|
||||
// turn obj->tangent into world->tangent
|
||||
Var *worldToTangent = new Var;
|
||||
worldToTangent->setType( "mat3" );
|
||||
worldToTangent->setName( "worldToTangent" );
|
||||
LangElement *worldToTangentDecl = new DecOp( worldToTangent );
|
||||
|
||||
// Get the world->obj transform
|
||||
Var *worldToObj = new Var;
|
||||
worldToObj->setType( "mat4" );
|
||||
worldToObj->setName( "worldToObj" );
|
||||
worldToObj->uniform = true;
|
||||
worldToObj->constSortPos = cspPrimitive;
|
||||
|
||||
Var *mat3Conversion = new Var;
|
||||
mat3Conversion->setType( "mat3" );
|
||||
mat3Conversion->setName( "worldToObjMat3" );
|
||||
LangElement* mat3Lang = new DecOp(mat3Conversion);
|
||||
meta->addStatement( new GenOp( " @ = mat3(@[0].xyz, @[1].xyz, @[2].xyz);\r\n ", mat3Lang, worldToObj, worldToObj, worldToObj) );
|
||||
|
||||
// assign world->tangent transform
|
||||
meta->addStatement( new GenOp( " @ = @ * @;\r\n", worldToTangentDecl, texSpaceMat, mat3Conversion ) );
|
||||
|
||||
// send transform to pixel shader
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
|
||||
Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR1->setName( "worldToTangentR1" );
|
||||
worldToTangentR1->setType( "vec3" );
|
||||
meta->addStatement( new GenOp( " @ = @[0];\r\n", worldToTangentR1, worldToTangent ) );
|
||||
|
||||
Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR2->setName( "worldToTangentR2" );
|
||||
worldToTangentR2->setType( "vec3" );
|
||||
meta->addStatement( new GenOp( " @ = @[1];\r\n", worldToTangentR2, worldToTangent ) );
|
||||
|
||||
Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR3->setName( "worldToTangentR3" );
|
||||
worldToTangentR3->setType( "vec3" );
|
||||
meta->addStatement( new GenOp( " @ = @[2];\r\n", worldToTangentR3, worldToTangent ) );
|
||||
|
||||
// Make sure there are texcoords
|
||||
if( !fd.features[MFT_DiffuseMap] )
|
||||
{
|
||||
// find incoming texture var
|
||||
Var *inTex = getVertTexCoord( "texCoord" );
|
||||
|
||||
// grab connector texcoord register
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *outTex = connectComp->getElement( RT_TEXCOORD );
|
||||
outTex->setName( "outTexCoord" );
|
||||
outTex->setType( "vec2" );
|
||||
outTex->mapsToSampler = true;
|
||||
|
||||
if( fd.features[MFT_TexAnim] )
|
||||
{
|
||||
inTex->setType( "vec4" );
|
||||
|
||||
// create texture mat var
|
||||
Var *texMat = new Var;
|
||||
texMat->setType( "mat4" );
|
||||
texMat->setName( "texMat" );
|
||||
texMat->uniform = true;
|
||||
texMat->constSortPos = cspPotentialPrimitive;
|
||||
|
||||
meta->addStatement( new GenOp( " @ = @ * @;\r\n", outTex, texMat, inTex ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// setup language elements to output incoming tex coords to output
|
||||
meta->addStatement( new GenOp( " @ = @;\r\n", outTex, inTex ) );
|
||||
}
|
||||
}
|
||||
|
||||
output = meta;
|
||||
}
|
||||
else if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_IsTranslucent] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
output = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// NULL output in case nothing gets handled
|
||||
output = NULL;
|
||||
|
||||
if( fd.features[MFT_PrePassConditioner] )
|
||||
{
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// Pull the world->tangent transform from the vertex shader
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
|
||||
Var *worldToTangentR1 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR1->setName( "worldToTangentR1" );
|
||||
worldToTangentR1->setType( "vec3" );
|
||||
|
||||
Var *worldToTangentR2 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR2->setName( "worldToTangentR2" );
|
||||
worldToTangentR2->setType( "vec3" );
|
||||
|
||||
Var *worldToTangentR3 = connectComp->getElement( RT_TEXCOORD );
|
||||
worldToTangentR3->setName( "worldToTangentR3" );
|
||||
worldToTangentR3->setType( "vec3" );
|
||||
|
||||
Var *worldToTangent = new Var;
|
||||
worldToTangent->setType( "mat3" );
|
||||
worldToTangent->setName( "worldToTangent" );
|
||||
LangElement *worldToTangentDecl = new DecOp( worldToTangent );
|
||||
|
||||
// Build world->tangent matrix
|
||||
meta->addStatement( new GenOp( " @;\r\n", worldToTangentDecl ) );
|
||||
meta->addStatement( new GenOp( " @[0] = @;\r\n", worldToTangent, worldToTangentR1 ) );
|
||||
meta->addStatement( new GenOp( " @[1] = @;\r\n", worldToTangent, worldToTangentR2 ) );
|
||||
meta->addStatement( new GenOp( " @[2] = @;\r\n", worldToTangent, worldToTangentR3 ) );
|
||||
|
||||
// create texture var
|
||||
Var *bumpMap = new Var;
|
||||
bumpMap->setType( "sampler2D" );
|
||||
bumpMap->setName( "bumpMap" );
|
||||
bumpMap->uniform = true;
|
||||
bumpMap->sampler = true;
|
||||
bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
Var *texCoord = (Var*) LangElement::find( "outTexCoord" );
|
||||
if( !texCoord )
|
||||
{
|
||||
// grab connector texcoord register
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
texCoord = connectComp->getElement( RT_TEXCOORD );
|
||||
texCoord->setName( "outTexCoord" );
|
||||
texCoord->setType( "vec2" );
|
||||
texCoord->mapsToSampler = true;
|
||||
}
|
||||
|
||||
LangElement * texOp = new GenOp( "texture2D(@, @)", bumpMap, texCoord );
|
||||
|
||||
// create bump normal
|
||||
Var *bumpNorm = new Var;
|
||||
bumpNorm->setName( "bumpNormal" );
|
||||
bumpNorm->setType( "vec4" );
|
||||
|
||||
LangElement *bumpNormDecl = new DecOp( bumpNorm );
|
||||
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
|
||||
|
||||
// This var is read from GBufferConditionerHLSL and
|
||||
// used in the prepass output.
|
||||
Var *gbNormal = new Var;
|
||||
gbNormal->setName( "gbNormal" );
|
||||
gbNormal->setType( "vec3" );
|
||||
LangElement *gbNormalDecl = new DecOp( gbNormal );
|
||||
|
||||
// Normalize is done later...
|
||||
// Note: The reverse mul order is intentional. Affine matrix.
|
||||
meta->addStatement( new GenOp( " @ = @.xyz * @;\r\n", gbNormalDecl, bumpNorm, worldToTangent ) );
|
||||
|
||||
output = meta;
|
||||
return;
|
||||
}
|
||||
else if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_IsTranslucent] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
else if ( fd.features[MFT_PixSpecular] )
|
||||
{
|
||||
Var *bumpSample = (Var *)LangElement::find( "bumpSample" );
|
||||
if( bumpSample == NULL )
|
||||
{
|
||||
Var *texCoord = (Var*) LangElement::find( "outTexCoord" );
|
||||
if( !texCoord )
|
||||
{
|
||||
// grab connector texcoord register
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
texCoord = connectComp->getElement( RT_TEXCOORD );
|
||||
texCoord->setName( "outTexCoord" );
|
||||
texCoord->setType( "vec2" );
|
||||
texCoord->mapsToSampler = true;
|
||||
}
|
||||
|
||||
Var *bumpMap = new Var;
|
||||
bumpMap->setType( "sampler2D" );
|
||||
bumpMap->setName( "bumpMap" );
|
||||
bumpMap->uniform = true;
|
||||
bumpMap->sampler = true;
|
||||
bumpMap->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
bumpSample = new Var;
|
||||
bumpSample->setType( "vec4" );
|
||||
bumpSample->setName( "bumpSample" );
|
||||
LangElement *bumpSampleDecl = new DecOp( bumpSample );
|
||||
|
||||
output = new GenOp( " @ = texture2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredBumpFeatGLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_IsTranslucent] ||
|
||||
fd.features[MFT_Parallax] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
return Parent::getResources( fd );
|
||||
|
||||
Resources res;
|
||||
if(!fd.features[MFT_SpecularMap])
|
||||
{
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredBumpFeatGLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_IsTranslucent] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::setTexData( stageDat, fd, passData, texIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
GFXTextureObject *normalMap = stageDat.getTex( MFT_NormalMap );
|
||||
if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] &&
|
||||
( fd.features[MFT_PrePassConditioner] ||
|
||||
fd.features[MFT_PixSpecular] ) &&
|
||||
normalMap )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::Bump;
|
||||
passData.mTexSlot[ texIndex++ ].texObject = normalMap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeferredPixelSpecularGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
Var *specular = new Var;
|
||||
specular->setType( "float" );
|
||||
specular->setName( "specular" );
|
||||
LangElement * specDecl = new DecOp( specular );
|
||||
|
||||
Var *specCol = (Var*)LangElement::find( "specularColor" );
|
||||
if(specCol == NULL)
|
||||
{
|
||||
specCol = new Var;
|
||||
specCol->setType( "vec4" );
|
||||
specCol->setName( "specularColor" );
|
||||
specCol->uniform = true;
|
||||
specCol->constSortPos = cspPotentialPrimitive;
|
||||
}
|
||||
|
||||
Var *specPow = new Var;
|
||||
specPow->setType( "float" );
|
||||
specPow->setName( "specularPower" );
|
||||
|
||||
// If the gloss map flag is set, than the specular power is in the alpha
|
||||
// channel of the specular map
|
||||
if( fd.features[ MFT_GlossMap ] )
|
||||
meta->addStatement( new GenOp( " @ = @.a * 255;\r\n", new DecOp( specPow ), specCol ) );
|
||||
else
|
||||
{
|
||||
specPow->uniform = true;
|
||||
specPow->constSortPos = cspPotentialPrimitive;
|
||||
}
|
||||
|
||||
Var *constSpecPow = new Var;
|
||||
constSpecPow->setType( "float" );
|
||||
constSpecPow->setName( "constantSpecularPower" );
|
||||
constSpecPow->uniform = true;
|
||||
constSpecPow->constSortPos = cspPass;
|
||||
|
||||
Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" );
|
||||
AssertFatal( lightInfoSamp, "Something hosed the deferred features! Can't find lightInfoSample" );
|
||||
|
||||
// (a^m)^n = a^(m*n)
|
||||
meta->addStatement( new GenOp( " @ = pow(d_specular, ceil(@ / @)) * d_NL_Att;\r\n", specDecl, specPow, constSpecPow ) );
|
||||
|
||||
LangElement *specMul = new GenOp( "@ * @", specCol, specular );
|
||||
LangElement *final = specMul;
|
||||
|
||||
// We we have a normal map then mask the specular
|
||||
if( !fd.features[MFT_SpecularMap] && fd.features[MFT_NormalMap] )
|
||||
{
|
||||
Var *bumpSample = (Var*)LangElement::find( "bumpSample" );
|
||||
final = new GenOp( "@ * @.a", final, bumpSample );
|
||||
}
|
||||
|
||||
// add to color
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredPixelSpecularGLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
return Parent::getResources( fd );
|
||||
|
||||
Resources res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ShaderFeature::Resources DeferredMinnaertGLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
Resources res;
|
||||
if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredMinnaertGLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find(RenderPrePassMgr::BufferName);
|
||||
if ( texTarget )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredMinnaertGLSL::processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( !fd.features[MFT_IsTranslucent] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
// Pull in the uncondition method for the g buffer
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( RenderPrePassMgr::BufferName );
|
||||
if ( texTarget && texTarget->getConditioner() )
|
||||
{
|
||||
ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod);
|
||||
unconditionMethod->createMethodMacro( String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition", macros );
|
||||
addDependency(unconditionMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredMinnaertGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// grab incoming vert position
|
||||
Var *inVertPos = (Var*) LangElement::find( "position" );
|
||||
AssertFatal( inVertPos, "Something went bad with ShaderGen. The vertex position should be already defined." );
|
||||
|
||||
// grab output for gbuffer normal
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *outWSEyeVec= connectComp->getElement( RT_TEXCOORD );
|
||||
outWSEyeVec->setName( "outWSViewVec" );
|
||||
outWSEyeVec->setType( "vec4" );
|
||||
|
||||
// create objToWorld variable
|
||||
Var *objToWorld = (Var*) LangElement::find( "objTrans" );
|
||||
if( !objToWorld )
|
||||
{
|
||||
objToWorld = new Var;
|
||||
objToWorld->setType( "mat4x4" );
|
||||
objToWorld->setName( "objTrans" );
|
||||
objToWorld->uniform = true;
|
||||
objToWorld->constSortPos = cspPrimitive;
|
||||
}
|
||||
|
||||
// Eye Pos world
|
||||
Var *eyePosWorld = (Var*) LangElement::find( "eyePosWorld" );
|
||||
if( !eyePosWorld )
|
||||
{
|
||||
eyePosWorld = new Var;
|
||||
eyePosWorld->setType( "vec3" );
|
||||
eyePosWorld->setName( "eyePosWorld" );
|
||||
eyePosWorld->uniform = true;
|
||||
eyePosWorld->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
// Kick out the world-space normal
|
||||
LangElement *statement = new GenOp( " @ = vec4(@, @) - vec4(@, 0.0);\r\n",
|
||||
outWSEyeVec, objToWorld, inVertPos, eyePosWorld );
|
||||
output = statement;
|
||||
}
|
||||
|
||||
void DeferredMinnaertGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Var *minnaertConstant = new Var;
|
||||
minnaertConstant->setType( "float" );
|
||||
minnaertConstant->setName( "minnaertConstant" );
|
||||
minnaertConstant->uniform = true;
|
||||
minnaertConstant->constSortPos = cspPotentialPrimitive;
|
||||
|
||||
// create texture var
|
||||
Var *prepassBuffer = new Var;
|
||||
prepassBuffer->setType( "sampler2D" );
|
||||
prepassBuffer->setName( "prepassBuffer" );
|
||||
prepassBuffer->uniform = true;
|
||||
prepassBuffer->sampler = true;
|
||||
prepassBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
// Texture coord
|
||||
Var *uvScene = (Var*) LangElement::find( "uvScene" );
|
||||
AssertFatal(uvScene != NULL, "Unable to find UVScene, no RTLighting feature?");
|
||||
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *wsViewVec = (Var*) LangElement::find( "wsPos" );
|
||||
if( !wsViewVec )
|
||||
{
|
||||
wsViewVec = connectComp->getElement( RT_TEXCOORD );
|
||||
wsViewVec->setName( "outWSViewVec" );
|
||||
wsViewVec->setType( "vec4" );
|
||||
wsViewVec->mapsToSampler = false;
|
||||
wsViewVec->uniform = false;
|
||||
}
|
||||
|
||||
String unconditionPrePassMethod = String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition";
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(texture2D(@, @));\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) );
|
||||
meta->addStatement( new GenOp( " vec3 worldViewVec = normalize(@.xyz / @.w);\r\n", wsViewVec, wsViewVec ) );
|
||||
meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, worldViewVec);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float Minnaert = pow(d_NL_Att, @) * pow(vDotN, 1.0 - @);\r\n", minnaertConstant, minnaertConstant ) );
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
|
||||
void DeferredSubSurfaceGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_IsTranslucent] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Var *subSurfaceParams = new Var;
|
||||
subSurfaceParams->setType( "vec4" );
|
||||
subSurfaceParams->setName( "subSurfaceParams" );
|
||||
subSurfaceParams->uniform = true;
|
||||
subSurfaceParams->constSortPos = cspPotentialPrimitive;
|
||||
|
||||
Var *inColor = (Var*) LangElement::find( "rtShading" );
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, d_NL_Att) - smoothstep(0.0, 1.0, d_NL_Att);\r\n", subSurfaceParams ) );
|
||||
meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@.rgb + (subLamb * @.rgb), 1.0)", inColor, subSurfaceParams ), Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _DEFERREDFEATURESGLSL_H_
|
||||
#define _DEFERREDFEATURESGLSL_H_
|
||||
|
||||
#include "shaderGen/GLSL/shaderFeatureGLSL.h"
|
||||
#include "shaderGen/GLSL/bumpGLSL.h"
|
||||
#include "shaderGen/GLSL/pixSpecularGLSL.h"
|
||||
|
||||
class ConditionerMethodDependency;
|
||||
|
||||
|
||||
/// Lights the pixel by sampling from the light prepass buffer. It will
|
||||
/// fall back to default vertex lighting functionality if
|
||||
class DeferredRTLightingFeatGLSL : public RTLightingFeatGLSL
|
||||
{
|
||||
typedef RTLightingFeatGLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Material::BlendOp getBlendOp(){ return Material::None; }
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Deferred RT Lighting Feature";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Used to write the normals during the depth/normal prepass.
|
||||
class DeferredBumpFeatGLSL : public BumpFeatGLSL
|
||||
{
|
||||
typedef BumpFeatGLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Material::BlendOp getBlendOp() { return Material::LerpAlpha; }
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Bumpmap [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Generates specular highlights in the forward pass
|
||||
/// from the light prepass buffer.
|
||||
class DeferredPixelSpecularGLSL : public PixelSpecularGLSL
|
||||
{
|
||||
typedef PixelSpecularGLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Pixel Specular [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
class DeferredMinnaertGLSL : public ShaderFeatureGLSL
|
||||
{
|
||||
typedef ShaderFeatureGLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Minnaert Shading [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
class DeferredSubSurfaceGLSL : public ShaderFeatureGLSL
|
||||
{
|
||||
typedef ShaderFeatureGLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Sub-Surface Approximation [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _DEFERREDFEATURESGLSL_H_
|
||||
320
Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp
Normal file
320
Engine/source/lighting/advanced/glsl/gBufferConditionerGLSL.cpp
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/glsl/gBufferConditionerGLSL.h"
|
||||
|
||||
#include "shaderGen/featureMgr.h"
|
||||
#include "gfx/gfxStringEnumTranslate.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "materials/materialFeatureData.h"
|
||||
|
||||
|
||||
GBufferConditionerGLSL::GBufferConditionerGLSL( const GFXFormat bufferFormat ) :
|
||||
Parent( bufferFormat )
|
||||
{
|
||||
// Figure out how we should store the normal data. These are the defaults.
|
||||
mCanWriteNegativeValues = false;
|
||||
mNormalStorageType = CartesianXYZ;
|
||||
|
||||
// Note: We clear to a depth 1 (the w component) so
|
||||
// that the unrendered parts of the scene end up
|
||||
// farthest to the camera.
|
||||
|
||||
switch(bufferFormat)
|
||||
{
|
||||
case GFXFormatR8G8B8A8:
|
||||
// TODO: Some kind of logic here. Spherical is better, but is more
|
||||
// expensive.
|
||||
mNormalStorageType = Spherical;
|
||||
mBitsPerChannel = 8;
|
||||
break;
|
||||
|
||||
case GFXFormatR16G16B16A16F:
|
||||
// Floating point buffers don't need to encode negative values
|
||||
mCanWriteNegativeValues = true;
|
||||
mNormalStorageType = Spherical;
|
||||
mBitsPerChannel = 16;
|
||||
break;
|
||||
|
||||
// Store a 32bit depth with a sperical normal in the
|
||||
// integer 16 format. This gives us perfect depth
|
||||
// precision and high quality normals within a 64bit
|
||||
// buffer format.
|
||||
case GFXFormatR16G16B16A16:
|
||||
mNormalStorageType = Spherical;
|
||||
mBitsPerChannel = 16;
|
||||
break;
|
||||
|
||||
case GFXFormatR32G32B32A32F:
|
||||
mCanWriteNegativeValues = true;
|
||||
mNormalStorageType = CartesianXYZ;
|
||||
mBitsPerChannel = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Unsupported G-Buffer format");
|
||||
}
|
||||
}
|
||||
|
||||
GBufferConditionerGLSL::~GBufferConditionerGLSL()
|
||||
{
|
||||
}
|
||||
|
||||
void GBufferConditionerGLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
output = NULL;
|
||||
|
||||
if( !fd.features[MFT_NormalMap] )
|
||||
{
|
||||
// grab incoming vert normal
|
||||
Var *inNormal = (Var*) LangElement::find( "normal" );
|
||||
AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." );
|
||||
|
||||
// grab output for gbuffer normal
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
|
||||
outNormal->setName( "gbNormal" );
|
||||
outNormal->setType( "vec3" );
|
||||
|
||||
// create objToWorld variable
|
||||
Var *objToWorld = (Var*) LangElement::find( "objTrans" );
|
||||
if( !objToWorld )
|
||||
{
|
||||
objToWorld = new Var;
|
||||
objToWorld->setType( "mat4" );
|
||||
objToWorld->setName( "objTrans" );
|
||||
objToWorld->uniform = true;
|
||||
objToWorld->constSortPos = cspPrimitive;
|
||||
}
|
||||
|
||||
// Kick out the world-space normal
|
||||
LangElement *statement = new GenOp( " @ = vec3(@ * vec4(normalize(@), 0.0));\r\n", outNormal, objToWorld, inNormal );
|
||||
output = statement;
|
||||
}
|
||||
}
|
||||
|
||||
void GBufferConditionerGLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// sanity
|
||||
AssertFatal( fd.features[MFT_EyeSpaceDepthOut], "No depth-out feature enabled! Bad news!" );
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// grab connector normal
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *gbNormal = (Var*) LangElement::find( "gbNormal" );
|
||||
if( !gbNormal )
|
||||
{
|
||||
gbNormal = connectComp->getElement( RT_TEXCOORD );
|
||||
gbNormal->setName( "gbNormal" );
|
||||
gbNormal->setType( "vec3" );
|
||||
gbNormal->mapsToSampler = false;
|
||||
gbNormal->uniform = false;
|
||||
}
|
||||
|
||||
// find depth
|
||||
ShaderFeature *depthFeat = FEATUREMGR->getByType( MFT_EyeSpaceDepthOut );
|
||||
AssertFatal( depthFeat != NULL, "No eye space depth feature found!" );
|
||||
|
||||
Var *depth = (Var*) LangElement::find(depthFeat->getOutputVarName());
|
||||
AssertFatal( depth, "Something went bad with ShaderGen. The depth should be already generated by the EyeSpaceDepthOut feature." );
|
||||
|
||||
|
||||
Var *unconditionedOut = new Var;
|
||||
unconditionedOut->setType("vec4");
|
||||
unconditionedOut->setName("normal_depth");
|
||||
|
||||
LangElement *outputDecl = new DecOp( unconditionedOut );
|
||||
|
||||
// NOTE: We renormalize the normal here as they
|
||||
// will not stay normalized during interpolation.
|
||||
meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "vec4(normalize(@), @)", gbNormal, depth ) ) );
|
||||
meta->addStatement( assignOutput( unconditionedOut ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources GBufferConditionerGLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
Resources res;
|
||||
|
||||
// Passing from VS->PS:
|
||||
// - world space normal (gbNormal)
|
||||
res.numTexReg = 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Var* GBufferConditionerGLSL::printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta )
|
||||
{
|
||||
const bool isCondition = ( methodType == ConditionerFeature::ConditionMethod );
|
||||
|
||||
Var *retVal = NULL;
|
||||
|
||||
// The uncondition method inputs are changed
|
||||
if( isCondition )
|
||||
retVal = Parent::printMethodHeader( methodType, methodName, stream, meta );
|
||||
else
|
||||
{
|
||||
Var *methodVar = new Var;
|
||||
methodVar->setName(methodName);
|
||||
methodVar->setType("vec4");
|
||||
DecOp *methodDecl = new DecOp(methodVar);
|
||||
|
||||
Var *prepassSampler = new Var;
|
||||
prepassSampler->setName("prepassSamplerVar");
|
||||
prepassSampler->setType("sampler2D");
|
||||
DecOp *prepassSamplerDecl = new DecOp(prepassSampler);
|
||||
|
||||
Var *screenUV = new Var;
|
||||
screenUV->setName("screenUVVar");
|
||||
screenUV->setType("vec2");
|
||||
DecOp *screenUVDecl = new DecOp(screenUV);
|
||||
|
||||
Var *bufferSample = new Var;
|
||||
bufferSample->setName("bufferSample");
|
||||
bufferSample->setType("vec4");
|
||||
DecOp *bufferSampleDecl = new DecOp(bufferSample);
|
||||
|
||||
meta->addStatement( new GenOp( "@(@, @)\r\n", methodDecl, prepassSamplerDecl, screenUVDecl ) );
|
||||
|
||||
meta->addStatement( new GenOp( "{\r\n" ) );
|
||||
|
||||
meta->addStatement( new GenOp( " // Sampler g-buffer\r\n" ) );
|
||||
|
||||
// The gbuffer has no mipmaps, so use tex2dlod when
|
||||
// so that the shader compiler can optimize.
|
||||
meta->addStatement( new GenOp( " @ = texture2DLod(@, @, 0.0);\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
|
||||
|
||||
// We don't use this way of passing var's around, so this should cause a crash
|
||||
// if something uses this improperly
|
||||
retVal = bufferSample;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
GenOp* GBufferConditionerGLSL::_posnegEncode( GenOp *val )
|
||||
{
|
||||
return mCanWriteNegativeValues ? val : new GenOp("0.5 * (@ + 1.0)", val);
|
||||
}
|
||||
|
||||
GenOp* GBufferConditionerGLSL::_posnegDecode( GenOp *val )
|
||||
{
|
||||
return mCanWriteNegativeValues ? val : new GenOp("@ * 2.0 - 1.0", val);
|
||||
}
|
||||
|
||||
Var* GBufferConditionerGLSL::_conditionOutput( Var *unconditionedOutput, MultiLine *meta )
|
||||
{
|
||||
Var *retVar = new Var;
|
||||
retVar->setType("vec4");
|
||||
retVar->setName("_gbConditionedOutput");
|
||||
LangElement *outputDecl = new DecOp( retVar );
|
||||
|
||||
switch(mNormalStorageType)
|
||||
{
|
||||
case CartesianXYZ:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xyz, depth)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl,
|
||||
_posnegEncode(new GenOp("@.xyz", unconditionedOutput)), unconditionedOutput ) );
|
||||
break;
|
||||
|
||||
case CartesianXY:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(@, @.a);", outputDecl,
|
||||
_posnegEncode(new GenOp("vec3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) );
|
||||
break;
|
||||
|
||||
case Spherical:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(@, 0.0, @.a);\r\n", outputDecl,
|
||||
_posnegEncode(new GenOp("vec2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ),
|
||||
unconditionedOutput ) );
|
||||
break;
|
||||
}
|
||||
|
||||
// Encode depth into two channels
|
||||
if(mNormalStorageType != CartesianXYZ)
|
||||
{
|
||||
const U64 maxValPerChannel = 1 << mBitsPerChannel;
|
||||
const U64 extraVal = (maxValPerChannel * maxValPerChannel - 1) - (maxValPerChannel - 1) * 2;
|
||||
meta->addStatement( new GenOp( " \r\n // Encode depth into hi/lo\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " vec3 _tempDepth = fract(@.a * vec3(1.0, %llu.0, %llu.0));\r\n", maxValPerChannel - 1, extraVal ),
|
||||
unconditionedOutput ) );
|
||||
meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yz * vec2(1.0/%llu.0, 1.0/%llu.0);\r\n\r\n", maxValPerChannel - 1, maxValPerChannel - 1 ),
|
||||
retVar ) );
|
||||
}
|
||||
|
||||
AssertFatal( retVar != NULL, avar( "Cannot condition output to buffer format: %s", GFXStringTextureFormat[getBufferFormat()] ) );
|
||||
return retVar;
|
||||
}
|
||||
|
||||
Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine *meta )
|
||||
{
|
||||
Var *retVar = new Var;
|
||||
retVar->setType("vec4");
|
||||
retVar->setName("_gbUnconditionedInput");
|
||||
LangElement *outputDecl = new DecOp( retVar );
|
||||
|
||||
switch(mNormalStorageType)
|
||||
{
|
||||
case CartesianXYZ:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xyz, depth)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl,
|
||||
_posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) );
|
||||
break;
|
||||
|
||||
case CartesianXY:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(@, @.a);\r\n", outputDecl,
|
||||
_posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) );
|
||||
meta->addStatement( new GenOp( " @.z *= sqrt(1.0 - dot(@.xy, @.xy));\r\n", retVar, retVar, retVar ) );
|
||||
break;
|
||||
|
||||
case Spherical:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: vec4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " vec2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) );
|
||||
meta->addStatement( new GenOp( " vec2 sincosTheta;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " sincosTheta.x = sin(spGPUAngles.x * 3.14159265358979323846);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " sincosTheta.y = cos(spGPUAngles.x * 3.14159265358979323846);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " vec2 sincosPhi = vec2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = vec4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) );
|
||||
break;
|
||||
}
|
||||
|
||||
// Recover depth from encoding
|
||||
if(mNormalStorageType != CartesianXYZ)
|
||||
{
|
||||
const U64 maxValPerChannel = 1 << mBitsPerChannel;
|
||||
meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, vec2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ),
|
||||
retVar, conditionedInput ) );
|
||||
}
|
||||
|
||||
|
||||
AssertFatal( retVar != NULL, avar( "Cannot uncondition input from buffer format: %s", GFXStringTextureFormat[getBufferFormat()] ) );
|
||||
return retVar;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GBUFFER_CONDITIONER_GLSL_H_
|
||||
#define _GBUFFER_CONDITIONER_GLSL_H_
|
||||
|
||||
#ifndef _CONDITIONER_BASE_H_
|
||||
#include "shaderGen/conditionerFeature.h"
|
||||
#endif
|
||||
#ifndef _SHADEROP_H_
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#endif
|
||||
|
||||
|
||||
///
|
||||
class GBufferConditionerGLSL : public ConditionerFeature
|
||||
{
|
||||
typedef ConditionerFeature Parent;
|
||||
|
||||
public:
|
||||
enum NormalStorage
|
||||
{
|
||||
CartesianXYZ,
|
||||
CartesianXY,
|
||||
Spherical,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
NormalStorage mNormalStorageType;
|
||||
bool mCanWriteNegativeValues;
|
||||
U32 mBitsPerChannel;
|
||||
|
||||
public:
|
||||
|
||||
GBufferConditionerGLSL( const GFXFormat bufferFormat );
|
||||
virtual ~GBufferConditionerGLSL();
|
||||
|
||||
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd );
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd );
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
virtual String getName() { return "GBuffer Conditioner"; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual Var *printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta );
|
||||
|
||||
virtual GenOp* _posnegEncode( GenOp *val );
|
||||
virtual GenOp* _posnegDecode( GenOp *val );
|
||||
virtual Var* _conditionOutput( Var *unconditionedOutput, MultiLine *meta );
|
||||
virtual Var* _unconditionInput( Var *conditionedInput, MultiLine *meta );
|
||||
};
|
||||
|
||||
#endif // _GBUFFER_CONDITIONER_GLSL_H_
|
||||
|
|
@ -0,0 +1,636 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/hlsl/advancedLightingFeaturesHLSL.h"
|
||||
|
||||
#include "lighting/advanced/advancedLightBinManager.h"
|
||||
#include "shaderGen/langElement.h"
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#include "shaderGen/conditionerFeature.h"
|
||||
#include "renderInstance/renderPrePassMgr.h"
|
||||
#include "materials/processedMaterial.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
|
||||
|
||||
void DeferredRTLightingFeatHLSL::processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// Skip deferred features, and use forward shading instead
|
||||
if ( fd.features[MFT_ForwardShading] )
|
||||
{
|
||||
Parent::processPixMacros( macros, fd );
|
||||
return;
|
||||
}
|
||||
|
||||
// Pull in the uncondition method for the light info buffer
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName );
|
||||
if ( texTarget && texTarget->getConditioner() )
|
||||
{
|
||||
ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod);
|
||||
unconditionMethod->createMethodMacro( String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition", macros );
|
||||
addDependency(unconditionMethod);
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// Skip deferred features, and use forward shading instead
|
||||
if ( fd.features[MFT_ForwardShading] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass screen space position to pixel shader to compute a full screen buffer uv
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *ssPos = connectComp->getElement( RT_TEXCOORD );
|
||||
ssPos->setName( "screenspacePos" );
|
||||
ssPos->setStructName( "OUT" );
|
||||
ssPos->setType( "float4" );
|
||||
|
||||
Var *outPosition = (Var*) LangElement::find( "hpos" );
|
||||
AssertFatal( outPosition, "No hpos, ohnoes." );
|
||||
|
||||
output = new GenOp( " @ = @;\r\n", ssPos, outPosition );
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// Skip deferred features, and use forward shading instead
|
||||
if ( fd.features[MFT_ForwardShading] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *ssPos = connectComp->getElement( RT_TEXCOORD );
|
||||
ssPos->setName( "screenspacePos" );
|
||||
ssPos->setStructName( "IN" );
|
||||
ssPos->setType( "float4" );
|
||||
|
||||
Var *uvScene = new Var;
|
||||
uvScene->setType( "float2" );
|
||||
uvScene->setName( "uvScene" );
|
||||
LangElement *uvSceneDecl = new DecOp( uvScene );
|
||||
|
||||
String rtParamName = String::ToString( "rtParams%d", mLastTexIndex );
|
||||
Var *rtParams = (Var*) LangElement::find( rtParamName );
|
||||
if( !rtParams )
|
||||
{
|
||||
rtParams = new Var;
|
||||
rtParams->setType( "float4" );
|
||||
rtParams->setName( rtParamName );
|
||||
rtParams->uniform = true;
|
||||
rtParams->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
meta->addStatement( new GenOp( " @ = @.xy / @.w;\r\n", uvSceneDecl, ssPos, ssPos ) ); // get the screen coord... its -1 to +1
|
||||
meta->addStatement( new GenOp( " @ = ( @ + 1.0 ) / 2.0;\r\n", uvScene, uvScene ) ); // get the screen coord to 0 to 1
|
||||
meta->addStatement( new GenOp( " @.y = 1.0 - @.y;\r\n", uvScene, uvScene ) ); // flip the y axis
|
||||
meta->addStatement( new GenOp( " @ = ( @ * @.zw ) + @.xy;\r\n", uvScene, uvScene, rtParams, rtParams) ); // scale it down and offset it to the rt size
|
||||
|
||||
Var *lightInfoSamp = new Var;
|
||||
lightInfoSamp->setType( "float4" );
|
||||
lightInfoSamp->setName( "lightInfoSample" );
|
||||
|
||||
// create texture var
|
||||
Var *lightInfoBuffer = new Var;
|
||||
lightInfoBuffer->setType( "sampler2D" );
|
||||
lightInfoBuffer->setName( "lightInfoBuffer" );
|
||||
lightInfoBuffer->uniform = true;
|
||||
lightInfoBuffer->sampler = true;
|
||||
lightInfoBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
// Declare the RTLighting variables in this feature, they will either be assigned
|
||||
// in this feature, or in the tonemap/lightmap feature
|
||||
Var *d_lightcolor = new Var( "d_lightcolor", "float3" );
|
||||
meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_lightcolor ) ) );
|
||||
|
||||
Var *d_NL_Att = new Var( "d_NL_Att", "float" );
|
||||
meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_NL_Att ) ) );
|
||||
|
||||
Var *d_specular = new Var( "d_specular", "float" );
|
||||
meta->addStatement( new GenOp( " @;\r\n", new DecOp( d_specular ) ) );
|
||||
|
||||
|
||||
// Perform the uncondition here.
|
||||
String unconditionLightInfo = String::ToLower( AdvancedLightBinManager::smBufferName ) + "Uncondition";
|
||||
meta->addStatement( new GenOp( avar( " %s(tex2D(@, @), @, @, @);\r\n",
|
||||
unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, d_lightcolor, d_NL_Att, d_specular ) );
|
||||
|
||||
// If this has an interlaced pre-pass, do averaging here
|
||||
if( fd.features[MFT_InterlacedPrePass] )
|
||||
{
|
||||
Var *oneOverTargetSize = (Var*) LangElement::find( "oneOverTargetSize" );
|
||||
if( !oneOverTargetSize )
|
||||
{
|
||||
oneOverTargetSize = new Var;
|
||||
oneOverTargetSize->setType( "float2" );
|
||||
oneOverTargetSize->setName( "oneOverTargetSize" );
|
||||
oneOverTargetSize->uniform = true;
|
||||
oneOverTargetSize->constSortPos = cspPass;
|
||||
}
|
||||
|
||||
meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n float3 id_lightcolor;\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + float2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n",
|
||||
unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, oneOverTargetSize ) );
|
||||
|
||||
meta->addStatement( new GenOp(" @ = lerp(@, id_lightcolor, 0.5);\r\n", d_lightcolor, d_lightcolor ) );
|
||||
meta->addStatement( new GenOp(" @ = lerp(@, id_NL_Att, 0.5);\r\n", d_NL_Att, d_NL_Att ) );
|
||||
meta->addStatement( new GenOp(" @ = lerp(@, id_specular, 0.5);\r\n", d_specular, d_specular ) );
|
||||
}
|
||||
|
||||
// This is kind of weak sauce
|
||||
if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] )
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@, 1.0)", d_lightcolor ), Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredRTLightingFeatHLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
// Skip deferred features, and use forward shading instead
|
||||
if ( fd.features[MFT_ForwardShading] )
|
||||
return Parent::getResources( fd );
|
||||
|
||||
// HACK: See DeferredRTLightingFeatHLSL::setTexData.
|
||||
mLastTexIndex = 0;
|
||||
|
||||
Resources res;
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredRTLightingFeatHLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
// Skip deferred features, and use forward shading instead
|
||||
if ( fd.features[MFT_ForwardShading] )
|
||||
{
|
||||
Parent::setTexData( stageDat, fd, passData, texIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( AdvancedLightBinManager::smBufferName );
|
||||
if( texTarget )
|
||||
{
|
||||
// HACK: We store this for use in DeferredRTLightingFeatHLSL::processPix()
|
||||
// which cannot deduce the texture unit itself.
|
||||
mLastTexIndex = texIndex;
|
||||
|
||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeferredBumpFeatHLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_PrePassConditioner] )
|
||||
{
|
||||
// There is an output conditioner active, so we need to supply a transform
|
||||
// to the pixel shader.
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// We need the view to tangent space transform in the pixel shader.
|
||||
getOutViewToTangent( componentList, meta, fd );
|
||||
|
||||
// Make sure there are texcoords
|
||||
if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] )
|
||||
{
|
||||
const bool useTexAnim = fd.features[MFT_TexAnim];
|
||||
|
||||
getOutTexCoord( "texCoord",
|
||||
"float2",
|
||||
true,
|
||||
useTexAnim,
|
||||
meta,
|
||||
componentList );
|
||||
|
||||
if ( fd.features.hasFeature( MFT_DetailNormalMap ) )
|
||||
addOutDetailTexCoord( componentList,
|
||||
meta,
|
||||
useTexAnim );
|
||||
}
|
||||
|
||||
output = meta;
|
||||
}
|
||||
else if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_ForwardShading] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
output = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredBumpFeatHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// NULL output in case nothing gets handled
|
||||
output = NULL;
|
||||
|
||||
if( fd.features[MFT_PrePassConditioner] )
|
||||
{
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
Var *viewToTangent = getInViewToTangent( componentList );
|
||||
|
||||
// create texture var
|
||||
Var *bumpMap = getNormalMapTex();
|
||||
Var *texCoord = getInTexCoord( "texCoord", "float2", true, componentList );
|
||||
LangElement *texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord );
|
||||
|
||||
// create bump normal
|
||||
Var *bumpNorm = new Var;
|
||||
bumpNorm->setName( "bumpNormal" );
|
||||
bumpNorm->setType( "float4" );
|
||||
|
||||
LangElement *bumpNormDecl = new DecOp( bumpNorm );
|
||||
meta->addStatement( expandNormalMap( texOp, bumpNormDecl, bumpNorm, fd ) );
|
||||
|
||||
// If we have a detail normal map we add the xy coords of
|
||||
// it to the base normal map. This gives us the effect we
|
||||
// want with few instructions and minial artifacts.
|
||||
if ( fd.features.hasFeature( MFT_DetailNormalMap ) )
|
||||
{
|
||||
bumpMap = new Var;
|
||||
bumpMap->setType( "sampler2D" );
|
||||
bumpMap->setName( "detailBumpMap" );
|
||||
bumpMap->uniform = true;
|
||||
bumpMap->sampler = true;
|
||||
bumpMap->constNum = Var::getTexUnitNum();
|
||||
|
||||
texCoord = getInTexCoord( "detCoord", "float2", true, componentList );
|
||||
texOp = new GenOp( "tex2D(@, @)", bumpMap, texCoord );
|
||||
|
||||
Var *detailBump = new Var;
|
||||
detailBump->setName( "detailBump" );
|
||||
detailBump->setType( "float4" );
|
||||
meta->addStatement( expandNormalMap( texOp, new DecOp( detailBump ), detailBump, fd ) );
|
||||
|
||||
Var *detailBumpScale = new Var;
|
||||
detailBumpScale->setType( "float" );
|
||||
detailBumpScale->setName( "detailBumpStrength" );
|
||||
detailBumpScale->uniform = true;
|
||||
detailBumpScale->constSortPos = cspPass;
|
||||
meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) );
|
||||
}
|
||||
|
||||
// This var is read from GBufferConditionerHLSL and
|
||||
// used in the prepass output.
|
||||
//
|
||||
// By using the 'half' type here we get a bunch of partial
|
||||
// precision optimized code on further operations on the normal
|
||||
// which helps alot on older Geforce cards.
|
||||
//
|
||||
Var *gbNormal = new Var;
|
||||
gbNormal->setName( "gbNormal" );
|
||||
gbNormal->setType( "half3" );
|
||||
LangElement *gbNormalDecl = new DecOp( gbNormal );
|
||||
|
||||
// Normalize is done later...
|
||||
// Note: The reverse mul order is intentional. Affine matrix.
|
||||
meta->addStatement( new GenOp( " @ = (half3)mul( @.xyz, @ );\r\n", gbNormalDecl, bumpNorm, viewToTangent ) );
|
||||
|
||||
output = meta;
|
||||
return;
|
||||
}
|
||||
else if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_ForwardShading] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
else if ( fd.features[MFT_PixSpecular] && !fd.features[MFT_SpecularMap] )
|
||||
{
|
||||
Var *bumpSample = (Var *)LangElement::find( "bumpSample" );
|
||||
if( bumpSample == NULL )
|
||||
{
|
||||
Var *texCoord = getInTexCoord( "texCoord", "float2", true, componentList );
|
||||
|
||||
Var *bumpMap = getNormalMapTex();
|
||||
|
||||
bumpSample = new Var;
|
||||
bumpSample->setType( "float4" );
|
||||
bumpSample->setName( "bumpSample" );
|
||||
LangElement *bumpSampleDecl = new DecOp( bumpSample );
|
||||
|
||||
output = new GenOp( " @ = tex2D(@, @);\r\n", bumpSampleDecl, bumpMap, texCoord );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredBumpFeatHLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_ForwardShading] ||
|
||||
fd.features[MFT_Parallax] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
return Parent::getResources( fd );
|
||||
|
||||
Resources res;
|
||||
if(!fd.features[MFT_SpecularMap])
|
||||
{
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
|
||||
if ( fd.features[MFT_PrePassConditioner] &&
|
||||
fd.features.hasFeature( MFT_DetailNormalMap ) )
|
||||
{
|
||||
res.numTex += 1;
|
||||
if ( !fd.features.hasFeature( MFT_DetailMap ) )
|
||||
res.numTexReg += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredBumpFeatHLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
if ( fd.materialFeatures[MFT_NormalsOut] ||
|
||||
fd.features[MFT_ForwardShading] ||
|
||||
!fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::setTexData( stageDat, fd, passData, texIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !fd.features[MFT_Parallax] && !fd.features[MFT_SpecularMap] &&
|
||||
( fd.features[MFT_PrePassConditioner] ||
|
||||
fd.features[MFT_PixSpecular] ) )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::Bump;
|
||||
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap );
|
||||
|
||||
if ( fd.features[MFT_PrePassConditioner] &&
|
||||
fd.features.hasFeature( MFT_DetailNormalMap ) )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::DetailBump;
|
||||
passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeferredPixelSpecularHLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processVert( componentList, fd );
|
||||
return;
|
||||
}
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
void DeferredPixelSpecularHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
Parent::processPix( componentList, fd );
|
||||
return;
|
||||
}
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
Var *specular = new Var;
|
||||
specular->setType( "float" );
|
||||
specular->setName( "specular" );
|
||||
LangElement * specDecl = new DecOp( specular );
|
||||
|
||||
Var *specCol = (Var*)LangElement::find( "specularColor" );
|
||||
if(specCol == NULL)
|
||||
{
|
||||
specCol = new Var;
|
||||
specCol->setType( "float4" );
|
||||
specCol->setName( "specularColor" );
|
||||
specCol->uniform = true;
|
||||
specCol->constSortPos = cspPotentialPrimitive;
|
||||
}
|
||||
|
||||
Var *specPow = new Var;
|
||||
specPow->setType( "float" );
|
||||
specPow->setName( "specularPower" );
|
||||
|
||||
// If the gloss map flag is set, than the specular power is in the alpha
|
||||
// channel of the specular map
|
||||
if( fd.features[ MFT_GlossMap ] )
|
||||
meta->addStatement( new GenOp( " @ = @.a * 255;\r\n", new DecOp( specPow ), specCol ) );
|
||||
else
|
||||
{
|
||||
specPow->uniform = true;
|
||||
specPow->constSortPos = cspPotentialPrimitive;
|
||||
}
|
||||
|
||||
Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" );
|
||||
Var *d_specular = (Var*)LangElement::find( "d_specular" );
|
||||
Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" );
|
||||
|
||||
AssertFatal( lightInfoSamp && d_specular && d_NL_Att,
|
||||
"DeferredPixelSpecularHLSL::processPix - Something hosed the deferred features!" );
|
||||
|
||||
// (a^m)^n = a^(m*n)
|
||||
meta->addStatement( new GenOp( " @ = pow( @, ceil(@ / AL_ConstantSpecularPower)) * @;\r\n",
|
||||
specDecl, d_specular, specPow, d_NL_Att ) );
|
||||
|
||||
LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular );
|
||||
LangElement *final = specMul;
|
||||
|
||||
// We we have a normal map then mask the specular
|
||||
if( !fd.features[MFT_SpecularMap] && fd.features[MFT_NormalMap] )
|
||||
{
|
||||
Var *bumpSample = (Var*)LangElement::find( "bumpSample" );
|
||||
final = new GenOp( "@ * @.a", final, bumpSample );
|
||||
}
|
||||
|
||||
// add to color
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( final, Material::Add ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources DeferredPixelSpecularHLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
return Parent::getResources( fd );
|
||||
|
||||
Resources res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ShaderFeature::Resources DeferredMinnaertHLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
Resources res;
|
||||
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
res.numTex = 1;
|
||||
res.numTexReg = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void DeferredMinnaertHLSL::setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex )
|
||||
{
|
||||
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find(RenderPrePassMgr::BufferName);
|
||||
if ( texTarget )
|
||||
{
|
||||
passData.mTexType[ texIndex ] = Material::TexTarget;
|
||||
passData.mTexSlot[ texIndex++ ].texTarget = texTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredMinnaertHLSL::processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
if( !fd.features[MFT_ForwardShading] && fd.features[MFT_RTLighting] )
|
||||
{
|
||||
// Pull in the uncondition method for the g buffer
|
||||
NamedTexTarget *texTarget = NamedTexTarget::find( RenderPrePassMgr::BufferName );
|
||||
if ( texTarget && texTarget->getConditioner() )
|
||||
{
|
||||
ConditionerMethodDependency *unconditionMethod = texTarget->getConditioner()->getConditionerMethodDependency(ConditionerFeature::UnconditionMethod);
|
||||
unconditionMethod->createMethodMacro( String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition", macros );
|
||||
addDependency(unconditionMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeferredMinnaertHLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we pass the world space position to the
|
||||
// pixel shader so we can calculate a view vector.
|
||||
MultiLine *meta = new MultiLine;
|
||||
addOutWsPosition( componentList, fd.features[MFT_UseInstancing], meta );
|
||||
output = meta;
|
||||
}
|
||||
|
||||
void DeferredMinnaertHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Var *minnaertConstant = new Var;
|
||||
minnaertConstant->setType( "float" );
|
||||
minnaertConstant->setName( "minnaertConstant" );
|
||||
minnaertConstant->uniform = true;
|
||||
minnaertConstant->constSortPos = cspPotentialPrimitive;
|
||||
|
||||
// create texture var
|
||||
Var *prepassBuffer = new Var;
|
||||
prepassBuffer->setType( "sampler2D" );
|
||||
prepassBuffer->setName( "prepassBuffer" );
|
||||
prepassBuffer->uniform = true;
|
||||
prepassBuffer->sampler = true;
|
||||
prepassBuffer->constNum = Var::getTexUnitNum(); // used as texture unit num here
|
||||
|
||||
// Texture coord
|
||||
Var *uvScene = (Var*) LangElement::find( "uvScene" );
|
||||
AssertFatal(uvScene != NULL, "Unable to find UVScene, no RTLighting feature?");
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// Get the world space view vector.
|
||||
Var *wsViewVec = getWsView( getInWsPosition( componentList ), meta );
|
||||
|
||||
String unconditionPrePassMethod = String::ToLower(RenderPrePassMgr::BufferName) + "Uncondition";
|
||||
|
||||
Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" );
|
||||
|
||||
meta->addStatement( new GenOp( avar( " float4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) );
|
||||
meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) );
|
||||
meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) );
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
|
||||
void DeferredSubSurfaceHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If there is no deferred information, bail on this feature
|
||||
if( fd.features[MFT_ForwardShading] || !fd.features[MFT_RTLighting] )
|
||||
{
|
||||
output = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
Var *subSurfaceParams = new Var;
|
||||
subSurfaceParams->setType( "float4" );
|
||||
subSurfaceParams->setName( "subSurfaceParams" );
|
||||
subSurfaceParams->uniform = true;
|
||||
subSurfaceParams->constSortPos = cspPotentialPrimitive;
|
||||
|
||||
Var *d_lightcolor = (Var*)LangElement::find( "d_lightcolor" );
|
||||
Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" );
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) );
|
||||
meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) );
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _DEFERREDFEATURESHLSL_H_
|
||||
#define _DEFERREDFEATURESHLSL_H_
|
||||
|
||||
#include "shaderGen/HLSL/shaderFeatureHLSL.h"
|
||||
#include "shaderGen/HLSL/bumpHLSL.h"
|
||||
#include "shaderGen/HLSL/pixSpecularHLSL.h"
|
||||
|
||||
class ConditionerMethodDependency;
|
||||
|
||||
|
||||
/// Lights the pixel by sampling from the light prepass
|
||||
/// buffer. It will fall back to forward lighting
|
||||
/// functionality for non-deferred rendered surfaces.
|
||||
///
|
||||
/// Also note that this feature is only used in the
|
||||
/// forward rendering pass. It is not used during the
|
||||
/// prepass step.
|
||||
///
|
||||
class DeferredRTLightingFeatHLSL : public RTLightingFeatHLSL
|
||||
{
|
||||
typedef RTLightingFeatHLSL Parent;
|
||||
|
||||
protected:
|
||||
|
||||
/// @see DeferredRTLightingFeatHLSL::processPix()
|
||||
U32 mLastTexIndex;
|
||||
|
||||
public:
|
||||
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Material::BlendOp getBlendOp(){ return Material::None; }
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Deferred RT Lighting";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// This is used during the
|
||||
class DeferredBumpFeatHLSL : public BumpFeatHLSL
|
||||
{
|
||||
typedef BumpFeatHLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Material::BlendOp getBlendOp() { return Material::LerpAlpha; }
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Bumpmap [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Generates specular highlights in the forward pass
|
||||
/// from the light prepass buffer.
|
||||
class DeferredPixelSpecularHLSL : public PixelSpecularHLSL
|
||||
{
|
||||
typedef PixelSpecularHLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Pixel Specular [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
class DeferredMinnaertHLSL : public ShaderFeatureHLSL
|
||||
{
|
||||
typedef ShaderFeatureHLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual void processPixMacros( Vector<GFXShaderMacro> ¯os,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
|
||||
virtual void setTexData( Material::StageData &stageDat,
|
||||
const MaterialFeatureData &fd,
|
||||
RenderPassData &passData,
|
||||
U32 &texIndex );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Minnaert Shading [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
class DeferredSubSurfaceHLSL : public ShaderFeatureHLSL
|
||||
{
|
||||
typedef ShaderFeatureHLSL Parent;
|
||||
|
||||
public:
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd );
|
||||
|
||||
virtual String getName()
|
||||
{
|
||||
return "Sub-Surface Approximation [Deferred]";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _DEFERREDFEATURESHLSL_H_
|
||||
404
Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp
Normal file
404
Engine/source/lighting/advanced/hlsl/gBufferConditionerHLSL.cpp
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/advanced/hlsl/gBufferConditionerHLSL.h"
|
||||
|
||||
#include "shaderGen/featureMgr.h"
|
||||
#include "gfx/gfxStringEnumTranslate.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "materials/materialFeatureData.h"
|
||||
#include "shaderGen/hlsl/shaderFeatureHLSL.h"
|
||||
|
||||
|
||||
GBufferConditionerHLSL::GBufferConditionerHLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace ) :
|
||||
Parent( bufferFormat )
|
||||
{
|
||||
// Figure out how we should store the normal data. These are the defaults.
|
||||
mCanWriteNegativeValues = false;
|
||||
mNormalStorageType = CartesianXYZ;
|
||||
|
||||
// Note: We clear to a depth 1 (the w component) so
|
||||
// that the unrendered parts of the scene end up
|
||||
// farthest to the camera.
|
||||
const NormalStorage &twoCmpNrmStorageType = ( nrmSpace == WorldSpace ? Spherical : LambertAzimuthal );
|
||||
switch(bufferFormat)
|
||||
{
|
||||
case GFXFormatR8G8B8A8:
|
||||
mNormalStorageType = twoCmpNrmStorageType;
|
||||
mBitsPerChannel = 8;
|
||||
break;
|
||||
|
||||
case GFXFormatR16G16B16A16F:
|
||||
// Floating point buffers don't need to encode negative values
|
||||
mCanWriteNegativeValues = true;
|
||||
mNormalStorageType = twoCmpNrmStorageType;
|
||||
mBitsPerChannel = 16;
|
||||
break;
|
||||
|
||||
// Store a 32bit depth with a sperical normal in the
|
||||
// integer 16 format. This gives us perfect depth
|
||||
// precision and high quality normals within a 64bit
|
||||
// buffer format.
|
||||
case GFXFormatR16G16B16A16:
|
||||
mNormalStorageType = twoCmpNrmStorageType;
|
||||
mBitsPerChannel = 16;
|
||||
break;
|
||||
|
||||
case GFXFormatR32G32B32A32F:
|
||||
mCanWriteNegativeValues = true;
|
||||
mNormalStorageType = CartesianXYZ;
|
||||
mBitsPerChannel = 32;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Unsupported G-Buffer format");
|
||||
}
|
||||
}
|
||||
|
||||
GBufferConditionerHLSL::~GBufferConditionerHLSL()
|
||||
{
|
||||
}
|
||||
|
||||
void GBufferConditionerHLSL::processVert( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// If we have a normal map then that feature will
|
||||
// take care of passing gbNormal to the pixel shader.
|
||||
if ( fd.features[MFT_NormalMap] )
|
||||
return;
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
output = meta;
|
||||
|
||||
// grab incoming vert normal
|
||||
Var *inNormal = (Var*) LangElement::find( "normal" );
|
||||
AssertFatal( inNormal, "Something went bad with ShaderGen. The normal should be already defined." );
|
||||
|
||||
// grab output for gbuffer normal
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *outNormal = connectComp->getElement( RT_TEXCOORD );
|
||||
outNormal->setName( "gbNormal" );
|
||||
outNormal->setStructName( "OUT" );
|
||||
outNormal->setType( "float3" );
|
||||
|
||||
if( !fd.features[MFT_ParticleNormal] )
|
||||
{
|
||||
// Kick out the view-space normal
|
||||
|
||||
// TODO: Total hack because Conditioner is directly derived
|
||||
// from ShaderFeature and not from ShaderFeatureHLSL.
|
||||
NamedFeatureHLSL dummy( String::EmptyString );
|
||||
dummy.mInstancingFormat = mInstancingFormat;
|
||||
Var *worldViewOnly = dummy.getWorldView( componentList, fd.features[MFT_UseInstancing], meta );
|
||||
|
||||
meta->addStatement( new GenOp(" @ = mul(@, float4( normalize(@), 0.0 ) ).xyz;\r\n",
|
||||
outNormal, worldViewOnly, inNormal ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume the particle normal generator has already put this in view space
|
||||
// and normalized it
|
||||
meta->addStatement( new GenOp( " @ = @;\r\n", outNormal, inNormal ) );
|
||||
}
|
||||
}
|
||||
|
||||
void GBufferConditionerHLSL::processPix( Vector<ShaderComponent*> &componentList,
|
||||
const MaterialFeatureData &fd )
|
||||
{
|
||||
// sanity
|
||||
AssertFatal( fd.features[MFT_EyeSpaceDepthOut], "No depth-out feature enabled! Bad news!" );
|
||||
|
||||
MultiLine *meta = new MultiLine;
|
||||
|
||||
// grab connector normal
|
||||
ShaderConnector *connectComp = dynamic_cast<ShaderConnector *>( componentList[C_CONNECTOR] );
|
||||
Var *gbNormal = (Var*) LangElement::find( "gbNormal" );
|
||||
if( !gbNormal )
|
||||
{
|
||||
gbNormal = connectComp->getElement( RT_TEXCOORD );
|
||||
gbNormal->setName( "gbNormal" );
|
||||
gbNormal->setStructName( "IN" );
|
||||
gbNormal->setType( "float3" );
|
||||
gbNormal->mapsToSampler = false;
|
||||
gbNormal->uniform = false;
|
||||
}
|
||||
|
||||
// find depth
|
||||
ShaderFeature *depthFeat = FEATUREMGR->getByType( MFT_EyeSpaceDepthOut );
|
||||
AssertFatal( depthFeat != NULL, "No eye space depth feature found!" );
|
||||
|
||||
Var *depth = (Var*) LangElement::find(depthFeat->getOutputVarName());
|
||||
AssertFatal( depth, "Something went bad with ShaderGen. The depth should be already generated by the EyeSpaceDepthOut feature." );
|
||||
|
||||
|
||||
Var *unconditionedOut = new Var;
|
||||
unconditionedOut->setType("float4");
|
||||
unconditionedOut->setName("normal_depth");
|
||||
|
||||
LangElement *outputDecl = new DecOp( unconditionedOut );
|
||||
|
||||
// If we're doing prepass blending then we need
|
||||
// to steal away the alpha channel before the
|
||||
// conditioner stomps on it.
|
||||
Var *alphaVal = NULL;
|
||||
if ( fd.features[ MFT_IsTranslucentZWrite ] )
|
||||
{
|
||||
alphaVal = new Var( "outAlpha", "float" );
|
||||
meta->addStatement( new GenOp( " @ = OUT.col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) );
|
||||
}
|
||||
|
||||
// If using interlaced normals, invert the normal
|
||||
if(fd.features[MFT_InterlacedPrePass])
|
||||
{
|
||||
// NOTE: Its safe to not call ShaderFeatureHLSL::addOutVpos() in the vertex
|
||||
// shader as for SM 3.0 nothing is needed there.
|
||||
Var *Vpos = ShaderFeatureHLSL::getInVpos( meta, componentList );
|
||||
|
||||
Var *iGBNormal = new Var( "interlacedGBNormal", "float3" );
|
||||
meta->addStatement(new GenOp(" @ = (frac(@.y * 0.5) < 0.1 ? reflect(@, float3(0.0, -1.0, 0.0)) : @);\r\n", new DecOp(iGBNormal), Vpos, gbNormal, gbNormal));
|
||||
gbNormal = iGBNormal;
|
||||
}
|
||||
|
||||
// NOTE: We renormalize the normal here as they
|
||||
// will not stay normalized during interpolation.
|
||||
meta->addStatement( new GenOp(" @ = @;", outputDecl, new GenOp( "float4(normalize(@), @)", gbNormal, depth ) ) );
|
||||
meta->addStatement( assignOutput( unconditionedOut ) );
|
||||
|
||||
// If we have an alpha var then we're doing prepass lerp blending.
|
||||
if ( alphaVal )
|
||||
{
|
||||
Var *outColor = (Var*)LangElement::find( getOutputTargetVarName( DefaultTarget ) );
|
||||
meta->addStatement( new GenOp( " @.ba = float2( 0, @ ); // MFT_IsTranslucentZWrite\r\n", outColor, alphaVal ) );
|
||||
}
|
||||
|
||||
output = meta;
|
||||
}
|
||||
|
||||
ShaderFeature::Resources GBufferConditionerHLSL::getResources( const MaterialFeatureData &fd )
|
||||
{
|
||||
Resources res;
|
||||
|
||||
// Passing from VS->PS:
|
||||
// - world space normal (gbNormal)
|
||||
res.numTexReg = 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Var* GBufferConditionerHLSL::printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta )
|
||||
{
|
||||
const bool isCondition = ( methodType == ConditionerFeature::ConditionMethod );
|
||||
|
||||
Var *retVal = NULL;
|
||||
|
||||
// The uncondition method inputs are changed
|
||||
if( isCondition )
|
||||
retVal = Parent::printMethodHeader( methodType, methodName, stream, meta );
|
||||
else
|
||||
{
|
||||
Var *methodVar = new Var;
|
||||
methodVar->setName(methodName);
|
||||
methodVar->setType("inline float4");
|
||||
DecOp *methodDecl = new DecOp(methodVar);
|
||||
|
||||
Var *prepassSampler = new Var;
|
||||
prepassSampler->setName("prepassSamplerVar");
|
||||
prepassSampler->setType("sampler2D");
|
||||
DecOp *prepassSamplerDecl = new DecOp(prepassSampler);
|
||||
|
||||
Var *screenUV = new Var;
|
||||
screenUV->setName("screenUVVar");
|
||||
screenUV->setType("float2");
|
||||
DecOp *screenUVDecl = new DecOp(screenUV);
|
||||
|
||||
Var *bufferSample = new Var;
|
||||
bufferSample->setName("bufferSample");
|
||||
bufferSample->setType("float4");
|
||||
DecOp *bufferSampleDecl = new DecOp(bufferSample);
|
||||
|
||||
meta->addStatement( new GenOp( "@(@, @)\r\n", methodDecl, prepassSamplerDecl, screenUVDecl ) );
|
||||
|
||||
meta->addStatement( new GenOp( "{\r\n" ) );
|
||||
|
||||
meta->addStatement( new GenOp( " // Sampler g-buffer\r\n" ) );
|
||||
|
||||
#ifdef TORQUE_OS_XENON
|
||||
meta->addStatement( new GenOp( " @;\r\n", bufferSampleDecl ) );
|
||||
meta->addStatement( new GenOp( " asm { tfetch2D @, @, @, MagFilter = point, MinFilter = point, MipFilter = point };\r\n", bufferSample, screenUV, prepassSampler ) );
|
||||
#else
|
||||
// The gbuffer has no mipmaps, so use tex2dlod when
|
||||
// possible so that the shader compiler can optimize.
|
||||
meta->addStatement( new GenOp( " #if TORQUE_SM >= 30\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
|
||||
meta->addStatement( new GenOp( " #else\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
|
||||
meta->addStatement( new GenOp( " #endif\r\n\r\n" ) );
|
||||
#endif
|
||||
|
||||
// We don't use this way of passing var's around, so this should cause a crash
|
||||
// if something uses this improperly
|
||||
retVal = bufferSample;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
GenOp* GBufferConditionerHLSL::_posnegEncode( GenOp *val )
|
||||
{
|
||||
if(mNormalStorageType == LambertAzimuthal)
|
||||
return mCanWriteNegativeValues ? val : new GenOp(avar("(%f * (@ + %f))", 1.0f/(M_SQRT2_F * 2.0f), M_SQRT2_F), val);
|
||||
else
|
||||
return mCanWriteNegativeValues ? val : new GenOp("(0.5 * (@ + 1.0))", val);
|
||||
}
|
||||
|
||||
GenOp* GBufferConditionerHLSL::_posnegDecode( GenOp *val )
|
||||
{
|
||||
if(mNormalStorageType == LambertAzimuthal)
|
||||
return mCanWriteNegativeValues ? val : new GenOp(avar("(@ * %f - %f)", M_SQRT2_F * 2.0f, M_SQRT2_F), val);
|
||||
else
|
||||
return mCanWriteNegativeValues ? val : new GenOp("(@ * 2.0 - 1.0)", val);
|
||||
}
|
||||
|
||||
Var* GBufferConditionerHLSL::_conditionOutput( Var *unconditionedOutput, MultiLine *meta )
|
||||
{
|
||||
Var *retVar = new Var;
|
||||
retVar->setType("float4");
|
||||
retVar->setName("_gbConditionedOutput");
|
||||
LangElement *outputDecl = new DecOp( retVar );
|
||||
|
||||
switch(mNormalStorageType)
|
||||
{
|
||||
case CartesianXYZ:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xyz, depth)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl,
|
||||
_posnegEncode(new GenOp("@.xyz", unconditionedOutput)), unconditionedOutput ) );
|
||||
break;
|
||||
|
||||
case CartesianXY:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, @.a);", outputDecl,
|
||||
_posnegEncode(new GenOp("float3(@.xy, sign(@.z))", unconditionedOutput, unconditionedOutput)), unconditionedOutput ) );
|
||||
break;
|
||||
|
||||
case Spherical:
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl,
|
||||
_posnegEncode(new GenOp("float2(atan2(@.y, @.x) / 3.14159265358979323846f, @.z)", unconditionedOutput, unconditionedOutput, unconditionedOutput ) ),
|
||||
unconditionedOutput ) );
|
||||
|
||||
// HACK: This fixes the noise present when using a floating point
|
||||
// gbuffer on Geforce cards and the "flat areas unlit" issues.
|
||||
//
|
||||
// We need work around atan2() above to fix this issue correctly
|
||||
// without the extra overhead of this test.
|
||||
//
|
||||
meta->addStatement( new GenOp( " if ( abs( dot( @.xyz, float3( 0.0, 0.0, 1.0 ) ) ) > 0.999f ) @ = float4( 0, 1 * sign( @.z ), 0, @.a );\r\n",
|
||||
unconditionedOutput, retVar, unconditionedOutput, unconditionedOutput ) );
|
||||
break;
|
||||
|
||||
case LambertAzimuthal:
|
||||
//http://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection
|
||||
//
|
||||
// Note we're casting to half to use partial precision
|
||||
// sqrt which is much faster on older Geforces while
|
||||
// still being acceptable for normals.
|
||||
//
|
||||
meta->addStatement( new GenOp( " // g-buffer conditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, 0.0, @.a);\r\n", outputDecl,
|
||||
_posnegEncode(new GenOp("sqrt(half(2.0/(1.0 - @.y))) * half2(@.xz)", unconditionedOutput, unconditionedOutput)),
|
||||
unconditionedOutput ) );
|
||||
break;
|
||||
}
|
||||
|
||||
// Encode depth into two channels
|
||||
if(mNormalStorageType != CartesianXYZ)
|
||||
{
|
||||
const U64 maxValPerChannel = 1 << mBitsPerChannel;
|
||||
meta->addStatement( new GenOp( " \r\n // Encode depth into hi/lo\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " float2 _tempDepth = frac(@.a * float2(1.0, %llu.0));\r\n", maxValPerChannel - 1 ),
|
||||
unconditionedOutput ) );
|
||||
meta->addStatement( new GenOp( avar( " @.zw = _tempDepth.xy - _tempDepth.yy * float2(1.0/%llu.0, 0.0);\r\n\r\n", maxValPerChannel - 1 ),
|
||||
retVar ) );
|
||||
}
|
||||
|
||||
AssertFatal( retVar != NULL, avar( "Cannot condition output to buffer format: %s", GFXStringTextureFormat[getBufferFormat()] ) );
|
||||
return retVar;
|
||||
}
|
||||
|
||||
Var* GBufferConditionerHLSL::_unconditionInput( Var *conditionedInput, MultiLine *meta )
|
||||
{
|
||||
Var *retVar = new Var;
|
||||
retVar->setType("float4");
|
||||
retVar->setName("_gbUnconditionedInput");
|
||||
LangElement *outputDecl = new DecOp( retVar );
|
||||
|
||||
switch(mNormalStorageType)
|
||||
{
|
||||
case CartesianXYZ:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xyz, depth)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl,
|
||||
_posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) );
|
||||
break;
|
||||
|
||||
case CartesianXY:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.xy, depth Hi + z-sign, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(@, @.a);\r\n", outputDecl,
|
||||
_posnegDecode(new GenOp("@.xyz", conditionedInput)), conditionedInput ) );
|
||||
meta->addStatement( new GenOp( " @.z *= sqrt(1.0 - dot(@.xy, @.xy));\r\n", retVar, retVar, retVar ) );
|
||||
break;
|
||||
|
||||
case Spherical:
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.theta, normal.phi, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float2 spGPUAngles = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) );
|
||||
meta->addStatement( new GenOp( " float2 sincosTheta;\r\n" ) );
|
||||
meta->addStatement( new GenOp( " sincos(spGPUAngles.x * 3.14159265358979323846f, sincosTheta.x, sincosTheta.y);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float2 sincosPhi = float2(sqrt(1.0 - spGPUAngles.y * spGPUAngles.y), spGPUAngles.y);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4(sincosTheta.y * sincosPhi.x, sincosTheta.x * sincosPhi.x, sincosPhi.y, @.a);\r\n", outputDecl, conditionedInput ) );
|
||||
break;
|
||||
|
||||
case LambertAzimuthal:
|
||||
// Note we're casting to half to use partial precision
|
||||
// sqrt which is much faster on older Geforces while
|
||||
// still being acceptable for normals.
|
||||
//
|
||||
meta->addStatement( new GenOp( " // g-buffer unconditioner: float4(normal.X, normal.Y, depth Hi, depth Lo)\r\n" ) );
|
||||
meta->addStatement( new GenOp( " float2 _inpXY = @;\r\n", _posnegDecode(new GenOp("@.xy", conditionedInput)) ) );
|
||||
meta->addStatement( new GenOp( " float _xySQ = dot(_inpXY, _inpXY);\r\n" ) );
|
||||
meta->addStatement( new GenOp( " @ = float4( sqrt(half(1.0 - (_xySQ / 4.0))) * _inpXY, -1.0 + (_xySQ / 2.0), @.a).xzyw;\r\n", outputDecl, conditionedInput ) );
|
||||
break;
|
||||
}
|
||||
|
||||
// Recover depth from encoding
|
||||
if(mNormalStorageType != CartesianXYZ)
|
||||
{
|
||||
const U64 maxValPerChannel = 1 << mBitsPerChannel;
|
||||
meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) );
|
||||
meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ),
|
||||
retVar, conditionedInput ) );
|
||||
}
|
||||
|
||||
|
||||
AssertFatal( retVar != NULL, avar( "Cannot uncondition input from buffer format: %s", GFXStringTextureFormat[getBufferFormat()] ) );
|
||||
return retVar;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 _GBUFFER_CONDITIONER_HLSL_H_
|
||||
#define _GBUFFER_CONDITIONER_HLSL_H_
|
||||
|
||||
#ifndef _CONDITIONER_BASE_H_
|
||||
#include "shaderGen/conditionerFeature.h"
|
||||
#endif
|
||||
#ifndef _SHADEROP_H_
|
||||
#include "shaderGen/shaderOp.h"
|
||||
#endif
|
||||
|
||||
|
||||
///
|
||||
class GBufferConditionerHLSL : public ConditionerFeature
|
||||
{
|
||||
typedef ConditionerFeature Parent;
|
||||
|
||||
public:
|
||||
enum NormalStorage
|
||||
{
|
||||
CartesianXYZ,
|
||||
CartesianXY,
|
||||
Spherical,
|
||||
LambertAzimuthal,
|
||||
};
|
||||
|
||||
enum NormalSpace
|
||||
{
|
||||
WorldSpace,
|
||||
ViewSpace,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
NormalStorage mNormalStorageType;
|
||||
bool mCanWriteNegativeValues;
|
||||
U32 mBitsPerChannel;
|
||||
|
||||
public:
|
||||
|
||||
GBufferConditionerHLSL( const GFXFormat bufferFormat, const NormalSpace nrmSpace );
|
||||
virtual ~GBufferConditionerHLSL();
|
||||
|
||||
|
||||
virtual void processVert( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd );
|
||||
virtual void processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd );
|
||||
virtual Resources getResources( const MaterialFeatureData &fd );
|
||||
virtual String getName() { return "GBuffer Conditioner"; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual Var *printMethodHeader( MethodType methodType, const String &methodName, Stream &stream, MultiLine *meta );
|
||||
|
||||
virtual GenOp* _posnegEncode( GenOp *val );
|
||||
virtual GenOp* _posnegDecode( GenOp *val );
|
||||
virtual Var* _conditionOutput( Var *unconditionedOutput, MultiLine *meta );
|
||||
virtual Var* _unconditionInput( Var *conditionedInput, MultiLine *meta );
|
||||
};
|
||||
|
||||
#endif // _GBUFFER_CONDITIONER_HLSL_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue