// Target GLSL 4.5. #version 450 core #define ATTRIBUTE_LOCATION(x) layout(location = x) #define FRAGMENT_OUTPUT_LOCATION(x) layout(location = x) #define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y) layout(location = x, index = y) #define UBO_BINDING(packing, x) layout(packing, set = 0, binding = (x - 1)) #define SAMPLER_BINDING(x) layout(set = 1, binding = x) #define SSBO_BINDING(x) layout(set = 2, binding = x) #define TEXEL_BUFFER_BINDING(x) layout(set = 2, binding = x) #define VARYING_LOCATION(x) layout(location = x) #define FORCE_EARLY_Z layout(early_fragment_tests) in // hlsl to glsl function translation #define float2 vec2 #define float3 vec3 #define float4 vec4 #define uint2 uvec2 #define uint3 uvec3 #define uint4 uvec4 #define int2 ivec2 #define int3 ivec3 #define int4 ivec4 #define frac fract #define lerp mix // These were changed in Vulkan #define gl_VertexID gl_VertexIndex #define gl_InstanceID gl_InstanceIndex UBO_BINDING(std140, 1) uniform PSBlock { float4 resolution; float4 src_rect; uint time; uint unused1; uint unused2; uint unused3; int A_BILINEAR_FILTER; int unused4; int unused5; int unused6; int A_BLOOM_TYPE; int unused7; int unused8; int unused9; float A_CONTRAST; float unused10; float unused11; float unused12; int A_DITHER_TYPE; int unused13; int unused14; int unused15; float A_EDGE_STRENGTH; float unused16; float unused17; float unused18; int A_FILMIC; int unused19; int unused20; int unused21; int A_FXAA_PASS; int unused22; int unused23; int unused24; float A_FXAA_SUBPIX_MAX; float unused25; float unused26; float unused27; float A_GAMMA; float unused28; float unused29; float unused30; float A_GRAIN_SIZE; float unused31; float unused32; float unused33; int A_PALETTE; int unused34; int unused35; int unused36; int A_SCALERS; int unused37; int unused38; int unused39; int A_SCANLINE_TYPE; int unused40; int unused41; int unused42; float A_SHARPEN_STRENGTH; float unused43; float unused44; float unused45; int A_TONEMAP_TYPE; int unused46; int unused47; int unused48; float A_VIBRANCE; float unused49; float unused50; float unused51; float A_VIG_RATIO; float unused52; float unused53; float unused54; int B_BICUBLIC_SCALER; int unused55; int unused56; int unused57; int B_BLOOM_PASS; int unused58; int unused59; int unused60; float B_BLOOM_STRENGTH; float unused61; float unused62; float unused63; float B_EDGE_FILTER; float unused64; float unused65; float unused66; float B_FXAA_EDGE_THRESHOLD; float unused67; float unused68; float unused69; float B_GRAIN_AMOUNT; float unused70; float unused71; float unused72; int B_LANCZOS_SCALER; int unused73; int unused74; int unused75; float B_RED_CORRECTION; float unused76; float unused77; float unused78; float B_RED_SHIFT; float unused79; float unused80; float unused81; float B_SCANLINE_BRIGHTNESS; float unused82; float unused83; float unused84; float B_SCANLINE_INTENSITY; float unused85; float unused86; float unused87; float B_SCANLINE_SPACING; float unused88; float unused89; float unused90; float B_SCANLINE_THICKNESS; float unused91; float unused92; float unused93; float B_SHARPEN_CLAMP; float unused94; float unused95; float unused96; float B_TONE_AMOUNT; float unused97; float unused98; float unused99; float B_VIG_RADIUS; float unused100; float unused101; float unused102; float C_BLACK_LEVELS; float unused103; float unused104; float unused105; float C_BLEND_STRENGTH; float unused106; float unused107; float unused108; int C_COLORED; int unused109; int unused110; int unused111; float C_EDGE_THICKNESS; float unused112; float unused113; float unused114; int C_FXAA_SHOW_EDGES; int unused115; int unused116; int unused117; float C_GREEN_CORRECTION; float unused118; float unused119; float unused120; float C_GREEN_SHIFT; float unused121; float unused122; float unused123; float C_SHARPEN_BIAS; float unused124; float unused125; float unused126; int C_TONEMAP_PASS; int unused127; int unused128; int unused129; float C_VIG_AMOUNT; float unused130; float unused131; float unused132; int DISABLE_EFFECTS; int unused133; int unused134; int unused135; float D_BLOOM_WIDTH; float unused136; float unused137; float unused138; float D_BLUE_CORRECTION; float unused139; float unused140; float unused141; float D_BLUE_SHIFT; float unused142; float unused143; float unused144; float D_COLOR_AMOUNT; float unused145; float unused146; float unused147; int D_COLOR_CORRECTION; int unused148; int unused149; int unused150; float D_EXPOSURE; float unused151; float unused152; float unused153; int D_PALETTE_TYPE; int unused154; int unused155; int unused156; int D_SEDGE_DETECTION; int unused157; int unused158; int unused159; int D_VIG_SLOPE; int unused160; int unused161; int unused162; float E_BLOOM_REDS; float unused163; float unused164; float unused165; int E_FILMIC_PROCESS; int unused166; int unused167; int unused168; float E_LUMA_AMOUNT; float unused169; float unused170; float unused171; float E_LUMINANCE; float unused172; float unused173; float unused174; float E_SHIFT_RATIO; float unused175; float unused176; float unused177; int E_YUV_LUMA; int unused178; int unused179; int unused180; float F_BLOOM_GREENS; float unused181; float unused182; float unused183; int F_GAMMA_CORRECTION; int unused184; int unused185; int unused186; float F_WHITEPOINT; float unused187; float unused188; float unused189; float G_BLOOM_BLUES; float unused190; float unused191; float unused192; int G_COLOR_ROUNDING; int unused193; int unused194; int unused195; int G_TEXTURE_SHARPEN; int unused196; int unused197; int unused198; int H_PIXEL_VIBRANCE; int unused199; int unused200; int unused201; int I_CONTRAST_ENHANCEMENT; int unused202; int unused203; int unused204; int J_CEL_SHADING; int unused205; int unused206; int unused207; int K_SCAN_LINES; int unused208; int unused209; int unused210; int L_FILM_GRAIN_PASS; int unused211; int unused212; int unused213; int L_VIGNETTE_PASS; int unused214; int unused215; int unused216; int M_DITHER_PASS; int unused217; int unused218; int unused219; int PASS_WARN; int unused220; int unused221; int unused222; } options; SAMPLER_BINDING(0) uniform sampler2DArray samp0; SAMPLER_BINDING(1) uniform sampler2D samp1; layout(location = 0) in float3 uv0; layout(location = 1) in float4 col0; layout(location = 0) out float4 ocol0; // Interfacing functions // The EFB may have a zero alpha value, which we don't want to write to the frame dump, so set it to one here. float4 Sample() { return float4(texture(samp0, uv0).xyz, 1.0); } float4 SampleLocation(float2 location) { return float4(texture(samp0, float3(location, uv0.z)).xyz, 1.0); } float4 SampleLayer(int layer) { return float4(texture(samp0, float3(uv0.xy, float(layer))).xyz, 1.0); } #define SampleOffset(offset) float4(textureOffset(samp0, uv0, offset).xyz, 1.0) float4 SampleFontLocation(float2 location) { return texture(samp1, location); } float2 GetResolution() { return options.resolution.xy; } float2 GetInvResolution() { return options.resolution.zw; } float2 GetCoordinates() { return uv0.xy; } uint GetTime() { return options.time; } void SetOutput(float4 color) { ocol0 = color; } #define GetOption(x) (options.x) #define OptionEnabled(x) (options.x != 0) // Workaround because there is no getter function for src rect/layer. float4 src_rect = options.src_rect; int layer = int(uv0.z); /*===============================================================================*\ |######################## [Dolphin FX Suite 2.00] #######################| |########################## By Asmodean ##########################| || || || This program is free software; you can redistribute it and/or || || modify it under the terms of the GNU General Public License || || as published by the Free Software Foundation; either version 2 || || of the License, or (at your option) any later version. || || || || This program is distributed in the hope that it will be useful, || || but WITHOUT ANY WARRANTY; without even the implied warranty of || || MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the || || GNU General Public License for more details. (C)2014 || || || |#################################################################################| \*===============================================================================*/ #extension GL_ARB_gpu_shader5 : enable /* [configuration] [OptionBool] GUIName = Disable All Effects (To reset all settings to default, delete them from dolphin.ini) OptionName = DISABLE_EFFECTS DefaultValue = false [OptionBool] GUIName = Scaling Filters OptionName = A_SCALERS DefaultValue = false [OptionRangeInteger] GUIName = Bilinear Filtering OptionName = A_BILINEAR_FILTER MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = A_SCALERS [OptionRangeInteger] GUIName = Bicubic Scaling OptionName = B_BICUBLIC_SCALER MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = A_SCALERS [OptionRangeInteger] GUIName = Lanczos Scaling OptionName = B_LANCZOS_SCALER MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = A_SCALERS [OptionBool] GUIName = Note: Use FXAA or a Scaling Filter, not both together. OptionName = PASS_WARN DefaultValue = true DependentOption = A_SCALERS [OptionBool] GUIName = FXAA OptionName = A_FXAA_PASS DefaultValue = true [OptionRangeFloat] GUIName = SubpixelMax OptionName = A_FXAA_SUBPIX_MAX MinValue = 0.00 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.25 DependentOption = A_FXAA_PASS [OptionRangeFloat] GUIName = EdgeThreshold OptionName = B_FXAA_EDGE_THRESHOLD MinValue = 0.010 MaxValue = 0.500 StepAmount = 0.001 DefaultValue = 0.050 DependentOption = A_FXAA_PASS [OptionRangeInteger] GUIName = ShowEdgeDetection OptionName = C_FXAA_SHOW_EDGES MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = A_FXAA_PASS [OptionBool] GUIName = Blended Bloom OptionName = B_BLOOM_PASS DefaultValue = true [OptionRangeInteger] GUIName = BloomType OptionName = A_BLOOM_TYPE MinValue = 0 MaxValue = 4 StepAmount = 1 DefaultValue = 0 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BloomStrength OptionName = B_BLOOM_STRENGTH MinValue = 0.000 MaxValue = 1.000 StepAmount = 0.001 DefaultValue = 0.250 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BlendStrength OptionName = C_BLEND_STRENGTH MinValue = 0.000 MaxValue = 1.500 StepAmount = 0.010 DefaultValue = 1.000 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BloomWidth OptionName = D_BLOOM_WIDTH MinValue = 1.000 MaxValue = 8.000 StepAmount = 0.100 DefaultValue = 4.000 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BloomReds OptionName = E_BLOOM_REDS MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BloomGreens OptionName = F_BLOOM_GREENS MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = B_BLOOM_PASS [OptionRangeFloat] GUIName = BloomBlues OptionName = G_BLOOM_BLUES MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = B_BLOOM_PASS [OptionBool] GUIName = Scene Tonemapping OptionName = C_TONEMAP_PASS DefaultValue = true [OptionRangeInteger] GUIName = TonemapType OptionName = A_TONEMAP_TYPE MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = C_TONEMAP_PASS [OptionRangeFloat] GUIName = ToneAmount OptionName = B_TONE_AMOUNT MinValue = 0.05 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 0.40 DependentOption = C_TONEMAP_PASS [OptionRangeFloat] GUIName = BlackLevels OptionName = C_BLACK_LEVELS MinValue = 0.05 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.30 DependentOption = C_TONEMAP_PASS [OptionRangeFloat] GUIName = Exposure OptionName = D_EXPOSURE MinValue = 0.25 MaxValue = 1.50 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = C_TONEMAP_PASS [OptionRangeFloat] GUIName = Luminance OptionName = E_LUMINANCE MinValue = 0.25 MaxValue = 1.50 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = C_TONEMAP_PASS [OptionRangeFloat] GUIName = WhitePoint OptionName = F_WHITEPOINT MinValue = 0.50 MaxValue = 1.50 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = C_TONEMAP_PASS [OptionBool] GUIName = Colour Correction OptionName = D_COLOR_CORRECTION DefaultValue = true [OptionRangeInteger] GUIName = CorrectionPalette OptionName = A_PALETTE MinValue = 0 MaxValue = 3 StepAmount = 1 DefaultValue = 1 DependentOption = D_COLOR_CORRECTION [OptionRangeFloat] GUIName = RedCorrection OptionName = B_RED_CORRECTION MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = D_COLOR_CORRECTION [OptionRangeFloat] GUIName = GreenCorrection OptionName = C_GREEN_CORRECTION MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = D_COLOR_CORRECTION [OptionRangeFloat] GUIName = BlueCorrection OptionName = D_BLUE_CORRECTION MinValue = 0.100 MaxValue = 4.000 StepAmount = 0.100 DefaultValue = 1.000 DependentOption = D_COLOR_CORRECTION [OptionBool] GUIName = Filmic Process OptionName = E_FILMIC_PROCESS DefaultValue = true [OptionRangeInteger] GUIName = FilmicProcess OptionName = A_FILMIC MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = E_FILMIC_PROCESS [OptionRangeFloat] GUIName = RedShift OptionName = B_RED_SHIFT MinValue = 0.10 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.50 DependentOption = E_FILMIC_PROCESS [OptionRangeFloat] GUIName = GreenShift OptionName = C_GREEN_SHIFT MinValue = 0.10 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.45 DependentOption = E_FILMIC_PROCESS [OptionRangeFloat] GUIName = BlueShift OptionName = D_BLUE_SHIFT MinValue = 0.10 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.45 DependentOption = E_FILMIC_PROCESS [OptionRangeFloat] GUIName = ShiftRatio OptionName = E_SHIFT_RATIO MinValue = 0.00 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.30 DependentOption = E_FILMIC_PROCESS [OptionBool] GUIName = Gamma Correction OptionName = F_GAMMA_CORRECTION DefaultValue = true [OptionRangeFloat] GUIName = Gamma OptionName = A_GAMMA MinValue = 1.00 MaxValue = 4.00 StepAmount = 0.01 DefaultValue = 2.20 DependentOption = F_GAMMA_CORRECTION [OptionBool] GUIName = Texture Sharpen OptionName = G_TEXTURE_SHARPEN DefaultValue = false [OptionRangeFloat] GUIName = SharpenStrength OptionName = A_SHARPEN_STRENGTH MinValue = 0.00 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.50 DependentOption = G_TEXTURE_SHARPEN [OptionRangeFloat] GUIName = SharpenClamp OptionName = B_SHARPEN_CLAMP MinValue = 0.005 MaxValue = 0.250 StepAmount = 0.001 DefaultValue = 0.020 DependentOption = G_TEXTURE_SHARPEN [OptionRangeFloat] GUIName = SharpenBias OptionName = C_SHARPEN_BIAS MinValue = 1.00 MaxValue = 4.00 StepAmount = 0.05 DefaultValue = 1.00 DependentOption = G_TEXTURE_SHARPEN [OptionRangeInteger] GUIName = ShowEdgeMask OptionName = D_SEDGE_DETECTION MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = G_TEXTURE_SHARPEN [OptionBool] GUIName = Pixel Vibrance OptionName = H_PIXEL_VIBRANCE DefaultValue = false [OptionRangeFloat] GUIName = Vibrance OptionName = A_VIBRANCE MinValue = -0.50 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.10 DependentOption = H_PIXEL_VIBRANCE [OptionBool] GUIName = Contrast Enhancement OptionName = I_CONTRAST_ENHANCEMENT DefaultValue = false [OptionRangeFloat] GUIName = Contrast OptionName = A_CONTRAST MinValue = 0.00 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.35 DependentOption = I_CONTRAST_ENHANCEMENT [OptionBool] GUIName = Cel Shading OptionName = J_CEL_SHADING DefaultValue = false [OptionRangeFloat] GUIName = EdgeStrength OptionName = A_EDGE_STRENGTH MinValue = 0.00 MaxValue = 4.00 StepAmount = 0.01 DefaultValue = 1.75 DependentOption = J_CEL_SHADING [OptionRangeFloat] GUIName = EdgeFilter OptionName = B_EDGE_FILTER MinValue = 0.25 MaxValue = 1.00 StepAmount = 0.01 DefaultValue = 0.65 DependentOption = J_CEL_SHADING [OptionRangeFloat] GUIName = EdgeThickness OptionName = C_EDGE_THICKNESS MinValue = 0.25 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = J_CEL_SHADING [OptionRangeInteger] GUIName = PaletteType OptionName = D_PALETTE_TYPE MinValue = 0 MaxValue = 2 StepAmount = 1 DefaultValue = 1 DependentOption = J_CEL_SHADING [OptionRangeInteger] GUIName = UseYuvLuma OptionName = E_YUV_LUMA MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 0 DependentOption = J_CEL_SHADING [OptionRangeInteger] GUIName = ColourRounding OptionName = G_COLOR_ROUNDING MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 1 DependentOption = J_CEL_SHADING [OptionBool] GUIName = Scanlines OptionName = K_SCAN_LINES DefaultValue = false [OptionRangeInteger] GUIName = ScanlineType OptionName = A_SCANLINE_TYPE MinValue = 0 MaxValue = 2 StepAmount = 1 DefaultValue = 0 DependentOption = K_SCAN_LINES [OptionRangeFloat] GUIName = ScanlineIntensity OptionName = B_SCANLINE_INTENSITY MinValue = 0.15 MaxValue = 0.30 StepAmount = 0.01 DefaultValue = 0.18 DependentOption = K_SCAN_LINES [OptionRangeFloat] GUIName = ScanlineThickness OptionName = B_SCANLINE_THICKNESS MinValue = 0.20 MaxValue = 0.80 StepAmount = 0.01 DefaultValue = 0.50 DependentOption = K_SCAN_LINES [OptionRangeFloat] GUIName = ScanlineBrightness OptionName = B_SCANLINE_BRIGHTNESS MinValue = 0.50 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = K_SCAN_LINES [OptionRangeFloat] GUIName = ScanlineSpacing OptionName = B_SCANLINE_SPACING MinValue = 0.10 MaxValue = 0.99 StepAmount = 0.01 DefaultValue = 0.25 DependentOption = K_SCAN_LINES [OptionBool] GUIName = Film Grain OptionName = L_FILM_GRAIN_PASS DefaultValue = false [OptionRangeFloat] GUIName = GrainSize OptionName = A_GRAIN_SIZE MinValue = 1.50 MaxValue = 2.50 StepAmount = 0.10 DefaultValue = 1.60 DependentOption = L_FILM_GRAIN_PASS [OptionRangeFloat] GUIName = GrainAmount OptionName = B_GRAIN_AMOUNT MinValue = 0.01 MaxValue = 0.50 StepAmount = 0.01 DefaultValue = 0.05 DependentOption = L_FILM_GRAIN_PASS [OptionRangeInteger] GUIName = ColouredGrain OptionName = C_COLORED MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 1 DependentOption = L_FILM_GRAIN_PASS [OptionRangeFloat] GUIName = ColourAmount OptionName = D_COLOR_AMOUNT MinValue = 0.10 MaxValue = 1.00 StepAmount = 0.10 DefaultValue = 0.60 DependentOption = L_FILM_GRAIN_PASS [OptionRangeFloat] GUIName = LumaFilter OptionName = E_LUMA_AMOUNT MinValue = 0.10 MaxValue = 1.00 StepAmount = 0.10 DefaultValue = 1.00 DependentOption = L_FILM_GRAIN_PASS [OptionBool] GUIName = Vignette OptionName = L_VIGNETTE_PASS DefaultValue = false [OptionRangeFloat] GUIName = VignetteRatio OptionName = A_VIG_RATIO MinValue = 1.00 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 1.50 DependentOption = L_VIGNETTE_PASS [OptionRangeFloat] GUIName = VignetteRadius OptionName = B_VIG_RADIUS MinValue = 0.50 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 1.00 DependentOption = L_VIGNETTE_PASS [OptionRangeFloat] GUIName = VignetteAmount OptionName = C_VIG_AMOUNT MinValue = 0.10 MaxValue = 2.00 StepAmount = 0.01 DefaultValue = 0.25 DependentOption = L_VIGNETTE_PASS [OptionRangeInteger] GUIName = VignetteSlope OptionName = D_VIG_SLOPE MinValue = 2 MaxValue = 16 StepAmount = 2 DefaultValue = 12 DependentOption = L_VIGNETTE_PASS [OptionBool] GUIName = Dithering OptionName = M_DITHER_PASS DefaultValue = false [OptionRangeInteger] GUIName = Dither Type OptionName = A_DITHER_TYPE MinValue = 0 MaxValue = 1 StepAmount = 1 DefaultValue = 1 DependentOption = M_DITHER_PASS [/configuration] */ /*------------------------------------------------------------------------------ [GLOBALS|FUNCTIONS] ------------------------------------------------------------------------------*/ uint timer = GetTime(); float2 texcoord = GetCoordinates(); float2 screenSize = GetResolution(); float2 pixelSize = GetInvResolution(); float2 texSize = textureSize(samp9, 0).xy; #define mul(x, y) y * x #define FIX(c) max(abs(c), 1e-5) #define Saturate(x) clamp(x, 0.0, 1.0) #define SampleLocationLod(location, lod) textureLod(samp9, float3(location, 0), lod) const float PI = 3.1415926535897932384626433832795; float2 invDefocus = float2(1.0 / 3840.0, 1.0 / 2160.0); const float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750); float RGBLuminance(float3 color) { return dot(color.rgb, lumCoeff); } /*------------------------------------------------------------------------------ [BICUBIC SCALER CODE SECTION] ------------------------------------------------------------------------------*/ float4 BicubicScaler(float2 uv, float2 txSize) { float2 inputSize = float2(1.0/txSize.x, 1.0/txSize.y); float2 coord_hg = uv * txSize - 0.5; float2 index = floor(coord_hg); float2 f = coord_hg - index; mat4 M = mat4( -1.0, 3.0,-3.0, 1.0, 3.0,-6.0, 3.0, 0.0, -3.0, 0.0, 3.0, 0.0, 1.0, 4.0, 1.0, 0.0 ); M /= 6.0; float4 wx = M * float4(f.x*f.x*f.x, f.x*f.x, f.x, 1.0); float4 wy = M * float4(f.y*f.y*f.y, f.y*f.y, f.y, 1.0); float2 w0 = float2(wx.x, wy.x); float2 w1 = float2(wx.y, wy.y); float2 w2 = float2(wx.z, wy.z); float2 w3 = float2(wx.w, wy.w); float2 g0 = w0 + w1; float2 g1 = w2 + w3; float2 h0 = w1 / g0 - 1.0; float2 h1 = w3 / g1 + 1.0; float2 coord00 = index + h0; float2 coord10 = index + float2(h1.x, h0.y); float2 coord01 = index + float2(h0.x, h1.y); float2 coord11 = index + h1; coord00 = (coord00 + 0.5) * inputSize; coord10 = (coord10 + 0.5) * inputSize; coord01 = (coord01 + 0.5) * inputSize; coord11 = (coord11 + 0.5) * inputSize; float4 tex00 = SampleLocationLod(coord00, 0.0); float4 tex10 = SampleLocationLod(coord10, 0.0); float4 tex01 = SampleLocationLod(coord01, 0.0); float4 tex11 = SampleLocationLod(coord11, 0.0); tex00 = lerp(tex01, tex00, float4(g0.y, g0.y, g0.y, g0.y)); tex10 = lerp(tex11, tex10, float4(g0.y, g0.y, g0.y, g0.y)); float4 res = lerp(tex10, tex00, float4(g0.x, g0.x, g0.x, g0.x)); return res; } float4 BicubicScalerPass(float4 color) { color = BicubicScaler(texcoord, screenSize); return color; } /*------------------------------------------------------------------------------ [LANCZOS SCALER CODE SECTION] ------------------------------------------------------------------------------*/ float3 PixelPos(float xpos, float ypos) { return SampleLocation(float2(xpos, ypos)).rgb; } float4 WeightQuad(float x) { float4 weight = FIX(PI * float4(1.0 + x, x, 1.0 - x, 2.0 - x)); float4 ret = sin(weight) * sin(weight / 2.0) / (weight * weight); return ret / dot(ret, float4(1.0, 1.0, 1.0, 1.0)); } float3 LineRun(float ypos, float4 xpos, float4 linetaps) { return mat4x3( PixelPos(xpos.x, ypos), PixelPos(xpos.y, ypos), PixelPos(xpos.z, ypos), PixelPos(xpos.w, ypos)) * linetaps; } float4 LanczosScaler(float2 inputSize) { float2 stepxy = float2(1.0/inputSize.x, 1.0/inputSize.y); float2 pos = texcoord + stepxy * 0.5; float2 f = frac(pos / stepxy); float2 xystart = (-1.5 -f) * stepxy + pos; float4 xpos = float4( xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0, xystart.x + stepxy.x * 3.0); float4 linetaps = WeightQuad(f.x); float4 columntaps = WeightQuad(f.y); return float4(mat4x3( LineRun(xystart.y, xpos, linetaps), LineRun(xystart.y + stepxy.y, xpos, linetaps), LineRun(xystart.y + stepxy.y * 2.0, xpos, linetaps), LineRun(xystart.y + stepxy.y * 3.0, xpos, linetaps)) * columntaps, 1.0); } float4 LanczosScalerPass(float4 color) { color = LanczosScaler(screenSize); return color; } /*------------------------------------------------------------------------------ [BILINEAR FILTERING CODE SECTION] ------------------------------------------------------------------------------*/ float4 SampleBilinear(float2 texcoord) { float texelSizeX = 1.0 / texSize.x; float texelSizeY = 1.0 / texSize.y; int nX = int(texcoord.x * texSize.x); int nY = int(texcoord.y * texSize.y); float2 uvCoord = float2(float(nX) / texSize.x, float(nY) / texSize.y); // Take nearest two data in current row. float4 SampleA = SampleLocation(uvCoord); float4 SampleB = SampleLocation(uvCoord + float2(texelSizeX, 0.0)); // Take nearest two data in bottom row. float4 SampleC = SampleLocation(uvCoord + float2(0.0, texelSizeY)); float4 SampleD = SampleLocation(uvCoord + float2(texelSizeX , texelSizeY)); float LX = fract(texcoord.x * texSize.x); //interpolation factor for X direction. float LY = fract(texcoord.y * texSize.y); //interpolation factor for Y direction. // Interpolate in X direction. float4 InterpolateA = mix(SampleA, SampleB, LX); //Top row in X direction. float4 InterpolateB = mix(SampleC, SampleD, LX); //Bottom row in X direction. return mix(InterpolateA, InterpolateB, LY); //Interpolate in Y direction. } float4 BilinearPass(float4 color) { color = SampleBilinear(texcoord); return color; } /*------------------------------------------------------------------------------ [GAMMA CORRECTION CODE SECTION] ------------------------------------------------------------------------------*/ float3 RGBGammaToLinear(float3 color, float gamma) { color = Saturate(color); color.r = (color.r <= 0.0404482362771082) ? color.r / 12.92 : pow((color.r + 0.055) / 1.055, gamma); color.g = (color.g <= 0.0404482362771082) ? color.g / 12.92 : pow((color.g + 0.055) / 1.055, gamma); color.b = (color.b <= 0.0404482362771082) ? color.b / 12.92 : pow((color.b + 0.055) / 1.055, gamma); return color; } float3 LinearToRGBGamma(float3 color, float gamma) { color = Saturate(color); color.r = (color.r <= 0.00313066844250063) ? color.r * 12.92 : 1.055 * pow(color.r, 1.0 / gamma) - 0.055; color.g = (color.g <= 0.00313066844250063) ? color.g * 12.92 : 1.055 * pow(color.g, 1.0 / gamma) - 0.055; color.b = (color.b <= 0.00313066844250063) ? color.b * 12.92 : 1.055 * pow(color.b, 1.0 / gamma) - 0.055; return color; } float4 GammaPass(float4 color) { const float GammaConst = 2.233; color.rgb = RGBGammaToLinear(color.rgb, GammaConst); color.rgb = LinearToRGBGamma(color.rgb, GetOption(A_GAMMA)); color.a = RGBLuminance(color.rgb); return color; } /*------------------------------------------------------------------------------ [BLENDED BLOOM CODE SECTION] ------------------------------------------------------------------------------*/ float4 PyramidFilter(float2 texcoord, float2 width) { float4 color = SampleLocation(texcoord + float2(0.5, 0.5) * width); color += SampleLocation(texcoord + float2(-0.5, 0.5) * width); color += SampleLocation(texcoord + float2(0.5, -0.5) * width); color += SampleLocation(texcoord + float2(-0.5, -0.5) * width); color *= 0.25; return color; } float3 BloomCorrection(float3 color) { float X = 1.0 / (1.0 + exp(GetOption(E_BLOOM_REDS) / 2.0)); float Y = 1.0 / (1.0 + exp(GetOption(F_BLOOM_GREENS) / 2.0)); float Z = 1.0 / (1.0 + exp(GetOption(G_BLOOM_BLUES) / 2.0)); color.r = (1.0 / (1.0 + exp(-GetOption(E_BLOOM_REDS) * (color.r - 0.5))) - X) / (1.0 - 2.0 * X); color.g = (1.0 / (1.0 + exp(-GetOption(F_BLOOM_GREENS) * (color.g - 0.5))) - Y) / (1.0 - 2.0 * Y); color.b = (1.0 / (1.0 + exp(-GetOption(G_BLOOM_BLUES) * (color.b - 0.5))) - Z) / (1.0 - 2.0 * Z); return color; } float3 Blend(float3 color, float3 bloom) { float3 BlendAddLight = (color + bloom) * 0.75; float3 BlendScreen = (color + bloom) - (color * bloom); float3 BlendLuma = lerp((color * bloom), (1.0 - ((1.0 - color) * (1.0 - bloom))), RGBLuminance(color + bloom)); float3 BlendGlow = step(0.5, color); BlendGlow = lerp((color + bloom) - (color * bloom), (bloom + bloom) - (bloom * bloom), BlendGlow); float3 BlendOverlay = step(0.5, color); BlendOverlay = lerp((color * bloom * 2.0), (1.0 - (2.0 * (1.0 - color) * (1.0 - bloom))), BlendOverlay); if (GetOption(A_BLOOM_TYPE) == 0) { return BlendGlow; } else if (GetOption(A_BLOOM_TYPE) == 1) { return BlendAddLight; } else if (GetOption(A_BLOOM_TYPE) == 2) { return BlendScreen; } else if (GetOption(A_BLOOM_TYPE) == 3) { return BlendLuma; } else if (GetOption(A_BLOOM_TYPE) == 4) { return BlendOverlay; } } float4 BloomPass(float4 color) { const float defocus = 1.25; float4 bloom = PyramidFilter(texcoord, (1.0/texSize) * defocus); float2 dx = float2(invDefocus.x * GetOption(D_BLOOM_WIDTH), 0.0); float2 dy = float2(0.0, invDefocus.y * GetOption(D_BLOOM_WIDTH)); float2 mdx = (dx * 2.0); float2 mdy = (dy * 2.0); float4 bloomBlend = bloom * 0.22520613262190495; bloomBlend += 0.002589001911021066 * SampleLocation(texcoord - mdx + mdy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord - dx + mdy); bloomBlend += 0.024146616900339800 * SampleLocation(texcoord + mdy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord + dx + mdy); bloomBlend += 0.002589001911021066 * SampleLocation(texcoord + mdx + mdy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord - mdx + dy); bloomBlend += 0.044875475183061630 * SampleLocation(texcoord - dx + dy); bloomBlend += 0.100529757860782610 * SampleLocation(texcoord + dy); bloomBlend += 0.044875475183061630 * SampleLocation(texcoord + dx + dy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord + mdx + dy); bloomBlend += 0.024146616900339800 * SampleLocation(texcoord - mdx); bloomBlend += 0.100529757860782610 * SampleLocation(texcoord - dx); bloomBlend += 0.100529757860782610 * SampleLocation(texcoord + dx); bloomBlend += 0.024146616900339800 * SampleLocation(texcoord + mdx); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord - mdx - dy); bloomBlend += 0.044875475183061630 * SampleLocation(texcoord - dx - dy); bloomBlend += 0.100529757860782610 * SampleLocation(texcoord - dy); bloomBlend += 0.044875475183061630 * SampleLocation(texcoord + dx - dy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord + mdx - dy); bloomBlend += 0.002589001911021066 * SampleLocation(texcoord - mdx - mdy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord - dx - mdy); bloomBlend += 0.024146616900339800 * SampleLocation(texcoord - mdy); bloomBlend += 0.010778807494659370 * SampleLocation(texcoord + dx - mdy); bloomBlend += 0.002589001911021066 * SampleLocation(texcoord + mdx - mdy); bloomBlend = lerp(color, bloomBlend, GetOption(C_BLEND_STRENGTH)); bloom.rgb = Blend(bloom.rgb, bloomBlend.rgb); bloom.rgb = BloomCorrection(bloom.rgb); color.a = RGBLuminance(color.rgb); bloom.a = RGBLuminance(bloom.rgb); color = lerp(color, bloom, GetOption(B_BLOOM_STRENGTH)); return color; } /*------------------------------------------------------------------------------ [COLOR CORRECTION/TONE MAPPING CODE SECTION] ------------------------------------------------------------------------------*/ float3 FilmicTonemap(float3 color) { float3 Q = color.xyz; float A = 0.10; float B = GetOption(C_BLACK_LEVELS); float C = 0.10; float D = GetOption(B_TONE_AMOUNT); float E = 0.02; float F = 0.30; float W = GetOption(F_WHITEPOINT); float3 numerator = ((Q*(A*Q + C*B) + D*E) / (Q*(A*Q + B) + D*F)) - E / F; float denominator = ((W*(A*W + C*B) + D*E) / (W*(A*W + B) + D*F)) - E / F; color.xyz = numerator / denominator; return color; } float3 ColorShift(float3 color) { float3 colMood; colMood.r = GetOption(B_RED_SHIFT); colMood.g = GetOption(C_GREEN_SHIFT); colMood.b = GetOption(D_BLUE_SHIFT); float fLum = RGBLuminance(color.rgb); colMood = lerp(float3(0.0), colMood, (fLum * 2.0)); colMood = lerp(colMood, float3(1.0), (fLum - 0.5) * 2.0); float3 colOutput = lerp(color, colMood, (fLum * GetOption(E_SHIFT_RATIO))); return colOutput; } float3 ColorCorrection(float3 color) { float X = 1.0 / (1.0 + exp(GetOption(B_RED_CORRECTION) / 2.0)); float Y = 1.0 / (1.0 + exp(GetOption(C_GREEN_CORRECTION) / 2.0)); float Z = 1.0 / (1.0 + exp(GetOption(D_BLUE_CORRECTION) / 2.0)); color.r = (1.0 / (1.0 + exp(-GetOption(B_RED_CORRECTION) * (color.r - 0.5))) - X) / (1.0 - 2.0 * X); color.g = (1.0 / (1.0 + exp(-GetOption(C_GREEN_CORRECTION) * (color.g - 0.5))) - Y) / (1.0 - 2.0 * Y); color.b = (1.0 / (1.0 + exp(-GetOption(D_BLUE_CORRECTION) * (color.b - 0.5))) - Z) / (1.0 - 2.0 * Z); return color; } float4 TonemapPass(float4 color) { const float delta = 0.001; const float wpoint = pow(1.002, 2.0); if (OptionEnabled(D_COLOR_CORRECTION) && GetOption(A_PALETTE) == 1) { color.rgb = ColorCorrection(color.rgb); } if (OptionEnabled(E_FILMIC_PROCESS) && GetOption(A_FILMIC) == 1) { color.rgb = ColorShift(color.rgb); } color.rgb = FilmicTonemap(color.rgb); // RGB -> XYZ conversion const mat3 RGB2XYZ = mat3( 0.4124564, 0.2126729, 0.0193339, 0.3575761, 0.7151522, 0.1191920, 0.1804375, 0.0721750, 0.9503041 ); float3 XYZ = (RGB2XYZ * color.rgb); // XYZ -> Yxy conversion float3 Yxy; Yxy.r = XYZ.g; // copy luminance Y Yxy.g = XYZ.r / (XYZ.r + XYZ.g + XYZ.b); // x = X / (X + Y + Z) Yxy.b = XYZ.g / (XYZ.r + XYZ.g + XYZ.b); // y = Y / (X + Y + Z) if (OptionEnabled(D_COLOR_CORRECTION) && GetOption(A_PALETTE) == 2) { Yxy.rgb = ColorCorrection(Yxy.rgb); } // (Lp) Map average luminance to the middlegrey zone by scaling pixel luminance float Lp; if (GetOption(A_TONEMAP_TYPE) == 1) { Lp = Yxy.r * FilmicTonemap(Yxy.rrr).r / RGBLuminance(Yxy.rrr) * GetOption(D_EXPOSURE) / (GetOption(E_LUMINANCE) + delta); } else { Lp = Yxy.r * GetOption(D_EXPOSURE) / (GetOption(E_LUMINANCE) + delta); } // (Ld) Scale all luminance within a displayable range of 0 to 1 Yxy.r = (Lp * (1.0 + Lp / wpoint)) / (1.0 + Lp); // Yxy -> XYZ conversion XYZ.r = Yxy.r * Yxy.g / Yxy.b; // X = Y * x / y XYZ.g = Yxy.r; // copy luminance Y XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b; // Z = Y * (1-x-y) / y if (OptionEnabled(D_COLOR_CORRECTION) && GetOption(A_PALETTE) == 3) { XYZ.rgb = ColorCorrection(XYZ.rgb); } // XYZ -> RGB conversion const mat3 XYZ2RGB = mat3( 3.2404542, -0.9692660, 0.0556434, -1.5371385, 1.8760108, -0.2040259, -0.4985314, 0.0415560, 1.0572252 ); color.rgb = (XYZ2RGB * XYZ); color.a = RGBLuminance(color.rgb); return color; } /*------------------------------------------------------------------------------ [TEXTURE SHARPEN CODE SECTION] ------------------------------------------------------------------------------*/ float Cubic(float coeff) { vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - coeff; vec4 s = n * n * n; float x = s.x; float y = s.y - 4.0 * s.x; float z = s.z - 4.0 * s.y + 6.0 * s.x; float w = 6.0 - x - y - z; return (x + y + z + w) / 4.0; } float4 SampleBicubic(float2 texcoord) { float texelSizeX = (1.0 / texSize.x) * GetOption(C_SHARPEN_BIAS); float texelSizeY = (1.0 / texSize.y) * GetOption(C_SHARPEN_BIAS); float4 nSum = float4(0.0, 0.0, 0.0, 0.0); float4 nDenom = float4(0.0, 0.0, 0.0, 0.0); float a = frac(texcoord.x * texSize.x); float b = frac(texcoord.y * texSize.y); int nX = int(texcoord.x * texSize.x); int nY = int(texcoord.y * texSize.y); float2 uvCoord = float2(float(nX) / texSize.x, float(nY) / texSize.y); for (int m = -1; m <= 2; m++) { for (int n = -1; n <= 2; n++) { float4 Samples = SampleLocation(uvCoord + float2(texelSizeX * float(m), texelSizeY * float(n))); float vc1 = Cubic(float(m) - a); float4 vecCoeff1 = float4(vc1, vc1, vc1, vc1); float vc2 = Cubic(-(float(n) - b)); float4 vecCoeff2 = float4(vc2, vc2, vc2, vc2); nSum = nSum + (Samples * vecCoeff2 * vecCoeff1); nDenom = nDenom + (vecCoeff2 * vecCoeff1); } } return nSum / nDenom; } float4 TexSharpenPass(float4 color) { float3 calcSharpen = lumCoeff * GetOption(A_SHARPEN_STRENGTH); float4 blurredColor = SampleBicubic(texcoord); float3 sharpenedColor = (color.rgb - blurredColor.rgb); float sharpenLuma = dot(sharpenedColor, calcSharpen); sharpenLuma = clamp(sharpenLuma, -GetOption(B_SHARPEN_CLAMP), GetOption(B_SHARPEN_CLAMP)); color.rgb = color.rgb + sharpenLuma; color.a = RGBLuminance(color.rgb); if (GetOption(D_SEDGE_DETECTION) == 1) { color = (0.5 + (sharpenLuma * 4)).xxxx; } return color; } /*------------------------------------------------------------------------------ [VIBRANCE CODE SECTION] ------------------------------------------------------------------------------*/ float4 VibrancePass(float4 color) { float luma = RGBLuminance(color.rgb); float colorMax = max(color.r, max(color.g, color.b)); float colorMin = min(color.r, min(color.g, color.b)); float colorSaturation = colorMax - colorMin; color.rgb = lerp(float3(luma), color.rgb, (1.0 + (GetOption(A_VIBRANCE) * (1.0 - (sign(GetOption(A_VIBRANCE)) * colorSaturation))))); color.a = RGBLuminance(color.rgb); return color; //Debug: return colorSaturation.xxxx; } /*------------------------------------------------------------------------------ [LOCAL CONTRAST CODE SECTION] ------------------------------------------------------------------------------*/ float4 ContrastPass(float4 color) { float3 luma = float3(RGBLuminance(color.rgb)); float3 chroma = color.rgb - luma; float3 x = luma; //Cubic Bezier spline float3 a = float3(0.00, 0.00, 0.00); //start point float3 b = float3(0.25, 0.25, 0.25); //control point 1 float3 c = float3(0.80, 0.80, 0.80); //control point 2 float3 d = float3(1.00, 1.00, 1.00); //endpoint float3 ab = lerp(a, b, x); //point between a and b (green) float3 bc = lerp(b, c, x); //point between b and c (green) float3 cd = lerp(c, d, x); //point between c and d (green) float3 abbc = lerp(ab, bc, x); //point between ab and bc (blue) float3 bccd = lerp(bc, cd, x); //point between bc and cd (blue) float3 dest = lerp(abbc, bccd, x); //point on the bezier-curve (black) x = dest; x = lerp(luma, x, GetOption(A_CONTRAST)); color.rgb = x + chroma; color.a = RGBLuminance(color.rgb); return Saturate(color); } /*------------------------------------------------------------------------------ [CEL SHADING CODE SECTION] ------------------------------------------------------------------------------*/ float3 GetYUV(float3 RGB) { const mat3 RGB2YUV = mat3(0.2126, 0.7152, 0.0722, -0.09991,-0.33609, 0.436, 0.615, -0.55861, -0.05639); return (RGB * RGB2YUV); } float3 GetRGB(float3 YUV) { const mat3 YUV2RGB = mat3(1.000, 0.000, 1.28033, 1.000,-0.21482,-0.38059, 1.000, 2.12798, 0.000); return (YUV * YUV2RGB); } float4 CelPass(float4 color) { float3 yuv; float3 sum = color.rgb; const int NUM = 9; const float2 RoundingOffset = float2(0.25, 0.25); const float3 thresholds = float3(9.0, 8.0, 6.0); float lum[NUM]; float3 col[NUM]; float2 set[NUM] = float2[NUM]( float2(-0.0078125, -0.0078125), float2(0.00, -0.0078125), float2(0.0078125, -0.0078125), float2(-0.0078125, 0.00), float2(0.00, 0.00), float2(0.0078125, 0.00), float2(-0.0078125, 0.0078125), float2(0.00, 0.0078125), float2(0.0078125, 0.0078125) ); for (int i = 0; i < NUM; i++) { col[i] = SampleLocation(texcoord + set[i] * RoundingOffset).rgb; if (GetOption(G_COLOR_ROUNDING) == 1) { col[i].r = round(col[i].r * thresholds.r) / thresholds.r; col[i].g = round(col[i].g * thresholds.g) / thresholds.g; col[i].b = round(col[i].b * thresholds.b) / thresholds.b; } lum[i] = RGBLuminance(col[i].xyz); yuv = GetYUV(col[i]); if (GetOption(E_YUV_LUMA) == 0) { yuv.r = round(yuv.r * thresholds.r) / thresholds.r; } else { yuv.r = Saturate(round(yuv.r * lum[i]) / thresholds.r + lum[i]); } yuv = GetRGB(yuv); sum += yuv; } float3 shadedColor = (sum / NUM); float2 pixel = float2((1.0/texSize.x) * GetOption(C_EDGE_THICKNESS), (1.0/texSize.y) * GetOption(C_EDGE_THICKNESS)); float edgeX = dot(SampleLocation(texcoord + pixel).rgb, lumCoeff); edgeX = dot(float4(SampleLocation(texcoord - pixel).rgb, edgeX), float4(lumCoeff, -1.0)); float edgeY = dot(SampleLocation(texcoord + float2(pixel.x, -pixel.y)).rgb, lumCoeff); edgeY = dot(float4(SampleLocation(texcoord + float2(-pixel.x, pixel.y)).rgb, edgeY), float4(lumCoeff, -1.0)); float edge = dot(float2(edgeX, edgeY), float2(edgeX, edgeY)); if (GetOption(D_PALETTE_TYPE) == 0) { color.rgb = lerp(color.rgb, color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), GetOption(A_EDGE_STRENGTH)); } else if (GetOption(D_PALETTE_TYPE) == 1) { color.rgb = lerp(color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), shadedColor, 0.30); } else if (GetOption(D_PALETTE_TYPE) == 2) { color.rgb = lerp(shadedColor + edge * -GetOption(A_EDGE_STRENGTH), pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH) + color.rgb, 0.50); } color.a = RGBLuminance(color.rgb); return Saturate(color); } /*------------------------------------------------------------------------------ [FILM GRAIN CODE SECTION] ------------------------------------------------------------------------------*/ float width = screenSize.x; float height = screenSize.y; const float permTexUnit = 1.0/256.0; const float permTexUnitHalf = 0.5/256.0; float Fade(in float t) { return t*t*t*(t*(t*6.0 - 15.0) + 10.0); } float2 CoordRot(in float2 tc, in float angle) { float aspect = width/height; float rotX = ((tc.x * 2.0-1.0) * aspect * cos(angle)) - ((tc.y * 2.0-1.0) * sin(angle)); float rotY = ((tc.y * 2.0-1.0) * cos(angle)) + ((tc.x * 2.0-1.0) * aspect * sin(angle)); rotX = ((rotX/aspect) * 0.5+0.5); rotY = rotY * 0.5+0.5; return float2(rotX,rotY); } float4 Randomize(in float2 texcoord) { float noise = (frac(sin(dot(texcoord, float2(12.9898, 78.233)*2.0)) * 43758.5453)); float noiseR = fract(noise) * 2.0-1.0; float noiseG = fract(noise * 1.2154) * 2.0-1.0; float noiseB = fract(noise * 1.3453) * 2.0-1.0; float noiseA = fract(noise * 1.3647) * 2.0-1.0; return float4(noiseR, noiseG, noiseB, noiseA); } float PerNoise(in float3 p) { float3 pf = fract(p); float3 pi = permTexUnit * floor(p) + permTexUnitHalf; // Noise contributions from (x=0, y=0), z=0 and z=1 float perm00 = Randomize(pi.xy).a ; float3 grad000 = Randomize(float2(perm00, pi.z)).rgb * 4.0 - 1.0; float n000 = dot(grad000, pf); float3 grad001 = Randomize(float2(perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0; float n001 = dot(grad001, pf - float3(0.0, 0.0, 1.0)); // Noise contributions from (x=0, y=1), z=0 and z=1 float perm01 = Randomize(pi.xy + float2(0.0, permTexUnit)).a ; float3 grad010 = Randomize(float2(perm01, pi.z)).rgb * 4.0 - 1.0; float n010 = dot(grad010, pf - float3(0.0, 1.0, 0.0)); float3 grad011 = Randomize(float2(perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0; float n011 = dot(grad011, pf - float3(0.0, 1.0, 1.0)); // Noise contributions from (x=1, y=0), z=0 and z=1 float perm10 = Randomize(pi.xy + float2(permTexUnit, 0.0)).a ; float3 grad100 = Randomize(float2(perm10, pi.z)).rgb * 4.0 - 1.0; float n100 = dot(grad100, pf - float3(1.0, 0.0, 0.0)); float3 grad101 = Randomize(float2(perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0; float n101 = dot(grad101, pf - float3(1.0, 0.0, 1.0)); // Noise contributions from (x=1, y=1), z=0 and z=1 float perm11 = Randomize(pi.xy + float2(permTexUnit, permTexUnit)).a ; float3 grad110 = Randomize(float2(perm11, pi.z)).rgb * 4.0 - 1.0; float n110 = dot(grad110, pf - float3(1.0, 1.0, 0.0)); float3 grad111 = Randomize(float2(perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0; float n111 = dot(grad111, pf - float3(1.0, 1.0, 1.0)); float4 n_x = mix(float4(n000, n001, n010, n011), float4(n100, n101, n110, n111), Fade(pf.x)); float2 n_xy = mix(n_x.xy, n_x.zw, Fade(pf.y)); float n_xyz = mix(n_xy.x, n_xy.y, Fade(pf.z)); return n_xyz; } float4 GrainPass(float4 color) { float3 rotOffset = float3(1.425, 3.892, 5.835); //rotation offset values float2 rotCoordsR = CoordRot(texcoord, timer + rotOffset.x); float3 noise = float3(PerNoise(float3(rotCoordsR * float2(width / GetOption(A_GRAIN_SIZE), height / GetOption(A_GRAIN_SIZE)), 0.0))); if (GetOption(C_COLORED) == 1) { float2 rotCoordsG = CoordRot(texcoord, timer + rotOffset.y); float2 rotCoordsB = CoordRot(texcoord, timer + rotOffset.z); noise.g = mix(noise.r,PerNoise(float3(rotCoordsG * float2(width / GetOption(A_GRAIN_SIZE), height / GetOption(A_GRAIN_SIZE)), 1.0)), GetOption(D_COLOR_AMOUNT)); noise.b = mix(noise.r,PerNoise(float3(rotCoordsB * float2(width / GetOption(A_GRAIN_SIZE), height / GetOption(A_GRAIN_SIZE)), 2.0)), GetOption(D_COLOR_AMOUNT)); } //noisiness response curve based on scene luminance float luminance = mix(0.0, dot(color.rgb, lumCoeff), GetOption(E_LUMA_AMOUNT)); float lum = smoothstep(0.2, 0.0, luminance); lum += luminance; noise = lerp(noise, float3(0.0), pow(lum, 4.0)); color.rgb = color.rgb + noise * GetOption(B_GRAIN_AMOUNT); return color; } /*------------------------------------------------------------------------------ [VIGNETTE CODE SECTION] ------------------------------------------------------------------------------*/ float4 VignettePass(float4 color) { const float2 VignetteCenter = float2(0.500, 0.500); float2 tc = texcoord - VignetteCenter; // hardcoded pre ratio calculations, for uniform output on arbitrary resolutions. tc *= float2((2560.0 / 1440.0), GetOption(A_VIG_RATIO)); tc /= GetOption(B_VIG_RADIUS); float v = dot(tc, tc); color.rgb *= (1.0 + pow(v, GetOption(D_VIG_SLOPE) * 0.25) * -GetOption(C_VIG_AMOUNT)); return color; } /*------------------------------------------------------------------------------ [SCANLINES CODE SECTION] ------------------------------------------------------------------------------*/ float4 ScanlinesPass(float4 color) { float4 intensity; if (GetOption(A_SCANLINE_TYPE) == 0) { //X coord scanlines if (fract(gl_FragCoord.y * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS)) { intensity = float4(0.0, 0.0, 0.0, 0.0); } else { intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) + normalize(float4(color.xyz, RGBLuminance(color.xyz))); } } else if (GetOption(A_SCANLINE_TYPE) == 1) { //Y coord scanlines if (fract(gl_FragCoord.x * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS)) { intensity = float4(0.0, 0.0, 0.0, 0.0); } else { intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) + normalize(float4(color.xyz, RGBLuminance(color.xyz))); } } else if (GetOption(A_SCANLINE_TYPE) == 2) { //XY coord scanlines if (fract(gl_FragCoord.x * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS) && fract(gl_FragCoord.y * GetOption(B_SCANLINE_SPACING)) > GetOption(B_SCANLINE_THICKNESS)) { intensity = float4(0.0, 0.0, 0.0, 0.0); } else { intensity = smoothstep(0.2, GetOption(B_SCANLINE_BRIGHTNESS), color) + normalize(float4(color.xyz, RGBLuminance(color.xyz))); } } float level = (4.0-texcoord.x) * GetOption(B_SCANLINE_INTENSITY); color = intensity * (0.5 - level) + color * 1.1; return Saturate(color); } /*------------------------------------------------------------------------------ [DITHERING CODE SECTION] ------------------------------------------------------------------------------*/ float4 DitherPass(float4 color) { float ditherBit = 8.0; if (GetOption(A_DITHER_TYPE) == 1) //Ordered grid { float gridPos = fract(dot(gl_FragCoord.xy - float2(0.5, 0.5), float2(1.0 / 16.0, 10.0 / 36.0) + 0.25)); float shift = (0.25) * (1.0 / (pow(2.0, ditherBit) - 1.0)); float3 rgbShift = float3(shift, -shift, shift); rgbShift = lerp(2.0 * rgbShift, -2.0 * rgbShift, gridPos); color.rgb += rgbShift; } else //Pseudo random { float seed = dot(texcoord, float2(12.9898, 78.233)); float sine = sin(seed); float noise = frac(sine * 43758.5453 + texcoord.x); float shift = (1.0 / (pow(2, ditherBit) - 1.0)); float halfShift = (shift * 0.5); shift = shift * noise - halfShift; color.rgb += float3(-shift, shift, -shift); } return color; } /*------------------------------------------------------------------------------ [FXAA CODE SECTION] ------------------------------------------------------------------------------*/ #define FXAA_GLSL_130 1 #define FXAA_GREEN_AS_LUMA 1 #ifndef FXAA_GLSL_120 #define FXAA_GLSL_120 0 #endif #ifndef FXAA_GLSL_130 #define FXAA_GLSL_130 0 #endif #ifndef FXAA_GREEN_AS_LUMA #define FXAA_GREEN_AS_LUMA 0 #endif #ifndef FXAA_EARLY_EXIT #define FXAA_EARLY_EXIT 1 #endif #ifndef FXAA_DISCARD #define FXAA_DISCARD 0 #endif #ifndef FXAA_FAST_PIXEL_OFFSET #ifdef GL_EXT_gpu_shader4 #define FXAA_FAST_PIXEL_OFFSET 1 #endif #ifdef GL_NV_gpu_shader5 #define FXAA_FAST_PIXEL_OFFSET 1 #endif #ifdef GL_ARB_gpu_shader5 #define FXAA_FAST_PIXEL_OFFSET 1 #endif #ifndef FXAA_FAST_PIXEL_OFFSET #define FXAA_FAST_PIXEL_OFFSET 0 #endif #endif #ifndef FXAA_GATHER4_ALPHA #if (FXAA_HLSL_5 == 1) #define FXAA_GATHER4_ALPHA 1 #endif #ifdef GL_ARB_gpu_shader5 #define FXAA_GATHER4_ALPHA 1 #endif #ifdef GL_NV_gpu_shader5 #define FXAA_GATHER4_ALPHA 1 #endif #ifndef FXAA_GATHER4_ALPHA #define FXAA_GATHER4_ALPHA 0 #endif #endif #define FXAA_QUALITY__PS 9 #define FXAA_QUALITY__P0 1.0 #define FXAA_QUALITY__P1 1.5 #define FXAA_QUALITY__P2 2.0 #define FXAA_QUALITY__P3 2.0 #define FXAA_QUALITY__P4 2.0 #define FXAA_QUALITY__P5 2.0 #define FXAA_QUALITY__P6 2.0 #define FXAA_QUALITY__P7 4.0 #define FXAA_QUALITY__P8 8.0 #define FxaaBool bool #define FxaaDiscard discard #define FxaaFloat float #define FxaaFloat2 vec2 #define FxaaFloat3 vec3 #define FxaaFloat4 vec4 #define FxaaHalf float #define FxaaHalf2 vec2 #define FxaaHalf3 vec3 #define FxaaHalf4 vec4 #define FxaaInt2 ivec2 #define FxaaSat(x) clamp(x, 0.0, 1.0) #define FxaaTex sampler2DArray #if (FXAA_GLSL_120 == 1) #define FxaaTexTop(t, p) texture2DLod(t, float3(p, 0), 0.0) #if (FXAA_FAST_PIXEL_OFFSET == 1) #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, float3(p, 0), 0.0, o) #else #define FxaaTexOff(t, p, o, r) texture2DLod(t, float3(p, 0) + (o * r), 0.0) #endif #if (FXAA_GATHER4_ALPHA == 1) // use #extension GL_ARB_gpu_shader5 : enable #define FxaaTexAlpha4(t, p) textureGather(t, float3(p, 0), 3) #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, float3(p, 0), o, 3) #define FxaaTexGreen4(t, p) textureGather(t, float3(p, 0), 1) #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, float3(p, 0), o, 1) #endif #endif #if (FXAA_GLSL_130 == 1) #define FxaaTexTop(t, p) textureLod(t, float3(p, 0), 0.0) #define FxaaTexOff(t, p, o, r) textureLodOffset(t, float3(p, 0), 0.0, o) #if (FXAA_GATHER4_ALPHA == 1) // use #extension GL_ARB_gpu_shader5 : enable #define FxaaTexAlpha4(t, p) textureGather(t, float3(p, 0), 3) #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, float3(p, 0), o, 3) #define FxaaTexGreen4(t, p) textureGather(t, float3(p, 0), 1) #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, float3(p, 0), o, 1) #endif #endif #if (FXAA_GREEN_AS_LUMA == 0) FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } #else FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } #endif FxaaFloat4 FxaaPixelShader(FxaaTex tex, FxaaFloat2 RcpFrame, FxaaFloat Subpix, FxaaFloat EdgeThreshold, FxaaFloat EdgeThresholdMin) { FxaaFloat2 posM; posM.x = texcoord.x; posM.y = texcoord.y; #if (FXAA_GATHER4_ALPHA == 1) #if (FXAA_DISCARD == 0) FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); #if (FXAA_GREEN_AS_LUMA == 0) #define lumaM rgbyM.w #else #define lumaM rgbyM.y #endif #endif #if (FXAA_GREEN_AS_LUMA == 0) FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); #else FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); #endif #if (FXAA_DISCARD == 1) #define lumaM luma4A.w #endif #define lumaE luma4A.z #define lumaS luma4A.x #define lumaSE luma4A.y #define lumaNW luma4B.w #define lumaN luma4B.z #define lumaW luma4B.x #else FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); #if (FXAA_GREEN_AS_LUMA == 0) #define lumaM rgbyM.w #else #define lumaM rgbyM.y #endif FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), RcpFrame.xy)); FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), RcpFrame.xy)); FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), RcpFrame.xy)); FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), RcpFrame.xy)); #endif FxaaFloat maxSM = max(lumaS, lumaM); FxaaFloat minSM = min(lumaS, lumaM); FxaaFloat maxESM = max(lumaE, maxSM); FxaaFloat minESM = min(lumaE, minSM); FxaaFloat maxWN = max(lumaN, lumaW); FxaaFloat minWN = min(lumaN, lumaW); FxaaFloat rangeMax = max(maxWN, maxESM); FxaaFloat rangeMin = min(minWN, minESM); FxaaFloat rangeMaxScaled = rangeMax * EdgeThreshold; FxaaFloat range = rangeMax - rangeMin; FxaaFloat rangeMaxClamped = max(EdgeThresholdMin, rangeMaxScaled); FxaaBool earlyExit = range < rangeMaxClamped; if(earlyExit) #if (FXAA_DISCARD == 1) FxaaDiscard; #else return rgbyM; #endif #if (FXAA_GATHER4_ALPHA == 0) FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), RcpFrame.xy)); FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), RcpFrame.xy)); FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), RcpFrame.xy)); FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), RcpFrame.xy)); #else FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), RcpFrame.xy)); FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), RcpFrame.xy)); #endif FxaaFloat lumaNS = lumaN + lumaS; FxaaFloat lumaWE = lumaW + lumaE; FxaaFloat subpixRcpRange = 1.0/range; FxaaFloat subpixNSWE = lumaNS + lumaWE; FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; FxaaFloat lumaNESE = lumaNE + lumaSE; FxaaFloat lumaNWNE = lumaNW + lumaNE; FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; FxaaFloat lumaNWSW = lumaNW + lumaSW; FxaaFloat lumaSWSE = lumaSW + lumaSE; FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; FxaaFloat lengthSign = RcpFrame.x; FxaaBool horzSpan = edgeHorz >= edgeVert; FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; if(!horzSpan) lumaN = lumaW; if(!horzSpan) lumaS = lumaE; if(horzSpan) lengthSign = RcpFrame.y; FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; FxaaFloat gradientN = lumaN - lumaM; FxaaFloat gradientS = lumaS - lumaM; FxaaFloat lumaNN = lumaN + lumaM; FxaaFloat lumaSS = lumaS + lumaM; FxaaBool pairN = abs(gradientN) >= abs(gradientS); FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); if(pairN) lengthSign = -lengthSign; FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); FxaaFloat2 posB; posB.x = posM.x; posB.y = posM.y; FxaaFloat2 offNP; offNP.x = (!horzSpan) ? 0.0 : RcpFrame.x; offNP.y = ( horzSpan) ? 0.0 : RcpFrame.y; if(!horzSpan) posB.x += lengthSign * 0.5; if( horzSpan) posB.y += lengthSign * 0.5; FxaaFloat2 posN; posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; FxaaFloat2 posP; posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); FxaaFloat subpixE = subpixC * subpixC; FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); if(!pairN) lumaNN = lumaSS; FxaaFloat gradientScaled = gradient * 1.0/4.0; FxaaFloat lumaMM = lumaM - lumaNN * 0.5; FxaaFloat subpixF = subpixD * subpixE; FxaaBool lumaMLTZero = lumaMM < 0.0; lumaEndN -= lumaNN * 0.5; lumaEndP -= lumaNN * 0.5; FxaaBool doneN = abs(lumaEndN) >= gradientScaled; FxaaBool doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; FxaaBool doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; if(doneNP) { if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; }}}}}}} FxaaFloat dstN = posM.x - posN.x; FxaaFloat dstP = posP.x - posM.x; if(!horzSpan) dstN = posM.y - posN.y; if(!horzSpan) dstP = posP.y - posM.y; FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; FxaaFloat spanLength = (dstP + dstN); FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; FxaaFloat spanLengthRcp = 1.0/spanLength; FxaaBool directionN = dstN < dstP; FxaaFloat dst = min(dstN, dstP); FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; FxaaFloat subpixG = subpixF * subpixF; FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; FxaaFloat subpixH = subpixG * Subpix; FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; #if (FXAA_DISCARD == 1) return FxaaTexTop(tex, posM); #else if (GetOption(C_FXAA_SHOW_EDGES) == 1) { return -rgbyM; } else { return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); } #endif } float4 FxaaPass(float4 color) { color = FxaaPixelShader(samp9, 1.0/texSize, GetOption(A_FXAA_SUBPIX_MAX), GetOption(B_FXAA_EDGE_THRESHOLD), 0.000); return color; } /*------------------------------------------------------------------------------ [MAIN() & COMBINE PASS CODE SECTION] ------------------------------------------------------------------------------*/ void main() { float4 color = Sample(); if (!OptionEnabled(DISABLE_EFFECTS)) { if (OptionEnabled(A_FXAA_PASS)) { color = FxaaPass(color); } if (OptionEnabled(A_BILINEAR_FILTER)) { color = BilinearPass(color); } if (OptionEnabled(B_BICUBLIC_SCALER)) { color = BicubicScalerPass(color); } if (OptionEnabled(B_LANCZOS_SCALER)) { color = LanczosScalerPass(color); } if (OptionEnabled(G_TEXTURE_SHARPEN)) { color = TexSharpenPass(color); } if (OptionEnabled(J_CEL_SHADING)) { color = CelPass(color); } if (OptionEnabled(K_SCAN_LINES)) { color = ScanlinesPass(color); } if (OptionEnabled(B_BLOOM_PASS)) { color = BloomPass(color); } if (OptionEnabled(C_TONEMAP_PASS)) { color = TonemapPass(color); } if (OptionEnabled(F_GAMMA_CORRECTION)) { color = GammaPass(color); } if (OptionEnabled(H_PIXEL_VIBRANCE)) { color = VibrancePass(color); } if (OptionEnabled(I_CONTRAST_ENHANCEMENT)) { color = ContrastPass(color); } if (OptionEnabled(L_FILM_GRAIN_PASS)) { color = GrainPass(color); } if (OptionEnabled(L_VIGNETTE_PASS)) { color = VignettePass(color); } if (OptionEnabled(M_DITHER_PASS)) { color = DitherPass(color); } } SetOutput(color); } Failed to parse shader Shader Info Log: Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. WARNING: 0:413: '#extension' : extension is only partially supported: GL_ARB_gpu_shader5 ERROR: 0:1015: 'GetTime' : can't call user function from global scope ERROR: 0:1015: '' : syntax error ERROR: 2 compilation errors. No code generated.