1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | // |
41 | // W A R N I N G |
42 | // ------------- |
43 | // |
44 | // This file is not part of the Qt API. It exists purely as an |
45 | // implementation detail. This header file may change from version to |
46 | // version without notice, or even be removed. |
47 | // |
48 | // We mean it. |
49 | // |
50 | |
51 | |
52 | #ifndef QOPENGL_ENGINE_SHADER_SOURCE_H |
53 | #define QOPENGL_ENGINE_SHADER_SOURCE_H |
54 | |
55 | #include <QtGui/private/qtguiglobal_p.h> |
56 | #include "qopenglengineshadermanager_p.h" |
57 | |
58 | QT_BEGIN_NAMESPACE |
59 | |
60 | |
61 | static const char* const qopenglslMainVertexShader = "\n\ |
62 | void setPosition(); \n\ |
63 | void main(void) \n\ |
64 | { \n\ |
65 | setPosition(); \n\ |
66 | }\n" ; |
67 | |
68 | static const char* const qopenglslMainWithTexCoordsVertexShader = "\n\ |
69 | attribute highp vec2 textureCoordArray; \n\ |
70 | varying highp vec2 textureCoords; \n\ |
71 | void setPosition(); \n\ |
72 | void main(void) \n\ |
73 | { \n\ |
74 | setPosition(); \n\ |
75 | textureCoords = textureCoordArray; \n\ |
76 | }\n" ; |
77 | |
78 | static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader = "\n\ |
79 | attribute highp vec2 textureCoordArray; \n\ |
80 | attribute lowp float opacityArray; \n\ |
81 | varying highp vec2 textureCoords; \n\ |
82 | varying lowp float opacity; \n\ |
83 | void setPosition(); \n\ |
84 | void main(void) \n\ |
85 | { \n\ |
86 | setPosition(); \n\ |
87 | textureCoords = textureCoordArray; \n\ |
88 | opacity = opacityArray; \n\ |
89 | }\n" ; |
90 | |
91 | // NOTE: We let GL do the perspective correction so texture lookups in the fragment |
92 | // shader are also perspective corrected. |
93 | static const char* const qopenglslPositionOnlyVertexShader = "\n\ |
94 | attribute highp vec2 vertexCoordsArray; \n\ |
95 | attribute highp vec3 pmvMatrix1; \n\ |
96 | attribute highp vec3 pmvMatrix2; \n\ |
97 | attribute highp vec3 pmvMatrix3; \n\ |
98 | void setPosition(void) \n\ |
99 | { \n\ |
100 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
101 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
102 | gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ |
103 | }\n" ; |
104 | |
105 | static const char* const qopenglslComplexGeometryPositionOnlyVertexShader = "\n\ |
106 | uniform highp mat3 matrix; \n\ |
107 | attribute highp vec2 vertexCoordsArray; \n\ |
108 | void setPosition(void) \n\ |
109 | { \n\ |
110 | gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ |
111 | } \n" ; |
112 | |
113 | static const char* const qopenglslUntransformedPositionVertexShader = "\n\ |
114 | attribute highp vec4 vertexCoordsArray; \n\ |
115 | void setPosition(void) \n\ |
116 | { \n\ |
117 | gl_Position = vertexCoordsArray; \n\ |
118 | }\n" ; |
119 | |
120 | // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 |
121 | static const char* const qopenglslPositionWithPatternBrushVertexShader = "\n\ |
122 | attribute highp vec2 vertexCoordsArray; \n\ |
123 | attribute highp vec3 pmvMatrix1; \n\ |
124 | attribute highp vec3 pmvMatrix2; \n\ |
125 | attribute highp vec3 pmvMatrix3; \n\ |
126 | uniform mediump vec2 halfViewportSize; \n\ |
127 | uniform highp vec2 invertedTextureSize; \n\ |
128 | uniform highp mat3 brushTransform; \n\ |
129 | varying highp vec2 patternTexCoords; \n\ |
130 | void setPosition(void) \n\ |
131 | { \n\ |
132 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
133 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
134 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
135 | mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
136 | mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ |
137 | mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
138 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
139 | patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ |
140 | }\n" ; |
141 | |
142 | static const char* const qopenglslAffinePositionWithPatternBrushVertexShader |
143 | = qopenglslPositionWithPatternBrushVertexShader; |
144 | |
145 | static const char* const qopenglslPatternBrushSrcFragmentShader = "\n\ |
146 | uniform sampler2D brushTexture; \n\ |
147 | uniform lowp vec4 patternColor; \n\ |
148 | varying highp vec2 patternTexCoords;\n\ |
149 | lowp vec4 srcPixel() \n\ |
150 | { \n\ |
151 | return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\ |
152 | }\n" ; |
153 | |
154 | |
155 | // Linear Gradient Brush |
156 | static const char* const qopenglslPositionWithLinearGradientBrushVertexShader = "\n\ |
157 | attribute highp vec2 vertexCoordsArray; \n\ |
158 | attribute highp vec3 pmvMatrix1; \n\ |
159 | attribute highp vec3 pmvMatrix2; \n\ |
160 | attribute highp vec3 pmvMatrix3; \n\ |
161 | uniform mediump vec2 halfViewportSize; \n\ |
162 | uniform highp vec3 linearData; \n\ |
163 | uniform highp mat3 brushTransform; \n\ |
164 | varying mediump float index; \n\ |
165 | void setPosition() \n\ |
166 | { \n\ |
167 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
168 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
169 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
170 | mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
171 | mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
172 | mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
173 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
174 | index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ |
175 | }\n" ; |
176 | |
177 | static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader |
178 | = qopenglslPositionWithLinearGradientBrushVertexShader; |
179 | |
180 | static const char* const qopenglslLinearGradientBrushSrcFragmentShader = "\n\ |
181 | uniform sampler2D brushTexture; \n\ |
182 | varying mediump float index; \n\ |
183 | lowp vec4 srcPixel() \n\ |
184 | { \n\ |
185 | mediump vec2 val = vec2(index, 0.5); \n\ |
186 | return texture2D(brushTexture, val); \n\ |
187 | }\n" ; |
188 | |
189 | |
190 | // Conical Gradient Brush |
191 | static const char* const qopenglslPositionWithConicalGradientBrushVertexShader = "\n\ |
192 | attribute highp vec2 vertexCoordsArray; \n\ |
193 | attribute highp vec3 pmvMatrix1; \n\ |
194 | attribute highp vec3 pmvMatrix2; \n\ |
195 | attribute highp vec3 pmvMatrix3; \n\ |
196 | uniform mediump vec2 halfViewportSize; \n\ |
197 | uniform highp mat3 brushTransform; \n\ |
198 | varying highp vec2 A; \n\ |
199 | void setPosition(void) \n\ |
200 | { \n\ |
201 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
202 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
203 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
204 | mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
205 | mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
206 | mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
207 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
208 | A = hTexCoords.xy * invertedHTexCoordsZ; \n\ |
209 | }\n" ; |
210 | |
211 | static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader |
212 | = qopenglslPositionWithConicalGradientBrushVertexShader; |
213 | |
214 | static const char* const qopenglslConicalGradientBrushSrcFragmentShader = "\n\ |
215 | #define INVERSE_2PI 0.1591549430918953358 \n\ |
216 | uniform sampler2D brushTexture; \n\ |
217 | uniform mediump float angle; \n\ |
218 | varying highp vec2 A; \n\ |
219 | lowp vec4 srcPixel() \n\ |
220 | { \n\ |
221 | highp float t; \n\ |
222 | if (abs(A.y) == abs(A.x)) \n\ |
223 | t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ |
224 | else \n\ |
225 | t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ |
226 | return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\ |
227 | }\n" ; |
228 | |
229 | |
230 | // Radial Gradient Brush |
231 | static const char* const qopenglslPositionWithRadialGradientBrushVertexShader = "\n\ |
232 | attribute highp vec2 vertexCoordsArray;\n\ |
233 | attribute highp vec3 pmvMatrix1; \n\ |
234 | attribute highp vec3 pmvMatrix2; \n\ |
235 | attribute highp vec3 pmvMatrix3; \n\ |
236 | uniform mediump vec2 halfViewportSize; \n\ |
237 | uniform highp mat3 brushTransform; \n\ |
238 | uniform highp vec2 fmp; \n\ |
239 | uniform mediump vec3 bradius; \n\ |
240 | varying highp float b; \n\ |
241 | varying highp vec2 A; \n\ |
242 | void setPosition(void) \n\ |
243 | {\n\ |
244 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
245 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
246 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
247 | mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
248 | mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
249 | mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
250 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
251 | A = hTexCoords.xy * invertedHTexCoordsZ; \n\ |
252 | b = bradius.x + 2.0 * dot(A, fmp); \n\ |
253 | }\n" ; |
254 | |
255 | static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader |
256 | = qopenglslPositionWithRadialGradientBrushVertexShader; |
257 | |
258 | static const char* const qopenglslRadialGradientBrushSrcFragmentShader = "\n\ |
259 | uniform sampler2D brushTexture; \n\ |
260 | uniform highp float fmp2_m_radius2; \n\ |
261 | uniform highp float inverse_2_fmp2_m_radius2; \n\ |
262 | uniform highp float sqrfr; \n\ |
263 | varying highp float b; \n\ |
264 | varying highp vec2 A; \n\ |
265 | uniform mediump vec3 bradius; \n\ |
266 | lowp vec4 srcPixel() \n\ |
267 | { \n\ |
268 | highp float c = sqrfr-dot(A, A); \n\ |
269 | highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\ |
270 | lowp vec4 result = vec4(0.0); \n\ |
271 | if (det >= 0.0) { \n\ |
272 | highp float detSqrt = sqrt(det); \n\ |
273 | highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\ |
274 | if (bradius.y + w * bradius.z >= 0.0) \n\ |
275 | result = texture2D(brushTexture, vec2(w, 0.5)); \n\ |
276 | } \n\ |
277 | return result; \n\ |
278 | }\n" ; |
279 | |
280 | |
281 | // Texture Brush |
282 | static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\ |
283 | attribute highp vec2 vertexCoordsArray; \n\ |
284 | attribute highp vec3 pmvMatrix1; \n\ |
285 | attribute highp vec3 pmvMatrix2; \n\ |
286 | attribute highp vec3 pmvMatrix3; \n\ |
287 | uniform mediump vec2 halfViewportSize; \n\ |
288 | uniform highp vec2 invertedTextureSize; \n\ |
289 | uniform highp mat3 brushTransform; \n\ |
290 | varying highp vec2 brushTextureCoords; \n\ |
291 | void setPosition(void) \n\ |
292 | { \n\ |
293 | highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
294 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
295 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
296 | mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
297 | mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
298 | mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
299 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
300 | brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ |
301 | }\n" ; |
302 | |
303 | static const char* const qopenglslAffinePositionWithTextureBrushVertexShader |
304 | = qopenglslPositionWithTextureBrushVertexShader; |
305 | |
306 | static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\ |
307 | varying highp vec2 brushTextureCoords; \n\ |
308 | uniform sampler2D brushTexture; \n\ |
309 | lowp vec4 srcPixel() \n\ |
310 | { \n\ |
311 | return texture2D(brushTexture, brushTextureCoords); \n\ |
312 | }\n" ; |
313 | |
314 | static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader = "\n\ |
315 | varying highp vec2 brushTextureCoords; \n\ |
316 | uniform lowp vec4 patternColor; \n\ |
317 | uniform sampler2D brushTexture; \n\ |
318 | lowp vec4 srcPixel() \n\ |
319 | { \n\ |
320 | return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\ |
321 | }\n" ; |
322 | |
323 | // Solid Fill Brush |
324 | static const char* const qopenglslSolidBrushSrcFragmentShader = "\n\ |
325 | uniform lowp vec4 fragmentColor; \n\ |
326 | lowp vec4 srcPixel() \n\ |
327 | { \n\ |
328 | return fragmentColor; \n\ |
329 | }\n" ; |
330 | |
331 | static const char* const qopenglslImageSrcFragmentShader = "\n\ |
332 | varying highp vec2 textureCoords; \n\ |
333 | uniform sampler2D imageTexture; \n\ |
334 | lowp vec4 srcPixel() \n\ |
335 | { \n" |
336 | "return texture2D(imageTexture, textureCoords); \n" |
337 | "}\n" ; |
338 | |
339 | static const char* const qopenglslCustomSrcFragmentShader = "\n\ |
340 | varying highp vec2 textureCoords; \n\ |
341 | uniform sampler2D imageTexture; \n\ |
342 | lowp vec4 srcPixel() \n\ |
343 | { \n\ |
344 | return customShader(imageTexture, textureCoords); \n\ |
345 | }\n" ; |
346 | |
347 | static const char* const qopenglslImageSrcWithPatternFragmentShader = "\n\ |
348 | varying highp vec2 textureCoords; \n\ |
349 | uniform lowp vec4 patternColor; \n\ |
350 | uniform sampler2D imageTexture; \n\ |
351 | lowp vec4 srcPixel() \n\ |
352 | { \n\ |
353 | return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\ |
354 | }\n" ; |
355 | |
356 | static const char* const qopenglslNonPremultipliedImageSrcFragmentShader = "\n\ |
357 | varying highp vec2 textureCoords; \n\ |
358 | uniform sampler2D imageTexture; \n\ |
359 | lowp vec4 srcPixel() \n\ |
360 | { \n\ |
361 | lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\ |
362 | sample.rgb = sample.rgb * sample.a; \n\ |
363 | return sample; \n\ |
364 | }\n" ; |
365 | |
366 | static const char* const qopenglslGrayscaleImageSrcFragmentShader = "\n\ |
367 | varying highp vec2 textureCoords; \n\ |
368 | uniform sampler2D imageTexture; \n\ |
369 | lowp vec4 srcPixel() \n\ |
370 | { \n\ |
371 | return texture2D(imageTexture, textureCoords).rrra; \n\ |
372 | }\n" ; |
373 | |
374 | static const char* const qopenglslAlphaImageSrcFragmentShader = "\n\ |
375 | varying highp vec2 textureCoords; \n\ |
376 | uniform sampler2D imageTexture; \n\ |
377 | lowp vec4 srcPixel() \n\ |
378 | { \n\ |
379 | return vec4(0, 0, 0, texture2D(imageTexture, textureCoords).r); \n\ |
380 | }\n" ; |
381 | |
382 | static const char* const qopenglslShockingPinkSrcFragmentShader = "\n\ |
383 | lowp vec4 srcPixel() \n\ |
384 | { \n\ |
385 | return vec4(0.98, 0.06, 0.75, 1.0); \n\ |
386 | }\n" ; |
387 | |
388 | static const char* const qopenglslMainFragmentShader_ImageArrays = "\n\ |
389 | varying lowp float opacity; \n\ |
390 | lowp vec4 srcPixel(); \n\ |
391 | void main() \n\ |
392 | { \n\ |
393 | gl_FragColor = srcPixel() * opacity; \n\ |
394 | }\n" ; |
395 | |
396 | static const char* const qopenglslMainFragmentShader_MO = "\n\ |
397 | uniform lowp float globalOpacity; \n\ |
398 | lowp vec4 srcPixel(); \n\ |
399 | lowp vec4 applyMask(lowp vec4); \n\ |
400 | void main() \n\ |
401 | { \n\ |
402 | gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\ |
403 | }\n" ; |
404 | |
405 | static const char* const qopenglslMainFragmentShader_M = "\n\ |
406 | lowp vec4 srcPixel(); \n\ |
407 | lowp vec4 applyMask(lowp vec4); \n\ |
408 | void main() \n\ |
409 | { \n\ |
410 | gl_FragColor = applyMask(srcPixel()); \n\ |
411 | }\n" ; |
412 | |
413 | static const char* const qopenglslMainFragmentShader_O = "\n\ |
414 | uniform lowp float globalOpacity; \n\ |
415 | lowp vec4 srcPixel(); \n\ |
416 | void main() \n\ |
417 | { \n\ |
418 | gl_FragColor = srcPixel()*globalOpacity; \n\ |
419 | }\n" ; |
420 | |
421 | static const char* const qopenglslMainFragmentShader = "\n\ |
422 | lowp vec4 srcPixel(); \n\ |
423 | void main() \n\ |
424 | { \n\ |
425 | gl_FragColor = srcPixel(); \n\ |
426 | }\n" ; |
427 | |
428 | static const char* const qopenglslMaskFragmentShader = "\n\ |
429 | varying highp vec2 textureCoords;\n\ |
430 | uniform sampler2D maskTexture;\n\ |
431 | lowp vec4 applyMask(lowp vec4 src) \n\ |
432 | {\n\ |
433 | lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ |
434 | return src * mask.a; \n\ |
435 | }\n" ; |
436 | |
437 | // For source over with subpixel antialiasing, the final color is calculated per component as follows |
438 | // (.a is alpha component, .c is red, green or blue component): |
439 | // alpha = src.a * mask.c * opacity |
440 | // dest.c = dest.c * (1 - alpha) + src.c * alpha |
441 | // |
442 | // In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color |
443 | // In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one |
444 | // |
445 | // If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color |
446 | |
447 | // For source composition with subpixel antialiasing, the final color is calculated per component as follows: |
448 | // alpha = src.a * mask.c * opacity |
449 | // dest.c = dest.c * (1 - mask.c) + src.c * alpha |
450 | // |
451 | |
452 | static const char* const qopenglslRgbMaskFragmentShaderPass1 = "\n\ |
453 | varying highp vec2 textureCoords;\n\ |
454 | uniform sampler2D maskTexture;\n\ |
455 | lowp vec4 applyMask(lowp vec4 src) \n\ |
456 | { \n\ |
457 | lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ |
458 | return src.a * mask; \n\ |
459 | }\n" ; |
460 | |
461 | static const char* const qopenglslRgbMaskFragmentShaderPass2 = "\n\ |
462 | varying highp vec2 textureCoords;\n\ |
463 | uniform sampler2D maskTexture;\n\ |
464 | lowp vec4 applyMask(lowp vec4 src) \n\ |
465 | { \n\ |
466 | lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ |
467 | return src * mask; \n\ |
468 | }\n" ; |
469 | |
470 | static const char* const qopenglslMultiplyCompositionModeFragmentShader = "\n\ |
471 | #ifdef GL_KHR_blend_equation_advanced\n\ |
472 | layout(blend_support_multiply) out;\n\ |
473 | #endif\n" ; |
474 | |
475 | static const char* const qopenglslScreenCompositionModeFragmentShader = "\n\ |
476 | #ifdef GL_KHR_blend_equation_advanced\n\ |
477 | layout(blend_support_screen) out;\n\ |
478 | #endif\n" ; |
479 | |
480 | static const char* const qopenglslOverlayCompositionModeFragmentShader = "\n\ |
481 | #ifdef GL_KHR_blend_equation_advanced\n\ |
482 | layout(blend_support_overlay) out;\n\ |
483 | #endif\n" ; |
484 | |
485 | static const char* const qopenglslDarkenCompositionModeFragmentShader = "\n\ |
486 | #ifdef GL_KHR_blend_equation_advanced\n\ |
487 | layout(blend_support_darken) out;\n\ |
488 | #endif\n" ; |
489 | |
490 | static const char* const qopenglslLightenCompositionModeFragmentShader = "\n\ |
491 | #ifdef GL_KHR_blend_equation_advanced\n\ |
492 | layout(blend_support_lighten) out;\n\ |
493 | #endif\n" ; |
494 | |
495 | static const char* const qopenglslColorDodgeCompositionModeFragmentShader = "\n\ |
496 | #ifdef GL_KHR_blend_equation_advanced\n\ |
497 | layout(blend_support_colordodge) out;\n\ |
498 | #endif\n" ; |
499 | |
500 | static const char* const qopenglslColorBurnCompositionModeFragmentShader = "\n\ |
501 | #ifdef GL_KHR_blend_equation_advanced\n\ |
502 | layout(blend_support_colorburn) out;\n\ |
503 | #endif\n" ; |
504 | |
505 | static const char* const qopenglslHardLightCompositionModeFragmentShader = "\n\ |
506 | #ifdef GL_KHR_blend_equation_advanced\n\ |
507 | layout(blend_support_hardlight) out;\n\ |
508 | #endif\n" ; |
509 | |
510 | static const char* const qopenglslSoftLightCompositionModeFragmentShader = "\n\ |
511 | #ifdef GL_KHR_blend_equation_advanced\n\ |
512 | layout(blend_support_softlight) out;\n\ |
513 | #endif\n" ; |
514 | |
515 | static const char* const qopenglslDifferenceCompositionModeFragmentShader = "\n\ |
516 | #ifdef GL_KHR_blend_equation_advanced\n\ |
517 | layout(blend_support_difference) out;\n\ |
518 | #endif\n" ; |
519 | |
520 | static const char* const qopenglslExclusionCompositionModeFragmentShader = "\n\ |
521 | #ifdef GL_KHR_blend_equation_advanced\n\ |
522 | layout(blend_support_exclusion) out;\n\ |
523 | #endif\n" ; |
524 | |
525 | /* |
526 | Left to implement: |
527 | RgbMaskFragmentShader, |
528 | RgbMaskWithGammaFragmentShader, |
529 | */ |
530 | |
531 | /* |
532 | OpenGL 3.2+ Core Profile shaders |
533 | The following shader snippets are copies of the snippets above |
534 | but use the modern GLSL 1.5 keywords. New shaders should make |
535 | a snippet for both profiles and add them appropriately in the |
536 | shader manager. |
537 | */ |
538 | static const char* const qopenglslMainVertexShader_core = |
539 | "#version 150 core\n\ |
540 | void setPosition(); \n\ |
541 | void main(void) \n\ |
542 | { \n\ |
543 | setPosition(); \n\ |
544 | }\n" ; |
545 | |
546 | static const char* const qopenglslMainWithTexCoordsVertexShader_core = |
547 | "#version 150 core\n\ |
548 | in vec2 textureCoordArray; \n\ |
549 | out vec2 textureCoords; \n\ |
550 | void setPosition(); \n\ |
551 | void main(void) \n\ |
552 | { \n\ |
553 | setPosition(); \n\ |
554 | textureCoords = textureCoordArray; \n\ |
555 | }\n" ; |
556 | |
557 | static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader_core = |
558 | "#version 150 core\n\ |
559 | in vec2 textureCoordArray; \n\ |
560 | in float opacityArray; \n\ |
561 | out vec2 textureCoords; \n\ |
562 | out float opacity; \n\ |
563 | void setPosition(); \n\ |
564 | void main(void) \n\ |
565 | { \n\ |
566 | setPosition(); \n\ |
567 | textureCoords = textureCoordArray; \n\ |
568 | opacity = opacityArray; \n\ |
569 | }\n" ; |
570 | |
571 | // NOTE: We let GL do the perspective correction so texture lookups in the fragment |
572 | // shader are also perspective corrected. |
573 | static const char* const qopenglslPositionOnlyVertexShader_core = "\n\ |
574 | in vec2 vertexCoordsArray; \n\ |
575 | in vec3 pmvMatrix1; \n\ |
576 | in vec3 pmvMatrix2; \n\ |
577 | in vec3 pmvMatrix3; \n\ |
578 | void setPosition(void) \n\ |
579 | { \n\ |
580 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
581 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
582 | gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ |
583 | }\n" ; |
584 | |
585 | static const char* const qopenglslComplexGeometryPositionOnlyVertexShader_core = "\n\ |
586 | in vec2 vertexCoordsArray; \n\ |
587 | uniform mat3 matrix; \n\ |
588 | void setPosition(void) \n\ |
589 | { \n\ |
590 | gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ |
591 | } \n" ; |
592 | |
593 | static const char* const qopenglslUntransformedPositionVertexShader_core = "\n\ |
594 | in vec4 vertexCoordsArray; \n\ |
595 | void setPosition(void) \n\ |
596 | { \n\ |
597 | gl_Position = vertexCoordsArray; \n\ |
598 | }\n" ; |
599 | |
600 | // Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 |
601 | static const char* const qopenglslPositionWithPatternBrushVertexShader_core = "\n\ |
602 | in vec2 vertexCoordsArray; \n\ |
603 | in vec3 pmvMatrix1; \n\ |
604 | in vec3 pmvMatrix2; \n\ |
605 | in vec3 pmvMatrix3; \n\ |
606 | out vec2 patternTexCoords; \n\ |
607 | uniform vec2 halfViewportSize; \n\ |
608 | uniform vec2 invertedTextureSize; \n\ |
609 | uniform mat3 brushTransform; \n\ |
610 | void setPosition(void) \n\ |
611 | { \n\ |
612 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
613 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
614 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
615 | vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
616 | vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ |
617 | float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
618 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
619 | patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ |
620 | }\n" ; |
621 | |
622 | static const char* const qopenglslAffinePositionWithPatternBrushVertexShader_core |
623 | = qopenglslPositionWithPatternBrushVertexShader_core; |
624 | |
625 | static const char* const qopenglslPatternBrushSrcFragmentShader_core = "\n\ |
626 | in vec2 patternTexCoords;\n\ |
627 | uniform sampler2D brushTexture; \n\ |
628 | uniform vec4 patternColor; \n\ |
629 | vec4 srcPixel() \n\ |
630 | { \n\ |
631 | return patternColor * (1.0 - texture(brushTexture, patternTexCoords).r); \n\ |
632 | }\n" ; |
633 | |
634 | |
635 | // Linear Gradient Brush |
636 | static const char* const qopenglslPositionWithLinearGradientBrushVertexShader_core = "\n\ |
637 | in vec2 vertexCoordsArray; \n\ |
638 | in vec3 pmvMatrix1; \n\ |
639 | in vec3 pmvMatrix2; \n\ |
640 | in vec3 pmvMatrix3; \n\ |
641 | out float index; \n\ |
642 | uniform vec2 halfViewportSize; \n\ |
643 | uniform vec3 linearData; \n\ |
644 | uniform mat3 brushTransform; \n\ |
645 | void setPosition() \n\ |
646 | { \n\ |
647 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
648 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
649 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
650 | vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
651 | vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
652 | float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
653 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
654 | index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ |
655 | }\n" ; |
656 | |
657 | static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader_core |
658 | = qopenglslPositionWithLinearGradientBrushVertexShader_core; |
659 | |
660 | static const char* const qopenglslLinearGradientBrushSrcFragmentShader_core = "\n\ |
661 | uniform sampler2D brushTexture; \n\ |
662 | in float index; \n\ |
663 | vec4 srcPixel() \n\ |
664 | { \n\ |
665 | vec2 val = vec2(index, 0.5); \n\ |
666 | return texture(brushTexture, val); \n\ |
667 | }\n" ; |
668 | |
669 | |
670 | // Conical Gradient Brush |
671 | static const char* const qopenglslPositionWithConicalGradientBrushVertexShader_core = "\n\ |
672 | in vec2 vertexCoordsArray; \n\ |
673 | in vec3 pmvMatrix1; \n\ |
674 | in vec3 pmvMatrix2; \n\ |
675 | in vec3 pmvMatrix3; \n\ |
676 | out vec2 A; \n\ |
677 | uniform vec2 halfViewportSize; \n\ |
678 | uniform mat3 brushTransform; \n\ |
679 | void setPosition(void) \n\ |
680 | { \n\ |
681 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
682 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
683 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
684 | vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
685 | vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
686 | float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
687 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
688 | A = hTexCoords.xy * invertedHTexCoordsZ; \n\ |
689 | }\n" ; |
690 | |
691 | static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader_core |
692 | = qopenglslPositionWithConicalGradientBrushVertexShader_core; |
693 | |
694 | static const char* const qopenglslConicalGradientBrushSrcFragmentShader_core = "\n\ |
695 | #define INVERSE_2PI 0.1591549430918953358 \n\ |
696 | in vec2 A; \n\ |
697 | uniform sampler2D brushTexture; \n\ |
698 | uniform float angle; \n\ |
699 | vec4 srcPixel() \n\ |
700 | { \n\ |
701 | float t; \n\ |
702 | if (abs(A.y) == abs(A.x)) \n\ |
703 | t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ |
704 | else \n\ |
705 | t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ |
706 | return texture(brushTexture, vec2(t - floor(t), 0.5)); \n\ |
707 | }\n" ; |
708 | |
709 | |
710 | // Radial Gradient Brush |
711 | static const char* const qopenglslPositionWithRadialGradientBrushVertexShader_core = "\n\ |
712 | in vec2 vertexCoordsArray;\n\ |
713 | in vec3 pmvMatrix1; \n\ |
714 | in vec3 pmvMatrix2; \n\ |
715 | in vec3 pmvMatrix3; \n\ |
716 | out float b; \n\ |
717 | out vec2 A; \n\ |
718 | uniform vec2 halfViewportSize; \n\ |
719 | uniform mat3 brushTransform; \n\ |
720 | uniform vec2 fmp; \n\ |
721 | uniform vec3 bradius; \n\ |
722 | void setPosition(void) \n\ |
723 | {\n\ |
724 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
725 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
726 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
727 | vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
728 | vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
729 | float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
730 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
731 | A = hTexCoords.xy * invertedHTexCoordsZ; \n\ |
732 | b = bradius.x + 2.0 * dot(A, fmp); \n\ |
733 | }\n" ; |
734 | |
735 | static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader_core |
736 | = qopenglslPositionWithRadialGradientBrushVertexShader_core; |
737 | |
738 | static const char* const qopenglslRadialGradientBrushSrcFragmentShader_core = "\n\ |
739 | in float b; \n\ |
740 | in vec2 A; \n\ |
741 | uniform sampler2D brushTexture; \n\ |
742 | uniform float fmp2_m_radius2; \n\ |
743 | uniform float inverse_2_fmp2_m_radius2; \n\ |
744 | uniform float sqrfr; \n\ |
745 | uniform vec3 bradius; \n\ |
746 | \n\ |
747 | vec4 srcPixel() \n\ |
748 | { \n\ |
749 | float c = sqrfr-dot(A, A); \n\ |
750 | float det = b*b - 4.0*fmp2_m_radius2*c; \n\ |
751 | vec4 result = vec4(0.0); \n\ |
752 | if (det >= 0.0) { \n\ |
753 | float detSqrt = sqrt(det); \n\ |
754 | float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\ |
755 | if (bradius.y + w * bradius.z >= 0.0) \n\ |
756 | result = texture(brushTexture, vec2(w, 0.5)); \n\ |
757 | } \n\ |
758 | return result; \n\ |
759 | }\n" ; |
760 | |
761 | |
762 | // Texture Brush |
763 | static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\n\ |
764 | in vec2 vertexCoordsArray; \n\ |
765 | in vec3 pmvMatrix1; \n\ |
766 | in vec3 pmvMatrix2; \n\ |
767 | in vec3 pmvMatrix3; \n\ |
768 | out vec2 brushTextureCoords; \n\ |
769 | uniform vec2 halfViewportSize; \n\ |
770 | uniform vec2 invertedTextureSize; \n\ |
771 | uniform mat3 brushTransform; \n\ |
772 | \n\ |
773 | void setPosition(void) \n\ |
774 | { \n\ |
775 | mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ |
776 | vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ |
777 | gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ |
778 | vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ |
779 | vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ |
780 | float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ |
781 | gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ |
782 | brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ |
783 | }\n" ; |
784 | |
785 | static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core |
786 | = qopenglslPositionWithTextureBrushVertexShader_core; |
787 | |
788 | static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\ |
789 | in vec2 brushTextureCoords; \n\ |
790 | uniform sampler2D brushTexture; \n\ |
791 | vec4 srcPixel() \n\ |
792 | { \n\ |
793 | return texture(brushTexture, brushTextureCoords); \n\ |
794 | }\n" ; |
795 | |
796 | static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader_core = "\n\ |
797 | in vec2 brushTextureCoords; \n\ |
798 | uniform vec4 patternColor; \n\ |
799 | uniform sampler2D brushTexture; \n\ |
800 | vec4 srcPixel() \n\ |
801 | { \n\ |
802 | return patternColor * (1.0 - texture(brushTexture, brushTextureCoords).r); \n\ |
803 | }\n" ; |
804 | |
805 | // Solid Fill Brush |
806 | static const char* const qopenglslSolidBrushSrcFragmentShader_core = "\n\ |
807 | uniform vec4 fragmentColor; \n\ |
808 | vec4 srcPixel() \n\ |
809 | { \n\ |
810 | return fragmentColor; \n\ |
811 | }\n" ; |
812 | |
813 | static const char* const qopenglslImageSrcFragmentShader_core = "\n\ |
814 | in vec2 textureCoords; \n\ |
815 | uniform sampler2D imageTexture; \n\ |
816 | vec4 srcPixel() \n\ |
817 | { \n\ |
818 | return texture(imageTexture, textureCoords); \n\ |
819 | }\n" ; |
820 | |
821 | static const char* const qopenglslCustomSrcFragmentShader_core = "\n\ |
822 | in vec2 textureCoords; \n\ |
823 | uniform sampler2D imageTexture; \n\ |
824 | vec4 srcPixel() \n\ |
825 | { \n\ |
826 | return customShader(imageTexture, textureCoords); \n\ |
827 | }\n" ; |
828 | |
829 | static const char* const qopenglslImageSrcWithPatternFragmentShader_core = "\n\ |
830 | in vec2 textureCoords; \n\ |
831 | uniform vec4 patternColor; \n\ |
832 | uniform sampler2D imageTexture; \n\ |
833 | vec4 srcPixel() \n\ |
834 | { \n\ |
835 | return patternColor * (1.0 - texture(imageTexture, textureCoords).r); \n\ |
836 | }\n" ; |
837 | |
838 | static const char* const qopenglslNonPremultipliedImageSrcFragmentShader_core = "\n\ |
839 | in vec2 textureCoords; \n\ |
840 | uniform sampler2D imageTexture; \n\ |
841 | vec4 srcPixel() \n\ |
842 | { \n\ |
843 | vec4 sample = texture(imageTexture, textureCoords); \n\ |
844 | sample.rgb = sample.rgb * sample.a; \n\ |
845 | return sample; \n\ |
846 | }\n" ; |
847 | |
848 | static const char* const qopenglslGrayscaleImageSrcFragmentShader_core = "\n\ |
849 | in vec2 textureCoords; \n\ |
850 | uniform sampler2D imageTexture; \n\ |
851 | vec4 srcPixel() \n\ |
852 | { \n\ |
853 | return texture(imageTexture, textureCoords).rrra; \n\ |
854 | }\n" ; |
855 | |
856 | static const char* const qopenglslAlphaImageSrcFragmentShader_core = "\n\ |
857 | in vec2 textureCoords; \n\ |
858 | uniform sampler2D imageTexture; \n\ |
859 | vec4 srcPixel() \n\ |
860 | { \n\ |
861 | return vec4(0, 0, 0, texture(imageTexture, textureCoords).r); \n\ |
862 | }\n" ; |
863 | |
864 | static const char* const qopenglslShockingPinkSrcFragmentShader_core = "\n\ |
865 | vec4 srcPixel() \n\ |
866 | { \n\ |
867 | return vec4(0.98, 0.06, 0.75, 1.0); \n\ |
868 | }\n" ; |
869 | |
870 | static const char* const qopenglslMainFragmentShader_ImageArrays_core = |
871 | "#version 150 core\n\ |
872 | in float opacity; \n\ |
873 | out vec4 fragColor; \n\ |
874 | vec4 srcPixel(); \n\ |
875 | void main() \n\ |
876 | { \n\ |
877 | fragColor = srcPixel() * opacity; \n\ |
878 | }\n" ; |
879 | |
880 | static const char* const qopenglslMainFragmentShader_MO_core = |
881 | "#version 150 core\n\ |
882 | out vec4 fragColor; \n\ |
883 | uniform float globalOpacity; \n\ |
884 | vec4 srcPixel(); \n\ |
885 | vec4 applyMask(vec4); \n\ |
886 | void main() \n\ |
887 | { \n\ |
888 | fragColor = applyMask(srcPixel()*globalOpacity); \n\ |
889 | }\n" ; |
890 | |
891 | static const char* const qopenglslMainFragmentShader_M_core = |
892 | "#version 150 core\n\ |
893 | out vec4 fragColor; \n\ |
894 | vec4 srcPixel(); \n\ |
895 | vec4 applyMask(vec4); \n\ |
896 | void main() \n\ |
897 | { \n\ |
898 | fragColor = applyMask(srcPixel()); \n\ |
899 | }\n" ; |
900 | |
901 | static const char* const qopenglslMainFragmentShader_O_core = |
902 | "#version 150 core\n\ |
903 | out vec4 fragColor; \n\ |
904 | uniform float globalOpacity; \n\ |
905 | vec4 srcPixel(); \n\ |
906 | void main() \n\ |
907 | { \n\ |
908 | fragColor = srcPixel()*globalOpacity; \n\ |
909 | }\n" ; |
910 | |
911 | static const char* const qopenglslMainFragmentShader_core = |
912 | "#version 150 core\n\ |
913 | out vec4 fragColor; \n\ |
914 | vec4 srcPixel(); \n\ |
915 | void main() \n\ |
916 | { \n\ |
917 | fragColor = srcPixel(); \n\ |
918 | }\n" ; |
919 | |
920 | static const char* const qopenglslMaskFragmentShader_core = "\n\ |
921 | in vec2 textureCoords;\n\ |
922 | uniform sampler2D maskTexture;\n\ |
923 | vec4 applyMask(vec4 src) \n\ |
924 | {\n\ |
925 | vec4 mask = texture(maskTexture, textureCoords); \n\ |
926 | return src * mask.r; \n\ |
927 | }\n" ; |
928 | |
929 | // For source over with subpixel antialiasing, the final color is calculated per component as follows |
930 | // (.a is alpha component, .c is red, green or blue component): |
931 | // alpha = src.a * mask.c * opacity |
932 | // dest.c = dest.c * (1 - alpha) + src.c * alpha |
933 | // |
934 | // In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color |
935 | // In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one |
936 | // |
937 | // If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color |
938 | |
939 | // For source composition with subpixel antialiasing, the final color is calculated per component as follows: |
940 | // alpha = src.a * mask.c * opacity |
941 | // dest.c = dest.c * (1 - mask.c) + src.c * alpha |
942 | // |
943 | |
944 | static const char* const qopenglslRgbMaskFragmentShaderPass1_core = "\n\ |
945 | in vec2 textureCoords;\n\ |
946 | uniform sampler2D maskTexture;\n\ |
947 | vec4 applyMask(vec4 src) \n\ |
948 | { \n\ |
949 | vec4 mask = texture(maskTexture, textureCoords); \n\ |
950 | return src.a * mask; \n\ |
951 | }\n" ; |
952 | |
953 | static const char* const qopenglslRgbMaskFragmentShaderPass2_core = "\n\ |
954 | in vec2 textureCoords;\n\ |
955 | uniform sampler2D maskTexture;\n\ |
956 | vec4 applyMask(vec4 src) \n\ |
957 | { \n\ |
958 | vec4 mask = texture(maskTexture, textureCoords); \n\ |
959 | return src * mask; \n\ |
960 | }\n" ; |
961 | |
962 | /* |
963 | Left to implement: |
964 | RgbMaskFragmentShader_core, |
965 | RgbMaskWithGammaFragmentShader_core, |
966 | */ |
967 | |
968 | QT_END_NAMESPACE |
969 | |
970 | #endif // GLGC_SHADER_SOURCE_H |
971 | |