source-engine/materialsystem/stdshaders/color_projection.cpp

291 lines
7.1 KiB
C++
Raw Permalink Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "BaseVSShader.h"
#include "color_projection_ps20.inc"
#include "color_projection_vs20.inc"
#include "../materialsystem_global.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar *mat_color_projection = NULL;
typedef struct SProjectionInfo
{
bool m_bNeedBlindMK;
bool m_bNeedMonochrome;
bool m_bNeedAnomylize;
float m_flCPU;
float m_flCPV;
float m_flAM;
float m_flAYI;
} TProjectionInfo;
#define MAX_PROJECTIONS 8
TProjectionInfo ProjectionInfo[ MAX_PROJECTIONS ] =
{
{ true, false, false, 0.735f, 0.265f, 1.273463f, -0.073894f }, // protanopia red-green blindness (no red cones)
{ true, false, false, 1.14f, -0.14f, 0.968437f, 0.003331f }, // deutanopia red-green blindness (no green cones)
{ true, false, false, 0.171f, -0.003f, 0.062921f, 0.292119f }, // tritanopia blue-yellow blindness (no blue cones)
{ false, true, false, 0.0f, 0.0f, 0.0f, 0.0f }, // typical achromatopsia (no cones; rod monochromat)
{ true, false, true, 0.735f, 0.265f, 1.273463f, -0.073894f }, // protanomaly (anomalous red cones)
{ true, false, true, 1.14f, -0.14f, 0.968437f, 0.003331f }, // deutanomaly (anomalous green cones)
{ true, false, true, 0.171f, -0.003f, 0.062921f, 0.292119f }, // tritanomaly (anomalous blue cones)
{ false, true, true, 0.0f, 0.0f, 0.0f, 0.0f } // atypical achromatopsia (low cones; cone monochromat)
};
#if 0
#define cpu ProjectionInfo[ 2 ].m_flCPU
#define cpv ProjectionInfo[ 2 ].m_flCPV
#define am ProjectionInfo[ 2 ].m_flAM
#define ayi ProjectionInfo[ 2 ].m_flAYI
Vector rgb_from_xyz( Vector vNum )
{
Vector vResult;
vResult.x=( 3.063218*vNum.x-1.393325*vNum.y-0.475802*vNum.z);
vResult.y=(-0.969243*vNum.x+1.875966*vNum.y+0.041555*vNum.z);
vResult.z=( 0.067871*vNum.x-0.228834*vNum.y+1.069251*vNum.z);
return vResult;
}
Vector xyz_from_rgb( Vector vNum )
{
Vector vResult;
vResult.x=(0.430574*vNum.x+0.341550*vNum.y+0.178325*vNum.z);
vResult.y=(0.222015*vNum.x+0.706655*vNum.y+0.071330*vNum.z);
vResult.z=(0.020183*vNum.x+0.129553*vNum.y+0.939180*vNum.z);
return vResult;
}
Vector anomylize( Vector a, Vector b )
{
return ( ( 1.75f * b ) + a ) / 2.75f;
}
Vector monochrome( Vector r)
{
float z = (r.x*0.299+r.y*0.587+r.z*0.114);
return Vector( z, z, z );;
}
Vector blindMK( Vector vColor )
{
const float wx=0.312713;
const float wy=0.329016;
const float wz=0.358271;
Vector c_xyz = xyz_from_rgb( vColor );
float sum_xyz=c_xyz.x+c_xyz.y+c_xyz.z;
Vector2D c_uv;
c_uv.x=0;
c_uv.y=0;
if ( sum_xyz!=0 )
{
c_uv.x=c_xyz.x/sum_xyz;
c_uv.y=c_xyz.y/sum_xyz;
}
float nx=wx*c_xyz.y/wy;
float nz=wz*c_xyz.y/wy;
Vector d_xyz;
d_xyz.y=0;
float clm;
if ( c_uv.x< cpu )
{
clm=(cpv-c_uv.y)/(cpu-c_uv.x);
}
else
{
clm=(c_uv.y-cpv)/(c_uv.x-cpu);
}
float clyi=c_uv.y-c_uv.x*clm;
Vector2D d_uv;
d_uv.x=(ayi-clyi)/(clm-am);
d_uv.y=(clm*d_uv.x)+clyi;
Vector s_xyz;
s_xyz.x=d_uv.x*c_xyz.y/d_uv.y;
s_xyz.y=c_xyz.y;
s_xyz.z=(1-(d_uv.x+d_uv.y))*c_xyz.y/d_uv.y;
Vector s_rgb = rgb_from_xyz( s_xyz );
d_xyz.x=nx-s_xyz.x;
d_xyz.z=nz-s_xyz.z;
Vector d_rgb = rgb_from_xyz( d_xyz );
Vector adj_rgb;
adj_rgb.Init();
if ( d_rgb.x!=0 )
{
adj_rgb.x=( s_rgb.x<0 ? 0 : 1)-s_rgb.x/d_rgb.x;
}
if ( d_rgb.y!=0 )
{
adj_rgb.y=( s_rgb.y<0 ? 0 : 1)-s_rgb.y/d_rgb.y;
}
if ( d_rgb.z!=0 )
{
adj_rgb.z=( s_rgb.z<0 ? 0 : 1)-s_rgb.z/d_rgb.z;
}
float adjust = 0;
if ( adj_rgb.x >= 0 && adj_rgb.x <= 1 )
{
adjust = adj_rgb.x;
}
if ( adj_rgb.y >= 0 && adj_rgb.y <= 1 && adj_rgb.y > adjust )
{
adjust = adj_rgb.y;
}
if ( adj_rgb.z >= 0 && adj_rgb.z <= 1 && adj_rgb.z > adjust )
{
adjust = adj_rgb.z;
}
s_rgb.x=s_rgb.x+(adjust*d_rgb.x);
s_rgb.y=s_rgb.y+(adjust*d_rgb.y);
s_rgb.z=s_rgb.z+(adjust*d_rgb.z);
return s_rgb;
}
#endif
BEGIN_VS_SHADER( color_projection, "Help for deferred color correction" )
BEGIN_SHADER_PARAMS
SHADER_PARAM( FRAME_TEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_FullFrameFB1", "" )
SHADER_PARAM( HSV_CORRECTION, SHADER_PARAM_TYPE_VEC3, "[ 0.0 0.0 0.0 ]", "" )
SHADER_PARAM( CONTRAST_CORRECTION, SHADER_PARAM_TYPE_FLOAT, "0.0", "" )
END_SHADER_PARAMS
SHADER_INIT_PARAMS()
{
SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE );
#if 0
Vector vResult;
vResult = blindMK( Vector( 1, 0, 0 ) );
vResult = blindMK( Vector( 1, 0, 0 ) );
vResult = blindMK( Vector( 1, 0, 0 ) );
vResult = blindMK( Vector( 1, 0, 0 ) );
vResult = blindMK( Vector( 1, 0, 0 ) );
vResult = blindMK( Vector( 1, 0, 0 ) );
Msg( "%g %g %g", vResult.x, vResult.y, vResult.z );
#endif
}
SHADER_FALLBACK
{
return 0;
}
SHADER_INIT
{
if ( mat_color_projection == NULL )
{
mat_color_projection = cvar->FindVar( "mat_color_projection" );
}
if ( params[ FRAME_TEXTURE ]->IsDefined() == false )
{
params[ FRAME_TEXTURE ]->SetStringValue( "_rt_FullFrameFB1" );
}
// params[ FRAME_TEXTURE ]->SetStringValue( "rj/colors" );
LoadTexture( FRAME_TEXTURE );
}
SHADER_DRAW
{
SHADOW_STATE
{
SetInitialShadowState( );
pShaderShadow->EnableDepthWrites( false );
pShaderShadow->EnableDepthTest( false );
// pShaderShadow->EnableBlending( true );
// pShaderShadow->BlendOp( SHADER_BLEND_OP_REVSUBTRACT );
// EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE );
pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
pShaderShadow->EnableSRGBWrite( false );
pShaderShadow->EnableAlphaWrites( true ); // writing water fog alpha always.
int fmt = VERTEX_POSITION;
int nTexCoordDims[ 2 ] = { 2, 3 };
pShaderShadow->VertexShaderVertexFormat( fmt, 2, nTexCoordDims, 0 );
DECLARE_STATIC_VERTEX_SHADER( color_projection_vs20 );
SET_STATIC_VERTEX_SHADER( color_projection_vs20 );
DECLARE_STATIC_PIXEL_SHADER( color_projection_ps20 );
SET_STATIC_PIXEL_SHADER( color_projection_ps20 );
}
DYNAMIC_STATE
{
pShaderAPI->SetDefaultState();
BindTexture( SHADER_SAMPLER4, FRAME_TEXTURE, -1 );
int nIndex = mat_color_projection->GetInt() - 1;
if ( nIndex < 0 || nIndex >= MAX_PROJECTIONS )
{
nIndex = 0;
}
Vector4D vCorrectionParms;
vCorrectionParms.x = ProjectionInfo[ nIndex ].m_flCPU;
vCorrectionParms.y = ProjectionInfo[ nIndex ].m_flCPV;
vCorrectionParms.z = ProjectionInfo[ nIndex ].m_flAM;
vCorrectionParms.w = ProjectionInfo[ nIndex ].m_flAYI;
pShaderAPI->SetPixelShaderConstant( 1, vCorrectionParms.Base() );
DECLARE_DYNAMIC_VERTEX_SHADER( color_projection_vs20 );
SET_DYNAMIC_VERTEX_SHADER( color_projection_vs20 );
DECLARE_DYNAMIC_PIXEL_SHADER( color_projection_ps20 );
SET_DYNAMIC_PIXEL_SHADER_COMBO( NEED_BLINDMK, ProjectionInfo[ nIndex ].m_bNeedBlindMK );
SET_DYNAMIC_PIXEL_SHADER_COMBO( NEED_MONOCHROME, ProjectionInfo[ nIndex ].m_bNeedMonochrome );
SET_DYNAMIC_PIXEL_SHADER_COMBO( NEED_ANOMYLIZE, ProjectionInfo[ nIndex ].m_bNeedAnomylize );
SET_DYNAMIC_PIXEL_SHADER( color_projection_ps20 );
}
Draw();
}
END_SHADER