/* Full Screen Colour Effects Shader by WrinklyNinja. Release Version 5.
* Gamma Alterations code by Donovan Baarda <abo@minkirri.apana.org.au>.
*
* Contains the following applicable effects:
* Luminosity-Dependent Film Grain
* Sepia
* Saturation/Contrast/Brightness Alteration
* Gamma (non-linear) Contrast/Brightness Alteration
* Colour Inversion
* Blur Highlighting
*
* To Do:
* A better film grain noise.
* More effects!
*/
// ---------------------------------------
// TWEAKABLE VARIABLES.
extern bool DoBlurHighlight = 0;
extern bool DoSepia = 0;
extern bool DoColorInvert = 0;
//Toggles for the on/off effects. 1 is enabled, and 0 is disabled.
extern float Saturation = 0.9;
//Saturation: Scales the saturation level.
//1 is vanilla, less than 1 decreases it, greater than 1 increases it.
extern float Brightness = 1;
//Brightness: Scales the brightness level.
//1 is vanilla, less than 1 decreases it, greater than 1 increases it.
extern float Contrast = 1;
//Contrast: Scales the contrast level.
//1 is vanilla, less than 1 decreases it, greater than 1 increases it.
extern float GContrast = 1;
//Gamma Contrast: Scales the contrast level.
//Default = 1.
extern float GBrightness = 1;
//Gamma Brightness: Scales the brightness level.
//Default = 1.
extern float FGIntensity = 0;
//Film Grain: Controls the intensity of the noise. 0 = no effect, 1 = full effect.
//Default = 0.
extern float BHMagnitude = 10;
//Blur Highlight: Controls the size of the blur.
//Default = 10.
extern float BHBrightness = 4;
//Blur Highlight: Corrects the darkening of the screen the effect causes.
//Default = 4.
// END OF TWEAKABLE VARIABLES.
// ---------------------------------------
float4 f4Time;
float2 rcpres;
texture obge_LastRendertarget0_EFFECTPASS;
sampler PassSampler = sampler_state {
texture = <obge_LastRendertarget0_EFFECTPASS>;
AddressU = CLAMP;
AddressV = CLAMP;
MINFILTER = POINT;
MAGFILTER = POINT;
};
static const float3 greyscale = float3(0.299, 0.587, 0.114);
static const float BlurWeights[13] = {
0.057424882f,
0.058107773f,
0.061460144f,
0.071020611f,
0.088092873f,
0.106530916f,
0.114725602f,
0.106530916f,
0.088092873f,
0.071020611f,
0.061460144f,
0.058107773f,
0.057424882f
};
static const float2 BlurOffsets[13] = {
float2(-6.0f * rcpres[0], -6.0f * rcpres[1]),
float2(-5.0f * rcpres[0], -5.0f * rcpres[1]),
float2(-4.0f * rcpres[0], -4.0f * rcpres[1]),
float2(-3.0f * rcpres[0], -3.0f * rcpres[1]),
float2(-2.0f * rcpres[0], -2.0f * rcpres[1]),
float2(-1.0f * rcpres[0], -1.0f * rcpres[1]),
float2( 0.0f * rcpres[0], 0.0f * rcpres[1]),
float2( 1.0f * rcpres[0], 1.0f * rcpres[1]),
float2( 2.0f * rcpres[0], 2.0f * rcpres[1]),
float2( 3.0f * rcpres[0], 3.0f * rcpres[1]),
float2( 4.0f * rcpres[0], 4.0f * rcpres[1]),
float2( 5.0f * rcpres[0], 5.0f * rcpres[1]),
float2( 6.0f * rcpres[0], 6.0f * rcpres[1])
};
struct VSOUT
{
float4 vertPos : POSITION;
float2 UVCoord : TEXCOORD0;
};
struct VSIN
{
float4 vertPos : POSITION0;
float2 UVCoord : TEXCOORD0;
};
VSOUT DummyVS(VSIN IN)
{
VSOUT OUT = (VSOUT)0.0f; // initialize to zero, avoid complaints.
OUT.vertPos = IN.vertPos;
OUT.UVCoord = IN.UVCoord;
return (OUT);
}
float3 Sepia(float3 frame) {
return max(0, dot(greyscale, frame) + float3(0.191, -0.054, -0.221));
}
float3 ColorInvert(float3 frame) {
return max(0, 1 - frame);
}
float3 AlterSatBrightCont(float3 frame) {
frame = lerp(dot(greyscale, frame), frame, Saturation);
frame *= Brightness;
frame = lerp(0.5, frame, Contrast);
return frame;
}
float3 FilmGrain(float3 frame, float2 UVCoord) {
float gradient = f4Time.x % (20000 * 3.141592654);
float x = UVCoord.x * UVCoord.y * gradient;
x = fmod(x, 13) * fmod(x, 123);
float dx = fmod(x, 0.01);
float lum = saturate(1 - dot(greyscale,frame));
float3 framenoise = frame + frame * saturate(0.1f + dx.xxx * 100);
framenoise = lerp(frame, framenoise, FGIntensity * lum);
framenoise = framenoise / (1 + FGIntensity / 2);
return framenoise;
}
float3 BlurHighlight(float3 frame, float2 UVCoord) {
float3 blur = 0;
for (int k = 0; k < 13; k++) {
blur += tex2D(PassSampler, UVCoord + (BlurOffsets[k] * float2(0, 1) * BHMagnitude) * BlurWeights[k]);
blur += tex2D(PassSampler, UVCoord + (BlurOffsets[k] * float2(1, 0) * BHMagnitude) * BlurWeights[k]);
}
blur = (blur / 24) - frame;
return lerp(frame, blur, 1) * BHBrightness;
}
//Originally written by Donovan Baarda.
float3 GammaContrast(float3 color) {
return pow(color, GContrast) / (pow(saturate(color), GContrast) + pow(1.0 - saturate(color), GContrast));
}
//Originally written by Donovan Baarda.
float3 GammaBrightness(float3 color) {
return pow(color, 1.0 / max(0.0001, GBrightness));
}
float4 ApplyEffects(float2 UVCoord : TEXCOORD0) : COLOR0
{
float3 frame = tex2D(PassSampler, UVCoord).rgb;
#ifdef BLURHIGHLIGHT
frame = BlurHighlight(frame, UVCoord);
#endif
frame = AlterSatBrightCont(frame);
frame = GammaBrightness(frame);
frame = GammaContrast(frame);
#ifdef COLORINVERT
frame = ColorInvert(frame);
#endif
frame = FilmGrain(frame, UVCoord);
#ifdef SEPIA
frame = Sepia(frame);
#endif
return float4(frame, 1);
}
technique t0
<
int group = EFFECTGROUP_POST;
int fxclass = EFFECTCLASS_COLOR;
>
{
pass p0 {
VertexShader = compile vs_3_0 DummyVS();
PixelShader = compile ps_3_0 ApplyEffects();
}
}