mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-14 22:50:45 +00:00
Improved filmic post processing
This commit is contained in:
parent
1b3378cb94
commit
5dedbc70a6
5 changed files with 240 additions and 490 deletions
|
@ -112,7 +112,7 @@ struct PS_OUT
|
|||
|
||||
float BlueNoise( float2 n, float x )
|
||||
{
|
||||
float noise = tex2D( samp2, ( n.xy / 256.0 ) ).r;
|
||||
float noise = tex2D( samp2, n.xy * rpJitterTexOffset.xy ).r;
|
||||
|
||||
#if TEMPORALLY_VARY_TAPS
|
||||
noise = fract( noise + 0.61803398875 * rpJitterTexOffset.z * x );
|
||||
|
@ -120,9 +120,8 @@ float BlueNoise( float2 n, float x )
|
|||
noise = fract( noise );
|
||||
#endif
|
||||
|
||||
noise = RemapNoiseTriErp( noise );
|
||||
|
||||
//noise = noise * 2.0 - 1.0;
|
||||
//noise = RemapNoiseTriErp( noise );
|
||||
//noise = noise * 2.0 - 0.5;
|
||||
|
||||
return noise;
|
||||
}
|
||||
|
|
|
@ -172,6 +172,32 @@ half4 LinearRGBToSRGB( half4 rgba )
|
|||
}
|
||||
|
||||
|
||||
float Linear1( float c )
|
||||
{
|
||||
return ( c <= 0.04045 ) ? c / 12.92 : pow( ( c + 0.055 ) / 1.055, 2.4 );
|
||||
}
|
||||
|
||||
float3 Linear3( float3 c )
|
||||
{
|
||||
return float3( Linear1( c.r ), Linear1( c.g ), Linear1( c.b ) );
|
||||
}
|
||||
|
||||
float Srgb1( float c )
|
||||
{
|
||||
return ( c < 0.0031308 ? c * 12.92 : 1.055 * pow( c, 0.41666 ) - 0.055 );
|
||||
}
|
||||
|
||||
float3 Srgb3( float3 c )
|
||||
{
|
||||
return float3( Srgb1( c.r ), Srgb1( c.g ), Srgb1( c.b ) );
|
||||
}
|
||||
|
||||
static const float3 photoLuma = float3( 0.2126, 0.7152, 0.0722 );
|
||||
float PhotoLuma( float3 c )
|
||||
{
|
||||
return dot( c, photoLuma );
|
||||
}
|
||||
|
||||
// RB end
|
||||
|
||||
// ----------------------
|
||||
|
@ -309,3 +335,36 @@ float3 Hash33( float3 p3 )
|
|||
return fract( ( p3.xxy + p3.yxx ) * p3.zyx );
|
||||
}
|
||||
|
||||
static float3 ditherRGB( float3 c, float2 uvSeed )
|
||||
{
|
||||
// uniform noise
|
||||
//float3 whiteNoise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) );
|
||||
|
||||
//float3 whiteNoise = float3( InterleavedGradientNoise( uvSeed ) );
|
||||
float3 whiteNoise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) );
|
||||
|
||||
|
||||
// triangular noise [-0.5;1.5[
|
||||
|
||||
#if 1
|
||||
whiteNoise.x = RemapNoiseTriErp( whiteNoise.x );
|
||||
whiteNoise = whiteNoise * 2.0 - 0.5;
|
||||
#endif
|
||||
|
||||
whiteNoise = float3( whiteNoise.x );
|
||||
|
||||
|
||||
// quantize/truncate color and dither the result
|
||||
//float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
|
||||
// lets assume 2^3 bits = 8
|
||||
float scale = 255.0;
|
||||
|
||||
float3 color = floor( c * scale + whiteNoise ) / scale;
|
||||
|
||||
#if defined( USE_LINEAR_RGB )
|
||||
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ float BlueNoise( float2 n, float x )
|
|||
noise = fract( noise + c_goldenRatioConjugate * rpJitterTexOffset.w * x );
|
||||
|
||||
//noise = RemapNoiseTriErp( noise );
|
||||
|
||||
//noise = noise * 2.0 - 1.0;
|
||||
//noise = noise * 2.0 - 0.5;
|
||||
|
||||
return noise;
|
||||
}
|
||||
|
@ -94,7 +93,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
{
|
||||
half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );
|
||||
half4 lightFalloff = ( idtex2Dproj( samp3, fragment.texcoord2 ) );
|
||||
half4 lightProj = ( idtex2Dproj( samp4, fragment.texcoord3 ) );
|
||||
half4 lightProj = ( idtex2Dproj( samp4, fragment.texcoord3 ) );
|
||||
half4 YCoCG = tex2D( samp2, fragment.texcoord4.xy );
|
||||
half4 specMapSRGB = tex2D( samp1, fragment.texcoord5.xy );
|
||||
half4 specMap = sRGBAToLinearRGBA( specMapSRGB );
|
||||
|
@ -418,13 +417,20 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
half3 specularColor = specMapSRGB.rgb; // RB: should be linear but it looks too flat
|
||||
#endif
|
||||
|
||||
diffuseColor = half3( 1.0 );
|
||||
//diffuseColor = half3( 1.0 );
|
||||
|
||||
// RB: compensate r_lightScale 3 and the division of Pi
|
||||
//lambert *= 1.3;
|
||||
|
||||
// rpDiffuseModifier contains light color multiplier
|
||||
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );// * rpDiffuseModifier.xyz;
|
||||
half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );
|
||||
//lightColor = ditherRGB( lightColor, fragment.position.xy );
|
||||
//lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz;
|
||||
|
||||
//lightColor = ditherRGB( lightColor, fragment.position.xy );
|
||||
|
||||
|
||||
//lightColor = ditherRGB( lightColor, fragment.position.xy * rpWindowCoord.xy );
|
||||
|
||||
half vdotN = clamp( dot3( viewVector, localNormal ), 0.0, 1.0 );
|
||||
half vdotH = clamp( dot3( viewVector, halfAngleVector ), 0.0, 1.0 );
|
||||
|
|
|
@ -46,7 +46,7 @@ struct PS_OUT
|
|||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
#define USE_CHROMATIC_ABERRATION 0
|
||||
#define USE_CHROMATIC_ABERRATION 1
|
||||
#define Chromatic_Amount 0.075
|
||||
|
||||
#define USE_TECHNICOLOR 0 // [0 or 1]
|
||||
|
@ -62,6 +62,11 @@ struct PS_OUT
|
|||
#define Vibrance_RGB_Balance float3( 1.0, 1.0, 1.0 )
|
||||
|
||||
#define USE_DITHERING 1
|
||||
#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits
|
||||
#define Dithering_NoiseBoost 1.0
|
||||
#define Dithering_Wide 1.0
|
||||
#define DITHER_IN_LINEAR_SPACE 0
|
||||
#define DITHER_GENERATE_NOISE 0
|
||||
|
||||
float3 overlay( float3 a, float3 b )
|
||||
{
|
||||
|
@ -208,31 +213,7 @@ void ChromaticAberrationPass( inout float4 color )
|
|||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
float Linear1( float c )
|
||||
{
|
||||
return ( c <= 0.04045 ) ? c / 12.92 : pow( ( c + 0.055 ) / 1.055, 2.4 );
|
||||
}
|
||||
|
||||
float3 Linear3( float3 c )
|
||||
{
|
||||
return float3( Linear1( c.r ), Linear1( c.g ), Linear1( c.b ) );
|
||||
}
|
||||
|
||||
float Srgb1( float c )
|
||||
{
|
||||
return ( c < 0.0031308 ? c * 12.92 : 1.055 * pow( c, 0.41666 ) - 0.055 );
|
||||
}
|
||||
|
||||
float3 Srgb3( float3 c )
|
||||
{
|
||||
return float3( Srgb1( c.r ), Srgb1( c.g ), Srgb1( c.b ) );
|
||||
}
|
||||
|
||||
float3 photoLuma = float3( 0.2126, 0.7152, 0.0722 );
|
||||
float PhotoLuma( float3 c )
|
||||
{
|
||||
return dot( c, photoLuma );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -306,7 +287,11 @@ float Step2( float2 uv, float n )
|
|||
{
|
||||
float a = 1.0, b = 2.0, c = -2.0, t = 1.0;
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
return ( 1.0 / ( a * 4.0 + b * 4.0 - c ) ) * (
|
||||
#else
|
||||
return ( 4.0 / ( a * 4.0 + b * 4.0 - c ) ) * (
|
||||
#endif
|
||||
Step1( uv + float2( -1.0, -1.0 ) * t, n ) * a +
|
||||
Step1( uv + float2( 0.0, -1.0 ) * t, n ) * b +
|
||||
Step1( uv + float2( 1.0, -1.0 ) * t, n ) * a +
|
||||
|
@ -322,7 +307,7 @@ float Step2( float2 uv, float n )
|
|||
// Used for stills.
|
||||
float3 Step3( float2 uv )
|
||||
{
|
||||
#if 0
|
||||
#if DITHER_GENERATE_NOISE
|
||||
float a = Step2( uv, 0.07 );
|
||||
float b = Step2( uv, 0.11 );
|
||||
float c = Step2( uv, 0.13 );
|
||||
|
@ -331,11 +316,13 @@ float3 Step3( float2 uv )
|
|||
#else
|
||||
float3 noise = BlueNoise3( uv, 0.0 );
|
||||
|
||||
#if 1
|
||||
noise.x = RemapNoiseTriErp( noise.x );
|
||||
noise.y = RemapNoiseTriErp( noise.y );
|
||||
noise.z = RemapNoiseTriErp( noise.z );
|
||||
|
||||
noise = noise * 2.0 - 1.0;
|
||||
#endif
|
||||
|
||||
return noise;
|
||||
#endif
|
||||
|
@ -344,7 +331,7 @@ float3 Step3( float2 uv )
|
|||
// Used for temporal dither.
|
||||
float3 Step3T( float2 uv )
|
||||
{
|
||||
#if 0
|
||||
#if DITHER_GENERATE_NOISE
|
||||
float a = Step2( uv, 0.07 * fract( rpJitterTexOffset.z ) );
|
||||
float b = Step2( uv, 0.11 * fract( rpJitterTexOffset.z ) );
|
||||
float c = Step2( uv, 0.13 * fract( rpJitterTexOffset.z ) );
|
||||
|
@ -353,19 +340,19 @@ float3 Step3T( float2 uv )
|
|||
#else
|
||||
float3 noise = BlueNoise3( uv, 1.0 );
|
||||
|
||||
#if 1
|
||||
noise.x = RemapNoiseTriErp( noise.x );
|
||||
noise.y = RemapNoiseTriErp( noise.y );
|
||||
noise.z = RemapNoiseTriErp( noise.z );
|
||||
|
||||
noise = noise * 2.0 - 1.0;
|
||||
#endif
|
||||
|
||||
return noise;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define STEPS 12.0
|
||||
|
||||
void DitheringPass( inout float4 fragColor )
|
||||
{
|
||||
float2 uv = fragment.position.xy * 1.0;
|
||||
|
@ -373,31 +360,39 @@ void DitheringPass( inout float4 fragColor )
|
|||
|
||||
float3 color = fragColor.rgb;
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
// BOTTOM: Show bands.
|
||||
if( uv2.y >= 0.975 )
|
||||
{
|
||||
// quantized signal
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS + Step3( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
|
||||
// dithered still
|
||||
//color = floor( color * Dithering_QuantizationSteps + Step3( uv ) * Dithering_NoiseBoost ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
}
|
||||
else if( uv2.y >= 0.95 )
|
||||
{
|
||||
// quantized signal
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
color = floor( color * Dithering_QuantizationSteps ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
}
|
||||
else if( uv2.y >= 0.925 )
|
||||
{
|
||||
// quantized signal dithered temporally
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
color = floor( color * Dithering_QuantizationSteps + Step3( uv ) * Dithering_NoiseBoost ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
}
|
||||
// TOP: Show dither texture.
|
||||
else if( uv2.y >= 0.9 )
|
||||
{
|
||||
color = Step3( uv ) * 1.0 + 0.5;
|
||||
color = Step3( uv ) * ( 0.25 * Dithering_NoiseBoost ) + 0.5;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
|
||||
color = Linear3( color );
|
||||
|
||||
// Add grain in linear space.
|
||||
|
@ -406,13 +401,13 @@ void DitheringPass( inout float4 fragColor )
|
|||
#if 1
|
||||
// Too expensive.
|
||||
// Helps understand the fast solutions.
|
||||
float3 amount = Linear3( Srgb3( color ) + ( 4.0 / STEPS ) ) - color;
|
||||
float3 amount = Linear3( Srgb3( color ) + ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ) - color;
|
||||
#else
|
||||
// Less too expensive.
|
||||
float luma = PhotoLuma( color );
|
||||
|
||||
// Implement this as a texture lookup table.
|
||||
float amount = Linear1( Srgb1( luma ) + ( 4.0 / STEPS ) ) - luma;
|
||||
float amount = Linear1( Srgb1( luma ) + ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ) - luma;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
@ -422,227 +417,43 @@ void DitheringPass( inout float4 fragColor )
|
|||
// For HDR need saturate() around luma.
|
||||
float luma = PhotoLuma( color );
|
||||
float amount = mix(
|
||||
Linear1( 4.0 / STEPS ),
|
||||
Linear1( ( 4.0 / STEPS ) + 1.0 ) - 1.0,
|
||||
Linear1( Dithering_NoiseBoost / Dithering_QuantizationSteps ),
|
||||
Linear1( ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) + 1.0 ) - 1.0,
|
||||
luma );
|
||||
#else
|
||||
// Hack 2 (slower?).
|
||||
// For HDR need saturate() around color in mix().
|
||||
float3 amount = mix(
|
||||
float3( Linear1( 4.0 / STEPS ) ),
|
||||
float3( Linear1( ( 4.0 / STEPS ) + 1.0 ) - 1.0 ),
|
||||
float3( Linear1( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ),
|
||||
float3( Linear1( ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) + 1.0 ) - 1.0 ),
|
||||
color );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
color += Step3T( uv ) * amount;
|
||||
color += Step3T( uv ) * amount;// * Dithering_NoiseBoost;
|
||||
|
||||
// The following represents hardware linear->sRGB xform
|
||||
// which happens on sRGB formatted render targets,
|
||||
// except using a lot less bits/pixel.
|
||||
color = max( float3( 0.0 ), color );
|
||||
color = Srgb3( color );
|
||||
color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
}
|
||||
color = floor( color * Dithering_QuantizationSteps ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
|
||||
fragColor.rgb = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ANIMATE_NOISE 1
|
||||
#define TARGET_BITS 4 // 2^3 = 8 dithered to this many bits
|
||||
#define DITHER_IN_LINEAR_SPACE 0
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Items of note!
|
||||
|
||||
* The blue noise texture sampling should be set to "nearest" (not mip map!) and repeat
|
||||
|
||||
* you should calculate the uv to use based on the pixel coordinate and the size of the blue noise texture.
|
||||
* aka you should tile the blue noise texture across the screen.
|
||||
* blue noise actually tiles really well unlike white noise.
|
||||
|
||||
* A blue noise texture is "low discrepancy over space" which means there are fewer visible patterns than white noise
|
||||
* it also gives more even coverage vs white noise. no clumps or voids.
|
||||
|
||||
* In an attempt to make it also blue noise over time, you can add the golden ratio and frac it.
|
||||
* that makes it lower discrepancy over time, but makes it less good over space.
|
||||
* thanks to r4unit for that tip! https://twitter.com/R4_Unit
|
||||
|
||||
* Animating the noise in this demo makes the noise basically disappear imo, it's really nice!
|
||||
|
||||
For more information:
|
||||
|
||||
What the heck is blue nois:
|
||||
https://blog.demofox.org/2018/01/30/what-the-heck-is-blue-noise/
|
||||
|
||||
Low discrepancy sequences:
|
||||
https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/
|
||||
|
||||
You can get your own blue noise textures here:
|
||||
http://momentsingraphics.de/?p=127
|
||||
|
||||
*/
|
||||
void DitheringPassDemoFox( inout float4 fragColor )
|
||||
{
|
||||
// texture color
|
||||
float2 uv = fragment.position.xy;
|
||||
float2 uv2 = fragment.texcoord0;
|
||||
float3 fg = fragColor.rgb;
|
||||
|
||||
float3 color = fg;
|
||||
|
||||
#if 1
|
||||
// TOP: show bands
|
||||
if( uv2.y >= 0.975 )
|
||||
{
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS + Step3( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
}
|
||||
else if( uv2.y >= 0.95 )
|
||||
{
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
}
|
||||
else if( uv2.y >= 0.925 )
|
||||
{
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
}
|
||||
// BOTTOM: show dither texture
|
||||
else if( uv2.y >= 0.9 )
|
||||
{
|
||||
color = Step3( uv ).rgb;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// right of the screen is dithered using white noise to a fewer number of bits per color channel
|
||||
if( uv2.x > 3.0 / 4.0 )
|
||||
{
|
||||
// get white noise "random" number
|
||||
#if ANIMATE_NOISE
|
||||
float3 whiteNoise = Hash33( float3( uv, rpJitterTexOffset.w / 256.0 ) );
|
||||
#else
|
||||
float3 whiteNoise = Hash33( float3( uv, 0.0 ) );
|
||||
#endif
|
||||
|
||||
// dither to the specified number of bits, using sRGB conversions if desired
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
fg = pow( fg, float3( 2.2 ) );
|
||||
#endif
|
||||
|
||||
float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
color = floor( fg * scale + whiteNoise ) / scale;
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
color = pow( col, 1.0 / float3( 2.2 ) );
|
||||
#endif
|
||||
}
|
||||
// middle right of the screen is dithered using blue noise to a fewer number of bits per color channel
|
||||
else if( uv2.x > 2.0 / 4.0 )
|
||||
{
|
||||
float3 blueNoise = BlueNoise3( uv, 1.0 );
|
||||
|
||||
// dither to the specified number of bits, using sRGB conversions if desired
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
fg = pow( fg, float3( 2.2 ) );
|
||||
#endif
|
||||
|
||||
float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
color = floor( fg * scale + blueNoise ) / scale;
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
color = pow( color, 1.0 / float3( 2.2 ) );
|
||||
#endif
|
||||
}
|
||||
// middle left of the screen is quantized but not dithered
|
||||
else if( uv2.x > 1.0 / 4.0 )
|
||||
{
|
||||
// dither to the specified number of bits, using sRGB conversions if desired
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
fg = pow( fg, float3( 2.2 ) );
|
||||
#endif
|
||||
|
||||
float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
color = floor( fg * scale + 0.5f ) / scale;
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
color = pow( color, 1.0 / float3( 2.2 ) );
|
||||
#endif
|
||||
}
|
||||
// left side of screen is left alone for comparison
|
||||
else
|
||||
{
|
||||
color = fg;
|
||||
}
|
||||
|
||||
if( abs( uv2.x - 1.0 / 4.0 ) < 0.001 || abs( uv2.x - 2.0 / 4.0 ) < 0.001 || abs( uv2.x - 3.0 / 4.0 ) < 0.001 )
|
||||
{
|
||||
color = float3( 0.0, 1.0, 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
fragColor.rgb = color;
|
||||
}
|
||||
|
||||
void DitheringPassSlim( inout float4 fragColor )
|
||||
{
|
||||
// texture color
|
||||
float2 uv = fragment.position.xy;
|
||||
float2 uv2 = fragment.texcoord0;
|
||||
float3 fg = fragColor.rgb;
|
||||
|
||||
float3 color = fg;
|
||||
|
||||
#if 0
|
||||
if( uv2.y >= 0.975 )
|
||||
{
|
||||
// source signal
|
||||
color = float3( uv2.x );
|
||||
}
|
||||
else if( uv2.y >= 0.95 )
|
||||
{
|
||||
color = float3( uv2.x );
|
||||
|
||||
// quantized signal
|
||||
float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
color = floor( color * scale + 0.0f ) / scale;
|
||||
}
|
||||
else if( uv2.y >= 0.925 )
|
||||
{
|
||||
// dithered quantized signal
|
||||
color = float3( uv2.x );
|
||||
color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );
|
||||
}
|
||||
else if( uv2.y >= 0.9 )
|
||||
{
|
||||
// dither texture
|
||||
color = Step3( uv ).rgb;
|
||||
}
|
||||
else
|
||||
if( uv2.x <= 0.5 )
|
||||
{
|
||||
// quantized but not dithered
|
||||
color = floor( 0.5 + color * ( Dithering_QuantizationSteps + Dithering_Wide - 1.0 ) + ( -Dithering_Wide * 0.5 ) ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
float3 noise = BlueNoise3( uv, 1.0 );
|
||||
|
||||
//noise.x = RemapNoiseTriErp( noise.x );
|
||||
//noise.y = RemapNoiseTriErp( noise.y );
|
||||
//noise.z = RemapNoiseTriErp( noise.z );
|
||||
|
||||
// dither to the specified number of bits, using sRGB conversions if desired
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
fg = pow( fg, float3( 2.2 ) );
|
||||
{
|
||||
color = floor( 0.5 + color * ( Dithering_QuantizationSteps + Dithering_Wide - 1.0 ) + ( -Dithering_Wide * 0.5 ) + Step3T( uv ) * ( Dithering_Wide ) ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
float scale = exp2( float( TARGET_BITS ) ) - 1.0;
|
||||
color = floor( fg * scale + noise ) / scale;
|
||||
|
||||
#if DITHER_IN_LINEAR_SPACE
|
||||
color = pow( color, 1.0 / float3( 2.2 ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
fragColor.rgb = color;
|
||||
|
@ -669,7 +480,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
#endif
|
||||
|
||||
#if USE_DITHERING
|
||||
DitheringPassSlim( color );
|
||||
DitheringPass( color );
|
||||
#endif
|
||||
|
||||
result.color = color;
|
||||
|
|
|
@ -186,6 +186,32 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"float Linear1( float c )\n"
|
||||
"{\n"
|
||||
" return ( c <= 0.04045 ) ? c / 12.92 : pow( ( c + 0.055 ) / 1.055, 2.4 );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float3 Linear3( float3 c )\n"
|
||||
"{\n"
|
||||
" return float3( Linear1( c.r ), Linear1( c.g ), Linear1( c.b ) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float Srgb1( float c )\n"
|
||||
"{\n"
|
||||
" return ( c < 0.0031308 ? c * 12.92 : 1.055 * pow( c, 0.41666 ) - 0.055 );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float3 Srgb3( float3 c )\n"
|
||||
"{\n"
|
||||
" return float3( Srgb1( c.r ), Srgb1( c.g ), Srgb1( c.b ) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static const float3 photoLuma = float3( 0.2126, 0.7152, 0.0722 );\n"
|
||||
"float PhotoLuma( float3 c )\n"
|
||||
"{\n"
|
||||
" return dot( c, photoLuma );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// RB end\n"
|
||||
"\n"
|
||||
"// ----------------------\n"
|
||||
|
@ -323,6 +349,39 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
" return fract( ( p3.xxy + p3.yxx ) * p3.zyx );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static float3 ditherRGB( float3 c, float2 uvSeed )\n"
|
||||
"{\n"
|
||||
" // uniform noise\n"
|
||||
" //float3 whiteNoise = Hash33( float3( uvSeed, rpJitterTexOffset.w ) );\n"
|
||||
"\n"
|
||||
" //float3 whiteNoise = float3( InterleavedGradientNoise( uvSeed ) );\n"
|
||||
" float3 whiteNoise = float3( InterleavedGradientNoiseAnim( uvSeed, rpJitterTexOffset.w ) );\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" // triangular noise [-0.5;1.5[\n"
|
||||
"\n"
|
||||
"#if 1\n"
|
||||
" whiteNoise.x = RemapNoiseTriErp( whiteNoise.x );\n"
|
||||
" whiteNoise = whiteNoise * 2.0 - 0.5;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" whiteNoise = float3( whiteNoise.x );\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" // quantize/truncate color and dither the result\n"
|
||||
" //float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
"\n"
|
||||
" // lets assume 2^3 bits = 8\n"
|
||||
" float scale = 255.0;\n"
|
||||
"\n"
|
||||
" float3 color = floor( c * scale + whiteNoise ) / scale;\n"
|
||||
"\n"
|
||||
"#if defined( USE_LINEAR_RGB )\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" return color;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
||||
},
|
||||
|
@ -2840,7 +2899,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"\n"
|
||||
"float BlueNoise( float2 n, float x )\n"
|
||||
"{\n"
|
||||
" float noise = tex2D( samp2, ( n.xy / 256.0 ) ).r;\n"
|
||||
" float noise = tex2D( samp2, n.xy * rpJitterTexOffset.xy ).r;\n"
|
||||
"\n"
|
||||
"#if TEMPORALLY_VARY_TAPS\n"
|
||||
" noise = fract( noise + 0.61803398875 * rpJitterTexOffset.z * x );\n"
|
||||
|
@ -2848,9 +2907,8 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
" noise = fract( noise );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" noise = RemapNoiseTriErp( noise );\n"
|
||||
"\n"
|
||||
" //noise = noise * 2.0 - 1.0;\n"
|
||||
" //noise = RemapNoiseTriErp( noise );\n"
|
||||
" //noise = noise * 2.0 - 0.5;\n"
|
||||
"\n"
|
||||
" return noise;\n"
|
||||
"}\n"
|
||||
|
@ -9883,8 +9941,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
" noise = fract( noise + c_goldenRatioConjugate * rpJitterTexOffset.w * x );\n"
|
||||
"\n"
|
||||
" //noise = RemapNoiseTriErp( noise );\n"
|
||||
"\n"
|
||||
" //noise = noise * 2.0 - 1.0;\n"
|
||||
" //noise = noise * 2.0 - 0.5;\n"
|
||||
"\n"
|
||||
" return noise;\n"
|
||||
"}\n"
|
||||
|
@ -9906,7 +9963,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"{\n"
|
||||
" half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );\n"
|
||||
" half4 lightFalloff = ( idtex2Dproj( samp3, fragment.texcoord2 ) );\n"
|
||||
" half4 lightProj = ( idtex2Dproj( samp4, fragment.texcoord3 ) );\n"
|
||||
" half4 lightProj = ( idtex2Dproj( samp4, fragment.texcoord3 ) );\n"
|
||||
" half4 YCoCG = tex2D( samp2, fragment.texcoord4.xy );\n"
|
||||
" half4 specMapSRGB = tex2D( samp1, fragment.texcoord5.xy );\n"
|
||||
" half4 specMap = sRGBAToLinearRGBA( specMapSRGB );\n"
|
||||
|
@ -10230,13 +10287,20 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
" half3 specularColor = specMapSRGB.rgb; // RB: should be linear but it looks too flat\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" diffuseColor = half3( 1.0 );\n"
|
||||
" //diffuseColor = half3( 1.0 );\n"
|
||||
"\n"
|
||||
" // RB: compensate r_lightScale 3 and the division of Pi\n"
|
||||
" //lambert *= 1.3;\n"
|
||||
"\n"
|
||||
" // rpDiffuseModifier contains light color multiplier\n"
|
||||
" half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );// * rpDiffuseModifier.xyz;\n"
|
||||
" half3 lightColor = sRGBToLinearRGB( lightProj.xyz * lightFalloff.xyz );\n"
|
||||
" //lightColor = ditherRGB( lightColor, fragment.position.xy );\n"
|
||||
" //lightColor *= sRGBToLinearRGB( lightFalloff.xyz );// * rpDiffuseModifier.xyz;\n"
|
||||
"\n"
|
||||
" //lightColor = ditherRGB( lightColor, fragment.position.xy );\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" //lightColor = ditherRGB( lightColor, fragment.position.xy * rpWindowCoord.xy );\n"
|
||||
"\n"
|
||||
" half vdotN = clamp( dot3( viewVector, localNormal ), 0.0, 1.0 );\n"
|
||||
" half vdotH = clamp( dot3( viewVector, halfAngleVector ), 0.0, 1.0 );\n"
|
||||
|
@ -10709,7 +10773,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"};\n"
|
||||
"// *INDENT-ON*\n"
|
||||
"\n"
|
||||
"#define USE_CHROMATIC_ABERRATION 0\n"
|
||||
"#define USE_CHROMATIC_ABERRATION 1\n"
|
||||
"#define Chromatic_Amount 0.075\n"
|
||||
"\n"
|
||||
"#define USE_TECHNICOLOR 0 // [0 or 1]\n"
|
||||
|
@ -10725,6 +10789,11 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"#define Vibrance_RGB_Balance float3( 1.0, 1.0, 1.0 )\n"
|
||||
"\n"
|
||||
"#define USE_DITHERING 1\n"
|
||||
"#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits\n"
|
||||
"#define Dithering_NoiseBoost 1.0\n"
|
||||
"#define Dithering_Wide 1.0\n"
|
||||
"#define DITHER_IN_LINEAR_SPACE 0\n"
|
||||
"#define DITHER_GENERATE_NOISE 0\n"
|
||||
"\n"
|
||||
"float3 overlay( float3 a, float3 b )\n"
|
||||
"{\n"
|
||||
|
@ -10871,31 +10940,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"\n"
|
||||
"//-----------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"float Linear1( float c )\n"
|
||||
"{\n"
|
||||
" return ( c <= 0.04045 ) ? c / 12.92 : pow( ( c + 0.055 ) / 1.055, 2.4 );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float3 Linear3( float3 c )\n"
|
||||
"{\n"
|
||||
" return float3( Linear1( c.r ), Linear1( c.g ), Linear1( c.b ) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float Srgb1( float c )\n"
|
||||
"{\n"
|
||||
" return ( c < 0.0031308 ? c * 12.92 : 1.055 * pow( c, 0.41666 ) - 0.055 );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float3 Srgb3( float3 c )\n"
|
||||
"{\n"
|
||||
" return float3( Srgb1( c.r ), Srgb1( c.g ), Srgb1( c.b ) );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float3 photoLuma = float3( 0.2126, 0.7152, 0.0722 );\n"
|
||||
"float PhotoLuma( float3 c )\n"
|
||||
"{\n"
|
||||
" return dot( c, photoLuma );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
|
@ -10969,7 +11014,11 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"{\n"
|
||||
" float a = 1.0, b = 2.0, c = -2.0, t = 1.0;\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" return ( 1.0 / ( a * 4.0 + b * 4.0 - c ) ) * (\n"
|
||||
"#else\n"
|
||||
" return ( 4.0 / ( a * 4.0 + b * 4.0 - c ) ) * (\n"
|
||||
"#endif\n"
|
||||
" Step1( uv + float2( -1.0, -1.0 ) * t, n ) * a +\n"
|
||||
" Step1( uv + float2( 0.0, -1.0 ) * t, n ) * b +\n"
|
||||
" Step1( uv + float2( 1.0, -1.0 ) * t, n ) * a +\n"
|
||||
|
@ -10985,7 +11034,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"// Used for stills.\n"
|
||||
"float3 Step3( float2 uv )\n"
|
||||
"{\n"
|
||||
"#if 0\n"
|
||||
"#if DITHER_GENERATE_NOISE\n"
|
||||
" float a = Step2( uv, 0.07 );\n"
|
||||
" float b = Step2( uv, 0.11 );\n"
|
||||
" float c = Step2( uv, 0.13 );\n"
|
||||
|
@ -10994,11 +11043,13 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"#else\n"
|
||||
" float3 noise = BlueNoise3( uv, 0.0 );\n"
|
||||
"\n"
|
||||
"#if 1\n"
|
||||
" noise.x = RemapNoiseTriErp( noise.x );\n"
|
||||
" noise.y = RemapNoiseTriErp( noise.y );\n"
|
||||
" noise.z = RemapNoiseTriErp( noise.z );\n"
|
||||
"\n"
|
||||
" noise = noise * 2.0 - 1.0;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" return noise;\n"
|
||||
"#endif\n"
|
||||
|
@ -11007,7 +11058,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"// Used for temporal dither.\n"
|
||||
"float3 Step3T( float2 uv )\n"
|
||||
"{\n"
|
||||
"#if 0\n"
|
||||
"#if DITHER_GENERATE_NOISE\n"
|
||||
" float a = Step2( uv, 0.07 * fract( rpJitterTexOffset.z ) );\n"
|
||||
" float b = Step2( uv, 0.11 * fract( rpJitterTexOffset.z ) );\n"
|
||||
" float c = Step2( uv, 0.13 * fract( rpJitterTexOffset.z ) );\n"
|
||||
|
@ -11016,19 +11067,19 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"#else\n"
|
||||
" float3 noise = BlueNoise3( uv, 1.0 );\n"
|
||||
"\n"
|
||||
"#if 1\n"
|
||||
" noise.x = RemapNoiseTriErp( noise.x );\n"
|
||||
" noise.y = RemapNoiseTriErp( noise.y );\n"
|
||||
" noise.z = RemapNoiseTriErp( noise.z );\n"
|
||||
"\n"
|
||||
" noise = noise * 2.0 - 1.0;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" return noise;\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define STEPS 12.0\n"
|
||||
"\n"
|
||||
"void DitheringPass( inout float4 fragColor )\n"
|
||||
"{\n"
|
||||
" float2 uv = fragment.position.xy * 1.0;\n"
|
||||
|
@ -11036,31 +11087,39 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"\n"
|
||||
" float3 color = fragColor.rgb;\n"
|
||||
"\n"
|
||||
"#if 1\n"
|
||||
"#if 0\n"
|
||||
"// BOTTOM: Show bands.\n"
|
||||
" if( uv2.y >= 0.975 )\n"
|
||||
" {\n"
|
||||
" // quantized signal\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS + Step3( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
"\n"
|
||||
" // dithered still\n"
|
||||
" //color = floor( color * Dithering_QuantizationSteps + Step3( uv ) * Dithering_NoiseBoost ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.95 )\n"
|
||||
" {\n"
|
||||
" // quantized signal\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" color = floor( color * Dithering_QuantizationSteps ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.925 )\n"
|
||||
" {\n"
|
||||
" // quantized signal dithered temporally\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" color = floor( color * Dithering_QuantizationSteps + Step3( uv ) * Dithering_NoiseBoost ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" // TOP: Show dither texture.\n"
|
||||
" else if( uv2.y >= 0.9 )\n"
|
||||
" {\n"
|
||||
" color = Step3( uv ) * 1.0 + 0.5;\n"
|
||||
" color = Step3( uv ) * ( 0.25 * Dithering_NoiseBoost ) + 0.5;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
"#endif\n"
|
||||
" {\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
"\n"
|
||||
" color = Linear3( color );\n"
|
||||
"\n"
|
||||
" // Add grain in linear space.\n"
|
||||
|
@ -11069,13 +11128,13 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"#if 1\n"
|
||||
" // Too expensive.\n"
|
||||
" // Helps understand the fast solutions.\n"
|
||||
" float3 amount = Linear3( Srgb3( color ) + ( 4.0 / STEPS ) ) - color;\n"
|
||||
" float3 amount = Linear3( Srgb3( color ) + ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ) - color;\n"
|
||||
"#else\n"
|
||||
" // Less too expensive.\n"
|
||||
" float luma = PhotoLuma( color );\n"
|
||||
"\n"
|
||||
" // Implement this as a texture lookup table.\n"
|
||||
" float amount = Linear1( Srgb1( luma ) + ( 4.0 / STEPS ) ) - luma;\n"
|
||||
" float amount = Linear1( Srgb1( luma ) + ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ) - luma;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#else\n"
|
||||
|
@ -11085,227 +11144,43 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
" // For HDR need saturate() around luma.\n"
|
||||
" float luma = PhotoLuma( color );\n"
|
||||
" float amount = mix(\n"
|
||||
" Linear1( 4.0 / STEPS ),\n"
|
||||
" Linear1( ( 4.0 / STEPS ) + 1.0 ) - 1.0,\n"
|
||||
" Linear1( Dithering_NoiseBoost / Dithering_QuantizationSteps ),\n"
|
||||
" Linear1( ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) + 1.0 ) - 1.0,\n"
|
||||
" luma );\n"
|
||||
"#else\n"
|
||||
" // Hack 2 (slower?).\n"
|
||||
" // For HDR need saturate() around color in mix().\n"
|
||||
" float3 amount = mix(\n"
|
||||
" float3( Linear1( 4.0 / STEPS ) ),\n"
|
||||
" float3( Linear1( ( 4.0 / STEPS ) + 1.0 ) - 1.0 ),\n"
|
||||
" float3( Linear1( Dithering_NoiseBoost / Dithering_QuantizationSteps ) ),\n"
|
||||
" float3( Linear1( ( Dithering_NoiseBoost / Dithering_QuantizationSteps ) + 1.0 ) - 1.0 ),\n"
|
||||
" color );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
" color += Step3T( uv ) * amount;\n"
|
||||
" color += Step3T( uv ) * amount;// * Dithering_NoiseBoost;\n"
|
||||
"\n"
|
||||
" // The following represents hardware linear->sRGB xform\n"
|
||||
" // which happens on sRGB formatted render targets,\n"
|
||||
" // except using a lot less bits/pixel.\n"
|
||||
" color = max( float3( 0.0 ), color );\n"
|
||||
" color = Srgb3( color );\n"
|
||||
" color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" color = floor( color * Dithering_QuantizationSteps ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
"\n"
|
||||
" fragColor.rgb = color;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"#define ANIMATE_NOISE 1\n"
|
||||
"#define TARGET_BITS 4 // 2^3 = 8 dithered to this many bits\n"
|
||||
"#define DITHER_IN_LINEAR_SPACE 0\n"
|
||||
"\n"
|
||||
"//----------------------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"/*\n"
|
||||
"Items of note!\n"
|
||||
"\n"
|
||||
"* The blue noise texture sampling should be set to \"nearest\" (not mip map!) and repeat\n"
|
||||
"\n"
|
||||
"* you should calculate the uv to use based on the pixel coordinate and the size of the blue noise texture.\n"
|
||||
" * aka you should tile the blue noise texture across the screen.\n"
|
||||
" * blue noise actually tiles really well unlike white noise.\n"
|
||||
"\n"
|
||||
"* A blue noise texture is \"low discrepancy over space\" which means there are fewer visible patterns than white noise\n"
|
||||
" * it also gives more even coverage vs white noise. no clumps or voids.\n"
|
||||
"\n"
|
||||
"* In an attempt to make it also blue noise over time, you can add the golden ratio and frac it.\n"
|
||||
" * that makes it lower discrepancy over time, but makes it less good over space.\n"
|
||||
" * thanks to r4unit for that tip! https://twitter.com/R4_Unit\n"
|
||||
"\n"
|
||||
"* Animating the noise in this demo makes the noise basically disappear imo, it's really nice!\n"
|
||||
"\n"
|
||||
"For more information:\n"
|
||||
"\n"
|
||||
"What the heck is blue nois:\n"
|
||||
"https://blog.demofox.org/2018/01/30/what-the-heck-is-blue-noise/\n"
|
||||
"\n"
|
||||
"Low discrepancy sequences:\n"
|
||||
"https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/\n"
|
||||
"\n"
|
||||
"You can get your own blue noise textures here:\n"
|
||||
"http://momentsingraphics.de/?p=127\n"
|
||||
"\n"
|
||||
"*/\n"
|
||||
"void DitheringPassDemoFox( inout float4 fragColor )\n"
|
||||
"{\n"
|
||||
" // texture color\n"
|
||||
" float2 uv = fragment.position.xy;\n"
|
||||
" float2 uv2 = fragment.texcoord0;\n"
|
||||
" float3 fg = fragColor.rgb;\n"
|
||||
"\n"
|
||||
" float3 color = fg;\n"
|
||||
"\n"
|
||||
"#if 1\n"
|
||||
" // TOP: show bands\n"
|
||||
" if( uv2.y >= 0.975 )\n"
|
||||
" {\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS + Step3( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.95 )\n"
|
||||
" {\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.925 )\n"
|
||||
" {\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" // BOTTOM: show dither texture\n"
|
||||
" else if( uv2.y >= 0.9 )\n"
|
||||
" {\n"
|
||||
" color = Step3( uv ).rgb;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
"#endif\n"
|
||||
" {\n"
|
||||
" // right of the screen is dithered using white noise to a fewer number of bits per color channel\n"
|
||||
" if( uv2.x > 3.0 / 4.0 )\n"
|
||||
" {\n"
|
||||
" // get white noise \"random\" number\n"
|
||||
"#if ANIMATE_NOISE\n"
|
||||
" float3 whiteNoise = Hash33( float3( uv, rpJitterTexOffset.w / 256.0 ) );\n"
|
||||
"#else\n"
|
||||
" float3 whiteNoise = Hash33( float3( uv, 0.0 ) );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" // dither to the specified number of bits, using sRGB conversions if desired\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" fg = pow( fg, float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
" color = floor( fg * scale + whiteNoise ) / scale;\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" color = pow( col, 1.0 / float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
" }\n"
|
||||
" // middle right of the screen is dithered using blue noise to a fewer number of bits per color channel\n"
|
||||
" else if( uv2.x > 2.0 / 4.0 )\n"
|
||||
" {\n"
|
||||
" float3 blueNoise = BlueNoise3( uv, 1.0 );\n"
|
||||
"\n"
|
||||
" // dither to the specified number of bits, using sRGB conversions if desired\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" fg = pow( fg, float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
" color = floor( fg * scale + blueNoise ) / scale;\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" color = pow( color, 1.0 / float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
" }\n"
|
||||
" // middle left of the screen is quantized but not dithered\n"
|
||||
" else if( uv2.x > 1.0 / 4.0 )\n"
|
||||
" {\n"
|
||||
" // dither to the specified number of bits, using sRGB conversions if desired\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" fg = pow( fg, float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
" color = floor( fg * scale + 0.5f ) / scale;\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" color = pow( color, 1.0 / float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
" }\n"
|
||||
" // left side of screen is left alone for comparison\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" color = fg;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if( abs( uv2.x - 1.0 / 4.0 ) < 0.001 || abs( uv2.x - 2.0 / 4.0 ) < 0.001 || abs( uv2.x - 3.0 / 4.0 ) < 0.001 )\n"
|
||||
" {\n"
|
||||
" color = float3( 0.0, 1.0, 0.0 );\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" fragColor.rgb = color;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void DitheringPassSlim( inout float4 fragColor )\n"
|
||||
"{\n"
|
||||
" // texture color\n"
|
||||
" float2 uv = fragment.position.xy;\n"
|
||||
" float2 uv2 = fragment.texcoord0;\n"
|
||||
" float3 fg = fragColor.rgb;\n"
|
||||
"\n"
|
||||
" float3 color = fg;\n"
|
||||
"\n"
|
||||
"#if 0\n"
|
||||
" if( uv2.y >= 0.975 )\n"
|
||||
" {\n"
|
||||
" // source signal\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.95 )\n"
|
||||
" {\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
"\n"
|
||||
" // quantized signal\n"
|
||||
" float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
" color = floor( color * scale + 0.0f ) / scale;\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.925 )\n"
|
||||
" {\n"
|
||||
" // dithered quantized signal\n"
|
||||
" color = float3( uv2.x );\n"
|
||||
" color = floor( color * STEPS + Step3T( uv ) * 4.0 ) * ( 1.0 / ( STEPS - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else if( uv2.y >= 0.9 )\n"
|
||||
" {\n"
|
||||
" // dither texture\n"
|
||||
" color = Step3( uv ).rgb;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" if( uv2.x <= 0.5 )\n"
|
||||
" {\n"
|
||||
" // quantized but not dithered\n"
|
||||
" color = floor( 0.5 + color * ( Dithering_QuantizationSteps + Dithering_Wide - 1.0 ) + ( -Dithering_Wide * 0.5 ) ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
"#endif\n"
|
||||
" {\n"
|
||||
" float3 noise = BlueNoise3( uv, 1.0 );\n"
|
||||
"\n"
|
||||
" //noise.x = RemapNoiseTriErp( noise.x );\n"
|
||||
" //noise.y = RemapNoiseTriErp( noise.y );\n"
|
||||
" //noise.z = RemapNoiseTriErp( noise.z );\n"
|
||||
"\n"
|
||||
" // dither to the specified number of bits, using sRGB conversions if desired\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" fg = pow( fg, float3( 2.2 ) );\n"
|
||||
" {\n"
|
||||
" color = floor( 0.5 + color * ( Dithering_QuantizationSteps + Dithering_Wide - 1.0 ) + ( -Dithering_Wide * 0.5 ) + Step3T( uv ) * ( Dithering_Wide ) ) * ( 1.0 / ( Dithering_QuantizationSteps - 1.0 ) );\n"
|
||||
" }\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" float scale = exp2( float( TARGET_BITS ) ) - 1.0;\n"
|
||||
" color = floor( fg * scale + noise ) / scale;\n"
|
||||
"\n"
|
||||
"#if DITHER_IN_LINEAR_SPACE\n"
|
||||
" color = pow( color, 1.0 / float3( 2.2 ) );\n"
|
||||
"#endif\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" fragColor.rgb = color;\n"
|
||||
|
@ -11332,7 +11207,7 @@ static const cgShaderDef_t cg_renderprogs[] =
|
|||
"#endif\n"
|
||||
"\n"
|
||||
"#if USE_DITHERING\n"
|
||||
" DitheringPassSlim( color );\n"
|
||||
" DitheringPass( color );\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" result.color = color;\n"
|
||||
|
|
Loading…
Reference in a new issue