Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "BaseVSShader.h"
  8. #include "screenspaceeffect_vs20.inc"
  9. #include "engine_post_ps20.inc"
  10. #include "engine_post_ps20b.inc"
  11. #include "../materialsystem_global.h"
  12. DEFINE_FALLBACK_SHADER( Engine_Post, Engine_Post_dx9 )
  13. BEGIN_VS_SHADER_FLAGS( Engine_Post_dx9, "Engine post-processing effects (software anti-aliasing, bloom, color-correction", SHADER_NOT_EDITABLE )
  14. BEGIN_SHADER_PARAMS
  15. SHADER_PARAM( FBTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_FullFrameFB", "Full framebuffer texture" )
  16. SHADER_PARAM( AAENABLE, SHADER_PARAM_TYPE_BOOL, "0", "Enable software anti-aliasing" )
  17. SHADER_PARAM( AAINTERNAL1, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" )
  18. SHADER_PARAM( AAINTERNAL2, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" )
  19. SHADER_PARAM( AAINTERNAL3, SHADER_PARAM_TYPE_VEC4, "[0 0 0 0]", "Internal anti-aliasing values set via material proxy" )
  20. SHADER_PARAM( BLOOMENABLE, SHADER_PARAM_TYPE_BOOL, "1", "Enable bloom" )
  21. END_SHADER_PARAMS
  22. SHADER_INIT_PARAMS()
  23. {
  24. if( !params[ AAENABLE ]->IsDefined() )
  25. {
  26. params[ AAENABLE ]->SetIntValue( 0 );
  27. }
  28. if( !params[ AAINTERNAL1 ]->IsDefined() )
  29. {
  30. params[ AAINTERNAL1 ]->SetVecValue( 0, 0, 0, 0 );
  31. }
  32. if( !params[ AAINTERNAL2 ]->IsDefined() )
  33. {
  34. params[ AAINTERNAL2 ]->SetVecValue( 0, 0, 0, 0 );
  35. }
  36. if( !params[ AAINTERNAL3 ]->IsDefined() )
  37. {
  38. params[ AAINTERNAL3 ]->SetVecValue( 0, 0, 0, 0 );
  39. }
  40. if( !params[ BLOOMENABLE ]->IsDefined() )
  41. {
  42. params[ BLOOMENABLE ]->SetIntValue( 1 );
  43. }
  44. SET_FLAGS2( MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE );
  45. }
  46. SHADER_FALLBACK
  47. {
  48. // This shader should not be *used* unless we're >= DX9 (bloomadd.vmt/screenspace_general_dx8 should be used for DX8)
  49. return 0;
  50. }
  51. SHADER_INIT
  52. {
  53. if ( params[BASETEXTURE]->IsDefined() )
  54. {
  55. LoadTexture( BASETEXTURE );
  56. }
  57. if ( params[FBTEXTURE]->IsDefined() )
  58. {
  59. LoadTexture( FBTEXTURE );
  60. }
  61. }
  62. SHADER_DRAW
  63. {
  64. SHADOW_STATE
  65. {
  66. // This shader uses opaque blending, but needs to match the behaviour of bloom_add/screen_spacegeneral,
  67. // which uses additive blending (and is used when bloom is enabled but col-correction and AA are not).
  68. // BUT!
  69. // Hardware sRGB blending is incorrect (on pre-DX10 cards, sRGB values are added directly).
  70. // SO...
  71. // When doing the bloom addition in the pixel shader, we need to emulate that incorrect
  72. // behaviour - by turning sRGB read OFF for the FB texture and by turning sRGB write OFF
  73. // (which is fine, since the AA process works better on an sRGB framebuffer than a linear
  74. // one; gamma colours more closely match luminance perception. The color-correction process
  75. // has always taken gamma-space values as input anyway).
  76. // On OpenGL OSX, we MUST do sRGB reads from the bloom and full framebuffer textures AND sRGB
  77. // writes on the way out to the framebuffer. Hence, our colors are linear in the shader.
  78. // Given this, we use the LINEAR_INPUTS combo to convert to sRGB for the purposes of color
  79. // correction, since that is how the color correction textures are authored.
  80. bool bLinearInput = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs();
  81. bool bLinearOutput = IsOSX() && !g_pHardwareConfig->FakeSRGBWrite() && g_pHardwareConfig->CanDoSRGBReadFromRTs();
  82. bool bForceSRGBReadsAndWrites = IsOSX() && g_pHardwareConfig->CanDoSRGBReadFromRTs();
  83. pShaderShadow->EnableBlending( false );
  84. // The (sRGB) bloom texture is bound to sampler 0
  85. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  86. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, bForceSRGBReadsAndWrites );
  87. pShaderShadow->EnableSRGBWrite( bForceSRGBReadsAndWrites );
  88. // The (sRGB) full framebuffer texture is bound to sampler 1:
  89. pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
  90. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER1, bForceSRGBReadsAndWrites );
  91. // Up to 4 (sRGB) color-correction lookup textures are bound to samplers 2-5:
  92. pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
  93. pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
  94. pShaderShadow->EnableTexture( SHADER_SAMPLER4, true );
  95. pShaderShadow->EnableTexture( SHADER_SAMPLER5, true );
  96. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER2, false );
  97. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER3, false );
  98. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
  99. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER5, false );
  100. int format = VERTEX_POSITION;
  101. int numTexCoords = 1;
  102. int * pTexCoordDimensions = NULL;
  103. int userDataSize = 0;
  104. pShaderShadow->VertexShaderVertexFormat( format, numTexCoords, pTexCoordDimensions, userDataSize );
  105. DECLARE_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 );
  106. SET_STATIC_VERTEX_SHADER( screenspaceeffect_vs20 );
  107. if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // GL always goes the ps2b way for this shader, even on "ps20" parts
  108. {
  109. DECLARE_STATIC_PIXEL_SHADER( engine_post_ps20b );
  110. SET_STATIC_PIXEL_SHADER_COMBO( LINEAR_INPUT, bLinearInput );
  111. SET_STATIC_PIXEL_SHADER_COMBO( LINEAR_OUTPUT, bLinearOutput );
  112. SET_STATIC_PIXEL_SHADER( engine_post_ps20b );
  113. }
  114. else
  115. {
  116. DECLARE_STATIC_PIXEL_SHADER( engine_post_ps20 );
  117. SET_STATIC_PIXEL_SHADER( engine_post_ps20 );
  118. }
  119. }
  120. DYNAMIC_STATE
  121. {
  122. BindTexture( SHADER_SAMPLER0, BASETEXTURE, -1 );
  123. // FIXME: need to set FBTEXTURE to be point-sampled (will speed up this shader significantly on 360)
  124. // and assert that it's set to SHADER_TEXWRAPMODE_CLAMP (since the shader will sample offscreen)
  125. BindTexture( SHADER_SAMPLER1, FBTEXTURE, -1 );
  126. ShaderColorCorrectionInfo_t ccInfo;
  127. pShaderAPI->GetCurrentColorCorrection( &ccInfo );
  128. int colCorrectNumLookups = ccInfo.m_nLookupCount;
  129. for( int i = 0; i < colCorrectNumLookups; i++ )
  130. {
  131. pShaderAPI->BindStandardTexture( (Sampler_t)(SHADER_SAMPLER2 + i), (StandardTextureId_t)(TEXTURE_COLOR_CORRECTION_VOLUME_0 + i) );
  132. }
  133. // Upload 1-pixel X&Y offsets [ (+dX,0,+dY,-dX) is chosen to work with the allowed ps20 swizzles ]
  134. // The shader will sample in a cross (up/down/left/right from the current sample), for 5-tap
  135. // (quality 0) mode and add another 4 samples in a diagonal cross, for 9-tap (quality 1) mode
  136. ITexture * pTarget = params[FBTEXTURE]->GetTextureValue();
  137. int width = pTarget->GetActualWidth();
  138. int height = pTarget->GetActualHeight();
  139. float dX = 1.0f / width;
  140. float dY = 1.0f / height;
  141. float offsets[4] = { +dX, 0, +dY, -dX };
  142. pShaderAPI->SetPixelShaderConstant( 0, &offsets[0], 1 );
  143. // Upload AA tweakables:
  144. // x - strength (this can be used to toggle the AA off, or to weaken it where pathological cases are showing)
  145. // y - reduction of 1-pixel-line blurring (blurring of 1-pixel lines causes issues, so it's tunable)
  146. // z - edge threshold multiplier (default 1.0, < 1.0 => more edges softened, > 1.0 => fewer edges softened)
  147. // w - tap offset multiplier (default 1.0, < 1.0 => sharper image, > 1.0 => blurrier image)
  148. float tweakables[4] = { params[ AAINTERNAL1 ]->GetVecValue()[0],
  149. params[ AAINTERNAL1 ]->GetVecValue()[1],
  150. params[ AAINTERNAL3 ]->GetVecValue()[0],
  151. params[ AAINTERNAL3 ]->GetVecValue()[1] };
  152. pShaderAPI->SetPixelShaderConstant( 1, &tweakables[0], 1 );
  153. // Upload AA UV transform (converts bloom texture UVs to framebuffer texture UVs)
  154. // NOTE: we swap the order of the z and w components since 'wz' is an allowed ps20 swizzle, but 'zw' is not:
  155. float uvTrans[4] = { params[ AAINTERNAL2 ]->GetVecValue()[0],
  156. params[ AAINTERNAL2 ]->GetVecValue()[1],
  157. params[ AAINTERNAL2 ]->GetVecValue()[3],
  158. params[ AAINTERNAL2 ]->GetVecValue()[2] };
  159. pShaderAPI->SetPixelShaderConstant( 2, &uvTrans[0], 1 );
  160. // Upload color-correction weights:
  161. pShaderAPI->SetPixelShaderConstant( 3, &ccInfo.m_flDefaultWeight );
  162. pShaderAPI->SetPixelShaderConstant( 4, ccInfo.m_pLookupWeights );
  163. int aaEnabled = ( params[ AAINTERNAL1 ]->GetVecValue()[0] == 0.0f ) ? 0 : 1;
  164. int aaReduceOnePixelLineBlur = ( params[ AAINTERNAL1 ]->GetVecValue()[1] == 0.0f ) ? 0 : 1;
  165. int aaQualityMode = (int)params[ AAINTERNAL1 ]->GetVecValue()[2];
  166. // int aaDebugMode = (int)params[ AAINTERNAL1 ]->GetVecValue()[3];
  167. int bloomEnabled = ( params[ BLOOMENABLE ]->GetIntValue() == 0 ) ? 0 : 1;
  168. int colCorrectEnabled = ccInfo.m_bIsEnabled;
  169. float flBloomFactor = bloomEnabled ? 1.0f : 0.0f;
  170. float bloomConstant[4] = { flBloomFactor, flBloomFactor, flBloomFactor, flBloomFactor };
  171. pShaderAPI->SetPixelShaderConstant( 5, bloomConstant );
  172. if ( !colCorrectEnabled )
  173. {
  174. colCorrectNumLookups = 0;
  175. }
  176. if( g_pHardwareConfig->SupportsPixelShaders_2_b() || g_pHardwareConfig->ShouldAlwaysUseShaderModel2bShaders() ) // GL always goes the ps2b way for this shader, even on "ps20" parts
  177. {
  178. DECLARE_DYNAMIC_PIXEL_SHADER( engine_post_ps20b );
  179. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_ENABLE, aaEnabled );
  180. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_QUALITY_MODE, aaQualityMode );
  181. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_REDUCE_ONE_PIXEL_LINE_BLUR, aaReduceOnePixelLineBlur );
  182. // SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_DEBUG_MODE, aaDebugMode );
  183. SET_DYNAMIC_PIXEL_SHADER_COMBO( COL_CORRECT_NUM_LOOKUPS, colCorrectNumLookups );
  184. SET_DYNAMIC_PIXEL_SHADER( engine_post_ps20b );
  185. }
  186. else
  187. {
  188. DECLARE_DYNAMIC_PIXEL_SHADER( engine_post_ps20 );
  189. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_ENABLE, aaEnabled );
  190. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_QUALITY_MODE, 0 ); // Only enough instruction slots in ps2b
  191. SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_REDUCE_ONE_PIXEL_LINE_BLUR, 0 );
  192. // SET_DYNAMIC_PIXEL_SHADER_COMBO( AA_DEBUG_MODE, aaDebugMode );
  193. SET_DYNAMIC_PIXEL_SHADER_COMBO( COL_CORRECT_NUM_LOOKUPS, colCorrectNumLookups );
  194. SET_DYNAMIC_PIXEL_SHADER( engine_post_ps20 );
  195. }
  196. DECLARE_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 );
  197. SET_DYNAMIC_VERTEX_SHADER( screenspaceeffect_vs20 );
  198. }
  199. Draw();
  200. }
  201. END_SHADER