]> git.sesse.net Git - casparcg/blob - accelerator/ogl/image/image_shader.cpp
2.1.0: -image_shader: Blend modes enabled by default.
[casparcg] / accelerator / ogl / image / image_shader.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../../stdafx.h"\r
23 \r
24 #include "image_shader.h"\r
25 \r
26 #include "../util/shader.h"\r
27 #include "../util/device.h"\r
28 \r
29 #include "blending_glsl.h"\r
30 \r
31 #include <common/gl/gl_check.h>\r
32 #include <common/env.h>\r
33 \r
34 #include <tbb/mutex.h>\r
35 \r
36 namespace caspar { namespace accelerator { namespace ogl {\r
37 \r
38 std::shared_ptr<shader> g_shader;\r
39 tbb::mutex                              g_shader_mutex;\r
40 bool                                    g_blend_modes = false;\r
41 \r
42 std::string get_blend_color_func()\r
43 {\r
44         return \r
45                         \r
46         get_adjustement_glsl()\r
47                 \r
48         +\r
49 \r
50         get_blend_glsl()\r
51                 \r
52         +\r
53                         \r
54         "vec3 get_blend_color(vec3 back, vec3 fore)                                                                                     \n"\r
55         "{                                                                                                                                                                      \n"\r
56         "       switch(blend_mode)                                                                                                                              \n"\r
57         "       {                                                                                                                                                               \n"\r
58         "       case  0: return BlendNormal(back, fore);                                                                                \n"\r
59         "       case  1: return BlendLighten(back, fore);                                                                               \n"\r
60         "       case  2: return BlendDarken(back, fore);                                                                                \n"\r
61         "       case  3: return BlendMultiply(back, fore);                                                                              \n"\r
62         "       case  4: return BlendAverage(back, fore);                                                                               \n"\r
63         "       case  5: return BlendAdd(back, fore);                                                                                   \n"\r
64         "       case  6: return BlendSubstract(back, fore);                                                                             \n"\r
65         "       case  7: return BlendDifference(back, fore);                                                                    \n"\r
66         "       case  8: return BlendNegation(back, fore);                                                                              \n"\r
67         "       case  9: return BlendExclusion(back, fore);                                                                             \n"\r
68         "       case 10: return BlendScreen(back, fore);                                                                                \n"\r
69         "       case 11: return BlendOverlay(back, fore);                                                                               \n"\r
70         //"     case 12: return BlendSoftLight(back, fore);                                                                             \n"\r
71         "       case 13: return BlendHardLight(back, fore);                                                                             \n"\r
72         "       case 14: return BlendColorDodge(back, fore);                                                                    \n"\r
73         "       case 15: return BlendColorBurn(back, fore);                                                                             \n"\r
74         "       case 16: return BlendLinearDodge(back, fore);                                                                   \n"\r
75         "       case 17: return BlendLinearBurn(back, fore);                                                                    \n"\r
76         "       case 18: return BlendLinearLight(back, fore);                                                                   \n"\r
77         "       case 19: return BlendVividLight(back, fore);                                                                    \n"\r
78         "       case 20: return BlendPinLight(back, fore);                                                                              \n"\r
79         "       case 21: return BlendHardMix(back, fore);                                                                               \n"\r
80         "       case 22: return BlendReflect(back, fore);                                                                               \n"\r
81         "       case 23: return BlendGlow(back, fore);                                                                                  \n"\r
82         "       case 24: return BlendPhoenix(back, fore);                                                                               \n"\r
83         "       case 25: return BlendHue(back, fore);                                                                                   \n"\r
84         "       case 26: return BlendSaturation(back, fore);                                                                    \n"\r
85         "       case 27: return BlendColor(back, fore);                                                                                 \n"\r
86         "       case 28: return BlendLuminosity(back, fore);                                                                    \n"\r
87         "       }                                                                                                                                                               \n"\r
88         "       return BlendNormal(back, fore);                                                                                                 \n"\r
89         "}                                                                                                                                                                      \n"\r
90         "                                                                                                                                                                       \n"                                                                                                                                                       \r
91         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
92         "{                                                                                                                                                                      \n"\r
93         "   vec4 back = texture2D(background, gl_TexCoord[1].st).bgra;                                          \n"\r
94         "   if(blend_mode != 0)                                                                                                                         \n"\r
95         "               fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a;\n"\r
96         "       switch(keyer)                                                                                                                                   \n"     \r
97         "       {                                                                                                                                                               \n"     \r
98         "               case 1:  return fore + back; // additive                                                                        \n"\r
99         "               default: return fore + (1.0-fore.a)*back; // linear                                                     \n"\r
100         "       }                                                                                                                                                               \n"\r
101         "}                                                                                                                                                                      \n";                    \r
102 }\r
103                 \r
104 std::string get_simple_blend_color_func()\r
105 {\r
106         return  \r
107                 \r
108         get_adjustement_glsl()\r
109                         \r
110         +\r
111 \r
112         "vec4 blend(vec4 fore)                                                                                                                          \n"\r
113         "{                                                                                                                                                                      \n"\r
114         "       return fore;                                                                                                                                    \n"\r
115         "}                                                                                                                                                                      \n";\r
116 }\r
117 \r
118 std::string get_vertex()\r
119 {\r
120         return \r
121 \r
122         "void main()                                                                                                                                            \n"\r
123         "{                                                                                                                                                                      \n"\r
124         "       gl_TexCoord[0] = gl_MultiTexCoord0;                                                                                             \n"\r
125         "       gl_TexCoord[1] = gl_MultiTexCoord1;                                                                                             \n"\r
126         "       gl_Position    = ftransform();                                                                                                  \n"\r
127         "}                                                                                                                                                                      \n";\r
128 }\r
129 \r
130 std::string get_fragment(bool blend_modes)\r
131 {\r
132         return\r
133 \r
134         "#version 130                                                                                                                                           \n"\r
135         "uniform sampler2D      background;                                                                                                             \n"\r
136         "uniform sampler2D      plane[4];                                                                                                               \n"\r
137         "uniform vec2           plane_size[4];                                                                                                  \n"\r
138         "uniform sampler2D      local_key;                                                                                                              \n"\r
139         "uniform sampler2D      layer_key;                                                                                                              \n"\r
140         "                                                                                                                                                                       \n"\r
141         "uniform bool           is_hd;                                                                                                                  \n"\r
142         "uniform bool           has_local_key;                                                                                                  \n"\r
143         "uniform bool           has_layer_key;                                                                                                  \n"\r
144         "uniform int            blend_mode;                                                                                                             \n"\r
145         "uniform int            keyer;                                                                                                                  \n"\r
146         "uniform int            pixel_format;                                                                                                   \n"\r
147         "uniform int            deinterlace;                                                                                                    \n"\r
148         "                                                                                                                                                                       \n"\r
149         "uniform float          opacity;                                                                                                                \n"\r
150         "uniform bool           levels;                                                                                                                 \n"\r
151         "uniform float          min_input;                                                                                                              \n"\r
152         "uniform float          max_input;                                                                                                              \n"\r
153         "uniform float          gamma;                                                                                                                  \n"\r
154         "uniform float          min_output;                                                                                                             \n"\r
155         "uniform float          max_output;                                                                                                             \n"\r
156         "                                                                                                                                                                       \n"\r
157         "uniform bool           csb;                                                                                                                    \n"\r
158         "uniform float          brt;                                                                                                                    \n"\r
159         "uniform float          sat;                                                                                                                    \n"\r
160         "uniform float          con;                                                                                                                    \n"\r
161         "                                                                                                                                                                       \n"     \r
162 \r
163         +\r
164                 \r
165         (blend_modes ? get_blend_color_func() : get_simple_blend_color_func())\r
166 \r
167         +\r
168         \r
169         "                                                                                                                                                                       \n"\r
170         "vec4 ycbcra_to_rgba_sd(float Y, float Cb, float Cr, float A)                                           \n"\r
171         "{                                                                                                                                                                      \n"\r
172         "   vec4 rgba;                                                                                                                                          \n"\r
173         "   rgba.b = (1.164*(Y*255 - 16) + 1.596*(Cr*255 - 128))/255;                                           \n"\r
174         "   rgba.g = (1.164*(Y*255 - 16) - 0.813*(Cr*255 - 128) - 0.391*(Cb*255 - 128))/255;\n"\r
175         "   rgba.r = (1.164*(Y*255 - 16) + 2.018*(Cb*255 - 128))/255;                                           \n"\r
176         "   rgba.a = A;                                                                                                                                         \n"\r
177         "       return rgba;                                                                                                                                    \n"     \r
178         "}                                                                                                                                                                      \n"                     \r
179         "                                                                                                                                                                       \n"\r
180         "vec4 ycbcra_to_rgba_hd(float Y, float Cb, float Cr, float A)                                           \n"\r
181         "{                                                                                                                                                                      \n"\r
182         "   vec4 rgba;                                                                                                                                          \n"\r
183         "   rgba.b = (1.164*(Y*255 - 16) + 1.793*(Cr*255 - 128))/255;                                           \n"\r
184         "   rgba.g = (1.164*(Y*255 - 16) - 0.534*(Cr*255 - 128) - 0.213*(Cb*255 - 128))/255;\n"\r
185         "   rgba.r = (1.164*(Y*255 - 16) + 2.115*(Cb*255 - 128))/255;                                           \n"\r
186         "   rgba.a = A;                                                                                                                                         \n"\r
187         "       return rgba;                                                                                                                                    \n"\r
188         "}                                                                                                                                                                      \n"                                     \r
189         "                                                                                                                                                                       \n"             \r
190         "vec4 ycbcra_to_rgba(float y, float cb, float cr, float a)                                                      \n"\r
191         "{                                                                                                                                                                      \n"\r
192         "       if(is_hd)                                                                                                                                               \n"\r
193         "               return ycbcra_to_rgba_hd(y, cb, cr, a);                                                                         \n"\r
194         "       else                                                                                                                                                    \n"\r
195         "               return ycbcra_to_rgba_sd(y, cb, cr, a);                                                                         \n"\r
196         "}                                                                                                                                                                      \n"\r
197         "                                                                                                                                                                       \n"\r
198         "vec4 get_sample(sampler2D sampler, vec2 coords, vec2 size)                                                     \n"\r
199         "{                                                                                                                                                                      \n"\r
200         "       switch(deinterlace)                                                                                                                             \n"\r
201         "       {                                                                                                                                                               \n"\r
202         "       case 1: // upper                                                                                                                                \n"\r
203         "               return texture2D(sampler, coords);                                                                                      \n"\r
204         "       case 2: // lower                                                                                                                                \n"\r
205         "               return texture2D(sampler, coords);                                                                                      \n"\r
206         "       default:                                                                                                                                                \n"\r
207         "               return texture2D(sampler, coords);                                                                                      \n"\r
208         "       }                                                                                                                                                               \n"\r
209         "}                                                                                                                                                                      \n"\r
210         "                                                                                                                                                                       \n"\r
211         "vec4 get_rgba_color()                                                                                                                          \n"\r
212         "{                                                                                                                                                                      \n"\r
213         "       switch(pixel_format)                                                                                                                    \n"\r
214         "       {                                                                                                                                                               \n"\r
215         "       case 0:         //gray                                                                                                                          \n"\r
216         "               return vec4(get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rrr, 1.0);\n"\r
217         "       case 1:         //bgra,                                                                                                                         \n"\r
218         "               return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).bgra;                     \n"\r
219         "       case 2:         //rgba,                                                                                                                         \n"\r
220         "               return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rgba;                     \n"\r
221         "       case 3:         //argb,                                                                                                                         \n"\r
222         "               return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).argb;                     \n"\r
223         "       case 4:         //abgr,                                                                                                                         \n"\r
224         "               return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).gbar;                     \n"\r
225         "       case 5:         //ycbcr,                                                                                                                        \n"\r
226         "               {                                                                                                                                                       \n"\r
227         "                       float y  = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
228         "                       float cb = get_sample(plane[1], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
229         "                       float cr = get_sample(plane[2], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
230         "                       return ycbcra_to_rgba(y, cb, cr, 1.0);                                                                  \n"\r
231         "               }                                                                                                                                                       \n"\r
232         "       case 6:         //ycbcra                                                                                                                        \n"\r
233         "               {                                                                                                                                                       \n"\r
234         "                       float y  = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
235         "                       float cb = get_sample(plane[1], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
236         "                       float cr = get_sample(plane[2], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
237         "                       float a  = get_sample(plane[3], gl_TexCoord[0].st, plane_size[0]).r;    \n"\r
238         "                       return ycbcra_to_rgba(y, cb, cr, a);                                                                    \n"\r
239         "               }                                                                                                                                                       \n"\r
240         "       case 7:         //luma                                                                                                                          \n"\r
241         "               {                                                                                                                                                       \n"\r
242         "                       vec3 y3 = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rrr;   \n"\r
243         "                       return vec4((y3-0.065)/0.859, 1.0);                                                                             \n"\r
244         "               }                                                                                                                                                       \n"\r
245         "       }                                                                                                                                                               \n"\r
246         "       return vec4(0.0, 0.0, 0.0, 0.0);                                                                                                \n"\r
247         "}                                                                                                                                                                      \n"\r
248         "                                                                                                                                                                       \n"\r
249         "void main()                                                                                                                                            \n"\r
250         "{                                                                                                                                                                      \n"\r
251         "       vec4 color = get_rgba_color();                                                                                                  \n"\r
252         "   if(levels)                                                                                                                                          \n"\r
253         "               color.rgb = LevelsControl(color.rgb, min_input, max_input, gamma, min_output, max_output); \n"\r
254         "       if(csb)                                                                                                                                                 \n"\r
255         "               color.rgb = ContrastSaturationBrightness(color.rgb, brt, sat, con);                     \n"\r
256         "       if(has_local_key)                                                                                                                               \n"\r
257         "               color *= texture2D(local_key, gl_TexCoord[1].st).r;                                                     \n"\r
258         "       if(has_layer_key)                                                                                                                               \n"\r
259         "               color *= texture2D(layer_key, gl_TexCoord[1].st).r;                                                     \n"\r
260         "       color *= opacity;                                                                                                                               \n"\r
261         "       color = blend(color);                                                                                                                   \n"\r
262         "       gl_FragColor = color.bgra;                                                                                                              \n"\r
263         "}                                                                                                                                                                      \n";\r
264 }\r
265 \r
266 spl::shared_ptr<shader> get_image_shader(bool& blend_modes)\r
267 {\r
268         tbb::mutex::scoped_lock lock(g_shader_mutex);\r
269 \r
270         if(g_shader)\r
271         {\r
272                 blend_modes = g_blend_modes;\r
273                 return spl::make_shared_ptr(g_shader);\r
274         }\r
275                 \r
276         try\r
277         {                               \r
278                 g_blend_modes  = glTextureBarrierNV ? env::properties().get(L"configuration.blend-modes", true) : false;\r
279                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
280         }\r
281         catch(...)\r
282         {\r
283                 CASPAR_LOG_CURRENT_EXCEPTION();\r
284                 CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";\r
285                                 \r
286                 g_blend_modes = false;\r
287                 g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));\r
288         }\r
289                                                 \r
290         //if(!g_blend_modes)\r
291         //{\r
292         //      ogl.blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);\r
293         //      CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";\r
294         //}\r
295 \r
296         blend_modes = g_blend_modes;\r
297         return spl::make_shared_ptr(g_shader);\r
298 }\r
299 \r
300 }}}\r