/* enbeffectpostpass.fx : MariENB3 extra shader. (C)2016-2017 Marisa Kirisame, UnSX Team. Part of MariENB3, the personal ENB of Marisa for Fallout 4. Released under the GNU GPLv3 (or later). */ #include "menbglobaldefs.fx" /* BlockGFX filter, I'm proud of it */ string str_block = "BlockGFX Suite"; bool useblock < string UIName = "Enable Block GFX"; string UIWidget = "Checkbox"; > = {false}; /* emulated resolution: 0 or 1 : real resolution <1 and >0 : multiple of real resolution (e.g.: 0.5 is half resolution) >1 : this resolution (e.g.: 320x200 is good ol' Mode 13h) */ float2 bres < string UIName = "Emulated Resolution"; string UIWidget = "Vector"; float2 UIMin = {0.0,0.0}; > = {0.5,0.5}; /* zooming factors (<=0 for stretch) */ float2 sres < string UIName = "Zoom Factor"; string UIWidget = "Vector"; float2 UIMin = {0.0,0.0}; > = {0.0,0.0}; /* palette type: -1 : disable 0 : CGA (320x200 4-color, or 640x200 monochrome) 1 : EGA (320x200, 16 colors) 2 : RGB2 (64-color quarter VGA palette, used in AOS) 3 : VGA (256 colors) 4 : RGB565 (ol' 16-bit "true color") */ int paltype < string UIName = "Palette Type"; string UIWidget = "Spinner"; int UIMin = -1; int UIMax = 4; > = {1}; /* CGA palette to use: 0 : black, white. 1 : black, cyan, magenta, white. low contrast 2 : black, cyan, magenta, white. high contrast 3 : black, green, red, brown. low contrast 4 : black, green, red, brown. high contrast 5 : black, cyan, red, white. low contrast 6 : black, cyan, red, white. high contrast */ int cgapal < string UIName = "CGA Palette"; string UIWidget = "Spinner"; int UIMin = 0; int UIMax = 6; > = {1}; /* EGA palette to use: 0 : Standard EGA 1 : AOS EGA (it's designed for text, but looks well on images too) */ int egapal < string UIName = "EGA Palette"; string UIWidget = "Spinner"; int UIMin = 0; int UIMax = 1; > = {0}; /* VGA palette to use: 0 : Standard VGA 1 : Amulets & Armor 2 : Blood 3 : Doom 4 : Duke Nukem 3D 5 : Hacx 2.0 6 : Heretic 7 : Hexen 8 : Hexen 2 9 : Quake 10 : Quake 2 11 : Rise of the Triad 12 : Shadow Warrior 13 : Strife 14 : Wolfenstein 3D TODO Project .Blank palette (when the design is finished) */ int vgapal < string UIName = "VGA Palette"; string UIWidget = "Spinner"; int UIMin = 0; int UIMax = 14; > = {0}; /* Dithering mode: -1 : No dithering, just raw banding 0 : 2x2 checkerboard dithering, looks like ass 1 : 2x2 ordered dithering 2 : 8x8 ordered dithering */ int dither < string UIName = "Dithering Pattern"; string UIWidget = "Spinner"; int UIMin = -1; int UIMax = 2; > = {2}; /* gamma modifier for base color, lower values raise midtones and viceversa */ float bgamma < string UIName = "Contrast Modifier"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.35}; /* saturation modifier for base color, helps with limited palettes */ float bsaturation < string UIName = "Saturation Modifier"; string UIWidget = "Spinner"; > = {1.1}; /* base brightness bump for the dither grid */ float bdbump < string UIName = "Dither Offset"; string UIWidget = "Spinner"; > = {-0.1}; /* range multiplier for the dither grid */ float bdmult < string UIName = "Dither Range"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.25}; string str_mask = "Depth Chroma Key"; bool maskenable < string UIName = "Enable Chroma Key"; string UIWidget = "Checkbox"; > = {false}; float3 mask < string UIName = "Chroma Key Red"; string UIWidget = "Color"; > = {0.0,1.0,0.0}; float maskd < string UIName = "Chroma Key Depth"; string UIWidget = "Spinner"; float UIMin = 0.0; float UIMax = 1.0; > = {0.5}; /* BlurSharpShift, some people are obsessed with this nonsense */ string str_bss = "BlurSharpShift"; bool bssblurenable < string UIName = "Enable Blur"; string UIWidget = "Checkbox"; > = {false}; float bssblurradius < string UIName = "Blur Sampling Range"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.25}; bool bsssharpenable < string UIName = "Enable Sharp"; string UIWidget = "Checkbox"; > = {false}; float bsssharpradius < string UIName = "Sharp Sampling Range"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {1.0}; float bsssharpamount < string UIName = "Sharpening Amount"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {6.0}; bool bssshiftenable < string UIName = "Enable Shift"; string UIWidget = "Checkbox"; > = {false}; float bssshiftradius < string UIName = "Shift Sampling Range"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.75}; /* luma sharpen because of reasons */ string str_lsharp = "Luma Sharpen"; bool lsharpenable < string UIName = "Luma Sharpen Enable"; string UIWidget = "Checkbox"; > = {false}; float lsharpradius < string UIName = "Luma Sharpen Radius"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.8}; float lsharpclamp < string UIName = "Luma Sharpen Clamp"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {0.02}; float lsharpblend < string UIName = "Luma Sharpen Blending"; string UIWidget = "Spinner"; float UIMin = 0.0; > = {1.2}; /* very cinematic black bars */ string str_box = "Black Bars"; bool boxenable < string UIName = "Enable Black Bars"; string UIWidget = "Checkbox"; > = {false}; float boxh < string UIName = "Box Horizontal Ratio"; string UIWidget = "Spinner"; float UIMin = 1.0; > = {2.39}; float boxv < string UIName = "Box Vertical Ratio"; string UIWidget = "Spinner"; float UIMin = 1.0; > = {1.0}; /* dithering threshold maps don't touch unless you know what you're doing */ static const float checkers[4] = { 1.0,0.0, 0.0,1.0 }; #define d(x) x/4.0 static const float ordered2[4] = { d(0),d(2), d(4),d(2) }; #undef d #define d(x) x/64.0 static const float ordered8[64] = { d( 0),d(48),d(12),d(60),d( 3),d(51),d(15),d(63), d(32),d(16),d(44),d(28),d(35),d(19),d(47),d(31), d( 8),d(56),d( 4),d(52),d(11),d(59),d( 7),d(55), d(40),d(24),d(36),d(20),d(43),d(27),d(39),d(23), d( 2),d(50),d(14),d(62),d( 1),d(49),d(13),d(61), d(34),d(18),d(46),d(30),d(33),d(17),d(45),d(29), d(10),d(58),d( 6),d(54),d( 9),d(57),d( 5),d(53), d(42),d(26),d(38),d(22),d(41),d(25),d(37),d(21) }; #undef d /* gauss stuff */ float gauss3[3] = { 0.444814, 0.239936, 0.037657 }; float4 ScreenSize; Texture2D TextureOriginal; Texture2D TextureColor; Texture2D TextureDepth; Texture2D TextureCGA < string ResourceName = "menbcgalut.png"; >; Texture2D TextureEGA < string ResourceName = "menbegalut.png"; >; Texture2D TextureVGA < string ResourceName = "menbvgalut.png"; >; SamplerState Sampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Clamp; AddressV = Clamp; }; SamplerState SamplerB { Filter = MIN_MAG_MIP_LINEAR; AddressU = Border; AddressV = Border; }; SamplerState SamplerLUT { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; AddressV = Clamp; MaxLOD = 0; MinLOD = 0; }; struct VS_INPUT_POST { float3 pos : POSITION; float2 txcoord : TEXCOORD0; }; struct VS_OUTPUT_POST { float4 pos : SV_POSITION; float2 txcoord : TEXCOORD0; }; VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN) { VS_OUTPUT_POST OUT; OUT.pos = float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0); OUT.txcoord.xy = IN.txcoord.xy; return OUT; } /* helpers */ /* photometric */ #define luminance(x) dot(x,float3(0.2126,0.7152,0.0722)) /* CCIR601 */ //#define luminance(x) dot(x,float3(0.299,0.587,0.114)) float3 rgb2hsv( float3 c ) { float4 K = float4(0.0,-1.0/3.0,2.0/3.0,-1.0); float4 p = (c.g= 1 || ncoord.y < 0 || ncoord.y >= 1 ) res *= 0; res.a = 1.0; return res; } float4 PS_ChromaKey( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !maskenable ) return res; if ( TextureDepth.Sample(Sampler,coord).x > maskd ) return float4(mask.r,mask.g,mask.b,1.0); return res; } /* Why am I doing this */ float4 PS_Blur( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !bssblurenable ) return res; float2 ofs[16] = { float2(1.0,1.0), float2(-1.0,-1.0), float2(-1.0,1.0), float2(1.0,-1.0), float2(1.0,0.0), float2(-1.0,0.0), float2(0.0,1.0), float2(0.0,-1.0), float2(1.41,0.0), float2(-1.41,0.0), float2(0.0,1.41), float2(0.0,-1.41), float2(1.41,1.41), float2(-1.41,-1.41), float2(-1.41,1.41), float2(1.41,-1.41) }; float2 bresl = float2(ScreenSize.x,ScreenSize.x*ScreenSize.w); float2 bof = (1.0/bresl)*bssblurradius; int i; [unroll] for ( i=0; i<16; i++ ) res += TextureColor.Sample(Sampler,coord+ofs[i]*bof); res /= 17.0; res.a = 1.0; return res; } float4 PS_Sharp( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !bsssharpenable ) return res; float2 ofs[8] = { float2(1.0,1.0), float2(-1.0,-1.0), float2(-1.0,1.0), float2(1.0,-1.0), float2(1.41,1.41), float2(-1.41,-1.41), float2(-1.41,1.41), float2(1.41,-1.41) }; float2 bresl = float2(ScreenSize.x,ScreenSize.x*ScreenSize.w); float2 bof = (1.0/bresl)*bsssharpradius; float4 tcol = res; int i; [unroll] for ( i=0; i<8; i++ ) tcol += TextureColor.Sample(Sampler,coord+ofs[i]*bof); tcol /= 9.0; float4 orig = res; res = orig*(1.0+dot(orig.rgb-tcol.rgb,0.333333)*bsssharpamount); float rg = clamp(pow(orig.b,3.0),0.0,1.0); res = lerp(res,orig,rg); res.a = 1.0; return res; } float4 PS_Shift( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !bssshiftenable ) return res; float2 bresl = float2(ScreenSize.x,ScreenSize.x*ScreenSize.w); float2 bof = (1.0/bresl)*bssshiftradius; res.g = TextureColor.Sample(Sampler,coord).g; res.r = TextureColor.Sample(Sampler,coord+float2(0,-bof.y)).r; res.b = TextureColor.Sample(Sampler,coord+float2(0,bof.y)).b; res.a = 1.0; return res; } /* That "luma sharpen" thingy, added just because someone might want it */ float4 PS_LumaSharp( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !lsharpenable ) return res; float2 bresl = float2(ScreenSize.x,ScreenSize.x*ScreenSize.w); float2 bof = float2(1.0/bresl.x,1.0/bresl.y)*lsharpradius; float4 crawling = TextureColor.Sample(Sampler,coord+float2(0,-1)*bof); crawling += TextureColor.Sample(Sampler,coord+float2(-1,0)*bof); crawling += TextureColor.Sample(Sampler,coord+float2(1,0)*bof); crawling += TextureColor.Sample(Sampler,coord+float2(0,1)*bof); crawling *= 0.25; float4 inmyskin = res-crawling; float thesewounds = luminance(inmyskin.rgb); thesewounds = clamp(thesewounds,-lsharpclamp*0.01,lsharpclamp*0.01); float4 theywillnotheal = res+thesewounds*lsharpblend; return theywillnotheal; } /* ultimate super-cinematic immersive black bars */ float4 PS_Cinematic( VS_OUTPUT_POST IN, float4 v0 : SV_Position0 ) : SV_Target { float2 coord = IN.txcoord.xy; float4 res = TextureColor.Sample(Sampler,coord); if ( !boxenable ) return res; float2 bresl = float2(ScreenSize.x,ScreenSize.x*ScreenSize.w); float sar = bresl.x/bresl.y; float tar = boxh/boxv; float2 box = (sar { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_LumaSharp())); } } technique11 ExtraFilters1 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_Blur())); } } technique11 ExtraFilters2 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_Sharp())); } } technique11 ExtraFilters3 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_Shift())); } } technique11 ExtraFilters4 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_ChromaKey())); } } technique11 ExtraFilters5 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_Retro())); } } technique11 ExtraFilters6 { pass p0 { SetVertexShader(CompileShader(vs_5_0,VS_PostProcess())); SetPixelShader(CompileShader(ps_5_0,PS_Cinematic())); } }