daedalus/Source/SysCTR/HLEGraphics/Combiner/RenderSettings.cpp
2022-04-14 15:01:56 +10:00

469 lines
13 KiB
C++

/*
Copyright (C) 2007 StrmnNrmn
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "stdafx.h"
#include "RenderSettings.h"
#include "BlendConstant.h"
/**
* Set how textures are applied
*
* Key for the apply-modes:
* - Cv - Color value result
* - Ct - Texture color
* - Cf - Fragment color
* - Cc - Constant color (specified by sceGuTexEnvColor())
*
* Available apply-modes are: (TFX)
* - GU_TFX_MODULATE - Cv=Ct*Cf TCC_RGB: Av=Af TCC_RGBA: Av=At*Af
* - GU_TFX_DECAL - TCC_RGB: Cv=Ct,Av=Af TCC_RGBA: Cv=Cf*(1-At)+Ct*At Av=Af
* - GU_TFX_BLEND - Cv=(Cf*(1-Ct))+(Cc*Ct) TCC_RGB: Av=Af TCC_RGBA: Av=At*Af
* - GU_TFX_REPLACE - Cv=Ct TCC_RGB: Av=Af TCC_RGBA: Av=At
* - GU_TFX_ADD - Cv=Cf+Ct TCC_RGB: Av=Af TCC_RGBA: Av=At*Af
*
* The fields TCC_RGB and TCC_RGBA specify components that differ between
* the two different component modes.
*
* - GU_TFX_MODULATE - The texture is multiplied with the current diffuse fragment
* - GU_TFX_REPLACE - The texture replaces the fragment
* - GU_TFX_ADD - The texture is added on-top of the diffuse fragment
*
* Available component-modes are: (TCC)
* - GU_TCC_RGB - The texture alpha does not have any effect
* - GU_TCC_RGBA - The texture alpha is taken into account
*
* @param tfx - Which apply-mode to use
* @param tcc - Which component-mode to use
**/
///* Texture Effect */
//#define GU_TFX_MODULATE (0)
//#define GU_TFX_DECAL (1)
//#define GU_TFX_BLEND (2)
//#define GU_TFX_REPLACE (3)
//#define GU_TFX_ADD (4)
//
///* Texture Color Component */
//#define GU_TCC_RGB (0)
//#define GU_TCC_RGBA (1)
//
//
///* Blending Op */
//#define GU_ADD (0)
//#define GU_SUBTRACT (1)
//#define GU_REVERSE_SUBTRACT (2)
//#define GU_MIN (3)
//#define GU_MAX (4)
//#define GU_ABS (5)
//*****************************************************************************
//
//*****************************************************************************
CAlphaRenderSettings::CAlphaRenderSettings( const char * description )
: mDescription( description )
, mInexact( false )
, mUsesTexel0( false )
, mUsesTexel1( false )
, mConstantExpression( NULL )
{
}
//*****************************************************************************
//
//*****************************************************************************
CAlphaRenderSettings::~CAlphaRenderSettings()
{
delete mConstantExpression;
}
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::AddTermTexel0()
{
if( mUsesTexel0 || mUsesTexel1 )
{
mInexact = true;
}
mUsesTexel0 = true;
}
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::AddTermTexel1()
{
if( mUsesTexel0 || mUsesTexel1 )
{
mInexact = true;
}
mUsesTexel1 = true;
}
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::AddTermConstant( const CBlendConstantExpression * constant_expression )
{
if( mConstantExpression != NULL )
{
mConstantExpression = new CBlendConstantExpressionMul( mConstantExpression, constant_expression );
}
else
{
mConstantExpression = constant_expression;
}
}
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::Finalise()
{
if( mConstantExpression == NULL )
{
mConstantExpression = new CBlendConstantExpressionValue( BC_1 );
}
}
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::Apply( bool texture_installed, const SRenderState & state, SRenderStateOut & out ) const
{
out.VertexExpressionA = mConstantExpression;
if( mUsesTexel0 || mUsesTexel1 )
{
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( texture_installed, "We have a texture, but it's not installed?" );
#endif
out.BlendAlphaMode = PBAM_RGBA;
}
else
{
out.BlendAlphaMode = PBAM_RGB;
}
}
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
//*****************************************************************************
//
//*****************************************************************************
void CAlphaRenderSettings::Print( bool texture_installed ) const
{
DAEDALUS_ASSERT( mConstantExpression != NULL, "Should always have settings" );
if( mUsesTexel0 || mUsesTexel1 )
{
// Replace vertex shade colour with modulate_colour
printf( " GU_TCC_RGBA, diffuse_a := %s\n", mConstantExpression->ToString().c_str() );
}
else
{
// Texel alpha ignored
// Replace vertex shade colour with modulate_colour
printf( " GU_TCC_RGB, diffuse_a := %s\n", mConstantExpression->ToString().c_str() );
}
}
#endif
//*****************************************************************************
//
//*****************************************************************************
CRenderSettingsModulate::CRenderSettingsModulate( const char * description )
: CRenderSettings( description )
, mConstantExpression( NULL )
, mUsesTexel0( false )
, mUsesTexel1( false )
, mInexact( false )
{
}
//*****************************************************************************
//
//*****************************************************************************
CRenderSettingsModulate::~CRenderSettingsModulate()
{
delete mConstantExpression;
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::AddTermTexel0()
{
if( mUsesTexel0 )
{
mInexact = true;
}
mUsesTexel0 = true;
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::AddTermTexel1()
{
if( mUsesTexel0 || mUsesTexel1 )
{
mInexact = true;
}
mUsesTexel1 = true;
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::AddTermConstant( const CBlendConstantExpression * constant_expression )
{
if( mConstantExpression != NULL )
{
mConstantExpression = new CBlendConstantExpressionMul( mConstantExpression, constant_expression );
}
else
{
mConstantExpression = constant_expression;
}
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::Finalise()
{
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::Apply( bool texture_installed, const SRenderState & state, SRenderStateOut & out ) const
{
out.VertexExpressionRGB = mConstantExpression;
if( texture_installed )
{
//
// Enable texturing
//
if( !mUsesTexel0 && !mUsesTexel1 )
{
// Make a white texture with the existing alpha channel
out.MakeTextureWhite = true;
}
if( mConstantExpression != NULL )
{
out.BlendMode = PBM_MODULATE;
}
else
{
out.BlendMode = PBM_REPLACE;
}
}
else
{
//
// Disable texturing
//
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( mConstantExpression != NULL, "No texture or diffuse" );
#endif
}
}
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsModulate::Print( bool texture_installed ) const
{
if( texture_installed )
{
// Enable texturing
if( !mUsesTexel0 && !mUsesTexel1 )
{
printf( " Need white texture\n" );
}
if( mConstantExpression != NULL )
{
// Replace vertex shade colour with modulate_colour
printf( " GU_TFX_MODULATE, diffuse_rgb := %s\n", mConstantExpression->ToString().c_str() );
}
else
{
printf( " GU_TFX_REPLACE, diffuse_rgb ignored\n" );
}
}
else
{
// Disable texturing
if( mConstantExpression != NULL )
{
// Replace vertex shade colour with modulate_colour
printf( " No tex, diffuse_rgb := %s\n", mConstantExpression->ToString().c_str() );
}
else
{
// What are we using
printf( " No texture or diffuse?\n" );
}
}
}
#endif
//*****************************************************************************
//
//*****************************************************************************
CRenderSettingsBlend::CRenderSettingsBlend( const char * description, const CBlendConstantExpression * a, const CBlendConstantExpression * b )
: CRenderSettings( description )
, mConstantExpressionA( a )
, mConstantExpressionB( b )
, mInexact( false )
{
}
//*****************************************************************************
//
//*****************************************************************************
CRenderSettingsBlend::~CRenderSettingsBlend()
{
delete mConstantExpressionA;
delete mConstantExpressionB;
}
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsBlend::Apply( bool texture_installed, const SRenderState & state, SRenderStateOut & out ) const
{
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( texture_installed, "No texture for blend?" );
#endif
//
// Apply expression A as a function of shade.
// Evaluate expression A as a constant
//
out.VertexExpressionRGB = mConstantExpressionA;
out.TextureFactor = mConstantExpressionB->EvaluateConstant( state.PrimitiveColour, state.EnvironmentColour );
out.BlendMode = PBM_BLEND;
}
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
//*****************************************************************************
//
//*****************************************************************************
void CRenderSettingsBlend::Print( bool texture_installed ) const
{
std::string mod_str_a( mConstantExpressionA->ToString() );
std::string mod_str_b( mConstantExpressionB->ToString() );
// Replace vertex shade colour with modulate_colour
printf( " GU_TFX_BLEND, shade(a) := %s, factor(b) := %s\n", mod_str_a.c_str(), mod_str_b.c_str() );
}
#endif
//*****************************************************************************
//
//*****************************************************************************
CBlendStates::CBlendStates()
: mAlphaSettings( NULL )
{
}
//*****************************************************************************
//
//*****************************************************************************
CBlendStates::~CBlendStates()
{
delete mAlphaSettings;
for( u32 i = 0; i < mColourSettings.size(); ++i )
{
delete mColourSettings[ i ];
}
}
//*****************************************************************************
//
//*****************************************************************************
bool CBlendStates::IsInexact() const
{
if(mAlphaSettings->IsInexact())
{
return true;
}
for( u32 i = 0; i < mColourSettings.size(); ++i )
{
const CRenderSettings * settings( mColourSettings[ i ] );
if( settings->IsInexact() )
{
return true;
}
}
return false;
}
#ifdef DAEDALUS_DEBUG_DISPLAYLIST
//*****************************************************************************
//
//*****************************************************************************
void CBlendStates::Print() const
{
if(mAlphaSettings->IsInexact())
{
printf( "Alpha: INEXACT: %s\n", mAlphaSettings->GetDescription() );
}
else
{
printf( "Alpha: %s\n", mAlphaSettings->GetDescription() );
}
for( u32 i = 0; i < mColourSettings.size(); ++i )
{
const CRenderSettings * settings( mColourSettings[ i ] );
bool install_texture0( settings->UsesTexture0() || mAlphaSettings->UsesTexture0() );
bool install_texture1( settings->UsesTexture1() || mAlphaSettings->UsesTexture1() );
if( settings->IsInexact() || (install_texture0 && install_texture1) )
{
printf( "Stage %d: INEXACT = %s", i, settings->GetDescription() );
if(install_texture0 && install_texture1)
{
printf( " Uses T0 and T1" );
}
printf( "\n" );
}
else
{
printf( "Stage %d: %s\n", i, settings->GetDescription() );
}
settings->Print( install_texture0 || install_texture1 );
mAlphaSettings->Print( install_texture0 || install_texture1 );
}
}
#endif