Implementation of sRGB image support. Overhauls the linearization setup to utilize the sRGB image types, as well as refactors the use of ColorF and ColorI to be properly internally consistent. ColorIs are used only for front-facing/editing/UI settings, and ColorFs, now renamed to LinearColorF to reduce confusion of purpose, are used for color info in the engine itself. This avoids confusing and expensive conversions back and forth between types and avoids botches with linearity. Majority work done by @rextimmy

This commit is contained in:
Areloch 2017-06-23 11:36:20 -05:00
parent 8780f83262
commit 25686ed4be
294 changed files with 3894 additions and 2813 deletions

View file

@ -141,7 +141,7 @@ void MatInstParameters::set(MaterialParameterHandle* handle, const Point4F& fv)
MATINSTPARAMSET(handle, fv);
}
void MatInstParameters::set(MaterialParameterHandle* handle, const ColorF& fv)
void MatInstParameters::set(MaterialParameterHandle* handle, const LinearColorF& fv)
{
MATINSTPARAMSET(handle, fv);
}

View file

@ -161,7 +161,7 @@ public:
virtual void set(MaterialParameterHandle* handle, const Point2F& fv);
virtual void set(MaterialParameterHandle* handle, const Point3F& fv);
virtual void set(MaterialParameterHandle* handle, const Point4F& fv);
virtual void set(MaterialParameterHandle* handle, const ColorF& fv);
virtual void set(MaterialParameterHandle* handle, const LinearColorF& fv);
virtual void set(MaterialParameterHandle* handle, const S32 f);
virtual void set(MaterialParameterHandle* handle, const Point2I& fv);
virtual void set(MaterialParameterHandle* handle, const Point3I& fv);

View file

@ -115,6 +115,7 @@ Material::Material()
for( U32 i=0; i<MAX_STAGES; i++ )
{
mDiffuse[i].set( 1.0f, 1.0f, 1.0f, 1.0f );
mDiffuseMapSRGB[i] = true;
mSpecular[i].set( 1.0f, 1.0f, 1.0f, 1.0f );
mSpecularPower[i] = 8.0f;
@ -226,6 +227,9 @@ void Material::initPersistFields()
addField("diffuseMap", TypeImageFilename, Offset(mDiffuseMapFilename, Material), MAX_STAGES,
"The diffuse color texture map." );
addField("diffuseMapSRGB", TypeBool, Offset(mDiffuseMapSRGB, Material), MAX_STAGES,
"Enable sRGB for the diffuse color texture map.");
addField("overlayMap", TypeImageFilename, Offset(mOverlayMapFilename, Material), MAX_STAGES,
"A secondary diffuse color texture map which will use the second texcoord of a mesh." );

View file

@ -200,6 +200,7 @@ public:
// Data
//-----------------------------------------------------------------------
FileName mDiffuseMapFilename[MAX_STAGES];
bool mDiffuseMapSRGB[MAX_STAGES]; // SRGB diffuse
bool mAccuEnabled[MAX_STAGES];
F32 mAccuScale[MAX_STAGES];
F32 mAccuDirection[MAX_STAGES];
@ -224,9 +225,9 @@ public:
/// This color is the diffuse color of the material
/// or if it has a texture it is multiplied against
/// the diffuse texture color.
ColorF mDiffuse[MAX_STAGES];
LinearColorF mDiffuse[MAX_STAGES];
ColorF mSpecular[MAX_STAGES];
LinearColorF mSpecular[MAX_STAGES];
F32 mSpecularPower[MAX_STAGES];
F32 mSpecularStrength[MAX_STAGES];
@ -242,7 +243,7 @@ public:
F32 mMinnaertConstant[MAX_STAGES];
bool mSubSurface[MAX_STAGES];
ColorF mSubSurfaceColor[MAX_STAGES];
LinearColorF mSubSurfaceColor[MAX_STAGES];
F32 mSubSurfaceRolloff[MAX_STAGES];
/// The repetition scale of the detail texture
@ -321,7 +322,7 @@ public:
bool mShowDust; ///< If true, show dust emitters (footpuffs, hover trails, etc) when on surface with this material. Defaults to false.
/// Color to use for particle effects and such when located on this material.
ColorF mEffectColor[ NUM_EFFECT_COLOR_STAGES ];
LinearColorF mEffectColor[ NUM_EFFECT_COLOR_STAGES ];
/// Footstep sound to play when walking on surface with this material.
/// Numeric ID of footstep sound defined on player datablock (0 == soft,

View file

@ -66,7 +66,8 @@ ImplementFeatureType( MFT_Fog, MFG_PostProcess, 3.0f, true );
ImplementFeatureType( MFT_HDROut, MFG_PostProcess, 999.0f, true );
ImplementFeatureType( MFT_IsDXTnm, U32(-1), -1, true );
ImplementFeatureType( MFT_IsBC3nm, U32(-1), -1, true );
ImplementFeatureType( MFT_IsBC5nm, U32(-1), -1, true);
ImplementFeatureType( MFT_IsTranslucent, U32(-1), -1, true );
ImplementFeatureType( MFT_IsTranslucentZWrite, U32(-1), -1, true );
ImplementFeatureType( MFT_IsEmissive, U32(-1), -1, true );

View file

@ -83,8 +83,9 @@ DeclareFeatureType( MFT_ParaboloidVertTransform );
/// feature to detect if it needs to generate a single pass.
DeclareFeatureType( MFT_IsSinglePassParaboloid );
/// This feature does normal map decompression for DXT1/5.
DeclareFeatureType( MFT_IsDXTnm );
/// This two feature do normal map decompression for DXT5/3dc
DeclareFeatureType( MFT_IsBC3nm );
DeclareFeatureType( MFT_IsBC5nm );
DeclareFeatureType( MFT_TexAnim );
DeclareFeatureType( MFT_Parallax );

View file

@ -331,14 +331,14 @@ void MaterialList::mapMaterial( U32 i )
GFXTexHandle texHandle;
if (mLookupPath.isEmpty())
{
texHandle.set( mMaterialNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
texHandle.set( mMaterialNames[i], &GFXStaticTextureSRGBProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
}
else
{
// Should we strip off the extension of the path here before trying
// to load the texture?
String fullPath = String::ToString( "%s/%s", mLookupPath.c_str(), mMaterialNames[i].c_str() );
texHandle.set( fullPath, &GFXDefaultStaticDiffuseProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
texHandle.set( fullPath, &GFXStaticTextureSRGBProfile, avar("%s() - handle (line %d)", __FUNCTION__, __LINE__) );
}
if ( texHandle.isValid() )

View file

@ -222,7 +222,7 @@ BaseMatInstance * MaterialManager::getWarningMatInstance()
}
#ifndef TORQUE_SHIPPING
BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const ColorF &meshColor)
BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const LinearColorF &meshColor)
{
String meshDebugStr = String::ToString( "Torque_MeshDebug_%d", meshColor.getRGBAPack() );
@ -256,7 +256,7 @@ BaseMatInstance * MaterialManager::createMeshDebugMatInstance(const ColorF &mesh
}
// Gets the global material instance for a given color, callers should not free this copy
BaseMatInstance *MaterialManager::getMeshDebugMatInstance(const ColorF &meshColor)
BaseMatInstance *MaterialManager::getMeshDebugMatInstance(const LinearColorF &meshColor)
{
DebugMaterialMap::Iterator itr = mMeshDebugMaterialInsts.find( meshColor.getRGBAPack() );

View file

@ -88,10 +88,10 @@ public:
#ifndef TORQUE_SHIPPING
// Allocate and return an instance of mesh debugging materials. Caller is responsible for the memory.
BaseMatInstance * createMeshDebugMatInstance(const ColorF &meshColor);
BaseMatInstance * createMeshDebugMatInstance(const LinearColorF &meshColor);
// Gets the global material instance for a given color, callers should not free this copy
BaseMatInstance * getMeshDebugMatInstance(const ColorF &meshColor);
BaseMatInstance * getMeshDebugMatInstance(const LinearColorF &meshColor);
#endif

View file

@ -73,7 +73,7 @@ public:
virtual void set(MaterialParameterHandle* handle, const Point2F& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point3F& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point4F& fv) {}
virtual void set(MaterialParameterHandle* handle, const ColorF& fv) {}
virtual void set(MaterialParameterHandle* handle, const LinearColorF& fv) {}
virtual void set(MaterialParameterHandle* handle, const S32 f) {}
virtual void set(MaterialParameterHandle* handle, const Point2I& fv) {}
virtual void set(MaterialParameterHandle* handle, const Point3I& fv) {}

View file

@ -173,7 +173,7 @@ void ProcessedCustomMaterial::_setStageData()
continue;
}
rpd->mTexSlot[i].texObject = _createTexture( filename, &GFXDefaultStaticDiffuseProfile );
rpd->mTexSlot[i].texObject = _createTexture( filename, &GFXStaticTextureSRGBProfile );
if ( !rpd->mTexSlot[i].texObject )
{
mMaterial->logError("Failed to load texture %s", _getTexturePath(filename).c_str());

View file

@ -248,7 +248,7 @@ void ProcessedFFMaterial::setSceneInfo(SceneRenderState * state, const SceneData
void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightInfo* light, U32 pass)
{
// Just in case
GFX->setGlobalAmbientColor(ColorF(0.0f, 0.0f, 0.0f, 1.0f));
GFX->setGlobalAmbientColor(LinearColorF(0.0f, 0.0f, 0.0f, 1.0f));
if ( light->getType() == LightInfo::Ambient )
{
// Ambient light
@ -260,10 +260,10 @@ void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightIn
GFX->setLight(1, NULL);
// This is a quick hack that lets us use FF lights
GFXLightMaterial lightMat;
lightMat.ambient = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.diffuse = ColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.emissive = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.specular = ColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.ambient = LinearColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.diffuse = LinearColorF(1.0f, 1.0f, 1.0f, 1.0f);
lightMat.emissive = LinearColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.specular = LinearColorF(0.0f, 0.0f, 0.0f, 0.0f);
lightMat.shininess = 128.0f;
GFX->setLightMaterial(lightMat);

View file

@ -275,6 +275,8 @@ void ProcessedMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockD
result.samplers[i].addressModeU = GFXAddressClamp;
result.samplers[i].addressModeV = GFXAddressClamp;
result.samplers[i].addressModeW = GFXAddressClamp;
result.samplers[i].minFilter = GFXTextureFilterLinear;
result.samplers[i].magFilter = GFXTextureFilterLinear;
break;
}
@ -389,7 +391,7 @@ void ProcessedMaterial::_setStageData()
// DiffuseMap
if( mMaterial->mDiffuseMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DiffuseMap, _createTexture( mMaterial->mDiffuseMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_DiffuseMap, _createTexture( mMaterial->mDiffuseMapFilename[i], &GFXStaticTextureSRGBProfile) );
if (!mStages[i].getTex( MFT_DiffuseMap ))
{
//If we start with a #, we're probably actually attempting to hit a named target and it may not get a hit on the first pass. So we'll
@ -399,14 +401,14 @@ void ProcessedMaterial::_setStageData()
// Load a debug texture to make it clear to the user
// that the texture for this stage was missing.
mStages[i].setTex( MFT_DiffuseMap, _createTexture( GFXTextureManager::getMissingTexturePath().c_str(), &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_DiffuseMap, _createTexture( GFXTextureManager::getMissingTexturePath().c_str(), &GFXStaticTextureSRGBProfile) );
}
}
// OverlayMap
if( mMaterial->mOverlayMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_OverlayMap, _createTexture( mMaterial->mOverlayMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_OverlayMap, _createTexture( mMaterial->mOverlayMapFilename[i], &GFXStaticTextureSRGBProfile ) );
if(!mStages[i].getTex( MFT_OverlayMap ))
mMaterial->logError("Failed to load overlay map %s for stage %i", _getTexturePath(mMaterial->mOverlayMapFilename[i]).c_str(), i);
}
@ -414,7 +416,7 @@ void ProcessedMaterial::_setStageData()
// LightMap
if( mMaterial->mLightMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_LightMap, _createTexture( mMaterial->mLightMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_LightMap, _createTexture( mMaterial->mLightMapFilename[i], &GFXStaticTextureSRGBProfile ) );
if(!mStages[i].getTex( MFT_LightMap ))
mMaterial->logError("Failed to load light map %s for stage %i", _getTexturePath(mMaterial->mLightMapFilename[i]).c_str(), i);
}
@ -422,7 +424,7 @@ void ProcessedMaterial::_setStageData()
// ToneMap
if( mMaterial->mToneMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_ToneMap, _createTexture( mMaterial->mToneMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_ToneMap, _createTexture( mMaterial->mToneMapFilename[i], &GFXStaticTextureProfile) );
if(!mStages[i].getTex( MFT_ToneMap ))
mMaterial->logError("Failed to load tone map %s for stage %i", _getTexturePath(mMaterial->mToneMapFilename[i]).c_str(), i);
}
@ -430,7 +432,7 @@ void ProcessedMaterial::_setStageData()
// DetailMap
if( mMaterial->mDetailMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DetailMap, _createTexture( mMaterial->mDetailMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_DetailMap, _createTexture( mMaterial->mDetailMapFilename[i], &GFXStaticTextureProfile) );
if(!mStages[i].getTex( MFT_DetailMap ))
mMaterial->logError("Failed to load detail map %s for stage %i", _getTexturePath(mMaterial->mDetailMapFilename[i]).c_str(), i);
}
@ -438,7 +440,7 @@ void ProcessedMaterial::_setStageData()
// NormalMap
if( mMaterial->mNormalMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_NormalMap, _createTexture( mMaterial->mNormalMapFilename[i], &GFXDefaultStaticNormalMapProfile ) );
mStages[i].setTex( MFT_NormalMap, _createTexture( mMaterial->mNormalMapFilename[i], &GFXNormalMapProfile) );
if(!mStages[i].getTex( MFT_NormalMap ))
mMaterial->logError("Failed to load normal map %s for stage %i", _getTexturePath(mMaterial->mNormalMapFilename[i]).c_str(), i);
}
@ -446,7 +448,7 @@ void ProcessedMaterial::_setStageData()
// Detail Normal Map
if( mMaterial->mDetailNormalMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_DetailNormalMap, _createTexture( mMaterial->mDetailNormalMapFilename[i], &GFXDefaultStaticNormalMapProfile ) );
mStages[i].setTex( MFT_DetailNormalMap, _createTexture( mMaterial->mDetailNormalMapFilename[i], &GFXNormalMapProfile) );
if(!mStages[i].getTex( MFT_DetailNormalMap ))
mMaterial->logError("Failed to load normal map %s for stage %i", _getTexturePath(mMaterial->mDetailNormalMapFilename[i]).c_str(), i);
}
@ -454,7 +456,7 @@ void ProcessedMaterial::_setStageData()
// SpecularMap
if( mMaterial->mSpecularMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_SpecularMap, _createTexture( mMaterial->mSpecularMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
mStages[i].setTex( MFT_SpecularMap, _createTexture( mMaterial->mSpecularMapFilename[i], &GFXStaticTextureProfile) );
if(!mStages[i].getTex( MFT_SpecularMap ))
mMaterial->logError("Failed to load specular map %s for stage %i", _getTexturePath(mMaterial->mSpecularMapFilename[i]).c_str(), i);
}

View file

@ -76,6 +76,7 @@ void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/
mWorldToObjSC = shader->getShaderConstHandle(ShaderGenVars::worldToObj);
mViewToObjSC = shader->getShaderConstHandle(ShaderGenVars::viewToObj);
mCubeTransSC = shader->getShaderConstHandle(ShaderGenVars::cubeTrans);
mCubeMipsSC = shader->getShaderConstHandle(ShaderGenVars::cubeMips);
mObjTransSC = shader->getShaderConstHandle(ShaderGenVars::objTrans);
mCubeEyePosSC = shader->getShaderConstHandle(ShaderGenVars::cubeEyePos);
mEyePosSC = shader->getShaderConstHandle(ShaderGenVars::eyePos);
@ -270,7 +271,7 @@ U32 ProcessedShaderMaterial::getNumStages()
// If this stage has diffuse color, it's active
if ( mMaterial->mDiffuse[i].alpha > 0 &&
mMaterial->mDiffuse[i] != ColorF::WHITE )
mMaterial->mDiffuse[i] != LinearColorF::WHITE )
stageActive = true;
// If we have a Material that is vertex lit
@ -394,9 +395,12 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
if ( fd.features[ MFT_NormalMap ] )
{
if ( mStages[stageNum].getTex( MFT_NormalMap )->mFormat == GFXFormatDXT5 &&
if ( mStages[stageNum].getTex( MFT_NormalMap )->mFormat == GFXFormatBC3 &&
!mStages[stageNum].getTex( MFT_NormalMap )->mHasTransparency )
fd.features.addFeature( MFT_IsDXTnm );
fd.features.addFeature( MFT_IsBC3nm );
else if ( mStages[stageNum].getTex(MFT_NormalMap)->mFormat == GFXFormatBC5 &&
!mStages[stageNum].getTex(MFT_NormalMap)->mHasTransparency )
fd.features.addFeature( MFT_IsBC5nm );
}
// Now for some more advanced features that we
@ -461,7 +465,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
// If we have a diffuse map and the alpha on the diffuse isn't
// zero and the color isn't pure white then multiply the color.
else if ( mMaterial->mDiffuse[stageNum].alpha > 0.0f &&
mMaterial->mDiffuse[stageNum] != ColorF::WHITE )
mMaterial->mDiffuse[stageNum] != LinearColorF::WHITE )
fd.features.addFeature( MFT_DiffuseColor );
// If lightmaps or tonemaps are enabled or we
@ -1096,7 +1100,7 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons
if ( handles->mSubSurfaceParamsSC->isValid() )
{
Point4F subSurfParams;
dMemcpy( &subSurfParams, &mMaterial->mSubSurfaceColor[stageNum], sizeof(ColorF) );
dMemcpy( &subSurfParams, &mMaterial->mSubSurfaceColor[stageNum], sizeof(LinearColorF) );
subSurfParams.w = mMaterial->mSubSurfaceRolloff[stageNum];
shaderConsts->set(handles->mSubSurfaceParamsSC, subSurfParams);
}

View file

@ -65,6 +65,7 @@ public:
GFXShaderConstHandle* mWorldToObjSC;
GFXShaderConstHandle* mViewToObjSC;
GFXShaderConstHandle* mCubeTransSC;
GFXShaderConstHandle* mCubeMipsSC;
GFXShaderConstHandle* mObjTransSC;
GFXShaderConstHandle* mCubeEyePosSC;
GFXShaderConstHandle* mEyePosSC;

View file

@ -71,13 +71,13 @@ struct SceneData
LightInfo* lights[8];
///
ColorF ambientLightColor;
LinearColorF ambientLightColor;
// fog
F32 fogDensity;
F32 fogDensityOffset;
F32 fogHeightFalloff;
ColorF fogColor;
LinearColorF fogColor;
// misc
const MatrixF *objTrans;

View file

@ -131,7 +131,7 @@ void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const PlaneF
SHADERMATPARAM_SET(handle, fv);
}
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const ColorF& fv)
void ShaderMaterialParameters::set(MaterialParameterHandle* handle, const LinearColorF& fv)
{
SHADERMATPARAM_SET(handle, fv);
}

View file

@ -73,7 +73,7 @@ public:
virtual void set(MaterialParameterHandle* handle, const Point3F& fv);
virtual void set(MaterialParameterHandle* handle, const Point4F& fv);
virtual void set(MaterialParameterHandle* handle, const PlaneF& fv);
virtual void set(MaterialParameterHandle* handle, const ColorF& fv);
virtual void set(MaterialParameterHandle* handle, const LinearColorF& fv);
virtual void set(MaterialParameterHandle* handle, const S32 f);
virtual void set(MaterialParameterHandle* handle, const Point2I& fv);
virtual void set(MaterialParameterHandle* handle, const Point3I& fv);