diff --git a/dithering/g-sharp_resampler.slangp b/dithering/g-sharp_resampler.slangp new file mode 100644 index 00000000..dee28043 --- /dev/null +++ b/dithering/g-sharp_resampler.slangp @@ -0,0 +1,5 @@ +shaders = 1 + +shader0 = shaders/g-sharp_resampler.slang +scale0 = 1.0 +scale_type0 = source diff --git a/dithering/jinc2-dedither.slangp b/dithering/jinc2-dedither.slangp new file mode 100644 index 00000000..0f34f736 --- /dev/null +++ b/dithering/jinc2-dedither.slangp @@ -0,0 +1,5 @@ +shaders = 1 + +shader0 = shaders/jinc2-dedither.slang +scale0 = 1.0 +scale_type0 = source diff --git a/dithering/shaders/bayer-matrix-dithering.slang b/dithering/shaders/bayer-matrix-dithering.slang index 671bb6e8..c6b70410 100644 --- a/dithering/shaders/bayer-matrix-dithering.slang +++ b/dithering/shaders/bayer-matrix-dithering.slang @@ -57,7 +57,7 @@ layout(location = 0) out vec2 vTexCoord; void main() { gl_Position = global.MVP * Position; - vTexCoord = TexCoord; + vTexCoord = TexCoord * 1.00001; } #pragma stage fragment @@ -84,4 +84,4 @@ finalRGB.b = find_closest(x, y, rgb.b); float final = find_closest(x, y, grayscale); FragColor = vec4(finalRGB, 1.0); -} \ No newline at end of file +} diff --git a/dithering/shaders/g-sharp_resampler.slang b/dithering/shaders/g-sharp_resampler.slang new file mode 100644 index 00000000..b55e2793 --- /dev/null +++ b/dithering/shaders/g-sharp_resampler.slang @@ -0,0 +1,135 @@ +#version 450 + +/* + G-sharp resampler - dynamic range, resizable + + Copyright (C) 2020 - 2021 guest(r) - guest.r@gmail.com + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Anti-Ringing inspired by Hyllian + +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float SIGMA_HV; + float HSHARP0; + float HAR; + float SHAR; +} params; + +#pragma parameter HSHARP0 "Filter Range" 1.2 1.0 6.0 0.1 +#define HSHARP0 params.HSHARP0 + +#pragma parameter SIGMA_HV "Gaussian Blur Sigma" 0.75 0.1 7.0 0.05 +#define SIGMA_HV params.SIGMA_HV + +#pragma parameter SHAR "Sharpness Definition" 0.5 0.0 2.0 0.05 +#define SHAR params.SHAR + +#pragma parameter HAR "Anti-Ringing" 0.5 0.0 1.0 0.10 +#define HAR params.HAR + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#define COMPAT_TEXTURE(c,d) texture(c,d) +#define SourceSize params.SourceSize + +float invsqrsigma_h = 1.0/(2.0*SIGMA_HV*SIGMA_HV); + +float gaussian(float x, float y) +{ + return exp(-(x*x + y*y)*invsqrsigma_h); +} + +void main() +{ + vec2 f = fract(SourceSize.xy * vTexCoord.xy); + f = 0.5 - f; + vec2 tex = floor(SourceSize.xy * vTexCoord)*SourceSize.zw + 0.5*SourceSize.zw; + vec2 dx = vec2(SourceSize.z, 0.0); + vec2 dy = vec2(0.0, SourceSize.w); + + vec3 colorx = 0.0.xxx; + vec3 colory = 0.0.xxx; + float wx, wy; + float wsumx = 0.0; + float wsumy = 0.0; + vec3 pixel; + float x; + + vec3 xcmax = 0.0.xxx; + vec3 xcmin = 1.0.xxx; + + float sharp = gaussian(HSHARP0, 0.0); + float maxsharp = 0.07; + float FPR = HSHARP0; + float fpx = 1.0; + + float LOOPSIZE = ceil(2.0*FPR); + float y = -LOOPSIZE; + + do + { + x = -LOOPSIZE; + + do + { + pixel = COMPAT_TEXTURE(Source, tex + x*dx + y*dy).rgb; + + wx = gaussian(x+f.x, y+f.y) - sharp; + fpx = (sqrt(dot(vec2(x+f.x,y+f.y),vec2(x+f.x,y+f.y)))-FPR)/FPR; + if (((x*x) + (y*y)) < 1.25*FPR) { xcmax = max(xcmax, pixel); xcmin = min(xcmin, pixel); } + if (wx < 0.0) wx = clamp(wx, mix(-maxsharp, 0.0, pow(abs(fpx), SHAR)), 0.0); + colorx = colorx + wx * pixel; + wsumx = wsumx + wx; + x = x + 1.0; + + } while (x <= LOOPSIZE); + + y = y + 1.0; + + } while (y <= LOOPSIZE); + + vec3 color = colorx/wsumx; + + color = mix(clamp(color, 0.0, 1.0), clamp(color, xcmin, xcmax), HAR); + + FragColor = vec4(color, 1.0); +} diff --git a/stereoscopic-3d/fubax_vr.slangp b/stereoscopic-3d/fubax_vr.slangp new file mode 100644 index 00000000..b7760f3c --- /dev/null +++ b/stereoscopic-3d/fubax_vr.slangp @@ -0,0 +1,28 @@ +shaders = 5 + +shader0 = ../stock.slang +scale_type0 = viewport +scale0 = 1.0 + +shader1 = shaders/fubax_vr/VR.slang +scale_type1 = viewport +scale1 = 1.0 +filter_linear1 = true + +shader2 = shaders/fubax_vr/Chromatic.slang +scale_type2 = viewport +scale2 = 1.0 +filter_linear2 = true + +shader3 = shaders/fubax_vr/FilmicSharpen.slang +scale_type3 = viewport +scale3 = 1.0 +filter_linear3 = true + +shader4 = shaders/fubax_vr/VR_nose.slang +scale_type4 = viewport +scale4 = 1.0 +filter_linear4 = true + +textures = "noseTex" +noseTex = shaders/fubax_vr/nose.png diff --git a/stereoscopic-3d/shaders/anaglyph-to-side-by-side b/stereoscopic-3d/shaders/anaglyph-to-side-by-side.slang similarity index 100% rename from stereoscopic-3d/shaders/anaglyph-to-side-by-side rename to stereoscopic-3d/shaders/anaglyph-to-side-by-side.slang diff --git a/stereoscopic-3d/shaders/fubax_vr/Chromatic.slang b/stereoscopic-3d/shaders/fubax_vr/Chromatic.slang new file mode 100644 index 00000000..eecfb691 --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/Chromatic.slang @@ -0,0 +1,163 @@ +#version 450 + +/* +/// VR shader /// + +Make any game VR and any screen with lenses a VR headset. +Thanks to this shader you'll be able to correct distortions of any lens types +(DIY, experimental) and chromatic aberration. +Also if a game outputs depth pass you can have a stereo-3D vision thanks to +the parallax mapping (which needs some further improvement). + +Copyright (c) 2019 Jacob Max Fober + +This work is licensed under the Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International License. +To view a copy of this license, visit +http://creativecommons.org/licenses/by-nc-sa/4.0/ + +If you want to use it commercially, contact me at jakub.m.fober@pm.me +If you have questions, visit https://reshade.me/forum/shader-discussion/ + +I'm author of most of equations present here, +beside Brown-Conrady distortion correction model and +Parallax Steep and Occlusion mapping which +I changed and adopted from various sources. + +Version 0.4.2 alpha +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "fubax_vr_params.inc" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 texcoord; + +void main() +{ + gl_Position = global.MVP * Position; + texcoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 texcoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#include "fubax_vr_shared_funcs.inc" + +void main() +{ + // Bypass chromatic aberration switch + if(!ChromaticAbrSwitch) + { + FragColor = vec4(texture(Source, texcoord).rgb, 1.0); + return; + } + + // Get display aspect ratio (horizontal/vertical resolution) + float rAspect = params.OutputSize.x*params.OutputSize.w; + + // Generate negative-positive stereo mask + float SideScreenSwitch = step(0.5, texcoord.x)*2.0-1.0; + + // Divide screen in two if stereo vision mode enabled + vec2 CenterCoord = StereoSwitch? StereoVision(texcoord, IPD) : texcoord; + + CenterCoord = CenterCoord*2.0-1.0; // Center coordinates + CenterCoord.x *= rAspect; // Correct aspect ratio + + float Diagonal = rAspect; + Diagonal *= StereoSwitch ? 0.5 : 1.0; + Diagonal = length(vec2(Diagonal, 1.0)); + + CenterCoord /= Diagonal; // Normalize diagonally + + // Left/right eye mask + float L = step(0.5, 1.0-texcoord.x); + float R = step(0.5, texcoord.x); + + // Offset center green + vec2 CoordGreen = ChGreenOffsetL * L + ChGreenOffsetR * R; + CoordGreen.x *= -1.0; + CoordGreen = 0.01 * CoordGreen + CenterCoord; + // Offset center blue + vec2 CoordBlue = ChBlueOffsetL * L + ChBlueOffsetR * R; + CoordBlue.x *= -1.0; + CoordBlue = 0.01 * CoordBlue + CenterCoord; + +// float RadiusGreen = dot(CoordGreen, CoordGreen); // Radius squared (techically accurate) +// float RadiusBlue = dot(CoordBlue, CoordBlue); // Radius squared (techically accurate) + float RadiusGreen = length(CoordGreen); // Radius + float RadiusBlue = length(CoordBlue); // Radius + + // Calculate radial distortion K + float correctionGreenK = (1.0+ChGreenK.x)*kRadial(RadiusGreen, ChGreenK.y, ChGreenK.z, ChGreenK.w, 0.0); + float correctionBlueK = (1.0+ChBlueK.x)*kRadial(RadiusBlue, ChBlueK.y, ChBlueK.z, ChBlueK.w, 0.0); + + // Apply chromatic aberration correction + CoordGreen = CoordGreen * correctionGreenK; + CoordBlue = CoordBlue * correctionBlueK; + + CoordGreen *= Diagonal; CoordBlue *= Diagonal; // Back to vertical normalization + CoordGreen.x /= rAspect; CoordBlue.x /= rAspect; // Back to square + + // Move origin to left top corner + CoordGreen = CoordGreen * 0.5 + 0.5; CoordBlue = CoordBlue * 0.5 + 0.5; + + // Generate border mask for green and blue channel + float MaskBlue, MaskGreen; if(StereoSwitch) + { + // Mask compensation for center cut + float CenterCut = 0.5+(0.5-IPD)*SideScreenSwitch; + + // Mask sides and center cut for blue channel + vec2 MaskCoordBlue; + MaskCoordBlue.x = CoordBlue.x*2.0 - CenterCut; // Compensate for 2 views + MaskCoordBlue.y = CoordBlue.y; + MaskBlue = BorderMaskAA(MaskCoordBlue); + + // Mask sides and center cut for green channel + vec2 MaskCoordGreen; + MaskCoordGreen.x = CoordGreen.x*2.0 - CenterCut; // Compensate for 2 views + MaskCoordGreen.y = CoordGreen.y; + MaskGreen = BorderMaskAA(MaskCoordGreen); + + // Reverse stereo coordinates to single view + CoordGreen = InvStereoVision(CoordGreen, int(SideScreenSwitch), IPD); + CoordBlue = InvStereoVision(CoordBlue, int(SideScreenSwitch), IPD); + } + else + { + MaskBlue = BorderMaskAA(CoordBlue); + MaskGreen = BorderMaskAA(CoordGreen); + }; + + vec3 Image; + // Sample image red + Image.r = texture(Source, texcoord).r; + // Sample image green + Image.g = mix( + texture(Source, CoordGreen).g, + 0.0, // Black borders + MaskGreen // Anti-aliased border mask + ); + // Sample image blue + Image.b = mix( + texture(Source, CoordBlue).b, + 0.0, // Black borders + MaskBlue // Anti-aliased border mask + ); + + // Display chromatic aberration + FragColor = vec4(Image, 1.0); +} diff --git a/stereoscopic-3d/shaders/fubax_vr/FilmicSharpen.slang b/stereoscopic-3d/shaders/fubax_vr/FilmicSharpen.slang new file mode 100644 index 00000000..34414708 --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/FilmicSharpen.slang @@ -0,0 +1,101 @@ +#version 450 + +/* +/// VR shader /// + +Make any game VR and any screen with lenses a VR headset. +Thanks to this shader you'll be able to correct distortions of any lens types +(DIY, experimental) and chromatic aberration. +Also if a game outputs depth pass you can have a stereo-3D vision thanks to +the parallax mapping (which needs some further improvement). + +Copyright (c) 2019 Jacob Max Fober + +This work is licensed under the Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International License. +To view a copy of this license, visit +http://creativecommons.org/licenses/by-nc-sa/4.0/ + +If you want to use it commercially, contact me at jakub.m.fober@pm.me +If you have questions, visit https://reshade.me/forum/shader-discussion/ + +I'm author of most of equations present here, +beside Brown-Conrady distortion correction model and +Parallax Steep and Occlusion mapping which +I changed and adopted from various sources. + +Version 0.4.2 alpha +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "fubax_vr_params.inc" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 texcoord; + +void main() +{ + gl_Position = global.MVP * Position; + texcoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 texcoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#include "fubax_vr_shared_funcs.inc" + +void main() +{ + vec2 UvCoord = texcoord; + // Bypass sharpening + if(!Sharpen) + { + FragColor = vec4(texture(Source, UvCoord).rgb, 1.0); + return; + } + + vec2 Pixel = (texcoord.xy * params.OutputSize.xy) * Offset; + // Sample display image + vec3 ImgSource = texture(Source, UvCoord).rgb; + + vec2 NorSouWesEst[4] = { + vec2(UvCoord.x, UvCoord.y + Pixel.y), + vec2(UvCoord.x, UvCoord.y - Pixel.y), + vec2(UvCoord.x + Pixel.x, UvCoord.y), + vec2(UvCoord.x - Pixel.x, UvCoord.y) + }; + + // Luma high-pass + float HighPass = 0.0; + for(int i=0; i<4; i++) + { + HighPass += Luma(texture(Source, NorSouWesEst[i]).rgb); + } + HighPass = 0.5 - 0.5 * (HighPass * 0.25 - Luma(ImgSource)); + + // Sharpen strength + HighPass = mix(0.5, HighPass, Strength * 0.01); + + // Clamping sharpen + HighPass = (Clamp != 1.0) ? max(min(HighPass, Clamp), 1.0 - Clamp) : HighPass; + + vec3 Sharpen = vec3( + Overlay(ImgSource.r, HighPass), + Overlay(ImgSource.g, HighPass), + Overlay(ImgSource.b, HighPass) + ); + + FragColor.rgb = (Preview) ? vec3(HighPass) : Sharpen; + FragColor.a = 1.0; +} diff --git a/stereoscopic-3d/shaders/fubax_vr/VR.slang b/stereoscopic-3d/shaders/fubax_vr/VR.slang new file mode 100644 index 00000000..42549180 --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/VR.slang @@ -0,0 +1,172 @@ +#version 450 + +/* +/// VR shader /// + +Make any game VR and any screen with lenses a VR headset. +Thanks to this shader you'll be able to correct distortions of any lens types +(DIY, experimental) and chromatic aberration. +Also if a game outputs depth pass you can have a stereo-3D vision thanks to +the parallax mapping (which needs some further improvement). + +Copyright (c) 2019 Jacob Max Fober + +This work is licensed under the Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International License. +To view a copy of this license, visit +http://creativecommons.org/licenses/by-nc-sa/4.0/ + +If you want to use it commercially, contact me at jakub.m.fober@pm.me +If you have questions, visit https://reshade.me/forum/shader-discussion/ + +I'm author of most of equations present here, +beside Brown-Conrady distortion correction model and +Parallax Steep and Occlusion mapping which +I changed and adopted from various sources. + +Version 0.4.2 alpha +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "fubax_vr_params.inc" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 texcoord; + +void main() +{ + gl_Position = global.MVP * Position; + texcoord = TexCoord * 1.00001; +} + +#pragma stage fragment +layout(location = 0) in vec2 texcoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#include "fubax_vr_shared_funcs.inc" + +void main() +{ + // Get display aspect ratio (horizontal/vertical resolution) + const float rAspect = params.OutputSize.x*params.OutputSize.w; + + // Divide screen in two + vec2 UvCoord = StereoSwitch? StereoVision(texcoord, IPD) : texcoord; + + // Generate negative-positive stereo mask + float StereoMask = step(0.5, texcoord.x)*2.0-1.0; + + // Correct lens distortion + if(PerspectiveSwitch) + { + // Center coordinates + UvCoord = UvCoord*2.0-1.0; + UvCoord.x *= rAspect; + vec2 StereoCoord = UvCoord; // Save coordinates for Brown-Conrady correction + + // Base distortion correction + if(bool(FOV)) // If FOV is not equal 0 + { + float radFOV = radians(FOV); + // Calculate radius + float Radius = length(UvCoord); + // Apply base lens correction + switch(LensType) + { + case 0: + { UvCoord *= Orthographic(radFOV, Radius); break; } + case 1: + { UvCoord *= Equisolid(radFOV, Radius); break; } + case 2: + { UvCoord *= Equidistant(radFOV, Radius); break; } + case 3: + { UvCoord *= Stereographic(radFOV, Radius); break; } + } + }; + + // Lens geometric aberration correction (Brown-Conrady model) + float Diagonal = rAspect; + Diagonal *= StereoSwitch ? 0.5 : 1.0; + Diagonal = length(vec2(Diagonal, 1.0)); + float InvDiagonal2 = 1.0 / pow(Diagonal, 2); + + StereoCoord /= Diagonal; // Normalize diagonally + float Radius2 = dot(StereoCoord, StereoCoord); // Squared radius + float correctionK = kRadial(Radius2, K.x, K.y, K.z, K.w); + // Apply negative-positive stereo mask for tangental distortion (flip side) + float SideScreenSwitch = (StereoSwitch) ? StereoMask : 1.0; + + vec2 correctionP = pTangental( + StereoCoord, + Radius2, + P.x * SideScreenSwitch, + P.y, + P.z, + 0.0 + ); + // Expand background to vertical border (but not for test grid for ease of calibration) + UvCoord /= TestGrid ? vec2(1.0) : vec2(kRadial(InvDiagonal2, K.x, K.y, K.z, K.w)); + UvCoord = UvCoord * correctionK + correctionP; // Apply lens correction + + // Scale image + UvCoord /= TestGrid ? vec2(1.0) : vec2(ImageScale); + + // Revert aspect ratio to square + UvCoord.x /= rAspect; + // Move origin back to left top corner + UvCoord = UvCoord*0.5 + vec2(0.5); + } + + // Display test grid + if(TestGrid) { + FragColor = vec4(Grid(UvCoord, rAspect), 1.0); + return; + } + +/* Disable for RetroArch since there's no depth buffer + // Create parallax effect + if(ParallaxSwitch) + { + float ParallaxDirection = ParallaxOffset*0.01; + // For stereo-vison flip direction on one side + ParallaxDirection *= StereoSwitch ? StereoMask : 1.0; + // Apply parallax effect + UvCoord = Parallax( + UvCoord, + ParallaxDirection, + ParallaxCenter, + ParallaxMaskScalar, + ParallaxSteps + ); + } +*/ + + // added by hunterk to adjust aspect ratio of the image + vec2 corrected_size = params.SourceSize.xy * vec2(img_ar.x / img_ar.y, 1.0) + * vec2(params.SourceSize.y / params.SourceSize.x, 1.0); + float full_scale = params.OutputSize.y / params.SourceSize.y; + vec2 scale = (params.OutputSize.xy / corrected_size) / full_scale; + vec2 middle = vec2(0.49999, 0.49999); + vec2 diff = UvCoord.xy - middle; + vec2 screen_coord = middle + diff * scale; + UvCoord = ((screen_coord - vec2(0.5)) * imgzoom) + vec2(0.5); + + // Sample image with black borders to display + vec3 Image = mix( + texture(Source, UvCoord).rgb, // Display image + vec3(0.0), // Black borders + BorderMaskAA(UvCoord) // Anti-aliased border mask + ); + + // Display image + FragColor = vec4(Image, 1.0); +} diff --git a/stereoscopic-3d/shaders/fubax_vr/VR_nose.slang b/stereoscopic-3d/shaders/fubax_vr/VR_nose.slang new file mode 100644 index 00000000..424e2f8f --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/VR_nose.slang @@ -0,0 +1,95 @@ +#version 450 + +/* +Nose PS (c) 2019 Jacob Maximilian Fober + +Anti-nausea shader for VR + +This work is licensed under the Creative Commons +Attribution-ShareAlike 4.0 International License. +To view a copy of this license, visit +http://creativecommons.org/licenses/by-sa/4.0/. +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#ifndef nose +#define nose 128 // Nose texture resolution +#endif + +#define mul(c,d) (d*c) + +#include "fubax_vr_params.inc" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 texcoord; + +void main() +{ + gl_Position = global.MVP * Position; + texcoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 texcoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D noseTex; + +//#include "fubax_vr_shared_funcs.inc" +// Convert RGB to YUV +vec3 yuv(vec3 rgbImage) +{ + // RGB to YUV709 matrix + const mat3 YUV709 = + mat3( + vec3(0.2126, 0.7152, 0.0722), + vec3(-0.09991, -0.33609, 0.436), + vec3(0.615, -0.55861, -0.05639) + ); + return mul(YUV709, rgbImage); +} + +// Overlay blending mode +float Overlay(float LayerAB) +{ + float MinAB = min(LayerAB, 0.5); + float MaxAB = max(LayerAB, 0.5); + return 2.0 * (MinAB*MinAB + 2.0*MaxAB - MaxAB*MaxAB) - 1.5; +} + +void main() +{ + vec2 UvCoord = texcoord; + // Bypass sharpening + if(!Nose) + { + FragColor = vec4(texture(Source, UvCoord).rgb, 1.0); + return; + } + + // Divide screen in two (mirrored) + vec2 StereoCoord = texcoord; + StereoCoord.x = 1.0-abs(StereoCoord.x*2.0-1.0)/Scale.x; + StereoCoord.y = 1.0-(1.0-StereoCoord.y)/Scale.y; + + // Sample display image + vec3 Display = texture(Source, texcoord).rgb; + // Sample nose texture + vec4 NoseTexture = texture(noseTex, StereoCoord); + // Change skintone + NoseTexture.rgb *= mix(smoothstep(0.0, 1.0, yuv(NoseTexture.rgb).x), 1.0, Brightness); + + + // Blend nose with display image + FragColor.rgb = mix(Display, NoseTexture.rgb, NoseTexture.a); + FragColor.a = 1.0; +} diff --git a/stereoscopic-3d/shaders/fubax_vr/fubax_vr_params.inc b/stereoscopic-3d/shaders/fubax_vr/fubax_vr_params.inc new file mode 100644 index 00000000..48459b88 --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/fubax_vr_params.inc @@ -0,0 +1,123 @@ +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + float SoloLines, TestGrid, IPD, StereoSwitch, FOV, LensType, K1, K2, + K3, K4, P1, P2, P3, ImageScale, PerspectiveSwitch, ChGreenK1, ChGreenK2, + ChGreenK3, ChGreenK4, SoloGreen, ChBlueK1, ChBlueK2, ChBlueK3, ChBlueK4, + SoloBlue, ChromaticAbrSwitch, ChGreenOffsetL_x, ChGreenOffsetL_y, + ChBlueOffsetL_x, ChBlueOffsetL_y, ChGreenOffsetR_x, ChGreenOffsetR_y, + ChBlueOffsetR_x, ChBlueOffsetR_y, Strength, Clamp, Offset, Preview, + Sharpen, Nose, Brightness, Scale_x, Scale_y, imgzoom, aspect_x, aspect_y; + /*ParallaxOffset, ParallaxCenter, ParallaxSteps, ParallaxMaskScalar, + ParallaxSwitch */ +} global; + +#ifndef MaximumParallaxSteps +#define MaximumParallaxSteps 1024 // Defefine max steps to make loop finite +#endif + +// Grid settings +#ifndef BoxAmount +#define BoxAmount 31 // Number of boxes horizontally (choose odd number) +#endif + +#ifndef thicknessA +#define thicknessA 0.25 // White grid thickness +#endif + +#ifndef thicknessB +#define thicknessB 0.125 // Yellow cross thickness +#endif + +#ifndef crossColor +#define crossColor vec3(1.0, 1.0, 0.0) // Center cross color (yellow) +#endif + +#pragma parameter TestGrid "Toggle Calibration Grid" 0.0 0.0 1.0 1.0 +#pragma parameter StereoSwitch "Toggle Stereo Vision" 1.0 0.0 1.0 1.0 +#pragma parameter PerspectiveSwitch "Toggle Lens Correction" 1.0 0.0 1.0 1.0 +//#pragma parameter ParallaxSwitch "Toggle Parallax Effect" 1.0 0.0 1.0 1.0 +#pragma parameter ChromaticAbrSwitch "Toggle Chromatic Correction" 1.0 0.0 1.0 1.0 +#pragma parameter Nose "Toggle Virtual Nose (helps nausea)" 0.0 0.0 1.0 1.0 +#pragma parameter Sharpen "Toggle Sharpening" 1.0 0.0 1.0 1.0 +#pragma parameter SoloLines "Lines (All, Horz, Vert, Rad)" 0.0 0.0 3.0 1.0 +#pragma parameter IPD "IPD (Interpupillary Distance)" 0.500 0.0 0.75 0.001 +#pragma parameter imgzoom "Image Zoom" 1.6 0.1 5.0 0.01 +#pragma parameter aspect_x "Image Aspect Ratio Numerator" 64.0 1.0 256.0 1.0 +#pragma parameter aspect_y "Image Aspect Ratio Denominator" 49.0 1.0 256. 1.0 +//#pragma parameter ParallaxOffset "Parallax Horizontal Offset" 0.355 0.0 1.0 0.001 +//#pragma parameter ParallaxCenter "Parallax Rotation Center (ZPD)" 1.0 0.0 1.0 0.001 +//#pragma parameter ParallaxSteps "Parallax Sampling Steps" 16.0 1.0 128.0 0.2 +//#pragma parameter ParallaxMaskScalar "Parallax Gap Compensation" 10.0 0.0 32.0 0.2 +#pragma parameter FOV "Lens Distortion Power" 96.0 0.0 170.0 0.1 +#pragma parameter LensType "Lens Dist Type (Ortho, Equisolid, Equidist, Stereo)" 0.0 0.0 3.0 1.0 +#pragma parameter K1 "Radial Correction #1 (Brown-Conrady Model)" 0.0 0.0 1.0 0.01 +#pragma parameter K2 "Radial Correction #2 (Brown-Conrady Model)" 0.0 0.0 1.0 0.01 +#pragma parameter K3 "Radial Correction #3 (Brown-Conrady Model)" 0.0 0.0 1.0 0.01 +#pragma parameter K4 "Radial Correction #4 (Brown-Conrady Model)" 0.0 0.0 1.0 0.01 +#pragma parameter P1 "Tangential Correction #1 (Brown-Conrady Model)" 0.0 0.0 1.0 0.001 +#pragma parameter P2 "Tangential Correction #2 (Brown-Conrady Model)" 0.0 0.0 1.0 0.001 +#pragma parameter P3 "Tangential Correction #3 (Brown-Conrady Model)" 0.0 0.0 1.0 0.001 +#pragma parameter ImageScale "Image Scale" 1.0 0.25 1.0 0.01 +#pragma parameter ChGreenK1 "Chromatic Green Correction (Zoom)" 0.0 0.0 1.0 0.001 +#pragma parameter ChGreenK2 "Chromatic Green Correction (K1)" 0.0 0.0 1.0 0.001 +#pragma parameter ChGreenK3 "Chromatic Green Correction (K2)" 0.0 0.0 1.0 0.001 +#pragma parameter ChGreenK4 "Chromatic Green Correction (K3)" 0.0 0.0 1.0 0.001 +#pragma parameter SoloGreen "Green Channel Adj Solo" 0.0 0.0 1.0 1.0 +#pragma parameter ChBlueK1 "Chromatic Blue Correction (Zoom)" 0.0 0.0 1.0 0.001 +#pragma parameter ChBlueK2 "Chromatic Blue Correction (K1)" 0.0 0.0 1.0 0.001 +#pragma parameter ChBlueK3 "Chromatic Blue Correction (K2)" 0.0 0.0 1.0 0.001 +#pragma parameter ChBlueK4 "Chromatic Blue Correction (K3)" 0.0 0.0 1.0 0.001 +#pragma parameter SoloBlue "Blue Channel Adj Solo" 0.0 0.0 1.0 1.0 +#pragma parameter ChGreenOffsetL_x "Left Green Center Offset X" 0.0 -0.2 0.2 0.001 +#pragma parameter ChGreenOffsetL_y "Left Green Center Offset Y" 0.0 -0.2 0.2 0.001 +#pragma parameter ChBlueOffsetL_x "Left Blue Center Offset X" 0.0 -0.2 0.2 0.001 +#pragma parameter ChBlueOffsetL_y "Left Blue Center Offset Y" 0.0 -0.2 0.2 0.001 +#pragma parameter ChGreenOffsetR_x "Right Green Center Offset X" 0.0 -0.2 0.2 0.001 +#pragma parameter ChGreenOffsetR_y "Right Green Center Offset Y" 0.0 -0.2 0.2 0.001 +#pragma parameter ChBlueOffsetR_x "Right Blue Center Offset X" 0.0 -0.2 0.2 0.001 +#pragma parameter ChBlueOffsetR_y "Right Blue Center Offset Y" 0.0 -0.2 0.2 0.001 +#pragma parameter Strength "Sharpen Strength" 25.0 0.0 100.0 0.5 +#pragma parameter Clamp "Sharpen Clamping" 0.65 0.5 1.0 0.001 +#pragma parameter Offset "High-pass Offset" 0.1 0.01 2.0 0.002 +#pragma parameter Preview "Preview Sharpen Layer" 0.0 0.0 1.0 1.0 +#pragma parameter Brightness "Virtual Nose Brightness" 1.0 0.0 1.0 0.01 +#pragma parameter Scale_x "Virtual Nose Scale X" 0.382 0.1 1.0 0.01 +#pragma parameter Scale_y "Virtual Nose Scale Y" 0.618 0.1 1.0 0.01 + +int SoloLines = int(global.SoloLines); +bool TestGrid = bool(global.TestGrid); +float IPD = global.IPD; +bool StereoSwitch = bool(global.StereoSwitch); +//float ParallaxOffset = global.ParallaxOffset; +//float ParallaxCenter = global.ParallaxCenter; +//int ParallaxSteps = int(global.ParallaxSteps); +//int ParallaxMaskScalar = int(global.ParallaxMaskScalar); +//bool ParallaxSwitch = bool(global.ParallaxSwitch); +int FOV = int(global.FOV); +int LensType = int(global.LensType); +vec4 K = vec4(global.K1, global.K2, global.K3, global.K4); +vec3 P = vec3(global.P1, global.P2, global.P3); +float ImageScale = global.ImageScale; +bool PerspectiveSwitch = bool(global.PerspectiveSwitch); +vec4 ChGreenK = vec4(global.ChGreenK1, global.ChGreenK2, global.ChGreenK3, + global.ChGreenK4); +bool SoloGreen = bool(global.SoloGreen); +vec4 ChBlueK = vec4(global.ChBlueK1, global.ChBlueK2, global.ChBlueK3, + global.ChBlueK4); +bool SoloBlue = bool(global.SoloBlue); +bool ChromaticAbrSwitch = bool(global.ChromaticAbrSwitch); +vec2 ChGreenOffsetL = vec2(global.ChGreenOffsetL_x, global.ChGreenOffsetL_y); +vec2 ChBlueOffsetL = vec2(global.ChBlueOffsetL_x, global.ChBlueOffsetL_y); +vec2 ChGreenOffsetR = vec2(global.ChGreenOffsetR_x, global.ChGreenOffsetR_y); +vec2 ChBlueOffsetR = vec2(global.ChBlueOffsetR_x, global.ChBlueOffsetR_y); +float Strength = global.Strength; +float Clamp = global.Clamp; +float Offset = global.Offset; +bool Preview = bool(global.Preview); +bool Sharpen = bool(global.Sharpen); +bool Nose = bool(global.Nose); +float Brightness = global.Brightness; +vec2 Scale = vec2(global.Scale_x, global.Scale_y); +float imgzoom = global.imgzoom; +vec2 img_ar = vec2(global.aspect_x, global.aspect_y); diff --git a/stereoscopic-3d/shaders/fubax_vr/fubax_vr_shared_funcs.inc b/stereoscopic-3d/shaders/fubax_vr/fubax_vr_shared_funcs.inc new file mode 100644 index 00000000..8cab660a --- /dev/null +++ b/stereoscopic-3d/shaders/fubax_vr/fubax_vr_shared_funcs.inc @@ -0,0 +1,205 @@ +// Adjust to limited RGB +vec3 tv(vec3 Input) +{ return Input*((235.0-16.0)/255.0)+16.0/255.0; } + +// Generate test grid +vec3 Grid(vec2 Coordinates, float AspectRatio) +{ +// Grid settings +#ifndef BoxAmount +#define BoxAmount 31 // Number of boxes horizontally (choose odd number) +#endif + +#ifndef thicknessA +#define thicknessA 0.25 // White grid thickness +#endif + +#ifndef thicknessB +#define thicknessB 0.125 // Yellow cross thickness +#endif + +#ifndef crossColor +#define crossColor vec3(1.0, 1.0, 0.0) // Center cross color (yellow) +#endif + + bool RadialPattern = (SoloLines == 3); + + vec2 GridCoord = Coordinates; + GridCoord.y -= 0.5; // Center coordinates vertically + GridCoord.y /= AspectRatio; // Correct aspect + GridCoord.y += 0.5; // Center at middle + + vec2 CrossUV = GridCoord; // Store center cross coordinates + + vec2 PixelSize; vec3 gridColor; + // Generate grid pattern + GridCoord = (RadialPattern) ? vec2(length(GridCoord-0.5)*1.618) : GridCoord; // Switch to radial pattern + GridCoord = abs(fract(GridCoord*BoxAmount)*2.0-1.0)*(thicknessA+1.0); + // Anti-aliased grid + PixelSize = fwidth(GridCoord.xy); + GridCoord = smoothstep(1.0-PixelSize, 1.0+PixelSize, GridCoord); + + // Combine/solo vertical and horizontal lines + switch(SoloLines) + { + case 1: + { gridColor = vec3(GridCoord.y); break; } + case 2: + { gridColor = vec3(GridCoord.x); break; } + default: + { gridColor = vec3(max(GridCoord.x, GridCoord.y)); break; } + }; + + // Generate center cross + CrossUV = 1.0-abs(CrossUV*2.0-1.0); + CrossUV = CrossUV*(thicknessB/BoxAmount+1.0); + // Anti-aliased cross + PixelSize = fwidth(CrossUV); + CrossUV = smoothstep(1.0-PixelSize, 1.0+PixelSize, CrossUV); + // Combine vertical and horizontal line + float CrossMask = max(CrossUV.y, CrossUV.x); + + // Blend grid and center cross + gridColor = mix(gridColor, ((RadialPattern) ? vec3(1.0) : crossColor), vec3(CrossMask)); + + // Solo colors + if(SoloGreen) gridColor.b = 0.0; + if(SoloBlue) gridColor.g = 0.0; + + // Reduce grid brightness + return tv(gridColor); +} + +// Divide screen into two halfs +vec2 StereoVision(vec2 Coordinates, float Center) +{ + vec2 StereoCoord = Coordinates; + StereoCoord.x = 0.25 + abs( StereoCoord.x*2.0-1.0 ) * 0.5; // Divide screen in two + StereoCoord.x -= mix(-0.25, 0.25, Center); // Change center for interpupillary distance (IPD) + // Mirror left half + float ScreenSide = step(0.5, Coordinates.x); + StereoCoord.x *= ScreenSide*2.0-1.0; + StereoCoord.x += 1.0 - ScreenSide; + return StereoCoord; +} + +// Convert stereo coordinates to mono +vec2 InvStereoVision(vec2 Coordinates, int ScreenMask, float Center) +{ + vec2 stereoCoord = Coordinates; + stereoCoord.x += Center*0.5 * ScreenMask; + return stereoCoord; +} + +// Generate border mask with anti-aliasing from UV coordinates +float BorderMaskAA(vec2 Coordinates) +{ + vec2 RaidalCoord = abs(Coordinates*2.0-1.0); + // Get pixel size in transformed coordinates (for anti-aliasing) + vec2 PixelSize = fwidth(RaidalCoord); + + // Create borders mask (with anti-aliasing) + vec2 Borders = smoothstep(1.0-PixelSize, 1.0+PixelSize, RaidalCoord); + + // Combine side and top borders + return max(Borders.x, Borders.y); +} + +/* +// Can't really use this one as RetroArch can't access the depth buffer +float GetDepth(vec2 texcoord) +{ + return ReShade::GetLinearizedDepth(texcoord); +} + + +// Horizontal parallax offset effect +vec2 Parallax(vec2 Coordinates, float Offset, float Center, int GapOffset, int Steps) +{ +// Limit amount of loop steps to make it finite +#ifndef MaximumParallaxSteps +#def MaximumParallaxSteps 64 +#endif + + // Offset per step progress + float LayerDepth = 1.0 / min(MaximumParallaxSteps, Steps); + + // Netto layer offset change + float deltaCoordinates = Offset * LayerDepth; + + vec2 ParallaxCoord = Coordinates; + // Offset image horizontally so that parallax is in the depth appointed center + ParallaxCoord.x += Offset * Center; + float CurrentDepthMapValue = GetDepth(ParallaxCoord); // Replace function + + // Steep parallax mapping + float CurrentLayerDepth = 0.0; + [loop] + while(CurrentLayerDepth < CurrentDepthMapValue) + { + // Shift coordinates horizontally in linear fasion + ParallaxCoord.x -= deltaCoordinates; + // Get depth value at current coordinates + CurrentDepthMapValue = GetDepth(ParallaxCoord); // Replace function + // Get depth of next layer + CurrentLayerDepth += LayerDepth; + continue; + } + + // Parallax Occlusion Mapping + vec2 PrevParallaxCoord = ParallaxCoord; + PrevParallaxCoord.x += deltaCoordinates; + float afterDepthValue = CurrentDepthMapValue - CurrentLayerDepth; + float beforeDepthValue = GetDepth(PrevParallaxCoord); // Replace function + // Store depth read difference for masking + float DepthDifference = beforeDepthValue - CurrentDepthMapValue; + + beforeDepthValue += LayerDepth - CurrentLayerDepth; + // Interpolate coordinates + float weight = afterDepthValue / (afterDepthValue - beforeDepthValue); + ParallaxCoord = PrevParallaxCoord * weight + ParallaxCoord * (1.0 - weight); + + // Apply gap masking (by JMF) + DepthDifference *= GapOffset * Offset * 100.0; + DepthDifference *= ReShade::PixelSize.x; // Replace function + ParallaxCoord.x += DepthDifference; + + return ParallaxCoord; +}; +*/ + +// Lens projection model (algorithm by JMF) +float Orthographic(float rFOV, float R){ return tan(asin(sin(rFOV*0.5)*R))/(tan(rFOV*0.5)*R); } +float Equisolid(float rFOV, float R){ return tan(asin(sin(rFOV*0.25)*R)*2.0)/(tan(rFOV*0.5)*R); } +float Equidistant(float rFOV, float R){ return tan(R*rFOV*0.5)/(tan(rFOV*0.5)*R); } +float Stereographic(float rFOV, float R){ return tan(atan(tan(rFOV*0.25)*R)*2.0)/(tan(rFOV*0.5)*R); } + +// Brown-Conrady radial distortion model (multiply by coordinates) +float kRadial(float R2, float K1, float K2, float K3, float K4) +{ return 1.0 + K1*R2 + K2*pow(R2,2) + K3*pow(R2,4) + K4*pow(R2,6); } + +// Brown-Conrady tangental distortion model (add to coordinates) +vec2 pTangental(vec2 Coord, float R2, float P1, float P2, float P3, float P4) +{ + return vec2( + (P1*(R2+pow(Coord.x,2)*2.0)+2.0*P2*Coord.x*Coord.y)*(1.0+P3*R2+P4*pow(R2,2)), + (P2*(R2+pow(Coord.y,2)*2.0)+2.0*P1*Coord.x*Coord.y)*(1.0+P3*R2+P4*pow(R2,2)) + ); +} + +// RGB to YUV709.luma +float Luma(vec3 Input) +{ + const vec3 Luma709 = vec3(0.2126, 0.7152, 0.0722); + return dot(Input, Luma709); +} + +// Overlay blending mode +float Overlay(float LayerA, float LayerB) +{ + float MinA = min(LayerA, 0.5); + float MinB = min(LayerB, 0.5); + float MaxA = max(LayerA, 0.5); + float MaxB = max(LayerB, 0.5); + return 2.0 * (MinA * MinB + MaxA + MaxB - MaxA * MaxB) - 1.5; +} diff --git a/stereoscopic-3d/shaders/fubax_vr/nose.png b/stereoscopic-3d/shaders/fubax_vr/nose.png new file mode 100644 index 00000000..18113cf9 Binary files /dev/null and b/stereoscopic-3d/shaders/fubax_vr/nose.png differ diff --git a/stereoscopic-3d/shaders/shutter-to-side-by-side.slang b/stereoscopic-3d/shaders/shutter-to-side-by-side.slang index 5d61d7a3..5d7be926 100644 --- a/stereoscopic-3d/shaders/shutter-to-side-by-side.slang +++ b/stereoscopic-3d/shaders/shutter-to-side-by-side.slang @@ -60,7 +60,7 @@ layout(location = 1) in vec2 right_coord; layout(location = 2) in float timer; layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform sampler2D Source; -layout(set = 0, binding = 2) uniform sampler2D OriginalHistory1; +layout(set = 0, binding = 3) uniform sampler2D OriginalHistory1; #define PrevTexture OriginalHistory1 diff --git a/stereoscopic-3d/side-by-side-simple.slangp b/stereoscopic-3d/side-by-side-simple.slangp index 11a84ab7..fb44af29 100644 --- a/stereoscopic-3d/side-by-side-simple.slangp +++ b/stereoscopic-3d/side-by-side-simple.slangp @@ -1,3 +1,3 @@ shaders = 1 -shaders0 = shaders/side-by-side-simple.slang +shader0 = shaders/side-by-side-simple.slang