slang-shaders/stereoscopic-3d/shaders/anaglyph-to-side-by-side.slang

98 lines
3.0 KiB
Plaintext

#version 450
// Anaglyph to Side-by-Side
// by hunterk
// license: public domain
//
// This shader is designed to convert Mednafen-VB's anaglyph 3D output to
// side-by-side 3D for use with VR headsets, such as Oculus Rift and Google Cardboard, and 3D TVs
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float eye_sep;
float y_loc;
float BOTH;
float ana_zoom;
float WIDTH;
float HEIGHT;
float palette;
float warp_enable;
float warpX;
float warpY;
float anaglyph_selector;
float eye_swap;
} params;
#pragma parameter eye_sep "Eye Separation" 0.5 -1.0 5.0 0.01
#pragma parameter y_loc "Vertical Placement" 0.50 -1.0 1.0 0.025
#pragma parameter BOTH "Horizontal Placement" 1.0 -2.0 2.0 0.005
#pragma parameter ana_zoom "Zoom" 0.75 -2.0 2.0 0.05
#pragma parameter WIDTH "Side-by-Side Image Width" 3.05 1.0 7.0 0.05
#pragma parameter HEIGHT "Side-by-Side Image Height" 2.0 1.0 5.0 0.1
#pragma parameter palette "Red Palette Toggle" 0.0 0.0 1.0 1.0
#pragma parameter warp_enable "Lens Correction" 1.0 0.0 1.0 1.0
#pragma parameter warpX "warpX" 0.3 0.0 0.5 0.05
#pragma parameter warpY "warpY" 0.3 0.0 0.5 0.05
#pragma parameter anaglyph_selector "Anaglyph Mode" 0.0 0.0 2.0 1.0
#pragma parameter eye_swap "Swap Eyes" 0.0 0.0 1.0 1.0
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.xy * 1.00001 - 0.5) * params.ana_zoom + 0.5) * vec2(params.WIDTH, params.HEIGHT) - vec2(params.BOTH, 0.0);
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
//warp function from Lottes' scanline shader
vec2 Warp(vec2 pos){
pos=pos*2.0-1.0;
pos*=vec2(1.0+(pos.y*pos.y)*params.warpX,1.0+(pos.x*pos.x)*params.warpY);
return pos*0.5+0.5;}
void main()
{
vec2 coord1 = (params.warp_enable > 0.5) ? Warp((vTexCoord.xy - vec2(params.eye_sep, params.y_loc))) : (vTexCoord.xy - vec2(params.eye_sep, params.y_loc));
vec2 coord2 = (params.warp_enable > 0.5) ? Warp((vTexCoord.xy + vec2(params.eye_sep, -params.y_loc))) : (vTexCoord.xy + vec2(params.eye_sep, -params.y_loc));
vec4 frame1;
vec4 frame2;
if (params.eye_swap < 0.5){
frame1 = texture(Source, coord1);
frame2 = texture(Source, coord2);}
else {
frame1 = texture(Source, coord2);
frame2 = texture(Source, coord1);}
if (params.anaglyph_selector == 0.0){ //red/blue and red/cyan
frame1.rgb = vec3(frame1.r);
frame2.rgb = vec3(max(frame2.g, frame2.b));}
else if (params.anaglyph_selector == 1.0){ //red/green and green/magenta
frame1.rgb = vec3(max(frame1.r, frame1.b));
frame2.rgb = vec3(frame2.g);}
else { //yellow and blue
frame1.rgb = vec3(max(frame1.r, frame1.g));
frame2.rgb = vec3(frame2.b);}
if (params.palette > 0.5)
FragColor = frame1 + frame2;
else
FragColor = vec4(frame1.r + frame2.r, 0.0, 0.0, 1.0);
}