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