2
* This file is part of bino, a 3D video player.
4
* Copyright (C) 2010-2011
5
* Martin Lambers <marlam@marlam.de>
6
* FrƩdƩric Devernay <Frederic.Devernay@inrialpes.fr>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 3 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
25
// mode_red_cyan_monochrome
26
// mode_red_cyan_half_color
27
// mode_red_cyan_full_color
28
// mode_red_cyan_dubois
29
// mode_green_magenta_monochrome
30
// mode_green_magenta_half_color
31
// mode_green_magenta_full_color
32
// mode_green_magenta_dubois
33
// mode_amber_blue_monochrome
34
// mode_amber_blue_half_color
35
// mode_amber_blue_full_color
36
// mode_amber_blue_dubois
37
// mode_red_green_monochrome
38
// mode_red_blue_monochrome
40
// mode_even_odd_columns
44
uniform sampler2D rgb_l;
45
uniform sampler2D rgb_r;
46
uniform float parallax;
48
uniform sampler2D subtitle;
49
uniform float subtitle_parallax;
51
#if defined(mode_onechannel)
52
uniform float channel; // 0.0 for left, 1.0 for right
55
#if defined(mode_even_odd_rows) || defined(mode_even_odd_columns) || defined(mode_checkerboard)
56
uniform sampler2D mask_tex;
61
#if defined(mode_onechannel) || defined(mode_even_odd_rows) || defined(mode_even_odd_columns) || defined(mode_checkerboard)
62
uniform vec3 crosstalk;
65
#if defined(mode_red_cyan_monochrome) || defined(mode_red_cyan_half_color) || defined(mode_green_magenta_monochrome) || defined(mode_green_magenta_half_color) || defined(mode_amber_blue_monochrome) || defined(mode_amber_blue_half_color) || defined(mode_red_green_monochrome) || defined(mode_red_blue_monochrome)
66
float srgb_to_lum(vec3 srgb)
68
// Values taken from http://www.fourcc.org/fccyvrgb.php
69
return dot(srgb, vec3(0.299, 0.587, 0.114));
73
float linear_to_nonlinear(float x)
75
return (x <= 0.0031308 ? (x * 12.92) : (1.055 * pow(x, 1.0 / 2.4) - 0.055));
78
vec3 rgb_to_srgb(vec3 rgb)
84
// Correct variant, see GL_ARB_framebuffer_sRGB extension
85
float sr = linear_to_nonlinear(rgb.r);
86
float sg = linear_to_nonlinear(rgb.g);
87
float sb = linear_to_nonlinear(rgb.b);
88
return vec3(sr, sg, sb);
92
return pow(rgb, 1.0 / 2.2);
95
// Even faster variant, assuming gamma = 2.0
101
#if defined(mode_onechannel) || defined(mode_even_odd_rows) || defined(mode_even_odd_columns) || defined(mode_checkerboard)
102
vec3 ghostbust(vec3 original, vec3 other)
104
return original + crosstalk - (other + original) * crosstalk;
108
vec3 tex_l(vec2 texcoord)
110
return texture2D(rgb_l, texcoord + vec2(parallax, 0.0)).rgb;
113
vec3 tex_r(vec2 texcoord)
115
return texture2D(rgb_r, texcoord - vec2(parallax, 0.0)).rgb;
118
vec4 sub_l(vec2 texcoord)
120
return texture2D(subtitle, vec2(texcoord.x + subtitle_parallax, 1.0 - texcoord.y));
123
vec4 sub_r(vec2 texcoord)
125
return texture2D(subtitle, vec2(texcoord.x - subtitle_parallax, 1.0 - texcoord.y));
128
vec3 blend_subtitle(vec3 rgb, vec4 sub)
130
return mix(rgb, sub.rgb, sub.a);
137
#if defined(mode_onechannel)
139
vec3 l = blend_subtitle(tex_l(gl_TexCoord[0].xy), sub_l(gl_TexCoord[0].xy));
140
vec3 r = blend_subtitle(tex_r(gl_TexCoord[1].xy), sub_r(gl_TexCoord[1].xy));
141
srgb = rgb_to_srgb(ghostbust(mix(l, r, channel), mix(r, l, channel)));
143
#elif defined(mode_even_odd_rows) || defined(mode_even_odd_columns) || defined(mode_checkerboard)
145
/* This implementation of the masked modes works around many different problems and therefore may seem strange.
146
* Why not use stencil buffers?
147
* - Because we want to filter, to account for masked out features
148
* - Because stencil did not work with some drivers when switching fullscreen on/off
149
* Why not use polygon stipple?
150
* - Because we want to filter, to account for masked out features
151
* - Because polygon stippling may not be hardware accelerated and is currently broken with many free drivers
152
* Why use a mask texture? Why not use the mod() function to check for even/odd pixels?
153
* - Because mod() is broken with many drivers, and I found no reliable way to work around it. Some
154
* drivers seem to use extremely low precision arithmetic in the shaders; too low for reliable pixel
155
* position computations.
157
float m = texture2D(mask_tex, gl_TexCoord[2].xy).x;
158
# if defined(mode_even_odd_rows)
159
vec3 rgb0_l = tex_l(gl_TexCoord[0].xy - vec2(0.0, step_y));
160
vec3 rgb1_l = tex_l(gl_TexCoord[0].xy);
161
vec3 rgb2_l = tex_l(gl_TexCoord[0].xy + vec2(0.0, step_y));
162
vec3 rgbc_l = (rgb0_l + 2.0 * rgb1_l + rgb2_l) / 4.0;
163
vec3 rgb0_r = tex_r(gl_TexCoord[1].xy - vec2(0.0, step_y));
164
vec3 rgb1_r = tex_r(gl_TexCoord[1].xy);
165
vec3 rgb2_r = tex_r(gl_TexCoord[1].xy + vec2(0.0, step_y));
166
vec3 rgbc_r = (rgb0_r + 2.0 * rgb1_r + rgb2_r) / 4.0;
167
# elif defined(mode_even_odd_columns)
168
vec3 rgb0_l = tex_l(gl_TexCoord[0].xy - vec2(step_x, 0.0));
169
vec3 rgb1_l = tex_l(gl_TexCoord[0].xy);
170
vec3 rgb2_l = tex_l(gl_TexCoord[0].xy + vec2(step_x, 0.0));
171
vec3 rgbc_l = (rgb0_l + 2.0 * rgb1_l + rgb2_l) / 4.0;
172
vec3 rgb0_r = tex_r(gl_TexCoord[1].xy - vec2(step_x, 0.0));
173
vec3 rgb1_r = tex_r(gl_TexCoord[1].xy);
174
vec3 rgb2_r = tex_r(gl_TexCoord[1].xy + vec2(step_x, 0.0));
175
vec3 rgbc_r = (rgb0_r + 2.0 * rgb1_r + rgb2_r) / 4.0;
176
# elif defined(mode_checkerboard)
177
vec3 rgb0_l = tex_l(gl_TexCoord[0].xy - vec2(0.0, step_y));
178
vec3 rgb1_l = tex_l(gl_TexCoord[0].xy - vec2(step_x, 0.0));
179
vec3 rgb2_l = tex_l(gl_TexCoord[0].xy);
180
vec3 rgb3_l = tex_l(gl_TexCoord[0].xy + vec2(step_x, 0.0));
181
vec3 rgb4_l = tex_l(gl_TexCoord[0].xy + vec2(0.0, step_y));
182
vec3 rgbc_l = (rgb0_l + rgb1_l + 4.0 * rgb2_l + rgb3_l + rgb4_l) / 8.0;
183
vec3 rgb0_r = tex_r(gl_TexCoord[1].xy - vec2(0.0, step_y));
184
vec3 rgb1_r = tex_r(gl_TexCoord[1].xy - vec2(step_x, 0.0));
185
vec3 rgb2_r = tex_r(gl_TexCoord[1].xy);
186
vec3 rgb3_r = tex_r(gl_TexCoord[1].xy + vec2(step_x, 0.0));
187
vec3 rgb4_r = tex_r(gl_TexCoord[1].xy + vec2(0.0, step_y));
188
vec3 rgbc_r = (rgb0_r + rgb1_r + 4.0 * rgb2_r + rgb3_r + rgb4_r) / 8.0;
190
vec3 rgbcs_l = blend_subtitle(rgbc_l, sub_l(gl_TexCoord[0].xy));
191
vec3 rgbcs_r = blend_subtitle(rgbc_r, sub_r(gl_TexCoord[1].xy));
192
srgb = rgb_to_srgb(ghostbust(mix(rgbcs_r, rgbcs_l, m), mix(rgbcs_l, rgbcs_r, m)));
194
#elif defined(mode_red_cyan_dubois) || defined(mode_green_magenta_dubois) || defined(mode_amber_blue_dubois)
196
// The Dubois anaglyph method is generally the highest quality anaglyph method.
197
// Authors page: http://www.site.uottawa.ca/~edubois/anaglyph/
198
// This method depends on the characteristics of the display device and the anaglyph glasses.
199
// According to the author, the matrices below are intended to be applied to linear RGB values,
200
// and are designed for CRT displays.
201
vec3 l = blend_subtitle(tex_l(gl_TexCoord[0].xy), sub_l(gl_TexCoord[0].xy));
202
vec3 r = blend_subtitle(tex_r(gl_TexCoord[1].xy), sub_r(gl_TexCoord[1].xy));
203
# if defined(mode_red_cyan_dubois)
204
// Source of this matrix: http://www.site.uottawa.ca/~edubois/anaglyph/LeastSquaresHowToPhotoshop.pdf
206
0.437, -0.062, -0.048,
207
0.449, -0.062, -0.050,
208
0.164, -0.024, -0.017);
210
-0.011, 0.377, -0.026,
211
-0.032, 0.761, -0.093,
212
-0.007, 0.009, 1.234);
213
# elif defined(mode_green_magenta_dubois)
214
// Source of this matrix: http://www.flickr.com/photos/e_dubois/5132528166/
216
-0.062, 0.284, -0.015,
217
-0.158, 0.668, -0.027,
218
-0.039, 0.143, 0.021);
220
0.529, -0.016, 0.009,
221
0.705, -0.015, 0.075,
222
0.024, -0.065, 0.937);
223
# elif defined(mode_amber_blue_dubois)
224
// Source of this matrix: http://www.flickr.com/photos/e_dubois/5230654930/
226
1.062, -0.026, -0.038,
227
-0.205, 0.908, -0.173,
228
0.299, 0.068, 0.022);
230
-0.016, 0.006, 0.094,
231
-0.123, 0.062, 0.185,
232
-0.017, -0.017, 0.911);
234
srgb = rgb_to_srgb(m0 * l + m1 * r);
236
#else // lower quality anaglyph methods
238
vec3 l = rgb_to_srgb(blend_subtitle(tex_l(gl_TexCoord[0].xy), sub_l(gl_TexCoord[0].xy)));
239
vec3 r = rgb_to_srgb(blend_subtitle(tex_r(gl_TexCoord[1].xy), sub_r(gl_TexCoord[1].xy)));
240
# if defined(mode_red_cyan_monochrome)
241
srgb = vec3(srgb_to_lum(l), srgb_to_lum(r), srgb_to_lum(r));
242
# elif defined(mode_red_cyan_half_color)
243
srgb = vec3(srgb_to_lum(l), r.g, r.b);
244
# elif defined(mode_red_cyan_full_color)
245
srgb = vec3(l.r, r.g, r.b);
246
# elif defined(mode_green_magenta_monochrome)
247
srgb = vec3(srgb_to_lum(r), srgb_to_lum(l), srgb_to_lum(r));
248
# elif defined(mode_green_magenta_half_color)
249
srgb = vec3(r.r, srgb_to_lum(l), r.b);
250
# elif defined(mode_green_magenta_full_color)
251
srgb = vec3(r.r, l.g, r.b);
252
# elif defined(mode_amber_blue_monochrome)
253
srgb = vec3(srgb_to_lum(l), srgb_to_lum(l), srgb_to_lum(r));
254
# elif defined(mode_amber_blue_half_color)
255
srgb = vec3(srgb_to_lum(l), srgb_to_lum(l), r.b);
256
# elif defined(mode_amber_blue_full_color)
257
srgb = vec3(l.r, l.g, r.b);
258
# elif defined(mode_red_green_monochrome)
259
srgb = vec3(srgb_to_lum(l), srgb_to_lum(r), 0.0);
260
# elif defined(mode_red_blue_monochrome)
261
srgb = vec3(srgb_to_lum(l), 0.0, srgb_to_lum(r));
266
gl_FragColor = vec4(srgb, 1.0);