mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Add support for both ies and cookie
Both ies and cookies can now exist on a light We are still not using all the capabilities of an IES profile, such as candela and luminance values we are just using them as a mask for the moment Issues compiling on mac and linux, will need to update the ies-loader to use torque methods instead of std::
This commit is contained in:
parent
a12d915180
commit
4417462499
|
|
@ -65,6 +65,21 @@ struct CompoundKey3
|
|||
bool operator==(const CompoundKey3 & compound) const { return key1==compound.key1 && key2==compound.key2 && key3==compound.key3; }
|
||||
};
|
||||
|
||||
template<class A, class B, class C, class D>
|
||||
struct CompoundKey4
|
||||
{
|
||||
A key1;
|
||||
B key2;
|
||||
C key3;
|
||||
D key4;
|
||||
|
||||
CompoundKey4() {};
|
||||
CompoundKey4(const A& a, const B& b, const C& c, const D& d) { key1 = a; key2 = b; key3 = c; key4 = d;};
|
||||
|
||||
bool operator==(const CompoundKey4& compound) const { return key1 == compound.key1 && key2 == compound.key2 && key3 == compound.key3 && key4 == compound.key4; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace DictHash
|
||||
{
|
||||
|
|
@ -110,6 +125,11 @@ namespace DictHash
|
|||
return hash(compound.key1) + hash(compound.key2) + hash(compound.key3);
|
||||
}
|
||||
|
||||
template<class A, class B, class C, class D>
|
||||
inline U32 hash(const CompoundKey4<A, B, C, D>& compound)
|
||||
{
|
||||
return hash(compound.key1) + hash(compound.key2) + hash(compound.key3) + hash(compound.key4);
|
||||
}
|
||||
U32 nextPrime(U32);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ void AdvancedLightBinManager::addLight( LightInfo *light )
|
|||
LightBinEntry lEntry;
|
||||
lEntry.lightInfo = light;
|
||||
lEntry.shadowMap = lsm;
|
||||
lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex() );
|
||||
lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex(), lsp->hasIesProfile() );
|
||||
|
||||
if( lightType == LightInfo::Spot )
|
||||
lEntry.vertBuffer = mLightManager->getConeMesh( lEntry.numPrims, lEntry.primBuffer );
|
||||
|
|
@ -399,9 +399,9 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
|
|||
sunLight->getCastShadows() &&
|
||||
!disableShadows &&
|
||||
sunLight->getExtended<ShadowMapParams>() )
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM, false );
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM );
|
||||
else
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None, false );
|
||||
vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None );
|
||||
|
||||
// Initialize and set the per-frame parameters after getting
|
||||
// the vector light material as we use lazy creation.
|
||||
|
|
@ -513,12 +513,13 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
|
|||
|
||||
AdvancedLightBinManager::LightMaterialInfo* AdvancedLightBinManager::_getLightMaterial( LightInfo::Type lightType,
|
||||
ShadowType shadowType,
|
||||
bool useCookieTex )
|
||||
bool useCookieTex,
|
||||
bool isPhotometric)
|
||||
{
|
||||
PROFILE_SCOPE( AdvancedLightBinManager_GetLightMaterial );
|
||||
|
||||
// Build the key.
|
||||
const LightMatKey key( lightType, shadowType, useCookieTex );
|
||||
const LightMatKey key( lightType, shadowType, useCookieTex, isPhotometric );
|
||||
|
||||
// See if we've already built this one.
|
||||
LightMatTable::Iterator iter = mLightMaterials.find( key );
|
||||
|
|
@ -558,6 +559,9 @@ AdvancedLightBinManager::LightMaterialInfo* AdvancedLightBinManager::_getLightMa
|
|||
if ( useCookieTex )
|
||||
shadowMacros.push_back( GFXShaderMacro( "USE_COOKIE_TEX" ) );
|
||||
|
||||
if(isPhotometric)
|
||||
shadowMacros.push_back(GFXShaderMacro("UES_PHOTOMETRIC_MASK"));
|
||||
|
||||
// Its safe to add the PSSM debug macro to all the materials.
|
||||
if ( smPSSMDebugRender )
|
||||
shadowMacros.push_back( GFXShaderMacro( "PSSM_DEBUG_RENDER" ) );
|
||||
|
|
|
|||
|
|
@ -233,14 +233,14 @@ protected:
|
|||
|
||||
static const GFXVertexFormat* smLightMatVertex[LightInfo::Count];
|
||||
|
||||
typedef CompoundKey3<LightInfo::Type,ShadowType,bool> LightMatKey;
|
||||
typedef CompoundKey4<LightInfo::Type,ShadowType,bool, 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 );
|
||||
LightMaterialInfo* _getLightMaterial( LightInfo::Type lightType, ShadowType shadowType, bool useCookieTex = false, bool isPhotometric = false );
|
||||
|
||||
///
|
||||
void _onShadowFilterChanged();
|
||||
|
|
|
|||
|
|
@ -277,6 +277,7 @@ void AdvancedLightManager::_initLightFields()
|
|||
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( iesProfile, TypeStringFilename, NULL );
|
||||
DEFINE_LIGHT_FIELD( cookie, TypeStringFilename, NULL );
|
||||
DEFINE_LIGHT_FIELD( numSplits, TypeS32, NULL );
|
||||
DEFINE_LIGHT_FIELD( logWeight, TypeF32, NULL );
|
||||
|
|
@ -300,6 +301,9 @@ void AdvancedLightManager::_initLightFields()
|
|||
ADD_LIGHT_FIELD( "shadowType", TYPEID< ShadowType >(), shadowType,
|
||||
"The type of shadow to use on this light." );
|
||||
|
||||
ADD_LIGHT_FIELD("iesProfile", TypeStringFilename, iesProfile,
|
||||
"A photometric profile for the light.");
|
||||
|
||||
ADD_LIGHT_FIELD( "cookie", TypeStringFilename, cookie,
|
||||
"A custom pattern texture which is projected from the light." );
|
||||
|
||||
|
|
@ -496,6 +500,17 @@ bool AdvancedLightManager::setTextureStage( const SceneData &sgData,
|
|||
|
||||
return true;
|
||||
}
|
||||
else if (currTexFlag == Material::PhotometricMask)
|
||||
{
|
||||
S32 reg = lsc->mIesProfileSC->getSamplerRegister();
|
||||
if (reg != -1 && sgData.lights[0])
|
||||
{
|
||||
ShadowMapParams* p = sgData.lights[0]->getExtended<ShadowMapParams>();
|
||||
GFX->setTexture(reg, p->getIesProfileTex());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -269,7 +269,8 @@ bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants*
|
|||
GFX->setTexture( reg, mShadowMapTex);
|
||||
|
||||
return true;
|
||||
} else if ( currTexFlag == Material::DynamicLightMask )
|
||||
}
|
||||
else if ( currTexFlag == Material::DynamicLightMask )
|
||||
{
|
||||
S32 reg = lsc->mCookieMapSC->getSamplerRegister();
|
||||
if ( reg != -1 )
|
||||
|
|
@ -284,6 +285,17 @@ bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants*
|
|||
|
||||
return true;
|
||||
}
|
||||
else if (currTexFlag == Material::PhotometricMask)
|
||||
{
|
||||
S32 reg = lsc->mIesProfileSC->getSamplerRegister();
|
||||
if (reg != -1)
|
||||
{
|
||||
ShadowMapParams* p = mLight->getExtended<ShadowMapParams>();
|
||||
GFX->setTexture(reg, p->getIesProfileTex());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -430,6 +442,7 @@ LightingShaderConstants::LightingShaderConstants()
|
|||
mShadowMapSC(NULL),
|
||||
mShadowMapSizeSC(NULL),
|
||||
mCookieMapSC(NULL),
|
||||
mIesProfileSC(NULL),
|
||||
mRandomDirsConst(NULL),
|
||||
mShadowSoftnessConst(NULL),
|
||||
mAtlasXOffsetSC(NULL),
|
||||
|
|
@ -490,6 +503,7 @@ void LightingShaderConstants::init(GFXShader* shader)
|
|||
mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize");
|
||||
|
||||
mCookieMapSC = shader->getShaderConstHandle("$cookieMap");
|
||||
mIesProfileSC = shader->getShaderConstHandle("$iesProfile");
|
||||
|
||||
mShadowSoftnessConst = shader->getShaderConstHandle("$shadowSoftness");
|
||||
mAtlasXOffsetSC = shader->getShaderConstHandle("$atlasXOffset");
|
||||
|
|
@ -542,7 +556,8 @@ ShadowMapParams::ShadowMapParams( LightInfo *light )
|
|||
fadeStartDist = 75.0f;
|
||||
lastSplitTerrainOnly = false;
|
||||
mQuery = GFX->createOcclusionQuery();
|
||||
cookie = StringTable->EmptyString();;
|
||||
cookie = StringTable->EmptyString();
|
||||
iesProfile = StringTable->EmptyString();
|
||||
|
||||
_validate();
|
||||
}
|
||||
|
|
@ -662,6 +677,22 @@ GFXTextureObject* ShadowMapParams::getCookieTex()
|
|||
return mCookieTex.getPointer();
|
||||
}
|
||||
|
||||
GFXTextureObject* ShadowMapParams::getIesProfileTex()
|
||||
{
|
||||
if (hasIesProfile() &&
|
||||
(mIesTex.isNull() ||
|
||||
iesProfile != StringTable->insert(mIesTex->getPath().c_str())))
|
||||
{
|
||||
mIesTex.set(iesProfile,
|
||||
&GFXStaticTextureSRGBProfile,
|
||||
"ShadowMapParams::getIesProfileTex()");
|
||||
}
|
||||
else if (!hasIesProfile())
|
||||
mIesTex = NULL;
|
||||
|
||||
return mIesTex.getPointer();
|
||||
}
|
||||
|
||||
GFXCubemap* ShadowMapParams::getCookieCubeTex()
|
||||
{
|
||||
if ( hasCookieTex() &&
|
||||
|
|
@ -695,6 +726,7 @@ void ShadowMapParams::packUpdate( BitStream *stream ) const
|
|||
stream->write( texSize );
|
||||
|
||||
stream->writeString( cookie );
|
||||
stream->writeString( iesProfile );
|
||||
|
||||
stream->write( numSplits );
|
||||
stream->write( logWeight );
|
||||
|
|
@ -725,6 +757,7 @@ void ShadowMapParams::unpackUpdate( BitStream *stream )
|
|||
stream->read( &texSize );
|
||||
|
||||
cookie = stream->readSTString();
|
||||
iesProfile = stream->readSTString();
|
||||
|
||||
stream->read( &numSplits );
|
||||
stream->read( &logWeight );
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ struct LightingShaderConstants
|
|||
GFXShaderConstHandle* mShadowMapSizeSC;
|
||||
|
||||
GFXShaderConstHandle* mCookieMapSC;
|
||||
GFXShaderConstHandle* mIesProfileSC;
|
||||
|
||||
GFXShaderConstHandle* mRandomDirsConst;
|
||||
GFXShaderConstHandle* mShadowSoftnessConst;
|
||||
|
|
@ -289,11 +290,14 @@ public:
|
|||
LightShadowMap* getOrCreateShadowMap();
|
||||
|
||||
bool hasCookieTex() const { return cookie != StringTable->EmptyString(); }
|
||||
bool hasIesProfile() const { return iesProfile != StringTable->EmptyString(); }
|
||||
|
||||
GFXOcclusionQuery* getOcclusionQuery() const { return mQuery; }
|
||||
|
||||
GFXTextureObject* getCookieTex();
|
||||
|
||||
GFXTextureObject* getIesProfileTex();
|
||||
|
||||
GFXCubemap* getCookieCubeTex();
|
||||
|
||||
// Validates the parameters after a field is changed.
|
||||
|
|
@ -313,6 +317,8 @@ protected:
|
|||
|
||||
GFXCubemapHandle mCookieCubeTex;
|
||||
|
||||
GFXTexHandle mIesTex;
|
||||
|
||||
public:
|
||||
|
||||
// We're leaving these public for easy access
|
||||
|
|
@ -326,6 +332,7 @@ public:
|
|||
|
||||
///
|
||||
StringTableEntry cookie;
|
||||
StringTableEntry iesProfile;
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ public:
|
|||
Misc,
|
||||
DynamicLight,
|
||||
DynamicLightMask,
|
||||
PhotometricMask,
|
||||
NormalizeCube,
|
||||
TexTarget,
|
||||
AccuMap,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,14 @@ void ProcessedCustomMaterial::_setStageData()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (filename.equal(String("$photometricmask"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::PhotometricMask;
|
||||
rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
|
||||
mMaxTex = i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(filename.equal(String("$lightmap"), String::NoCase))
|
||||
{
|
||||
rpd->mTexType[i] = Material::Lightmap;
|
||||
|
|
|
|||
|
|
@ -107,10 +107,13 @@ TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1);
|
|||
#include "softShadow.hlsl"
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 3);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 4);
|
||||
#ifdef USE_COOKIE_TEX
|
||||
/// The texture for cookie rendering.
|
||||
#ifdef SHADOW_CUBE
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(cookieMap, 5);
|
||||
#else
|
||||
TORQUE_UNIFORM_SAMPLER2D(cookieMap, 5);
|
||||
#endif
|
||||
TORQUE_UNIFORM_SAMPLER2D(iesProfile, 6);
|
||||
|
||||
uniform float4 rtParams0;
|
||||
uniform float4 lightColor;
|
||||
|
|
@ -159,8 +162,8 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
{
|
||||
float distToLight = dist / lightRange;
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
|
||||
float shadow = 1.0;
|
||||
float3 lightCol = lightColor.rgb;
|
||||
float shadow = 1.0;
|
||||
#ifndef NO_SHADOW
|
||||
if (getFlag(surface.matFlag, 0)) //also skip if we don't recieve shadows
|
||||
{
|
||||
|
|
@ -176,8 +179,21 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
#endif
|
||||
}
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
float3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
// Lookup the cookie sample.
|
||||
#ifdef SHADOW_CUBE
|
||||
float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L));
|
||||
#else
|
||||
float2 cookieCoord = decodeShadowCoord( mul( worldToLightProj, -surfaceToLight.L ) ).xy;
|
||||
float4 cookie = TORQUE_TEX2D(cookieMap, cookieCoord);
|
||||
#endif
|
||||
// Multiply the light with the cookie tex.
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
#ifdef DIFFUSE_LIGHT_VIZ
|
||||
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
|
||||
float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
|
||||
|
|
@ -210,13 +226,13 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
//get punctual light contribution
|
||||
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadow);
|
||||
|
||||
#ifdef USE_COOKIE_TEX
|
||||
#ifdef UES_PHOTOMETRIC_MASK
|
||||
// Lookup the cookie sample.d
|
||||
float cosTheta = dot(-surfaceToLight.L, lightDirection);
|
||||
float angle = acos(cosTheta) * ( M_1OVER_PI_F);
|
||||
float cookie = TORQUE_TEX2D(cookieMap, float2(angle, 0.0)).r;
|
||||
// Multiply the light with the cookie tex.
|
||||
lighting *= cookie;
|
||||
float iesMask = TORQUE_TEX2D(iesProfile, float2(angle, 0.0)).r;
|
||||
// Multiply the light with the iesMask tex.
|
||||
lighting *= iesMask;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,11 +42,10 @@ TORQUE_UNIFORM_SAMPLER2D(shadowMap, 1);
|
|||
#include "softShadow.hlsl"
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 3);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 4);
|
||||
#ifdef USE_COOKIE_TEX
|
||||
/// The texture for cookie rendering.
|
||||
TORQUE_UNIFORM_SAMPLER2D(cookieMap, 5);
|
||||
TORQUE_UNIFORM_SAMPLER2D(iesProfile, 6);
|
||||
|
||||
#endif
|
||||
uniform float4 rtParams0;
|
||||
|
||||
uniform float lightBrightness;
|
||||
|
|
@ -96,8 +95,7 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
if(dist < lightRange)
|
||||
{
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
float3 lightCol = lightColor.rgb;
|
||||
|
||||
|
||||
float shadow = 1.0;
|
||||
#ifndef NO_SHADOW
|
||||
if (getFlag(surface.matFlag, 0)) //also skip if we don't recieve shadows
|
||||
|
|
@ -109,10 +107,23 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
//distance to light in shadow map space
|
||||
float distToLight = pxlPosLightProj.z / lightRange;
|
||||
shadow = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
float4 pxlPosLightProj = mul( worldToLightProj, float4( surface.P, 1 ) );
|
||||
float2 cookieCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
|
||||
// Lookup the cookie sample.
|
||||
float4 cookie = TORQUE_TEX2D(cookieMap, cookieCoord);
|
||||
// Multiply the light with the cookie tex.
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
|
||||
#ifdef DIFFUSE_LIGHT_VIZ
|
||||
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
|
||||
float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
|
||||
|
|
@ -144,13 +155,13 @@ float4 main( ConvexConnectP IN ) : SV_TARGET
|
|||
|
||||
//get spot light contribution
|
||||
lighting = getSpotlight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, lightDirection, lightSpotParams, shadow);
|
||||
#ifdef USE_COOKIE_TEX
|
||||
#ifdef UES_PHOTOMETRIC_MASK
|
||||
// Lookup the cookie sample.d
|
||||
float cosTheta = dot(-surfaceToLight.L, lightDirection);
|
||||
float angle = acos(cosTheta) * ( M_1OVER_PI_F);
|
||||
float cookie = TORQUE_TEX2D(cookieMap, float2(angle, 0.0)).r;
|
||||
// Multiply the light with the cookie tex.
|
||||
lighting *= cookie;
|
||||
float iesMask = TORQUE_TEX2D(iesProfile, float2(angle, 0.0)).r;
|
||||
// Multiply the light with the iesMask tex.
|
||||
lighting *= iesMask;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue