├── README.md ├── Shaders ├── Bumpmapping.fx ├── DilationErosion.fx ├── FastBilateral.fx ├── LowLife.fx ├── LumaSharpen.fx ├── SmartNoise.fx ├── VHSPro.fx └── xBRv4.fx └── Textures ├── bapho_blue_noise.png └── hd_noise.png /README.md: -------------------------------------------------------------------------------- 1 | # reshade-shaders 2 | 3 | A collection of shaders that i created, ported or collected for ReShade. 4 | 5 | https://reshade.me/ 6 | -------------------------------------------------------------------------------- /Shaders/Bumpmapping.fx: -------------------------------------------------------------------------------- 1 | /* 2 | Bumpmapping Shader 3 | 4 | Copyright (C) 2019 guest(r) - guest.r@gmail.com 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #include "ReShadeUI.fxh" 22 | #include "ReShade.fxh" 23 | 24 | uniform float SMOOTHING < __UNIFORM_SLIDER_FLOAT1 25 | ui_min = 0.0; ui_max = 1.0; 26 | ui_label = "Effect Smoothing"; 27 | ui_tooltip = "Effect Smoothing"; 28 | > = 0.5; 29 | 30 | uniform float RANGE < __UNIFORM_SLIDER_FLOAT1 31 | ui_min = 0.5; ui_max = 2.0; 32 | ui_label = "Effect Width"; 33 | ui_tooltip = "Effect Width"; 34 | > = 1.0; 35 | 36 | uniform float EMBOSS < __UNIFORM_SLIDER_FLOAT1 37 | ui_min = 0.0; ui_max = 2.0; 38 | ui_label = "BumpMapping Strength"; 39 | ui_tooltip = "BumpMapping Strength"; 40 | > = 1.0; 41 | 42 | uniform float CONTRAST < __UNIFORM_SLIDER_FLOAT1 43 | ui_min = 0.0; ui_max = 0.40; 44 | ui_label = "Contrast"; 45 | ui_tooltip = "Ammount of haloing etc."; 46 | > = 0.20; 47 | 48 | uniform float SMART < __UNIFORM_SLIDER_FLOAT1 49 | ui_min = 0.0; ui_max = 1.0; 50 | ui_label = "Smart Bumpmapping"; 51 | ui_tooltip = "Smart Bumpmapping"; 52 | > = 0.75; 53 | 54 | 55 | texture SmoothTexture01 { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; }; 56 | sampler Texture01S { Texture = SmoothTexture01; }; 57 | 58 | 59 | static const float2 g10 = float2( 0.333,-1.0)*ReShade::PixelSize; 60 | static const float2 g01 = float2(-1.0,-0.333)*ReShade::PixelSize; 61 | static const float2 g12 = float2(-0.333, 1.0)*ReShade::PixelSize; 62 | static const float2 g21 = float2( 1.0, 0.333)*ReShade::PixelSize; 63 | 64 | float3 SMOOTH (float4 pos : SV_Position, float2 uv : TexCoord) : SV_Target 65 | { 66 | float3 c10 = tex2D(ReShade::BackBuffer, uv + g10).rgb; 67 | float3 c01 = tex2D(ReShade::BackBuffer, uv + g01).rgb; 68 | float3 c11 = tex2D(ReShade::BackBuffer, uv ).rgb; 69 | float3 c21 = tex2D(ReShade::BackBuffer, uv + g21).rgb; 70 | float3 c12 = tex2D(ReShade::BackBuffer, uv + g12).rgb; 71 | 72 | float3 b11 = (c10+c01+c12+c21+c11)*0.2; 73 | 74 | c11 = lerp(c11,b11,SMOOTHING); 75 | 76 | return c11; 77 | } 78 | 79 | 80 | float3 GetWeight(float3 dif1) 81 | { 82 | return lerp(float3(1.0,1.0,1.0), 0.7*dif1 + 0.3, SMART); 83 | } 84 | 85 | float3 BUMP(float4 pos : SV_Position, float2 uv : TexCoord) : SV_Target 86 | { 87 | const float3 dt = float3(1.0,1.0,1.0); 88 | 89 | // Calculating texel coordinates 90 | float2 inv_size = RANGE * ReShade::PixelSize; 91 | 92 | float2 dx = float2(inv_size.x,0.0); 93 | float2 dy = float2(0.0, inv_size.y); 94 | float2 g1 = float2(inv_size.x,inv_size.y); 95 | 96 | float2 pC4 = uv; 97 | 98 | // Reading the texels 99 | float3 c00 = tex2D(Texture01S,uv - g1).rgb; 100 | float3 c10 = tex2D(Texture01S,uv - dy).rgb; 101 | float3 c01 = tex2D(Texture01S,uv - dx).rgb; 102 | float3 c11 = 0.5*(tex2D(ReShade::BackBuffer,uv).rgb + tex2D(Texture01S,uv).rgb); 103 | float3 c21 = tex2D(Texture01S,uv + dx).rgb; 104 | float3 c12 = tex2D(Texture01S,uv + dy).rgb; 105 | float3 c22 = tex2D(Texture01S,uv + g1).rgb; 106 | 107 | float3 w00 = GetWeight(saturate(2.25*abs(c00-c22)/(c00+c22+0.25))); 108 | float3 w01 = GetWeight(saturate(2.25*abs(c01-c21)/(c01+c21+0.25))); 109 | float3 w10 = GetWeight(saturate(2.25*abs(c10-c12)/(c10+c12+0.25))); 110 | 111 | float3 b11 = (w00*(c00-c22) + w01*(c01-c21) + w10*(c10-c12)) + c11; 112 | 113 | c11 = clamp(lerp(c11,b11,-EMBOSS), c11*(1.0-CONTRAST),c11*(1.0+CONTRAST)); 114 | 115 | return c11; 116 | } 117 | 118 | technique BUMPMAPPING 119 | { 120 | pass bump1 121 | { 122 | VertexShader = PostProcessVS; 123 | PixelShader = SMOOTH; 124 | RenderTarget = SmoothTexture01; 125 | } 126 | pass bump2 127 | { 128 | VertexShader = PostProcessVS; 129 | PixelShader = BUMP; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Shaders/DilationErosion.fx: -------------------------------------------------------------------------------- 1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | // DilationErosion by Bapho - https://github.com/Bapho https://www.shadertoy.com/user/Bapho 3 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | 5 | uniform int type < 6 | ui_type = "combo"; 7 | ui_items = "Dilation" "\0" 8 | "Erosion" "\0"; 9 | ui_label = "Choose a type"; 10 | > = 0; 11 | 12 | uniform int amount < 13 | ui_type = "slider"; 14 | ui_min = 0; ui_max = 30; 15 | ui_label = "Amount"; 16 | > = 10; 17 | 18 | uniform int multiplier < 19 | ui_type = "slider"; 20 | ui_min = 1; ui_max = 30; 21 | ui_label = "Multiplier"; 22 | > = 1; 23 | 24 | uniform int steps < 25 | ui_type = "slider"; 26 | ui_min = 1; ui_max = 3; 27 | ui_label = "Steps"; 28 | > = 3; 29 | 30 | uniform int quality < 31 | ui_type = "combo"; 32 | ui_items = "Low" "\0" 33 | "Medium" "\0" 34 | "High" "\0"; 35 | ui_label = "Quality"; 36 | > = 1; 37 | 38 | uniform float depthBalance < 39 | ui_type = "slider"; 40 | ui_min = -1.0; ui_max = 1.0; ui_step = 0.01; 41 | ui_label = "Depth Balance"; 42 | ui_tooltip = "Balancing between far and near objects"; 43 | > = 0; 44 | 45 | uniform bool useInDepthOnly < 46 | ui_label = "Use in depth only"; 47 | ui_tooltip = "Fully near areas like some UI elements will be skipped"; 48 | > = false; 49 | 50 | #include "ReShade.fxh" 51 | 52 | texture texOne { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; }; 53 | texture texTwo { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; }; 54 | texture texThree { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; }; 55 | sampler2D samOne { Texture = texOne; }; 56 | sampler2D samTwo { Texture = texTwo; }; 57 | sampler2D samThree { Texture = texThree; }; 58 | 59 | float3 dilateErode(int stepCount, sampler sam, float2 texcoord) 60 | { 61 | if (stepCount > steps || amount <= 0.0) { 62 | return tex2D(sam, texcoord).rgb; 63 | } 64 | 65 | float am = amount / 32.0 * multiplier / (stepCount * stepCount); 66 | 67 | float d = ReShade::GetLinearizedDepth(texcoord); 68 | if (useInDepthOnly && d == 1.0) { 69 | am = 0.0; 70 | } else if (depthBalance == 0.0) { 71 | 72 | } else { 73 | d = 1.0 - d; 74 | if (depthBalance > 0.5) { 75 | d = lerp(d, pow(d, 128.0), (depthBalance * 2.0) - 1.0); 76 | } else if (depthBalance > 0.0) { 77 | d = lerp(1.0, d, depthBalance * 2.0); 78 | } else if (depthBalance >= -0.5) { 79 | d = lerp(1.0, d, depthBalance * -2.0); 80 | } else { 81 | d = lerp(d, 1.0 - d, (depthBalance * -2.0) - 1.0); 82 | } 83 | am *= d; 84 | } 85 | 86 | float2 dz = float2(am / ReShade::ScreenSize.x, am / ReShade::ScreenSize.y); 87 | 88 | /* 89 | 90 | A | B | C 91 | D | E | F 92 | G | H | I 93 | 94 | */ 95 | 96 | float3 A = tex2D(sam, texcoord + float2(-1, -1) * dz).rgb; 97 | float3 B; 98 | float3 C = tex2D(sam, texcoord + float2(+1, -1) * dz).rgb; 99 | float3 D; 100 | float3 E = tex2D(sam, texcoord + float2(+0, +0) * dz).rgb; 101 | float3 F; 102 | float3 G = tex2D(sam, texcoord + float2(-1, +1) * dz).rgb; 103 | float3 H; 104 | float3 I = tex2D(sam, texcoord + float2(+1, +1) * dz).rgb; 105 | 106 | bool exacter = quality > 1 || (quality == 1 && am > 1.0); 107 | 108 | if (exacter){ 109 | B = tex2D(sam, texcoord + float2(+0, -1) * dz).rgb; 110 | D = tex2D(sam, texcoord + float2(-1, +0) * dz).rgb; 111 | F = tex2D(sam, texcoord + float2(+1, +0) * dz).rgb; 112 | H = tex2D(sam, texcoord + float2(+0, +1) * dz).rgb; 113 | } 114 | 115 | float3 res; 116 | if (type <= 0){ 117 | if (exacter){ 118 | res = max(E, max(max(max(F, D), max(B, H)), max(max(A, I), max(C, G)))); 119 | } else { 120 | res = max(E, max(max(A, I), max(C, G))); 121 | } 122 | } else { 123 | if (exacter){ 124 | res = min(E, min(min(min(F, D), min(B, H)), min(min(A, I), min(C, G)))); 125 | } else { 126 | res = min(E, min(min(A, I), min(C, G))); 127 | } 128 | } 129 | 130 | return res; 131 | } 132 | 133 | float3 DilationErosionStepOne(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 134 | { 135 | return dilateErode(1, ReShade::BackBuffer, texcoord); 136 | } 137 | 138 | float3 DilationErosionStepTwo(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 139 | { 140 | return dilateErode(2, samOne, texcoord); 141 | } 142 | 143 | float3 DilationErosionStepThree(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 144 | { 145 | return dilateErode(3, samTwo, texcoord); 146 | } 147 | 148 | technique DilationErosion 149 | { 150 | pass 151 | { 152 | VertexShader = PostProcessVS; 153 | PixelShader = DilationErosionStepOne; 154 | RenderTarget = texOne; 155 | } 156 | pass 157 | { 158 | VertexShader = PostProcessVS; 159 | PixelShader = DilationErosionStepTwo; 160 | RenderTarget = texTwo; 161 | } 162 | pass 163 | { 164 | VertexShader = PostProcessVS; 165 | PixelShader = DilationErosionStepThree; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Shaders/FastBilateral.fx: -------------------------------------------------------------------------------- 1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | // Fast Bilateral Shader ported by Bapho 3 | // Github - https://github.com/Bapho 4 | // ShaderToy - https://www.shadertoy.com/user/Bapho 5 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 | /* 7 | Hyllian's Fast Bilateral Shader 8 | 9 | Source: 10 | https://github.com/libretro/glsl-shaders/blob/master/denoisers/shaders/fast-bilateral.glsl 11 | 12 | Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | THE SOFTWARE. 28 | */ 29 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 30 | 31 | uniform float SIGMA_R < 32 | ui_type = "drag"; 33 | ui_min = 0.01; ui_max = 1.0; 34 | ui_label = "Bilateral Blur"; 35 | > = 0.1; 36 | 37 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 38 | 39 | #include "ReShade.fxh" 40 | 41 | #define BIL(M,K) {col=GET(M,K);ds=M*M+K*K;weight=exp(-ds/sd2)*exp(-(col-center)*(col-center)/si2);color+=(weight*col);wsum+=weight;} 42 | 43 | #define GET(M,K) (tex2D(ReShade::BackBuffer, tc + M * dx + K * dy).xyz) 44 | 45 | float3 FastBilateral(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 46 | { 47 | float ds, sd2, si2; 48 | float sigma_d = 3.0; 49 | float sigma_r = SIGMA_R * 0.04; 50 | 51 | float3 color = float3(0.0, 0.0, 0.0); 52 | float3 wsum = float3(0.0, 0.0, 0.0); 53 | float3 weight; 54 | 55 | float2 dx = float2(1.0, 0.0) * ReShade::PixelSize; 56 | float2 dy = float2(0.0, 1.0) * ReShade::PixelSize; 57 | 58 | sd2 = 2.0 * sigma_d * sigma_d; 59 | si2 = 2.0 * sigma_r * sigma_r; 60 | 61 | float2 tc = texcoord; 62 | 63 | float3 col; 64 | float3 center = GET(0., 0.); 65 | 66 | BIL(-2.,-2.); 67 | BIL(-1.,-2.); 68 | BIL( 0.,-2.); 69 | BIL( 1.,-2.); 70 | BIL( 2.,-2.); 71 | BIL(-2.,-1.); 72 | BIL(-1.,-1.); 73 | BIL( 0.,-1.); 74 | BIL( 1.,-1.); 75 | BIL( 2.,-1.); 76 | BIL(-2., 0.); 77 | BIL(-1., 0.); 78 | BIL( 0., 0.); 79 | BIL( 1., 0.); 80 | BIL( 2., 0.); 81 | BIL(-2., 1.); 82 | BIL(-1., 1.); 83 | BIL( 0., 1.); 84 | BIL( 1., 1.); 85 | BIL( 2., 1.); 86 | BIL(-2., 2.); 87 | BIL(-1., 2.); 88 | BIL( 0., 2.); 89 | BIL( 1., 2.); 90 | BIL( 2., 2.); 91 | 92 | // Weight normalization 93 | color /= wsum; 94 | 95 | return color; 96 | } 97 | 98 | technique FastBilateral 99 | { 100 | pass 101 | { 102 | VertexShader = PostProcessVS; 103 | PixelShader = FastBilateral; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Shaders/LowLife.fx: -------------------------------------------------------------------------------- 1 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | // LowLife by Bapho - https://github.com/Bapho https://www.shadertoy.com/view/3tBGzw 3 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | // Can be used to display a red warning screen when being on low life in a video game with a life bar. 5 | // Please don't use this shader to cheat in a competetive multiplayer game ;) 6 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 | 8 | uniform float red < 9 | ui_type = "slider"; 10 | ui_min = 0.0; ui_max = 1.0; 11 | ui_step = 0.01; 12 | ui_label = " Red amount of warning screen"; 13 | ui_tooltip = "Defines how reddish the triggered warning screen is displayed."; 14 | > = 0.4; 15 | 16 | uniform bool blinkingWarningScreen < 17 | ui_type = "bool"; 18 | ui_label = "Blinking warning screen"; 19 | > = true; 20 | 21 | uniform float horizontalPosLifeCap < 22 | ui_type = "slider"; 23 | ui_min = 0.0; ui_max = 1.0; 24 | ui_step = 0.001; 25 | ui_label = " Horizontal life bar warning positon"; 26 | ui_tooltip = "Triggers the warning screen when this point loses it's reddish color."; 27 | > = 0.05; 28 | 29 | uniform float verticalPosLifeCap < 30 | ui_type = "slider"; 31 | ui_min = 0.0; ui_max = 1.0; 32 | ui_step = 0.001; 33 | ui_label = " Vertical life bar warning positon"; 34 | ui_tooltip = "Triggers the warning screen when this point loses it's reddish color."; 35 | > = 0.86; 36 | 37 | uniform bool enableOneLifePoint < 38 | ui_spacing = 2; 39 | ui_type = "bool"; 40 | ui_label = "Enable false-positive point (close to 1 life)"; 41 | ui_tooltip = "The warning screen will not be triggered when this point is not reddish. Can be used to eliminate false-positives, for example when being in the game menu where no life bar is displayed."; 42 | > = false; 43 | 44 | uniform float horizontalPosOneLife < 45 | ui_type = "slider"; 46 | ui_min = 0.0; ui_max = 1.0; 47 | ui_step = 0.001; 48 | ui_label = " Horizontal posisiton close to 1 life"; 49 | ui_tooltip = "The warning screen will not be triggered when this point is not reddish."; 50 | > = 0.068; 51 | 52 | uniform float verticalPosOneLife < 53 | ui_type = "slider"; 54 | ui_min = 0.0; ui_max = 1.0; 55 | ui_step = 0.001; 56 | ui_label = " Vertical posisiton close to 1 life"; 57 | ui_tooltip = "The warning screen will not be triggered when this point is not reddish."; 58 | > = 0.97; 59 | 60 | uniform bool displayPos < 61 | ui_spacing = 1; 62 | ui_type = "bool"; 63 | ui_label = "Display life bar warning and false-positive points"; 64 | ui_tooltip = "Life bar warning position is displayed red. False-positive point is displayed blue."; 65 | > = true; 66 | 67 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 68 | 69 | #include "ReShade.fxh" 70 | 71 | uniform float2 pingpong < source = "pingpong"; min = 1; max = 2; step = 1; >; 72 | 73 | static const float redCap = 0.25; 74 | static const float greenBlueCap = 0.6; 75 | 76 | float4 LowLife(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 77 | { 78 | float4 color = tex2D(ReShade::BackBuffer, texcoord); 79 | float4 lifeCapColor = tex2D(ReShade::BackBuffer, float2(horizontalPosLifeCap, verticalPosLifeCap)); 80 | float4 oneLifeColor = tex2D(ReShade::BackBuffer, float2(horizontalPosOneLife, verticalPosOneLife)); 81 | 82 | if ((!enableOneLifePoint || (oneLifeColor.r >= redCap && oneLifeColor.g <= greenBlueCap && oneLifeColor.b <= greenBlueCap)) 83 | && (lifeCapColor.r < redCap || lifeCapColor.g > greenBlueCap || lifeCapColor.b > greenBlueCap)) { 84 | 85 | color.r = lerp(color.r, 1.0, red / 2.0 * (blinkingWarningScreen ? pingpong.x : 2.0)); 86 | } 87 | 88 | if (displayPos) { 89 | if (abs(texcoord.x - horizontalPosLifeCap) < 0.002 && abs(texcoord.y - verticalPosLifeCap) < 0.003) { 90 | color = float4(0.0, 1.0, 0.0, 1.0); 91 | 92 | } else if (abs(texcoord.x - horizontalPosOneLife) < 0.002 && abs(texcoord.y - verticalPosOneLife) < 0.003) { 93 | color = float4(0.0, 0.0, 1.0, 1.0); 94 | } 95 | } 96 | 97 | return color; 98 | } 99 | 100 | technique LowLife 101 | { 102 | pass 103 | { 104 | VertexShader = PostProcessVS; 105 | PixelShader = LowLife; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Shaders/LumaSharpen.fx: -------------------------------------------------------------------------------- 1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | // inversed attribution added by Bapho - https://github.com/Bapho https://www.shadertoy.com/user/Bapho 3 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | /** 5 | LumaSharpen version 1.5.0 6 | by Christian Cann Schuldt Jensen ~ CeeJay.dk 7 | 8 | It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image. 9 | It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts. 10 | This is similar to using Unsharp Mask in Photoshop. 11 | 12 | Version 1.5.1 13 | - UI improvements for Reshade 3.x 14 | */ 15 | 16 | #include "ReShadeUI.fxh" 17 | 18 | uniform float sharp_strength < __UNIFORM_SLIDER_FLOAT1 19 | ui_min = 0.1; ui_max = 5.0; 20 | ui_label = "Shapening strength"; 21 | ui_tooltip = "Strength of the sharpening"; 22 | 23 | > = 0.65; 24 | uniform bool inversedAttribution < 25 | ui_label = "Inverse Attribution"; 26 | ui_tooltip = "Activate inverse attribution so that already sharp areas will get less sharpness"; 27 | > = true; 28 | uniform float sharp_clamp < __UNIFORM_SLIDER_FLOAT1 29 | ui_min = 0.0; ui_max = 1.0; ui_step = 0.005; 30 | ui_label = "Sharpening limit"; 31 | ui_tooltip = "Limits maximum amount of sharpening a pixel receives\nThis helps avoid \"haloing\" artifacts which would otherwise occur when you raised the strength too much."; 32 | > = 0.035; 33 | uniform int pattern < 34 | ui_type = "combo"; 35 | ui_items = "Fast" "\0" 36 | "Normal" "\0" 37 | "Wider" "\0" 38 | "Pyramid shaped" "\0"; 39 | ui_label = "Sample pattern"; 40 | ui_tooltip = "Choose a sample pattern.\n" 41 | "Fast is faster but slightly lower quality.\n" 42 | "Normal is normal.\n" 43 | "Wider is less sensitive to noise but also to fine details.\n" 44 | "Pyramid has a slightly more aggresive look."; 45 | > = 1; 46 | uniform float offset_bias < __UNIFORM_SLIDER_FLOAT1 47 | ui_min = 0.0; ui_max = 6.0; 48 | ui_label = "Offset bias"; 49 | ui_tooltip = "Offset bias adjusts the radius of the sampling pattern. I designed the pattern for offset_bias 1.0, but feel free to experiment."; 50 | > = 1.0; 51 | uniform bool show_sharpen < 52 | ui_label = "Show sharpening pattern"; 53 | ui_tooltip = "Visualize the strength of the sharpen\nThis is useful for seeing what areas the sharpning affects the most"; 54 | > = false; 55 | 56 | #include "ReShade.fxh" 57 | 58 | /*-----------------------------------------------------------. 59 | / Developer settings / 60 | '-----------------------------------------------------------*/ 61 | #define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television) 62 | //#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television) 63 | //#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient 64 | 65 | /*-----------------------------------------------------------. 66 | / Main code / 67 | '-----------------------------------------------------------*/ 68 | 69 | float3 LumaSharpenPass(float4 position : SV_Position, float2 tex : TEXCOORD0) : SV_Target 70 | { 71 | // -- Get the original pixel -- 72 | float3 ori = tex2D(ReShade::BackBuffer, tex).rgb; // ori = original pixel 73 | 74 | // -- Combining the strength and luma multipliers -- 75 | float3 sharp_strength_luma = (CoefLuma * sharp_strength); //I'll be combining even more multipliers with it later on 76 | 77 | /*-----------------------------------------------------------. 78 | / Sampling patterns / 79 | '-----------------------------------------------------------*/ 80 | float3 blur_ori; 81 | 82 | // [ NW, , NE ] Each texture lookup (except ori) 83 | // [ ,ori, ] samples 4 pixels 84 | // [ SW, , SE ] 85 | 86 | // -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches. 87 | if (pattern == 0) 88 | { 89 | // -- Gaussian filter -- 90 | // [ 1/9, 2/9, ] [ 1 , 2 , ] 91 | // [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ] 92 | // [ , 2/9, 1/9] [ , 2 , 1 ] 93 | 94 | blur_ori = tex2D(ReShade::BackBuffer, tex + (ReShade::PixelSize / 3.0) * offset_bias).rgb; // North West 95 | blur_ori += tex2D(ReShade::BackBuffer, tex + (-ReShade::PixelSize / 3.0) * offset_bias).rgb; // South East 96 | 97 | //blur_ori += tex2D(ReShade::BackBuffer, tex + (ReShade::PixelSize / 3.0) * offset_bias); // North East 98 | //blur_ori += tex2D(ReShade::BackBuffer, tex + (-ReShade::PixelSize / 3.0) * offset_bias); // South West 99 | 100 | blur_ori /= 2; //Divide by the number of texture fetches 101 | 102 | sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2 103 | } 104 | 105 | // -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches. 106 | if (pattern == 1) 107 | { 108 | // -- Gaussian filter -- 109 | // [ .25, .50, .25] [ 1 , 2 , 1 ] 110 | // [ .50, 1, .50] = [ 2 , 4 , 2 ] 111 | // [ .25, .50, .25] [ 1 , 2 , 1 ] 112 | 113 | blur_ori = tex2D(ReShade::BackBuffer, tex + float2(ReShade::PixelSize.x, -ReShade::PixelSize.y) * 0.5 * offset_bias).rgb; // South East 114 | blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * 0.5 * offset_bias).rgb; // South West 115 | blur_ori += tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * 0.5 * offset_bias).rgb; // North East 116 | blur_ori += tex2D(ReShade::BackBuffer, tex - float2(ReShade::PixelSize.x, -ReShade::PixelSize.y) * 0.5 * offset_bias).rgb; // North West 117 | 118 | blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches 119 | } 120 | 121 | // -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches. 122 | if (pattern == 2) 123 | { 124 | // -- Gaussian filter -- 125 | // [ , 4 , 6 , , ] 126 | // [ ,16 ,24 ,16 , 4 ] 127 | // [ 6 ,24 , ,24 , 6 ] 128 | // [ 4 ,16 ,24 ,16 , ] 129 | // [ , , 6 , 4 , ] 130 | 131 | blur_ori = tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * float2(0.4, -1.2) * offset_bias).rgb; // South South East 132 | blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * float2(1.2, 0.4) * offset_bias).rgb; // West South West 133 | blur_ori += tex2D(ReShade::BackBuffer, tex + ReShade::PixelSize * float2(1.2, 0.4) * offset_bias).rgb; // East North East 134 | blur_ori += tex2D(ReShade::BackBuffer, tex - ReShade::PixelSize * float2(0.4, -1.2) * offset_bias).rgb; // North North West 135 | 136 | blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches 137 | 138 | sharp_strength_luma *= 0.51; 139 | } 140 | 141 | // -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches. 142 | if (pattern == 3) 143 | { 144 | // -- Gaussian filter -- 145 | // [ .50, .50, .50] [ 1 , 1 , 1 ] 146 | // [ .50, , .50] = [ 1 , , 1 ] 147 | // [ .50, .50, .50] [ 1 , 1 , 1 ] 148 | 149 | blur_ori = tex2D(ReShade::BackBuffer, tex + float2(0.5 * ReShade::PixelSize.x, -ReShade::PixelSize.y * offset_bias)).rgb; // South South East 150 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * -ReShade::PixelSize.x, 0.5 * -ReShade::PixelSize.y)).rgb; // West South West 151 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * ReShade::PixelSize.x, 0.5 * ReShade::PixelSize.y)).rgb; // East North East 152 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(0.5 * -ReShade::PixelSize.x, ReShade::PixelSize.y * offset_bias)).rgb; // North North West 153 | 154 | //blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect. 155 | 156 | blur_ori /= 4.0; //Divide by the number of texture fetches 157 | 158 | sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2 159 | } 160 | 161 | /*-----------------------------------------------------------. 162 | / Sharpen / 163 | '-----------------------------------------------------------*/ 164 | 165 | // -- Calculate the sharpening -- 166 | float3 sharp = ori - blur_ori; //Subtracting the blurred image from the original image 167 | 168 | #if 0 //older CeeJay 1.4 code (included here because the new code while faster can be difficult to understand) 169 | 170 | // -- Adjust strength of the sharpening -- 171 | float sharp_luma = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength 172 | 173 | // -- Clamping the maximum amount of sharpening to prevent halo artifacts -- 174 | sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp 175 | 176 | #else //new code 177 | 178 | if (inversedAttribution){ 179 | float3 revert_sharp_strength = (1.01 / (abs(sharp) + 0.01)) / 30.0; 180 | sharp_strength_luma *= revert_sharp_strength; 181 | } 182 | 183 | // -- Adjust strength of the sharpening and clamp it-- 184 | float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp),0.5); //Roll part of the clamp into the dot 185 | 186 | //sharp_luma = saturate((0.5 / sharp_clamp) * sharp_luma + 0.5); //scale up and clamp 187 | float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp)); //Calculate the luma, adjust the strength, scale up and clamp 188 | sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down 189 | #endif 190 | 191 | // -- Combining the values to get the final sharpened pixel -- 192 | float3 outputcolor = ori + sharp_luma; // Add the sharpening to the the original. 193 | 194 | /*-----------------------------------------------------------. 195 | / Returning the output / 196 | '-----------------------------------------------------------*/ 197 | 198 | if (show_sharpen) 199 | { 200 | 201 | float3 normal = tex2D(ReShade::BackBuffer, tex).rgb; 202 | 203 | if (((normal.r > 0.0 && normal.r < 1.0) 204 | || (normal.g > 0.0 && normal.g < 1.0) 205 | || (normal.b > 0.0 && normal.b < 1.0)) 206 | && ((outputcolor.r >= 1.0 && outputcolor.g >= 1.0 && outputcolor.b >= 1.0) 207 | || (outputcolor.r <= 0.0 && outputcolor.g <= 0.0 && outputcolor.b <= 0.0))){ 208 | 209 | outputcolor = float3(1.0, 0.0, 0.0); 210 | } else { 211 | //outputcolor = abs(sharp * 4.0); 212 | outputcolor = saturate(0.5 + (sharp_luma * 4.0)).rrr; 213 | } 214 | } 215 | 216 | return saturate(outputcolor); 217 | } 218 | 219 | technique LumaSharpen 220 | { 221 | pass 222 | { 223 | VertexShader = PostProcessVS; 224 | PixelShader = LumaSharpenPass; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /Shaders/SmartNoise.fx: -------------------------------------------------------------------------------- 1 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 | // SmartNoise by Bapho - https://github.com/Bapho https://www.shadertoy.com/view/3tBGzw 3 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 | // I created this shader because i did not liked the the noise behaviour 5 | // of most shaders. Temporal noise shaders, which are changing the noise 6 | // pattern every frame, are very noticeable when the "image isn't moving". 7 | // Fixed pattern noise shaders, which are never changing the noise pattern, 8 | // are very noticeable when the "image is moving". So i was searching a way 9 | // to bypass those disadvantages. I used the unique position of the current 10 | // texture in combination with the color and depth to get a unique seed 11 | // for the noise function. The result is a noise pattern that is only 12 | // changing when the color or depth of the position is changing. 13 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 | 15 | static const float PHI = 1.61803398874989484820459 * 00000.1; // Golden Ratio 16 | static const float PI = 3.14159265358979323846264 * 00000.1; // PI 17 | static const float SQ2 = 1.41421356237309504880169 * 10000.0; // Square Root of Two 18 | static const float SAT = 0.33333333333333333333334; 19 | static const int TYPE_MIXED = 0; 20 | static const int TYPE_GOLDEN = 1; 21 | static const int TYPE_BLUE = 2; 22 | 23 | uniform float noise < 24 | ui_type = "drag"; 25 | ui_min = 0.0; ui_max = 4.0; 26 | ui_step = 0.2; 27 | ui_label = "Amount of noise"; 28 | > = 1.0; 29 | 30 | uniform int type < 31 | ui_type = "combo"; 32 | ui_label = "Noise type"; 33 | ui_items = "Mixed\0Dynamic golden noise\0Fixed blue noise\0"; 34 | > = TYPE_MIXED; 35 | 36 | uniform float balance < 37 | ui_type = "drag"; 38 | ui_min = 1.0; ui_max = 6.0; 39 | ui_step = 0.1; 40 | ui_label = "Mix (golden - blue)"; 41 | > = 4.0; 42 | 43 | uniform bool compensateSaturation < 44 | ui_type = "bool"; 45 | ui_label = "Compensate saturation"; 46 | > = true; 47 | 48 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 49 | 50 | #include "ReShade.fxh" 51 | 52 | texture texBlueNoise < source = "bapho_blue_noise.png"; > { Width = 256; Height = 256; Format = RGBA8; }; 53 | sampler samplerBlueNoise { Texture = texBlueNoise; }; 54 | 55 | float gold_noise(float2 coordinate, float seed){ 56 | return frac(tan(distance(coordinate*(seed+PHI), float2(PHI, PI)))*SQ2); 57 | } 58 | 59 | float getLuminance( in float3 x ) 60 | { 61 | return dot( x, float3( 0.212656, 0.715158, 0.072186 )); 62 | } 63 | 64 | float3 sat( float3 res, float x ) 65 | { 66 | return min( lerp( getLuminance( res.xyz ), res.xyz, x + 1.0f ), 1.0f ); 67 | } 68 | 69 | float4 SmartNoise(float4 pos : SV_Position, float2 texcoord : TEXCOORD0) : SV_Target 70 | { 71 | float amount = noise * 0.08; 72 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 73 | 74 | // the luminance/brightness 75 | float luminance = (0.2126 * color.r) + (0.7152 * color.g) + (0.0722 * color.b); 76 | 77 | // calculating a unique position 78 | float uniquePos = ((ReShade::ScreenSize.x * pos.y) + pos.x) * 0.001; 79 | 80 | // depth is also used 81 | float depthSeed = ReShade::GetLinearizedDepth(texcoord) * ReShade::ScreenSize.y; 82 | 83 | // adjusting "noise contrast" 84 | if (luminance < 0.5){ 85 | amount *= (luminance / 0.5); 86 | } else { 87 | amount *= ((1.0 - luminance) / 0.5); 88 | } 89 | 90 | // reddish pixels will get less noise 91 | float redDiff = color.r - ((color.g + color.b) / 2.0); 92 | if (redDiff > 0.0){ 93 | amount *= (1.0 - (redDiff * 0.5)); 94 | } 95 | 96 | // a very low unique seed will lead to slow noise pattern changes on slow moving color gradients 97 | float uniqueSeed = ((luminance * ReShade::ScreenSize.y) + uniquePos + depthSeed) * 98 | 0.0001; 99 | //0.00000000500001; 100 | 101 | // using a fictive coordinate as a workaround to fix a pattern bug 102 | float2 coordinate = float2(pos.x, pos.y * 1.001253543); 103 | 104 | // average noise luminance to subtract 105 | float sub = (0.5 * amount); 106 | float add; 107 | float ran; 108 | 109 | // "noise clipping" 110 | if (luminance - sub < 0.0){ 111 | amount *= (luminance / sub); 112 | sub *= (luminance / sub); 113 | } else if (luminance + sub > 1.0){ 114 | if (luminance > sub){ 115 | amount *= (sub / luminance); 116 | sub *= (sub / luminance); 117 | } else { 118 | amount *= (luminance / sub); 119 | sub *= (luminance / sub); 120 | } 121 | } 122 | 123 | // calculating and adding/subtracting the golden noise 124 | if (type != TYPE_BLUE) { 125 | ran = gold_noise(coordinate, uniqueSeed); 126 | float div = type == 1 ? 1 : balance; 127 | add = saturate(ran * amount / div); 128 | color.rgb += (add - sub / div); 129 | } 130 | 131 | // calculating and adding/subtracting the blue noise 132 | if (type != TYPE_GOLDEN) { 133 | int blueNoiseX = (texcoord.x * BUFFER_WIDTH) % 256; 134 | int blueNoiseY = (texcoord.y * BUFFER_HEIGHT) % 256; 135 | color.rgb += (tex2Dfetch(samplerBlueNoise, int2(blueNoiseX, blueNoiseY)).rgb * amount.rrr - sub.rrr); 136 | } 137 | 138 | // compensating the saturation since the noise is luma noise 139 | if (compensateSaturation) { 140 | color.rgb = sat(color.rgb, SAT * amount); 141 | } 142 | 143 | return float4(color, 1.0); 144 | } 145 | 146 | technique SmartNoise 147 | { 148 | pass 149 | { 150 | VertexShader = PostProcessVS; 151 | PixelShader = SmartNoise; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Shaders/VHSPro.fx: -------------------------------------------------------------------------------- 1 | /* 2 | VHS Pro by Vladmir Storm 3 | 4 | Ported by Marty McFly and Matsilagi 5 | 6 | Updated for ReShade 4+ by Marot Satil and Bapho 7 | */ 8 | 9 | #include "ReShade.fxh" 10 | 11 | uniform float screenLinesNum < 12 | ui_type = "slider"; 13 | ui_min = 1.0; 14 | ui_max = (float)BUFFER_HEIGHT; 15 | ui_label = "Screen Resolution [VHSPro]"; 16 | ui_tooltip = "Screen Resolution (in lines).\nChange screenLinesRes in Preprocessor Definitions to have the same value as this."; 17 | > = (float)BUFFER_HEIGHT; 18 | 19 | uniform bool VHS_Bleed < 20 | ui_label = "Bleeding [VHSPro]"; 21 | ui_tooltip = "Enables beam screen bleeding (makes the image blurry)."; 22 | > = true; 23 | 24 | uniform int VHS_BleedMode < 25 | ui_type = "combo"; 26 | ui_items = "Three Phase\0Old Three Phase\0Two Phase (slow)\0Three-Phase (RetroArch)\0Two Phase (RetroArch)\0"; 27 | ui_label = "Bleeding Mode [VHSPro]"; 28 | ui_tooltip = "Toggles between different bleeding modes."; 29 | > = 0; 30 | 31 | uniform float bleedAmount < 32 | ui_type = "slider"; 33 | ui_min = 0.0; 34 | ui_max = 15.0; 35 | ui_label = "Bleed Stretch [VHSPro]"; 36 | ui_tooltip = "Length of the bleeding."; 37 | > = 1.0; 38 | 39 | uniform bool VHS_FishEye < 40 | ui_label = "Fisheye [VHSPro]"; 41 | ui_tooltip = "Enables a CRT Curvature."; 42 | > = true; 43 | 44 | uniform bool VHS_FishEye_Hyperspace < 45 | ui_label = "Fisheye Hyperspace [VHSPro]"; 46 | ui_tooltip = "Changes the curvature to look like some sort of hyperspace warping."; 47 | > = false; 48 | 49 | uniform float fisheyeBend < 50 | ui_type = "slider"; 51 | ui_min = 0.0; 52 | ui_max = 50.0; 53 | ui_label = "Fisheye Bend [VHSPro]"; 54 | ui_tooltip = "Curvature of the CRT."; 55 | > = 2.0; 56 | 57 | uniform float cutoffX < 58 | ui_type = "slider"; 59 | ui_min = 0.0; 60 | ui_max = 50.0; 61 | ui_label = "Fisheye Cutoff X [VHSPro]"; 62 | ui_tooltip = "Cutoff of the Horizontal Borders."; 63 | > = 2.0; 64 | 65 | uniform float cutoffY < 66 | ui_type = "slider"; 67 | ui_min = 0.0; 68 | ui_max = 50.0; 69 | ui_label = "Fisheye Cutoff Y [VHSPro]"; 70 | ui_tooltip = "Cutoff of the Vertical Borders."; 71 | > = 3.0; 72 | 73 | uniform float cutoffFadeX < 74 | ui_type = "slider"; 75 | ui_min = 0.0; 76 | ui_max = 50.0; 77 | ui_label = "Fisheye Cutoff Fade X [VHSPro]"; 78 | ui_tooltip = "Size of the Horizontal gradient cutoff."; 79 | > = 25.0; 80 | 81 | uniform float cutoffFadeY < 82 | ui_type = "slider"; 83 | ui_min = 0.0; 84 | ui_max = 50.0; 85 | ui_label = "Fisheye Cutoff Fade Y [VHSPro]"; 86 | ui_tooltip = "Size of the Vertical gradient cutoff."; 87 | > = 25.0; 88 | 89 | uniform bool VHS_Vignette < 90 | ui_type = "bool"; 91 | ui_label = "Vignette [VHSPro]"; 92 | ui_tooltip = "Enables screen vignetting"; 93 | > = false; 94 | 95 | uniform float vignetteAmount < 96 | ui_type = "slider"; 97 | ui_min = 0.0; 98 | ui_max = 5.0; 99 | ui_label = "Vignette Amount [VHSPro]"; 100 | ui_tooltip = "Strength of the vignette."; 101 | > = 1.0; 102 | 103 | uniform float vignetteSpeed < 104 | ui_type = "slider"; 105 | ui_min = 0.0; 106 | ui_max = 5.0; 107 | ui_label = "Vignette Pulse Speed [VHSPro]"; 108 | ui_tooltip = "Speed of the vignette pulsing. (Setting it to 0 makes it stop pulsing)"; 109 | > = 1.0; 110 | 111 | uniform float noiseLinesNum < 112 | ui_type = "slider"; 113 | ui_min = 1.0; 114 | ui_max = (float)BUFFER_HEIGHT; 115 | ui_label = "Vertical Resolution [VHSPro]"; 116 | ui_tooltip = "Noise Resolution (in lines).\nChange noiseLinesRes in Preprocessor Definitions to have the same value as this."; 117 | > = 240.0; 118 | 119 | uniform float noiseQuantizeX < 120 | ui_type = "slider"; 121 | ui_min = 0.0; 122 | ui_max = 1.0; 123 | ui_label = "Quantize Noise X [VHSPro]"; 124 | ui_tooltip = "Makes the noise longer or shorter."; 125 | > = 0.0; 126 | 127 | uniform bool VHS_FilmGrain < 128 | ui_label = "Film Grain [VHSPro]"; 129 | ui_tooltip = "Enables a Film Grain on the screen."; 130 | > = false; 131 | 132 | uniform float filmGrainAmount < 133 | ui_type = "slider"; 134 | ui_min = 0.0; 135 | ui_max = 0.1; 136 | ui_label = "Film Grain Alpha [VHSPro]"; 137 | ui_tooltip = "Intensity of the Film Grain."; 138 | > = 0.016; 139 | 140 | uniform bool VHS_YIQNoise < 141 | ui_label = "Signal Noise [VHSPro]"; 142 | ui_tooltip = "Adds noise to the YIQ Signal, causing a Pink (or green) noise."; 143 | > = true; 144 | 145 | uniform int signalNoiseType < 146 | ui_type = "combo"; 147 | ui_items = "Type 1\0Type 2\0Type 3\0"; 148 | ui_label = "Signal Noise Type [VHS Pro]"; 149 | > = 0; 150 | 151 | uniform float signalNoiseAmount < 152 | ui_type = "slider"; 153 | ui_min = 0.0; 154 | ui_max = 1.0; 155 | ui_label = "Signal Noise Amount [VHSPro]"; 156 | ui_tooltip = "Amount of the signal noise."; 157 | > = 0.15; 158 | 159 | uniform float signalNoisePower < 160 | ui_type = "slider"; 161 | ui_min = 0.0; 162 | ui_max = 1.0; 163 | ui_label = "Signal Noise Power [VHSPro]"; 164 | ui_tooltip = "Power of the signal noise. Higher values will make it green, lower values will make it more pink."; 165 | > = 0.83; 166 | 167 | uniform bool VHS_LineNoise < 168 | ui_label = "Line Noise [VHSPro]"; 169 | ui_tooltip = "Enables blinking line noise in the image."; 170 | > = true; 171 | 172 | uniform float lineNoiseAmount < 173 | ui_type = "slider"; 174 | ui_min = 0.0; 175 | ui_max = 10.0; 176 | ui_label = "Line Noise Amount [VHSPro]"; 177 | ui_tooltip = "Intensity of the line noise."; 178 | > = 1.0; 179 | 180 | uniform float lineNoiseSpeed < 181 | ui_type = "slider"; 182 | ui_min = 0.0; 183 | ui_max = 10.0; 184 | ui_label = "Line Noise Speed [VHSPro]"; 185 | ui_tooltip = "Speed of the line noise blinking delay."; 186 | > = 5.0; 187 | 188 | uniform bool VHS_TapeNoise < 189 | ui_label = "Tape Noise [VHSPro]"; 190 | ui_tooltip = "Adds scrolling noise like in old VHS Tapes."; 191 | > = true; 192 | 193 | uniform float tapeNoiseTH < 194 | ui_type = "slider"; 195 | ui_min = 0.0; 196 | ui_max = 1.5; 197 | ui_label = "Tape Noise Amount [VHSPro]"; 198 | ui_tooltip = "Intensity of Tape Noise in the image."; 199 | > = 0.63; 200 | 201 | uniform float tapeNoiseAmount < 202 | ui_type = "slider"; 203 | ui_min = 0.0; 204 | ui_max = 1.5; 205 | ui_label = "Tape Noise Alpha [VHSPro]"; 206 | ui_tooltip = "Amount of Tape Noise in the image."; 207 | > = 0.05; 208 | 209 | uniform float tapeNoiseSpeed < 210 | ui_type = "slider"; 211 | ui_min = -1.5; 212 | ui_max = 1.5; 213 | ui_label = "Tape Noise Speed [VHSPro]"; 214 | ui_tooltip = "Scrolling speed of the Tape Noise."; 215 | > = 1.0; 216 | 217 | uniform bool VHS_ScanLines < 218 | ui_label = "Scanlines [VHSPro]"; 219 | ui_tooltip = "Enables TV/CRT Scanlines"; 220 | > = false; 221 | 222 | uniform float scanLineWidth < 223 | ui_type = "slider"; 224 | ui_min = 0.0; 225 | ui_max = 20.0; 226 | ui_label = "Scanlines Width [VHSPro]"; 227 | ui_tooltip = "Width of the Scanlines"; 228 | > = 10.0; 229 | 230 | uniform bool VHS_LinesFloat < 231 | ui_label = "Lines Float [VHSPro]"; 232 | ui_tooltip = "Makes the lines of the screen floats up or down. Works best with low Screen Lines resolutions."; 233 | > = false; 234 | 235 | uniform float linesFloatSpeed < 236 | ui_type = "slider"; 237 | ui_min = -3.0; 238 | ui_max = 3.0; 239 | ui_label = "Lines Float Speed [VHSPro]"; 240 | ui_tooltip = "Speed (and direction) of the floating lines."; 241 | > = 1.0; 242 | 243 | uniform bool VHS_Stretch < 244 | ui_label = "Stretch Noise [VHSPro]"; 245 | ui_tooltip = "Enables a stretching noise that scrolls up and down on the Image, simulating magnetic interference of VHS tapes."; 246 | > = true; 247 | 248 | uniform bool VHS_Jitter_H < 249 | ui_type = "bool"; 250 | ui_label = "Interlacing [VHSPro]"; 251 | ui_tooltip = "Enables Interlacing."; 252 | > = true; 253 | 254 | uniform float jitterHAmount < 255 | ui_type = "slider"; 256 | ui_min = 0.0; 257 | ui_max = 5.0; 258 | ui_label = "Interlacing Amount [VHSPro]"; 259 | ui_tooltip = "Strength of the Interlacing."; 260 | > = 0.5; 261 | 262 | uniform bool VHS_Jitter_V < 263 | ui_label = "Jitter [VHSPro]"; 264 | ui_tooltip = "Adds vertical jittering noise."; 265 | > = false; 266 | 267 | uniform float jitterVAmount < 268 | ui_type = "slider"; 269 | ui_min = 0.0; 270 | ui_max = 15.0; 271 | ui_label = "Jitter Amount [VHSPro]"; 272 | ui_tooltip = "Amount of the vertical jittering noise."; 273 | > = 1.0; 274 | 275 | uniform float jitterVSpeed < 276 | ui_type = "slider"; 277 | ui_min = 0.0; 278 | ui_max = 5.0; 279 | ui_label = "Jitter Speed [VHSPro]"; 280 | ui_tooltip = "Speed of the vertical jittering noise."; 281 | > = 1.0; 282 | 283 | uniform bool VHS_Twitch_H < 284 | ui_label = "Horizontal Twitch [VHSPro]"; 285 | ui_tooltip = "Makes the image twitches horizontally in certain timed intervals."; 286 | > = false; 287 | 288 | uniform float twitchHFreq < 289 | ui_type = "slider"; 290 | ui_min = 0.0; 291 | ui_max = 5.0; 292 | ui_label = "Horizontal Twitch Frequency [VHSPro]"; 293 | ui_tooltip = "Frequency of time in which the image twitches horizontally."; 294 | > = 1.0; 295 | 296 | uniform bool VHS_Twitch_V < 297 | ui_label = "Vertical Twitch [VHSPro]"; 298 | ui_tooltip = "Makes the image twitches vertically in certain timed intervals."; 299 | > = false; 300 | 301 | uniform float twitchVFreq < 302 | ui_type = "slider"; 303 | ui_min = 0.0; 304 | ui_max = 5.0; 305 | ui_label = "Vertical Twitch Frequency [VHSPro]"; 306 | ui_tooltip = "Frequency of time in which the image twitches vertically."; 307 | > = 1.0; 308 | 309 | uniform bool VHS_SignalTweak < 310 | ui_label = "Signal Tweak [VHSPro]"; 311 | ui_tooltip = "Tweak the values of the YIQ signal."; 312 | > = false; 313 | 314 | uniform float signalAdjustY < 315 | ui_type = "slider"; 316 | ui_min = -0.25; 317 | ui_max = 0.25; 318 | ui_label = "Signal Shift Y [VHSPro]"; 319 | ui_tooltip = "Shifts/Tweaks the Luma part of the signal."; 320 | > = 0.0; 321 | uniform float signalAdjustI < 322 | ui_type = "slider"; 323 | ui_min = -0.25; 324 | ui_max = 0.25; 325 | ui_label = "Signal Shift I [VHSPro]"; 326 | ui_tooltip = "Shifts/Tweaks the Chroma part of the signal."; 327 | > = 0.0; 328 | 329 | uniform float signalAdjustQ < 330 | ui_type = "slider"; 331 | ui_min = -0.25; 332 | ui_max = 0.25; 333 | ui_label = "Signal Shift Q [VHSPro]"; 334 | ui_tooltip = "Shifts/Tweaks the Chroma part of the signal."; 335 | > = 0.0; 336 | 337 | uniform float signalShiftY < 338 | ui_type = "slider"; 339 | ui_min = -2.0; 340 | ui_max = 2.0; 341 | ui_label = "Signal Adjust Y [VHSPro]"; 342 | ui_tooltip = "Adjusts the Luma part of the signal."; 343 | > = 1.0; 344 | 345 | uniform float signalShiftI < 346 | ui_type = "slider"; 347 | ui_min = -2.0; 348 | ui_max = 2.0; 349 | ui_label = "Signal Adjust I [VHSPro]"; 350 | ui_tooltip = "Adjusts the Chroma part of the signal."; 351 | > = 1.0; 352 | 353 | uniform float signalShiftQ < 354 | ui_type = "slider"; 355 | ui_min = -2.0; 356 | ui_max = 2.0; 357 | ui_label = "Signal Adjust Q [VHSPro]"; 358 | ui_tooltip = "Adjusts the Chroma part of the signal."; 359 | > = 1.0; 360 | 361 | uniform float gammaCorection < 362 | ui_type = "slider"; 363 | ui_min = 0.0; 364 | ui_max = 2.0; 365 | ui_label = "Signal Gamma Correction [VHSPro]"; 366 | ui_tooltip = "Gamma corrects the image."; 367 | > = 1.0; 368 | 369 | uniform bool VHS_Feedback < 370 | ui_label = "Phosphor Trails [VHSPro]"; 371 | ui_tooltip = "Enables phosphor-trails from old CRT monitors."; 372 | > = false; 373 | 374 | uniform float feedbackAmount < 375 | ui_type = "slider"; 376 | ui_min = 0.0; 377 | ui_max = 3.0; 378 | ui_label = "Input Amount [VHSPro]"; 379 | ui_tooltip = "Amount of Phosphor Trails."; 380 | > = 2.0; 381 | 382 | uniform float feedbackFade < 383 | ui_type = "slider"; 384 | ui_min = 0.0; 385 | ui_max = 1.0; 386 | ui_label = "Phosphor Fade [VHSPro]"; 387 | ui_tooltip = "Fade-time of the phosphor-trails."; 388 | > = 0.82; 389 | 390 | uniform float feedbackThresh < 391 | ui_type = "slider"; 392 | ui_min = 0.0; 393 | ui_max = 1.0; 394 | ui_label = "Input Cutoff [VHSPro]"; 395 | ui_tooltip = "Cutoff of the trail."; 396 | > = 0.1; 397 | 398 | uniform float3 feedbackColor < 399 | ui_type = "color"; 400 | ui_label = "Phosphor Trail Color [VHSPro]"; 401 | ui_tooltip = "Color of the trail."; 402 | > = float3(1.0,0.5,0.0); 403 | 404 | uniform bool feedbackDebug < 405 | ui_type = "bool"; 406 | ui_label = "Debug Trail [VHS Pro]"; 407 | ui_tooltip = "Enables the visualization of the phosphor-trails only."; 408 | > = false; 409 | 410 | uniform int VHS_Filter < 411 | ui_type = "slider"; 412 | ui_min = 0.0; 413 | ui_max = 0.0; 414 | ui_label = "Linear Filtering [VHSPro]"; 415 | ui_tooltip = "Filters the image linearly, increasing quality.\nDefine VHSLINEARFILTER in Preprocessor Definitions to take effect, this is only here as a reminder."; 416 | > = 0.0; 417 | 418 | //textures and samplers 419 | #ifndef screenLinesRes 420 | #define screenLinesRes BUFFER_HEIGHT //Screen Resolution (to use in _TapeTex, has to be the same as screenLinesNum) 421 | #endif 422 | 423 | #ifndef noiseLinesRes 424 | #define noiseLinesRes 240.0 //Vertical Resolution (to use in _TapeTex, has to be the same as noiseLinesNum) 425 | #endif 426 | 427 | #ifdef VHSLINEARFILTER 428 | #define VHSFILTERMODE LINEAR 429 | #else 430 | #define VHSFILTERMODE POINT 431 | #endif 432 | 433 | static const float fisheyeSize = 1.2; //Size (DO NOT CHANGE) 434 | static const float filmGrainPower = 1.0; //Film Grain Power (DO NOT CHANGE) 435 | static const float feedbackAmp = 1.0; //Feedback Amp (DO NOT CHANGE) 436 | 437 | #define _ScreenParams float2(BUFFER_WIDTH, BUFFER_HEIGHT) 438 | #undef PixelSize 439 | #define PixelSize float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT) 440 | uniform float Timer < source = "timer"; >; 441 | 442 | static const float Pi2 = 6.283185307; 443 | 444 | #define TEXHEIGHT int(noiseLinesRes) 445 | #define TEXWIDTH int(((float)TEXHEIGHT*(float)BUFFER_WIDTH/(float)BUFFER_HEIGHT)) 446 | 447 | texture2D VHS_InputTexA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; }; 448 | texture2D VHS_InputTexB { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; }; 449 | texture2D VHS_FeedbackTexA { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; }; 450 | texture2D VHS_FeedbackTexB { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; }; 451 | texture2D _TapeTex { Width = TEXWIDTH; Height = TEXHEIGHT; Format = RGBA8; }; 452 | 453 | sampler2D SamplerColorVHS 454 | { 455 | Texture = ReShade::BackBufferTex; 456 | MinFilter = VHSFILTERMODE; 457 | MagFilter = VHSFILTERMODE; 458 | MipFilter = VHSFILTERMODE; 459 | AddressU = Clamp; 460 | AddressV = Clamp; 461 | }; 462 | 463 | sampler2D SamplerTape 464 | { 465 | Texture = _TapeTex; 466 | MinFilter = POINT; 467 | MagFilter = POINT; 468 | MipFilter = POINT; 469 | AddressU = Clamp; 470 | AddressV = Clamp; 471 | }; 472 | 473 | sampler2D VHS_InputA { Texture = VHS_InputTexA; MinFilter = VHSFILTERMODE; MagFilter = VHSFILTERMODE; MipFilter = VHSFILTERMODE; }; 474 | sampler2D VHS_InputB { Texture = VHS_InputTexB; MinFilter = VHSFILTERMODE; MagFilter = VHSFILTERMODE; MipFilter = VHSFILTERMODE; }; 475 | sampler2D VHS_FeedbackA { Texture = VHS_FeedbackTexA; MinFilter = VHSFILTERMODE; MagFilter = VHSFILTERMODE; MipFilter = VHSFILTERMODE; }; 476 | sampler2D _FeedbackTex { Texture = VHS_FeedbackTexB; MinFilter = VHSFILTERMODE; MagFilter = VHSFILTERMODE; MipFilter = VHSFILTERMODE; }; 477 | 478 | //functions 479 | 480 | #define PI 3.14159265359 481 | static const float3 MOD3 = float3(443.8975, 397.2973, 491.1871); 482 | 483 | float fmod(float a, float b) { 484 | const float c = frac(abs(a / b)) * abs(b); 485 | if (a < 0) 486 | return -c; 487 | else 488 | return c; 489 | } 490 | 491 | float3 bms(float3 c1, float3 c2){ return 1.0- (1.0-c1)*(1.0-c2); } 492 | 493 | //turns sth on and off //a - how often 494 | float onOff(float a, float b, float c, float t) 495 | { 496 | return step(c, sin(t + a*cos(t*b))); 497 | } 498 | 499 | float hash( float n ){ return frac(sin(n)*43758.5453123); } 500 | 501 | float hash12(float2 p){ 502 | float3 p3 = frac(float3(p.xyx) * MOD3); 503 | p3 += dot(p3, p3.yzx + 19.19); 504 | return frac(p3.x * p3.z * p3.y); 505 | } 506 | 507 | float2 hash22(float2 p) { 508 | float3 p3 = frac(float3(p.xyx) * MOD3); 509 | p3 += dot(p3.zxy, p3.yzx+19.19); 510 | return frac(float2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); 511 | } 512 | 513 | //random hash 514 | float4 hash42(float2 p) 515 | { 516 | float4 p4 = frac(float4(p.xyxy) * float4(443.8975,397.2973, 491.1871, 470.7827)); 517 | p4 += dot(p4.wzxy, p4 + 19.19); 518 | return frac(float4(p4.x * p4.y, p4.x*p4.z, p4.y*p4.w, p4.x*p4.w)); 519 | } 520 | 521 | float niq( in float3 x ){ 522 | const float3 p = floor(x); 523 | float3 f = frac(x); 524 | f = f*f*(3.0-2.0*f); 525 | const float n = p.x + p.y*57.0 + 113.0*p.z; 526 | return lerp(lerp( lerp( hash(n+ 0.0), hash(n+ 1.0),f.x), 527 | lerp( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y), 528 | lerp( lerp( hash(n+113.0), hash(n+114.0),f.x), 529 | lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); 530 | } 531 | 532 | float filmGrain(float2 uv, float t, float c ) 533 | { 534 | //cheap noise - is ok atm 535 | return pow(hash12( uv + 0.07*frac( t ) ), 3); 536 | } 537 | 538 | float2 n4rand_bw( float2 p, float t, float c ) 539 | { 540 | t = frac( t );//that's why its sort of twitching 541 | float2 nrnd0 = hash22( p + 0.07*t ); 542 | c = 1.0 / (10.0*c); //iMouse.y / iResolution.y 543 | return pow(nrnd0, c); //TODO try to invert 1-... 544 | } 545 | 546 | float scanLines(float2 p, float t) 547 | { 548 | 549 | //cheap (maybe make an option later) 550 | // float scanLineWidth = 0.26; 551 | // float scans = 0.5*(cos((p.y*screenLinesNum+t+.5)*2.0*PI) + 1.0); 552 | // if(scans>scanLineWidth) scans = 1.; else scans = 0.; 553 | 554 | float t_sl = 0.0; 555 | //if lines aren't floating -> scanlines also shudn't 556 | if (VHS_LinesFloat) { 557 | t_sl = t*linesFloatSpeed; 558 | } 559 | 560 | //expensive but better 561 | float scans = 0.5*(cos( (p.y*screenLinesNum+t_sl)*2.0*PI) + 1.0); 562 | scans = pow(scans, scanLineWidth); 563 | return 1.0 - scans; 564 | } 565 | 566 | float gcos(float2 uv, float s, float p) 567 | { 568 | return (cos( uv.y * PI * 2.0 * s + p)+1.0)*0.5; 569 | } 570 | 571 | //mw - maximum width 572 | //wcs = widthChangeSpeed 573 | //lfs = line float speed = .5 574 | //lf phase = line float phase = .0 575 | float2 stretch(float2 uv, float t, float mw, float wcs, float lfs, float lfp){ 576 | 577 | const float SLN = screenLinesNum; //TODO use only SLN 578 | //width change 579 | const float tt = t*wcs; //widthChangeSpeed 580 | const float t2 = tt-fmod(tt, 0.5); 581 | 582 | //float dw = hash42( vec2(0.01, t2) ).x ; //on t and not on y 583 | float w = gcos(uv, 2.0*(1.0-frac(t2)), PI-t2) * clamp( gcos(uv, frac(t2), t2) , 0.5, 1.0); 584 | //w = clamp(w,0.,1.); 585 | w = floor(w*mw)/mw; 586 | w *= mw; 587 | //get descreete line number 588 | float ln = (1.0-frac(t*lfs + lfp)) *screenLinesNum; 589 | ln = ln - frac(ln); 590 | // float ln = (1.-fmod(t*lfs + lfp, 1.))*SLN; 591 | // ln = ln - fmod(ln, 1.); //descreete line number 592 | 593 | //ln = 10.; 594 | //w = 4.; 595 | 596 | //////stretching part/////// 597 | 598 | const float oy = 1.0/SLN; //TODO global 599 | const float sh2 = 1.0 - fmod(ln, w)/w; // shift 0..1 600 | 601 | // #if VHS_LINESFLOAT_ON 602 | // float sh = fmod(t, 1.); 603 | // uv.y = floor( uv.y *SLN +sh )/SLN - sh/SLN; 604 | // #else 605 | // uv.y = floor( uv.y *SLN )/SLN; 606 | // #endif 607 | 608 | // uv.y = floor( uv.y *SLN )/SLN ; 609 | 610 | const float slb = SLN / w; //screen lines big 611 | 612 | //TODO finish 613 | // #if VHS_LINESFLOAT_ON 614 | 615 | // if(uv.yoy*(ln-w)) ////if(uv.y>oy*ln && uv.yoy*(ln-w)) ////if(uv.y>oy*ln && uv.y 0.0) bind = sqrt(dot(m, m));//stick to corners 780 | else {if (prop < 1.0) bind = m.x; else bind = m.x;}//stick to borders 781 | 782 | if (power > 0.0) //fisheye 783 | uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power); 784 | else if (power < 0.0) //antifisheye 785 | uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0); 786 | else uv = (uv*_ScreenParams.xy) /_ScreenParams.x; 787 | 788 | uv.y *= prop; 789 | } 790 | 791 | //adjust size 792 | // uv -= float2(0.5,0.5); 793 | // uv *= size; 794 | // uv += float2(0.5,0.5); 795 | 796 | return uv; 797 | } 798 | 799 | //pulse vignette 800 | float vignette(float2 uv, float t) 801 | { 802 | const float vigAmt = 2.5+0.1*sin(t + 5.0*cos(t*5.0)); 803 | float c = (1.0-vigAmt*(uv.y-0.5)*(uv.y-0.5))*(1.0-vigAmt*(uv.x-0.5)*(uv.x-0.5)); 804 | c = pow(abs(c), vignetteAmount); //expensive! 805 | return c; 806 | } 807 | 808 | float3 t2d(float2 p) 809 | { 810 | return rgb2yiq( tex2D (SamplerColorVHS, p ).rgb ); 811 | } 812 | 813 | float3 yiqDist(float2 uv, float m, float t) 814 | { 815 | m *= 0.0001; // float m = 0.0009; 816 | float3 offsetX = float3( uv.x, uv.x, uv.x ); 817 | 818 | offsetX.r += rnd_rd(float2(t*0.03, uv.y*0.42)) * 0.001 + sin(rnd_rd(float2(t*0.2, uv.y)))*m; 819 | offsetX.g += rnd_rd(float2(t*0.004,uv.y*0.002)) * 0.004 + sin(t*9.0)*m; 820 | // offsetX.b = uv.y + rnd_rd(float2(cos(t*0.01),sin(uv.y)))*m; 821 | // offsetX.b = uv.y + rand_rd(float2(cos(t*0.01),sin(uv.y)))*m; 822 | 823 | float3 signal = float3(0.0, 0.0, 0.0); 824 | //it cud be optimized / but hm 825 | signal.x = rgb2yiq( tex2D( SamplerColorVHS, float2(offsetX.r, uv.y) ).rgb ).x; 826 | signal.y = rgb2yiq( tex2D( SamplerColorVHS, float2(offsetX.g, uv.y) ).rgb ).y; 827 | signal.z = rgb2yiq( tex2D( SamplerColorVHS, float2(offsetX.b, uv.y) ).rgb ).z; 828 | 829 | // signal = yiq2rgb(col); 830 | return signal; 831 | } 832 | 833 | #define fixCoord (p - float2( 0.5 * PixelSize.x, .0)) 834 | #define fetch_offset(offset, one_x) t2d(fixCoord + float2( (offset) * (ONE_X), 0.0)); 835 | 836 | /////////////////////////PIXEL SHADERS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 837 | /////////////////////////PIXEL SHADERS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 838 | 839 | float4 PS_VHS1(float4 pos : SV_Position, float2 txcoord : TEXCOORD) : SV_Target 840 | { 841 | const float t = Timer.x * 0.001;//_Time.y; 842 | float2 p = txcoord.xy; 843 | 844 | float SLN = screenLinesNum; //TODO use only SLN 845 | float SLN_Noise = noiseLinesNum; //TODO only SLN_Noise 846 | float ONE_X = 0.0; 847 | float ONE_Y = 0.0; 848 | 849 | //basically if its 0 -> set it to fullscreen 850 | //TODO calc it before shader / already float done 851 | SLN = screenLinesNum; //TODO use only SLN 852 | SLN_Noise = noiseLinesNum; //TODO only SLN_Noise 853 | if(SLN==0.0) SLN = _ScreenParams.y; 854 | 855 | if(SLN_Noise==0 || SLN_Noise>SLN) SLN_Noise = SLN; 856 | 857 | ONE_X = 1.0/_ScreenParams.x; //assigning works only here 858 | ONE_Y = 1.0/_ScreenParams.y; 859 | 860 | 861 | if (VHS_Twitch_V){ 862 | p = twitchVertical(0.5*twitchVFreq, p, t); 863 | } 864 | 865 | if (VHS_Twitch_H){ 866 | p = twitchHorizonal(0.1*twitchHFreq, p, t); 867 | } 868 | 869 | //make discrete lines /w or wo float 870 | if(VHS_LinesFloat){ 871 | float sh = frac(-t*linesFloatSpeed); //shift // float sh = fmod(t, 1.); //shift 872 | // if(p.x>0.5) 873 | p.y = -floor( -p.y * SLN + sh )/SLN + sh/SLN; //v1.3 874 | // p.y = floor( p.y * SLN + sh )/SLN - sh/SLN; //v1.2 875 | } else { 876 | // if(p.x>0.5) 877 | p.y = -floor( -p.y * SLN )/SLN; //v1.3 878 | // p.y = floor( p.y * SLN )/SLN; //v1.2 879 | } 880 | 881 | if (VHS_Stretch){ 882 | p = stretch(p, t, 15.0, 1.0, 0.5, 0.0); 883 | p = stretch(p, t, 8.0, 1.2, 0.45, 0.5); 884 | p = stretch(p, t, 11.0, 0.5, -0.35, 0.25); //up 885 | } 886 | 887 | if (VHS_Jitter_H){ 888 | if( fmod( p.y * SLN, 2.0)<1.0) 889 | p.x += ONE_X*sin(t*13000.0)*jitterHAmount; 890 | } 891 | 892 | //just init 893 | float3 col = float3(0.0,0.0,0.0); 894 | float3 signal = float3(0.0,0.0,0.0);// rgb2yiq(col); 895 | 896 | //gotta initiate all these things here coz of tape noise distortion 897 | 898 | //[NOISE uv init] 899 | //if SLN_Noise different from SLN->recalc linefloat 900 | float2 pn = p; 901 | if(SLN!=SLN_Noise){ 902 | if(VHS_LineNoise){ 903 | const float sh = frac(t); //shift // float sh = fmod(t, 1.); //shift 904 | pn.y = floor( pn.y * SLN_Noise + sh )/SLN_Noise - sh/SLN_Noise; 905 | } else { 906 | pn.y = floor( pn.y * SLN_Noise )/SLN_Noise; 907 | } 908 | } 909 | 910 | //SLN_X is quantization of X. goest from _ScreenParams.x to SLN_X 911 | const float ScreenLinesNumX = SLN_Noise * _ScreenParams.x / _ScreenParams.y; 912 | const float SLN_X = noiseQuantizeX*(_ScreenParams.x - ScreenLinesNumX) + ScreenLinesNumX; 913 | pn.x = floor( pn.x * SLN_X )/SLN_X; 914 | 915 | const float2 pn_ = pn*_ScreenParams.xy; 916 | 917 | //TODO probably it shud be 1.0/SLN_Noise 918 | const float ONEXN = 1.0/SLN_X; 919 | //[//noise uv init] 920 | 921 | float distShift = 0; // for 2nd part of tape noise 922 | 923 | if (VHS_TapeNoise) { 924 | 925 | //uv distortion part of tapenoise 926 | distShift = 0; // for 2nd part of tape noise 927 | for (int ii = 0; ii < 20 % 1023; ii++){ 928 | 929 | //this is t.n. line value at pn.y and down each pixel 930 | //TODO i guess ONEXN shud be 1.0/sln noise 931 | const float tnl = tex2Dlod(SamplerTape, float4(0.0,pn.y-ONEXN*ii, 0.0, 0.0)).y; 932 | // float tnl = tex2D(SamplerTape, float2(0.0,pn.y-ONEXN*ii)).y; 933 | // float tnl = tapeNoiseLines(float2(0.0,pn.y-ONEXN*i), t*tapeNoiseSpeed)*tapeNoiseAmount; 934 | 935 | // float fadediff = hash12(float2(pn.x-ONEXN*i,pn.y)); 936 | if(tnl>0.55) { 937 | //TODO get integer part other way 938 | const float sh = sin( 1.0*PI*(float(ii)/float(20))) ; //0..1 939 | p.x -= float(int(sh)*4.0*ONEXN); //displacement 940 | distShift += sh ; //for 2nd part 941 | // p.x += ONEXN * float(int(((tnl-thth)/thth)*4.0)); 942 | // col.x = sh; 943 | } 944 | } 945 | } 946 | 947 | //uv transforms over 948 | 949 | //picture proccess start 950 | if (VHS_Jitter_V){ 951 | signal = yiqDist(p, jitterVAmount, t*jitterVSpeed); 952 | } else { 953 | col = tex2D(SamplerColorVHS, p).rgb; 954 | // col = float3(p.xy, 0.0);//debug 955 | signal = rgb2yiq(col); 956 | } 957 | 958 | 959 | if (VHS_LineNoise || VHS_FilmGrain){ 960 | signal.x += tex2D(SamplerTape, pn).z; 961 | } 962 | 963 | //iq noise from yiq 964 | if (VHS_YIQNoise){ 965 | if (signalNoiseType == 0) { 966 | //TODO make cheaper noise 967 | //type 1 (best) w Y mask 968 | const float2 noise = n4rand_bw( pn_,t,1.0-signalNoisePower ) ; 969 | signal.y += (noise.x*2.0-1.0)*signalNoiseAmount*signal.x; 970 | signal.z += (noise.y*2.0-1.0)*signalNoiseAmount*signal.x; 971 | } else if (signalNoiseType == 1){ 972 | //type 2 973 | const float2 noise = n4rand_bw( pn_,t, 1.0-signalNoisePower ) ; 974 | signal.y += (noise.x*2.0-1.0)*signalNoiseAmount; 975 | signal.z += (noise.y*2.0-1.0)*signalNoiseAmount; 976 | } else { 977 | //type 3 978 | const float2 noise = n4rand_bw( pn_,t, 1.0-signalNoisePower )*signalNoiseAmount ; 979 | signal.y *= noise.x; 980 | signal.z *= noise.y; 981 | signal.x += (noise.x*2.0-1.0)*0.05; 982 | } 983 | } 984 | 985 | //2nd part with noise, tail and yiq col shift 986 | if (VHS_TapeNoise){ 987 | 988 | //here is normilized p (0..1) 989 | float tn = tex2D(SamplerTape, pn).x; 990 | signal.x = bms(signal.x, tn*tapeNoiseAmount ).x; 991 | // float tn = tapeNoise(pn, t*tapeNoiseSpeed)*tapeNoiseAmount; 992 | 993 | //tape noise tail 994 | const int tailLength=10; //TODO adjustable 995 | 996 | for(int j = 0; j < tailLength % 1023; j++){ 997 | 998 | const float jj = float(j); 999 | const float2 d = float2(pn.x-ONEXN*jj,pn.y); 1000 | tn = tex2Dlod(SamplerTape, float4(d,0.0,0.0) ).x; 1001 | // tn = tex2D(SamplerTape, d).x; 1002 | // tn = tapeNoise(float2(pn.x-ONEXN*i,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount; 1003 | 1004 | float fadediff = 0.0; 1005 | 1006 | //for tails length difference 1007 | if(__RENDERER__ == 0x0A100 || __RENDERER__ == 0x0B000) { 1008 | fadediff = tex2Dlod(SamplerTape, float4(d,0.0,0.0)).a; //hash12(d); 1009 | } 1010 | 1011 | if(__RENDERER__ == 0x09300 || __RENDERER__ >= 0x10000) { 1012 | fadediff = tex2D(SamplerTape, d).a; //hash12(d); 1013 | } 1014 | 1015 | if( tn > 0.8 ){ 1016 | float nsx = 0.0; //new signal x 1017 | const float newlength = float(tailLength)*(1.0-fadediff); //tail lenght diff 1018 | if( jj <= newlength ) nsx = 1.0-( jj/ newlength ); //tail 1019 | signal.x = bms(signal.x, nsx*tapeNoiseAmount).x; 1020 | } 1021 | } 1022 | 1023 | //tape noise color shift 1024 | if(distShift>0.4){ 1025 | // float tnl = tapeNoiseLines(float2(0.0,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount; 1026 | const float tnl = tex2D(SamplerTape, pn).y;//tapeNoiseLines(float2(0.0,pn.y), t*tapeNoiseSpeed)*tapeNoiseAmount; 1027 | signal.y *= 1.0/distShift;//tnl*0.1;//*distShift;//*signal.x; 1028 | signal.z *= 1.0/distShift;//*distShift;//*signal.x; 1029 | 1030 | } 1031 | } 1032 | 1033 | //back to rgb color space 1034 | //signal has negative values 1035 | col = yiq2rgb(signal); 1036 | 1037 | //TODO put it into 2nd pass 1038 | if (VHS_ScanLines){ 1039 | col *= scanLines(txcoord.xy, t); 1040 | } 1041 | 1042 | //fisheye cutoff / outside fisheye 1043 | //helps to remove noise outside the fisheye 1044 | if (VHS_FishEye){ 1045 | 1046 | p = txcoord.xy; 1047 | 1048 | float far; 1049 | const float2 hco = float2(ONE_X*cutoffX, ONE_Y*cutoffY); //hard cuttoff x 1050 | const float2 sco = float2(ONE_X*cutoffFadeX, ONE_Y*cutoffFadeY); //soft cuttoff x 1051 | 1052 | //hard cutoff 1053 | if( p.x<=(0.0+hco.x) || p.x>=(1.0-hco.x) || p.y<=(0.0+hco.y) || p.y>=(1.0-hco.y) ){ 1054 | col = float3(0.0,0.0,0.0); 1055 | } else { 1056 | //fades 1057 | 1058 | if( //X 1059 | (p.x>(0.0+hco.x) && p.x<(0.0+(sco.x+hco.x) )) || (p.x>(1.0-(sco.x+hco.x)) && p.x<(1.0-hco.x)) 1060 | ){ 1061 | if(p.x<0.5) far = (0.0-hco.x+p.x)/(sco.x); 1062 | else 1063 | far = (1.0-hco.x-p.x)/(sco.x); 1064 | 1065 | col *= float(far).xxx; 1066 | }; 1067 | 1068 | if( //Y 1069 | (p.y>(0.0+hco.y) && p.y<(0.0+(sco.y+hco.y) )) || (p.y>(1.0-(sco.y+hco.y)) && p.y<(1.0-hco.y)) 1070 | ){ 1071 | if(p.y<0.5) far = (0.0-hco.y+p.y)/(sco.y); 1072 | else 1073 | far = (1.0-hco.y-p.y)/(sco.y); 1074 | 1075 | col *= float(far).xxx; 1076 | } 1077 | } 1078 | } 1079 | 1080 | // col = tex2D(SamplerTape, txcoord.xy).x; 1081 | 1082 | return float4(col, 1.0); 1083 | 1084 | } 1085 | 1086 | float4 PS_VHS2(float4 pos : SV_Position, float2 txcoord : TEXCOORD) : SV_Target 1087 | { 1088 | const float t = Timer.x * 0.001;//_Time.y; 1089 | float2 p = txcoord.xy; 1090 | float SLN = screenLinesNum; //TODO use only SLN 1091 | 1092 | //basically if its 0 -> set it to fullscreen 1093 | if(SLN==0.0) SLN = _ScreenParams.y; 1094 | 1095 | //TODO maybe make it based on num of lines? and height ? 1096 | //TODO make switch between real pixels and pixelated pixels! 1097 | // ONE_X = 1.0 / screenLinesNum; 1098 | 1099 | float ONE_X = 1.0 / _ScreenParams.x; // 1px 1100 | ONE_X *= bleedAmount; // longer tails, more bleeding, default 1. 1101 | 1102 | //distortions 1103 | if (VHS_FishEye){ 1104 | p = fishEye(p, fisheyeSize, fisheyeBend); // p = fishEye(p, 1.2, 2.0); 1105 | // return float4( frac(p*5.0)/2.5, 1.0, 1.0); //debug 1106 | } 1107 | 1108 | int bleedLength = 21; 1109 | 1110 | if((VHS_BleedMode == 0 || VHS_BleedMode == 1 || VHS_BleedMode == 3)) 1111 | { 1112 | bleedLength = 25; 1113 | } 1114 | 1115 | if((VHS_BleedMode == 2 || VHS_BleedMode == 4)) 1116 | { 1117 | bleedLength = 32; 1118 | } 1119 | 1120 | float luma_filter[33] = { 1121 | 0.000000000, 1122 | 0.000000000, 1123 | 0.000000000, 1124 | 0.000000000, 1125 | 0.000000000, 1126 | 0.000000000, 1127 | 0.000000000, 1128 | 0.000000000, 1129 | 0.000000000, 1130 | 0.000000000, 1131 | 0.000000000, 1132 | 0.000000000, 1133 | 0.000000000, 1134 | 0.000000000, 1135 | 0.000000000, 1136 | 0.000000000, 1137 | 0.000000000, 1138 | 0.000000000, 1139 | 0.000000000, 1140 | 0.000000000, 1141 | 0.000000000, 1142 | 0.000000000, 1143 | 0.000000000, 1144 | 0.000000000, 1145 | 0.000000000, 1146 | 0.000000000, 1147 | 0.000000000, 1148 | 0.000000000, 1149 | 0.000000000, 1150 | 0.000000000, 1151 | 0.000000000, 1152 | 0.000000000, 1153 | 0.000000000 1154 | }; 1155 | 1156 | float chroma_filter[33] = { 1157 | 0.000000000, 1158 | 0.000000000, 1159 | 0.000000000, 1160 | 0.000000000, 1161 | 0.000000000, 1162 | 0.000000000, 1163 | 0.000000000, 1164 | 0.000000000, 1165 | 0.000000000, 1166 | 0.000000000, 1167 | 0.000000000, 1168 | 0.000000000, 1169 | 0.000000000, 1170 | 0.000000000, 1171 | 0.000000000, 1172 | 0.000000000, 1173 | 0.000000000, 1174 | 0.000000000, 1175 | 0.000000000, 1176 | 0.000000000, 1177 | 0.000000000, 1178 | 0.000000000, 1179 | 0.000000000, 1180 | 0.000000000, 1181 | 0.000000000, 1182 | 0.000000000, 1183 | 0.000000000, 1184 | 0.000000000, 1185 | 0.000000000, 1186 | 0.000000000, 1187 | 0.000000000, 1188 | 0.000000000, 1189 | 0.000000000 1190 | }; 1191 | 1192 | if (VHS_BleedMode == 0 || VHS_BleedMode == 3){ //Three Phase and Three Phase (RetroArch) 1193 | luma_filter[0] = -0.000012020; 1194 | luma_filter[1] = -0.000022146; 1195 | luma_filter[2] = -0.000013155; 1196 | luma_filter[3] = -0.000012020; 1197 | luma_filter[4] = -0.000049979; 1198 | luma_filter[5] = -0.000113940; 1199 | luma_filter[6] = -0.000122150; 1200 | luma_filter[7] = -0.000005612; 1201 | luma_filter[8] = 0.000170516; 1202 | luma_filter[9] = 0.000237199; 1203 | luma_filter[10] = 0.000169640; 1204 | luma_filter[11] = 0.000285688; 1205 | luma_filter[12] = 0.000984574; 1206 | luma_filter[13] = 0.002018683; 1207 | luma_filter[14] = 0.002002275; 1208 | luma_filter[15] = -0.000909882; 1209 | luma_filter[16] = -0.007049081; 1210 | luma_filter[17] = -0.013222860; 1211 | luma_filter[18] = -0.012606931; 1212 | luma_filter[19] = 0.002460860; 1213 | luma_filter[20] = 0.035868225; 1214 | luma_filter[21] = 0.084016453; 1215 | luma_filter[22] = 0.135563500; 1216 | luma_filter[23] = 0.175261268; 1217 | luma_filter[24] = 0.190176552; 1218 | 1219 | chroma_filter[0] = -0.000118847; 1220 | chroma_filter[1] = -0.000271306; 1221 | chroma_filter[2] = -0.000502642; 1222 | chroma_filter[3] = -0.000930833; 1223 | chroma_filter[4] = -0.001451013; 1224 | chroma_filter[5] = -0.002064744; 1225 | chroma_filter[6] = -0.002700432; 1226 | chroma_filter[7] = -0.003241276; 1227 | chroma_filter[8] = -0.003524948; 1228 | chroma_filter[9] = -0.003350284; 1229 | chroma_filter[10] = -0.002491729; 1230 | chroma_filter[11] = -0.000721149; 1231 | chroma_filter[12] = 0.002164659; 1232 | chroma_filter[13] = 0.006313635; 1233 | chroma_filter[14] = 0.011789103; 1234 | chroma_filter[15] = 0.018545660; 1235 | chroma_filter[16] = 0.026414396; 1236 | chroma_filter[17] = 0.035100710; 1237 | chroma_filter[18] = 0.044196567; 1238 | chroma_filter[19] = 0.053207202; 1239 | chroma_filter[20] = 0.061590275; 1240 | chroma_filter[21] = 0.068803602; 1241 | chroma_filter[22] = 0.074356193; 1242 | chroma_filter[23] = 0.077856564; 1243 | chroma_filter[24] = 0.079052396; 1244 | } 1245 | 1246 | else if (VHS_BleedMode == 1) { //Old Three-Phase 1247 | luma_filter[0] = -0.000071070; 1248 | luma_filter[1] = -0.000032816; 1249 | luma_filter[2] = 0.000128784; 1250 | luma_filter[3] = 0.000134711; 1251 | luma_filter[4] = -0.000226705; 1252 | luma_filter[5] = -0.000777988; 1253 | luma_filter[6] = -0.000997809; 1254 | luma_filter[7] = -0.000522802; 1255 | luma_filter[8] = 0.000344691; 1256 | luma_filter[9] = 0.000768930; 1257 | luma_filter[10] = 0.000275591; 1258 | luma_filter[11] = -0.000373434; 1259 | luma_filter[12] = 0.000522796; 1260 | luma_filter[13] = 0.003813817; 1261 | luma_filter[14] = 0.007502825; 1262 | luma_filter[15] = 0.006786001; 1263 | luma_filter[16] = -0.002636726; 1264 | luma_filter[17] = -0.019461182; 1265 | luma_filter[18] = -0.033792479; 1266 | luma_filter[19] = -0.029921972; 1267 | luma_filter[20] = 0.005032552; 1268 | luma_filter[21] = 0.071226466; 1269 | luma_filter[22] = 0.151755921; 1270 | luma_filter[23] = 0.218166470; 1271 | luma_filter[24] = 0.243902439; 1272 | 1273 | chroma_filter[0] = 0.001845562; 1274 | chroma_filter[1] = 0.002381606; 1275 | chroma_filter[2] = 0.003040177; 1276 | chroma_filter[3] = 0.003838976; 1277 | chroma_filter[4] = 0.004795341; 1278 | chroma_filter[5] = 0.005925312; 1279 | chroma_filter[6] = 0.007242534; 1280 | chroma_filter[7] = 0.008757043; 1281 | chroma_filter[8] = 0.010473987; 1282 | chroma_filter[9] = 0.012392365; 1283 | chroma_filter[10] = 0.014503872; 1284 | chroma_filter[11] = 0.016791957; 1285 | chroma_filter[12] = 0.019231195; 1286 | chroma_filter[13] = 0.021787070; 1287 | chroma_filter[14] = 0.024416251; 1288 | chroma_filter[15] = 0.027067414; 1289 | chroma_filter[16] = 0.029682613; 1290 | chroma_filter[17] = 0.032199202; 1291 | chroma_filter[18] = 0.034552198; 1292 | chroma_filter[19] = 0.036677005; 1293 | chroma_filter[20] = 0.038512317; 1294 | chroma_filter[21] = 0.040003044; 1295 | chroma_filter[22] = 0.041103048; 1296 | chroma_filter[23] = 0.041777517; 1297 | chroma_filter[24] = 0.042004791; 1298 | } 1299 | 1300 | else if (VHS_BleedMode == 2) { //Two-Phase 1301 | luma_filter[0] = -0.000205844; 1302 | luma_filter[1] = -0.000149453; 1303 | luma_filter[2] = -0.000051693; 1304 | luma_filter[3] = 0.000000000; 1305 | luma_filter[4] = -0.000066171; 1306 | luma_filter[5] = -0.000245058; 1307 | luma_filter[6] = -0.000432928; 1308 | luma_filter[7] = -0.000472644; 1309 | luma_filter[8] = -0.000252236; 1310 | luma_filter[9] = 0.000198929; 1311 | luma_filter[10] = 0.000687058; 1312 | luma_filter[11] = 0.000944112; 1313 | luma_filter[12] = 0.000803467; 1314 | luma_filter[13] = 0.000363199; 1315 | luma_filter[14] = 0.000013422; 1316 | luma_filter[15] = 0.000253402; 1317 | luma_filter[16] = 0.001339461; 1318 | luma_filter[17] = 0.002932972; 1319 | luma_filter[18] = 0.003983485; 1320 | luma_filter[19] = 0.003026683; 1321 | luma_filter[20] = -0.001102056; 1322 | luma_filter[21] = -0.008373026; 1323 | luma_filter[22] = -0.016897700; 1324 | luma_filter[23] = -0.022914480; 1325 | luma_filter[24] = -0.021642347; 1326 | luma_filter[25] = -0.008863273; 1327 | luma_filter[26] = 0.017271957; 1328 | luma_filter[27] = 0.054921920; 1329 | luma_filter[28] = 0.098342579; 1330 | luma_filter[29] = 0.139044281; 1331 | luma_filter[30] = 0.168055832; 1332 | luma_filter[31] = 0.178571429; 1333 | 1334 | chroma_filter[0] = 0.001384762; 1335 | chroma_filter[1] = 0.001678312; 1336 | chroma_filter[2] = 0.002021715; 1337 | chroma_filter[3] = 0.002420562; 1338 | chroma_filter[4] = 0.002880460; 1339 | chroma_filter[5] = 0.003406879; 1340 | chroma_filter[6] = 0.004004985; 1341 | chroma_filter[7] = 0.004679445; 1342 | chroma_filter[8] = 0.005434218; 1343 | chroma_filter[9] = 0.006272332; 1344 | chroma_filter[10] = 0.007195654; 1345 | chroma_filter[11] = 0.008204665; 1346 | chroma_filter[12] = 0.009298238; 1347 | chroma_filter[13] = 0.010473450; 1348 | chroma_filter[14] = 0.011725413; 1349 | chroma_filter[15] = 0.013047155; 1350 | chroma_filter[16] = 0.014429548; 1351 | chroma_filter[17] = 0.015861306; 1352 | chroma_filter[18] = 0.017329037; 1353 | chroma_filter[19] = 0.018817382; 1354 | chroma_filter[20] = 0.020309220; 1355 | chroma_filter[21] = 0.021785952; 1356 | chroma_filter[22] = 0.023227857; 1357 | chroma_filter[23] = 0.024614500; 1358 | chroma_filter[24] = 0.025925203; 1359 | chroma_filter[25] = 0.027139546; 1360 | chroma_filter[26] = 0.028237893; 1361 | chroma_filter[27] = 0.029201910; 1362 | chroma_filter[28] = 0.030015081; 1363 | chroma_filter[29] = 0.030663170; 1364 | chroma_filter[30] = 0.031134640; 1365 | chroma_filter[31] = 0.031420995; 1366 | chroma_filter[32] = 0.031517031; 1367 | } 1368 | 1369 | else if (VHS_BleedMode == 4) { //Two-Phase (RetroArch) 1370 | luma_filter[0] = -0.000174844; 1371 | luma_filter[1] = -0.000205844; 1372 | luma_filter[2] = -0.000149453; 1373 | luma_filter[3] = -0.000051693; 1374 | luma_filter[4] = 0.000000000; 1375 | luma_filter[5] = -0.000066171; 1376 | luma_filter[6] = -0.000245058; 1377 | luma_filter[7] = -0.000432928; 1378 | luma_filter[8] = -0.000472644; 1379 | luma_filter[9] = -0.000252236; 1380 | luma_filter[10] = 0.000198929; 1381 | luma_filter[11] = 0.000687058; 1382 | luma_filter[12] = 0.000944112; 1383 | luma_filter[13] = 0.000803467; 1384 | luma_filter[14] = 0.000363199; 1385 | luma_filter[15] = 0.000013422; 1386 | luma_filter[16] = 0.000253402; 1387 | luma_filter[17] = 0.001339461; 1388 | luma_filter[18] = 0.002932972; 1389 | luma_filter[19] = 0.003983485; 1390 | luma_filter[20] = 0.003026683; 1391 | luma_filter[21] = -0.001102056; 1392 | luma_filter[22] = -0.008373026; 1393 | luma_filter[23] = -0.016897700; 1394 | luma_filter[24] = -0.022914480; 1395 | luma_filter[25] = -0.021642347; 1396 | luma_filter[26] = -0.008863273; 1397 | luma_filter[27] = 0.017271957; 1398 | luma_filter[28] = 0.054921920; 1399 | luma_filter[29] = 0.098342579; 1400 | luma_filter[30] = 0.139044281; 1401 | luma_filter[31] = 0.168055832; 1402 | luma_filter[32] = 0.178571429; 1403 | 1404 | chroma_filter[0] = 0.001384762; 1405 | chroma_filter[1] = 0.001678312; 1406 | chroma_filter[2] = 0.002021715; 1407 | chroma_filter[3] = 0.002420562; 1408 | chroma_filter[4] = 0.002880460; 1409 | chroma_filter[5] = 0.003406879; 1410 | chroma_filter[6] = 0.004004985; 1411 | chroma_filter[7] = 0.004679445; 1412 | chroma_filter[8] = 0.005434218; 1413 | chroma_filter[9] = 0.006272332; 1414 | chroma_filter[10] = 0.007195654; 1415 | chroma_filter[11] = 0.008204665; 1416 | chroma_filter[12] = 0.009298238; 1417 | chroma_filter[13] = 0.010473450; 1418 | chroma_filter[14] = 0.011725413; 1419 | chroma_filter[15] = 0.013047155; 1420 | chroma_filter[16] = 0.014429548; 1421 | chroma_filter[17] = 0.015861306; 1422 | chroma_filter[18] = 0.017329037; 1423 | chroma_filter[19] = 0.018817382; 1424 | chroma_filter[20] = 0.020309220; 1425 | chroma_filter[21] = 0.021785952; 1426 | chroma_filter[22] = 0.023227857; 1427 | chroma_filter[23] = 0.024614500; 1428 | chroma_filter[24] = 0.025925203; 1429 | chroma_filter[25] = 0.027139546; 1430 | chroma_filter[26] = 0.028237893; 1431 | chroma_filter[27] = 0.029201910; 1432 | chroma_filter[28] = 0.030015081; 1433 | chroma_filter[29] = 0.030663170; 1434 | chroma_filter[30] = 0.031134640; 1435 | chroma_filter[31] = 0.031420995; 1436 | chroma_filter[32] = 0.031517031; 1437 | } 1438 | 1439 | 1440 | //Bleeding 1441 | float3 signal = float3(0.0,0.0,0.0); 1442 | 1443 | if (VHS_Bleed){ 1444 | 1445 | float3 norm = float3(0.0,0.0,0.0); 1446 | float3 adj = float3(0.0,0.0,0.0); 1447 | 1448 | const int taps = bleedLength-4; 1449 | //int taps = bleedLength; //RetroArch 1450 | 1451 | for (int ii = 0; float(ii) < float(taps) % 1023; ii++){ 1452 | 1453 | const float offset = float(ii); 1454 | const float3 sums = fetch_offset(offset - float(taps), ONE_X) + 1455 | fetch_offset(float(taps) - offset, ONE_X) ; 1456 | 1457 | adj = float3(luma_filter[ii+3], chroma_filter[ii], chroma_filter[ii]); 1458 | //adj = float3(luma_filter[ii], chroma_filter[ii], chroma_filter[ii]); //RetroArch 1459 | 1460 | signal += sums * adj; 1461 | norm += adj; 1462 | 1463 | } 1464 | 1465 | adj = float3(luma_filter[taps], chroma_filter[taps], chroma_filter[taps]); 1466 | 1467 | signal += t2d(fixCoord) * adj; 1468 | norm += adj; 1469 | signal = signal / norm; 1470 | } else { 1471 | //no bleeding 1472 | signal = t2d(p); 1473 | } 1474 | 1475 | //[Signal Tweak] 1476 | if (VHS_SignalTweak){ 1477 | 1478 | //adjust 1479 | signal.x += signalAdjustY; 1480 | signal.y += signalAdjustI; 1481 | signal.z += signalAdjustQ; 1482 | 1483 | //shift 1484 | signal.x *= signalShiftY; 1485 | signal.y *= signalShiftI; 1486 | signal.z *= signalShiftQ; 1487 | 1488 | // //test YIQ 1489 | // signal.x = 0.5; 1490 | // signal.y = p.x*2.0-1.0; 1491 | // signal.z = p.y*2.0-1.0; 1492 | 1493 | //signal noise 1494 | // float2 noise = n4rand_bw( p,t, 1.0-signalNoisePower )*signalNoiseAmount ; 1495 | // signal.y *= noise.x; 1496 | // signal.z *= noise.y; 1497 | 1498 | 1499 | //phase - it cant be dont coz of intervals 1500 | // signal.x = frac( (signal.x +1.0)*0.5f )*2.0f - 1.0f ; 1501 | //signal.y = frac( (signal.y +1.0)*0.5f )*2.0f - 1.0f ; 1502 | //signal.z = frac( (signal.z +1.0)*0.5f )*2.0f - 1.0f ; 1503 | } 1504 | 1505 | float3 rgb = yiq2rgb(signal); 1506 | 1507 | if (VHS_SignalTweak){ 1508 | if(gammaCorection!=1.0) rgb = pow(abs(rgb), gammaCorection); //float3(gammaCorection).rgb 1509 | } 1510 | 1511 | //cut trash after fish eye 1512 | // if( p.x<0. || p.x>1. || p.y<0. || p.y>1.){ 1513 | // rgb *= 0.0; 1514 | // } 1515 | 1516 | //TODO maybe on yiq channel 1517 | if (VHS_Vignette){ 1518 | rgb *= vignette(p, t*vignetteSpeed); //TODO params //txcoord.xy 1519 | } 1520 | 1521 | return float4(rgb, 1.0); 1522 | } 1523 | 1524 | //third pass 1525 | 1526 | float3 bm_screen(float3 a, float3 b){ return 1.0- (1.0-a)*(1.0-b); } 1527 | 1528 | void PS_VHS3(float4 vpos : SV_Position, out float4 feedbackoutput : SV_Target0, 1529 | float2 texcoord : TEXCOORD, out float4 feedback : SV_Target1 ) 1530 | { 1531 | float2 p = texcoord.xy; 1532 | const float one_x = 1.0/_ScreenParams.x; 1533 | float3 fc = tex2D( SamplerColorVHS, texcoord).rgb; // curent frame 1534 | 1535 | //new feedback 1536 | const float3 fl = tex2D( VHS_InputB, texcoord).rgb; //last frame without feedback 1537 | float diff = abs(fl.x-fc.x + fl.y-fc.y + fl.z-fc.z)/3.0; //dfference between frames 1538 | if(diff = 0.25; 43 | 44 | uniform int xBRtype < 45 | ui_type = "combo"; 46 | ui_label = "xBR type"; 47 | ui_items = "type A - round\0type B: semi-round\0type C: semi-square\0type D: square\0"; 48 | ui_tooltip = "Changes the edge type."; 49 | > = 2; 50 | 51 | #define TEX(dx,dy,dz) tex2D(ReShade::BackBuffer, tex + float2(dx, dy) * dz) 52 | 53 | static const precise float XBR_SCALE = 4096.0; 54 | static const float coef = 2.0; 55 | static const float4 eq_threshold = float4(15.0, 15.0, 15.0, 15.0); 56 | static const float3 rgbw = float3(14.352, 28.176, 5.472); 57 | static const float3 dt = float3(1.0,1.0,1.0); 58 | 59 | bool4 greaterThanEqual(float4 A, float4 B){ 60 | bool4 result = bool4(A.x >= B.x, A.y >= B.y, A.z >= B.z, A.w >= B.w); 61 | return result; 62 | } 63 | 64 | bool4 notEqual(float4 A, float4 B){ 65 | bool4 result = bool4(A.x != B.x, A.y != B.y, A.z != B.z, A.w != B.w); 66 | return result; 67 | } 68 | 69 | bool4 lessThanEqual(float4 A, float4 B){ 70 | bool4 result = bool4(A.x <= B.x, A.y <= B.y, A.z <= B.z, A.w <= B.w); 71 | return result; 72 | } 73 | 74 | bool4 lessThan(float4 A, float4 B){ 75 | bool4 result = bool4(A.x < B.x, A.y < B.y, A.z < B.z, A.w < B.w); 76 | return result; 77 | } 78 | 79 | float4 noteq(float4 A, float4 B) 80 | { 81 | return float4(notEqual(A, B)); 82 | } 83 | 84 | float4 not(float4 A) 85 | { 86 | return float4(1.0, 1.0, 1.0, 1.0)-A; 87 | } 88 | 89 | float4 df(float4 A, float4 B) 90 | { 91 | return abs(A-B); 92 | } 93 | 94 | float4 eq(float4 A, float4 B) 95 | { 96 | return float4(lessThan(df(A, B),eq_threshold)); 97 | } 98 | 99 | float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, float4 e, float4 f, float4 g, float4 h) 100 | { 101 | return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h)); 102 | } 103 | 104 | float3 xBRv4(float4 position : SV_Position, float2 tex : TEXCOORD0) : SV_Target 105 | { 106 | float2 OGLSize = float2(ReShade::ScreenSize.x * 0.25, ReShade::ScreenSize.y * 0.25); 107 | float2 OGLInvSize = float2(1.0/OGLSize.x, 1.0/OGLSize.y); 108 | 109 | float2 dx = float2( OGLInvSize.x, 0.0); 110 | float2 dy = float2( 0.0, OGLInvSize.y ); 111 | 112 | float2 fp = frac(tex*OGLSize); 113 | float2 TexCoord_0 = tex-fp*OGLInvSize + 0.5*OGLInvSize; 114 | 115 | float4 edr, edr_left, edr_up; // px = pixel, edr = edge detection rule 116 | float4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up; 117 | float4 nc30, nc60, nc45; // new_color 118 | float4 fx, fx_left, fx_up, final_fx; // inequations of straight lines. 119 | float3 res1, res2, pix1, pix2; 120 | bool4 nc, px; 121 | float blend1, blend2; 122 | 123 | float OGLInvSizeY2 = OGLInvSize.y * 2; 124 | float2 x2 = float2( OGLInvSize.y, 0.0); 125 | float2 y2 = float2( 0.0 , OGLInvSizeY2 ); 126 | float4 xy = float4( OGLInvSize.x, OGLInvSize.y, -OGLInvSize.x, -OGLInvSize.y ); 127 | float4 zw = float4( OGLInvSize.y, OGLInvSize.y, -OGLInvSize.y, -OGLInvSizeY2 ); 128 | float4 wz = float4( OGLInvSize.x, OGLInvSizeY2, -OGLInvSize.x, -OGLInvSizeY2 ); 129 | 130 | float4 delta = float4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE); 131 | float4 deltaL = float4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE); 132 | float4 deltaU = deltaL.yxwz; 133 | 134 | float3 A = tex2D(ReShade::BackBuffer, TexCoord_0 + xy.zw ).xyz; 135 | float3 B = tex2D(ReShade::BackBuffer, TexCoord_0 -dy ).xyz; 136 | float3 C = tex2D(ReShade::BackBuffer, TexCoord_0 + xy.xw ).xyz; 137 | float3 D = tex2D(ReShade::BackBuffer, TexCoord_0 - dx ).xyz; 138 | float3 E = tex2D(ReShade::BackBuffer, TexCoord_0 ).xyz; 139 | float3 F = tex2D(ReShade::BackBuffer, TexCoord_0 + dx ).xyz; 140 | float3 G = tex2D(ReShade::BackBuffer, TexCoord_0 + xy.zy ).xyz; 141 | float3 H = tex2D(ReShade::BackBuffer, TexCoord_0 +dy ).xyz; 142 | float3 I = tex2D(ReShade::BackBuffer, TexCoord_0 + xy.xy ).xyz; 143 | float3 A1 = tex2D(ReShade::BackBuffer, TexCoord_0 + wz.zw ).xyz; 144 | float3 C1 = tex2D(ReShade::BackBuffer, TexCoord_0 + wz.xw ).xyz; 145 | float3 A0 = tex2D(ReShade::BackBuffer, TexCoord_0 + zw.zw ).xyz; 146 | float3 G0 = tex2D(ReShade::BackBuffer, TexCoord_0 + zw.zy ).xyz; 147 | float3 C4 = tex2D(ReShade::BackBuffer, TexCoord_0 + zw.xw ).xyz; 148 | float3 I4 = tex2D(ReShade::BackBuffer, TexCoord_0 + zw.xy ).xyz; 149 | float3 G5 = tex2D(ReShade::BackBuffer, TexCoord_0 + wz.zy ).xyz; 150 | float3 I5 = tex2D(ReShade::BackBuffer, TexCoord_0 + wz.xy ).xyz; 151 | float3 B1 = tex2D(ReShade::BackBuffer, TexCoord_0 - y2 ).xyz; 152 | float3 D0 = tex2D(ReShade::BackBuffer, TexCoord_0 - x2 ).xyz; 153 | float3 H5 = tex2D(ReShade::BackBuffer, TexCoord_0 + y2 ).xyz; 154 | float3 F4 = tex2D(ReShade::BackBuffer, TexCoord_0 + x2 ).xyz; 155 | 156 | float4 b = float4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw)); 157 | float4 c = float4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw)); 158 | float4 d = b.yzwx; 159 | float eV = dot(E,rgbw); 160 | float4 e = float4(eV, eV, eV, eV); 161 | float4 f = b.wxyz; 162 | float4 g = c.zwxy; 163 | float4 h = b.zwxy; 164 | float4 i = c.wxyz; 165 | float4 i4 = float4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw)); 166 | float4 i5 = float4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw)); 167 | float4 h5 = float4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw)); 168 | float4 f4 = h5.yzwx; 169 | float4 c1 = i4.yzwx; 170 | float4 g0 = i5.wxyz; 171 | 172 | float4 Ao = float4( 1.0, -1.0, -1.0, 1.0 ); 173 | float4 Bo = float4( 1.0, 1.0, -1.0,-1.0 ); 174 | float4 Co = float4( 1.5, 0.5, -0.5, 0.5 ); 175 | float4 Ax = float4( 1.0, -1.0, -1.0, 1.0 ); 176 | float4 Bx = float4( 0.5, 2.0, -0.5,-2.0 ); 177 | float4 Cx = float4( 1.0, 1.0, -0.5, 0.0 ); 178 | float4 Ay = float4( 1.0, -1.0, -1.0, 1.0 ); 179 | float4 By = float4( 2.0, 0.5, -2.0,-0.5 ); 180 | float4 Cy = float4( 2.0, 0.0, -1.0, 0.5 ); 181 | 182 | // These inequations define the line below which interpolation occurs. 183 | 184 | fx = (Ao*fp.y+Bo*fp.x); 185 | 186 | fx_left = (Ax*fp.y+Bx*fp.x); 187 | 188 | fx_up = (Ay*fp.y+By*fp.x); 189 | 190 | if (xBRtype <= 0){ 191 | interp_restriction_lv1 = sign(noteq(e,f) * noteq(e,h)); 192 | } else if (xBRtype <= 1){ 193 | interp_restriction_lv1 = sign(noteq(e,f) * noteq(e,h) * ( not(eq(f,b)) * not(eq(h,d)) + eq(e,i) * not(eq(f,i4)) * not(eq(h,i5)) + eq(e,g) + eq(e,c))); 194 | } else if (xBRtype <= 2){ 195 | interp_restriction_lv1 = sign(noteq(e,f)*noteq(e,h)*(not(eq(f,b))* not(eq(h,d)) + eq(e,i) * not(eq(f,i4)) * not(eq(h,i5)) + eq(e,g) + eq(e,c) ) * (noteq(f,f4)* noteq(f,i) + noteq(h,h5) * noteq(h,i) + noteq(h,g) + noteq(f,c) + eq(b,c1) * eq(d,g0))); 196 | } else { 197 | interp_restriction_lv1 = sign(noteq(e,f) * noteq(e,h) * ( not(eq(f,b)) * not(eq(f,c)) + not(eq(h,d)) * not(eq(h,g)) + eq(e,i) * (not(eq(f,f4)) * not(eq(f,i4)) + not(eq(h,h5)) * not(eq(h,i5))) + eq(e,g) + eq(e,c)) ); 198 | } 199 | 200 | interp_restriction_lv2_left = float4(notEqual(e,g))*float4(notEqual(d,g)); 201 | interp_restriction_lv2_up = float4(notEqual(e,c))*float4(notEqual(b,c)); 202 | 203 | float4 fx45 = clamp((fx + delta -Co)/(2*delta ),0.0,1.0); 204 | float4 fx30 = clamp((fx_left + deltaL -Cx)/(2*deltaL),0.0,1.0); 205 | float4 fx60 = clamp((fx_up + deltaU -Cy)/(2*deltaU),0.0,1.0); 206 | 207 | edr = float4(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)))*interp_restriction_lv1; 208 | edr_left = float4(lessThanEqual(coef*df(f,g),df(h,c)))*interp_restriction_lv2_left*edr; 209 | edr_up = float4(greaterThanEqual(df(f,g),coef*df(h,c)))*interp_restriction_lv2_up*edr; 210 | 211 | fx45 = edr*fx45; 212 | fx30 = edr_left*fx30; 213 | fx60 = edr_up*fx60; 214 | 215 | px = lessThanEqual(df(e,f),df(e,h)); 216 | float4 maximo = max(max(fx30, fx60), fx45); 217 | 218 | float3 zero = lerp(E, lerp(H, F, float(px.x)), maximo.x).rgb; 219 | float3 one = lerp(E, lerp(F, B, float(px.y)), maximo.y).rgb; 220 | float3 two = lerp(E, lerp(B, D, float(px.z)), maximo.z).rgb; 221 | float3 three = lerp(E, lerp(D, H, float(px.w)), maximo.w).rgb; 222 | 223 | float4 pixel = float4(dot(zero,rgbw),dot(one,rgbw),dot(two,rgbw),dot(three,rgbw)); 224 | 225 | float4 diff = df(pixel,e); 226 | 227 | float3 res = zero; 228 | float mx = diff.x; 229 | 230 | if (diff.y > mx) {res = one; mx = diff.y;} 231 | if (diff.z > mx) {res = two; mx = diff.z;} 232 | if (diff.w > mx) {res = three;} 233 | 234 | return res; 235 | } 236 | 237 | float3 dilation(float4 position : SV_Position, float2 tex : TEXCOORD0) : SV_Target 238 | { 239 | float2 dz = float2( 1.0 / ReShade::ScreenSize.x * dilationAmount, 240 | 1.0 / ReShade::ScreenSize.y * dilationAmount); 241 | 242 | float x = ReShade::PixelSize.x; 243 | float y = ReShade::PixelSize.y; 244 | 245 | float3 B = TEX( 0,-1, dz).rgb; 246 | float3 D = TEX(-1, 0, dz).rgb; 247 | float3 E = TEX( 0, 0, dz).rgb; 248 | float3 F = TEX( 1, 0, dz).rgb; 249 | float3 H = TEX( 0, 1, dz).rgb; 250 | 251 | return max(E, max(max(F, D), max(B, H))); 252 | } 253 | 254 | technique xBRv4 255 | { 256 | pass 257 | { 258 | VertexShader = PostProcessVS; 259 | PixelShader = dilation; 260 | } 261 | pass 262 | { 263 | VertexShader = PostProcessVS; 264 | PixelShader = dilation; 265 | } 266 | pass 267 | { 268 | VertexShader = PostProcessVS; 269 | PixelShader = xBRv4; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /Textures/bapho_blue_noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bapho/reshade-shaders/8f6c1ede391dea5604550d763d31de566e8c0156/Textures/bapho_blue_noise.png -------------------------------------------------------------------------------- /Textures/hd_noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bapho/reshade-shaders/8f6c1ede391dea5604550d763d31de566e8c0156/Textures/hd_noise.png --------------------------------------------------------------------------------