1#version 450
2
3// Anaglyph to Side-by-Side
4// by hunterk
5// license: public domain
6//
7// This shader is designed to convert Mednafen-VB's anaglyph 3D output to
8// side-by-side 3D for use with VR headsets, such as Oculus Rift and Google Cardboard, and 3D TVs
9
10layout(push_constant) uniform Push
11{
12	vec4 SourceSize;
13	vec4 OriginalSize;
14	vec4 OutputSize;
15	uint FrameCount;
16	float eye_sep;
17	float y_loc;
18	float BOTH;
19	float ana_zoom;
20	float WIDTH;
21	float HEIGHT;
22	float palette;
23	float warp_enable;
24	float warpX;
25	float warpY;
26	float anaglyph_selector;
27	float eye_swap;
28} params;
29
30#pragma parameter eye_sep "Eye Separation" 0.5 -1.0 5.0 0.01
31#pragma parameter y_loc "Vertical Placement" 0.50 -1.0 1.0 0.025
32#pragma parameter BOTH "Horizontal Placement" 1.0 -2.0 2.0 0.005
33#pragma parameter ana_zoom "Zoom" 0.75 -2.0 2.0 0.05
34#pragma parameter WIDTH "Side-by-Side Image Width" 3.05 1.0 7.0 0.05
35#pragma parameter HEIGHT "Side-by-Side Image Height" 2.0 1.0 5.0 0.1
36#pragma parameter palette "Red Palette Toggle" 0.0 0.0 1.0 1.0
37#pragma parameter warp_enable "Lens Correction" 1.0 0.0 1.0 1.0
38#pragma parameter warpX "warpX" 0.3 0.0 0.5 0.05
39#pragma parameter warpY "warpY" 0.3 0.0 0.5 0.05
40#pragma parameter anaglyph_selector "Anaglyph Mode" 0.0 0.0 2.0 1.0
41#pragma parameter eye_swap "Swap Eyes" 0.0 0.0 1.0 1.0
42
43layout(std140, set = 0, binding = 0) uniform UBO
44{
45	mat4 MVP;
46} global;
47
48#pragma stage vertex
49layout(location = 0) in vec4 Position;
50layout(location = 1) in vec2 TexCoord;
51layout(location = 0) out vec2 vTexCoord;
52
53void main()
54{
55   gl_Position = global.MVP * Position;
56   vTexCoord = ((TexCoord.xy * 1.00001 - 0.5) * params.ana_zoom + 0.5) * vec2(params.WIDTH, params.HEIGHT) - vec2(params.BOTH, 0.0);
57}
58
59#pragma stage fragment
60layout(location = 0) in vec2 vTexCoord;
61layout(location = 0) out vec4 FragColor;
62layout(set = 0, binding = 2) uniform sampler2D Source;
63
64//warp function from Lottes' scanline shader
65vec2 Warp(vec2 pos){
66  pos=pos*2.0-1.0;
67  pos*=vec2(1.0+(pos.y*pos.y)*params.warpX,1.0+(pos.x*pos.x)*params.warpY);
68  return pos*0.5+0.5;}
69
70void main()
71{
72	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));
73	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));
74
75	vec4 frame1;
76	vec4 frame2;
77if (params.eye_swap < 0.5){
78	frame1 = texture(Source, coord1);
79	frame2 = texture(Source, coord2);}
80else {
81	frame1 = texture(Source, coord2);
82	frame2 = texture(Source, coord1);}
83
84if (params.anaglyph_selector == 0.0){ //red/blue and red/cyan
85	frame1.rgb = vec3(frame1.r);
86	frame2.rgb = vec3(max(frame2.g, frame2.b));}
87else if (params.anaglyph_selector == 1.0){ //red/green and green/magenta
88	frame1.rgb = vec3(max(frame1.r, frame1.b));
89	frame2.rgb = vec3(frame2.g);}
90else { //yellow and blue
91	frame1.rgb = vec3(max(frame1.r, frame1.g));
92	frame2.rgb = vec3(frame2.b);}
93
94if (params.palette > 0.5)
95	FragColor = frame1 + frame2;
96else
97	FragColor = vec4(frame1.r + frame2.r, 0.0, 0.0, 1.0);
98}