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:
marauder2k7 2024-02-21 07:40:57 +00:00
parent a12d915180
commit 4417462499
10 changed files with 142 additions and 27 deletions

View file

@ -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);
};

View file

@ -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" ) );

View file

@ -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();

View file

@ -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;
}

View file

@ -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 );

View file

@ -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;
/// @}

View file

@ -94,6 +94,7 @@ public:
Misc,
DynamicLight,
DynamicLightMask,
PhotometricMask,
NormalizeCube,
TexTarget,
AccuMap,

View file

@ -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;

View file

@ -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
}

View file

@ -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
}