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 QGL_ENGINE_SHADER_SOURCE_H
53#define QGL_ENGINE_SHADER_SOURCE_H
54
55#include "qglengineshadermanager_p.h"
56
57QT_BEGIN_NAMESPACE
58
59
60
61static const char* const qglslMainVertexShader = "\n\
62 void setPosition(); \n\
63 void main(void) \n\
64 { \n\
65 setPosition(); \n\
66 }\n";
67
68static const char* const qglslMainWithTexCoordsVertexShader = "\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
78static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\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.
93static const char* const qglslPositionOnlyVertexShader = "\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
105static const char* const qglslComplexGeometryPositionOnlyVertexShader = "\n\
106 uniform highp mat3 matrix; \n\
107 uniform highp float translateZ; \n\
108 attribute highp vec2 vertexCoordsArray; \n\
109 void setPosition(void) \n\
110 { \n\
111 vec3 v = matrix * vec3(vertexCoordsArray, 1.0); \n\
112 vec4 vz = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, translateZ, 1) * vec4(v, 1.0); \n\
113 gl_Position = vec4(vz.xyz, 1.0);\n\
114 } \n";
115
116static const char* const qglslUntransformedPositionVertexShader = "\n\
117 attribute highp vec4 vertexCoordsArray; \n\
118 void setPosition(void) \n\
119 { \n\
120 gl_Position = vertexCoordsArray; \n\
121 }\n";
122
123// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
124static const char* const qglslPositionWithPatternBrushVertexShader = "\n\
125 attribute highp vec2 vertexCoordsArray; \n\
126 attribute highp vec3 pmvMatrix1; \n\
127 attribute highp vec3 pmvMatrix2; \n\
128 attribute highp vec3 pmvMatrix3; \n\
129 uniform mediump vec2 halfViewportSize; \n\
130 uniform highp vec2 invertedTextureSize; \n\
131 uniform highp mat3 brushTransform; \n\
132 varying highp vec2 patternTexCoords; \n\
133 void setPosition(void) \n\
134 { \n\
135 highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
136 vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
137 gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
138 mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
139 mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
140 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
141 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
142 patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
143 }\n";
144
145static const char* const qglslAffinePositionWithPatternBrushVertexShader
146 = qglslPositionWithPatternBrushVertexShader;
147
148static const char* const qglslPatternBrushSrcFragmentShader = "\n\
149 uniform sampler2D brushTexture; \n\
150 uniform lowp vec4 patternColor; \n\
151 varying highp vec2 patternTexCoords;\n\
152 lowp vec4 srcPixel() \n\
153 { \n\
154 return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\
155 }\n";
156
157
158// Linear Gradient Brush
159static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\n\
160 attribute highp vec2 vertexCoordsArray; \n\
161 attribute highp vec3 pmvMatrix1; \n\
162 attribute highp vec3 pmvMatrix2; \n\
163 attribute highp vec3 pmvMatrix3; \n\
164 uniform mediump vec2 halfViewportSize; \n\
165 uniform highp vec3 linearData; \n\
166 uniform highp mat3 brushTransform; \n\
167 varying mediump float index; \n\
168 void setPosition() \n\
169 { \n\
170 highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
171 vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
172 gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
173 mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
174 mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
175 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
176 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
177 index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
178 }\n";
179
180static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader
181 = qglslPositionWithLinearGradientBrushVertexShader;
182
183static const char* const qglslLinearGradientBrushSrcFragmentShader = "\n\
184 uniform sampler2D brushTexture; \n\
185 varying mediump float index; \n\
186 lowp vec4 srcPixel() \n\
187 { \n\
188 mediump vec2 val = vec2(index, 0.5); \n\
189 return texture2D(brushTexture, val); \n\
190 }\n";
191
192
193// Conical Gradient Brush
194static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\n\
195 attribute highp vec2 vertexCoordsArray; \n\
196 attribute highp vec3 pmvMatrix1; \n\
197 attribute highp vec3 pmvMatrix2; \n\
198 attribute highp vec3 pmvMatrix3; \n\
199 uniform mediump vec2 halfViewportSize; \n\
200 uniform highp mat3 brushTransform; \n\
201 varying highp vec2 A; \n\
202 void setPosition(void) \n\
203 { \n\
204 highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
205 vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
206 gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
207 mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
208 mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
209 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
210 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
211 A = hTexCoords.xy * invertedHTexCoordsZ; \n\
212 }\n";
213
214static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader
215 = qglslPositionWithConicalGradientBrushVertexShader;
216
217static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
218 #define INVERSE_2PI 0.1591549430918953358 \n\
219 uniform sampler2D brushTexture; \n\
220 uniform mediump float angle; \n\
221 varying highp vec2 A; \n\
222 lowp vec4 srcPixel() \n\
223 { \n\
224 highp float t; \n\
225 if (abs(A.y) == abs(A.x)) \n\
226 t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
227 else \n\
228 t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
229 return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\
230 }\n";
231
232
233// Radial Gradient Brush
234static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
235 attribute highp vec2 vertexCoordsArray;\n\
236 attribute highp vec3 pmvMatrix1; \n\
237 attribute highp vec3 pmvMatrix2; \n\
238 attribute highp vec3 pmvMatrix3; \n\
239 uniform mediump vec2 halfViewportSize; \n\
240 uniform highp mat3 brushTransform; \n\
241 uniform highp vec2 fmp; \n\
242 uniform mediump vec3 bradius; \n\
243 varying highp float b; \n\
244 varying highp vec2 A; \n\
245 void setPosition(void) \n\
246 {\n\
247 highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
248 vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
249 gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
250 mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
251 mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
252 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
253 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
254 A = hTexCoords.xy * invertedHTexCoordsZ; \n\
255 b = bradius.x + 2.0 * dot(A, fmp); \n\
256 }\n";
257
258static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
259 = qglslPositionWithRadialGradientBrushVertexShader;
260
261static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\
262 uniform sampler2D brushTexture; \n\
263 uniform highp float fmp2_m_radius2; \n\
264 uniform highp float inverse_2_fmp2_m_radius2; \n\
265 uniform highp float sqrfr; \n\
266 varying highp float b; \n\
267 varying highp vec2 A; \n\
268 uniform mediump vec3 bradius; \n\
269 lowp vec4 srcPixel() \n\
270 { \n\
271 highp float c = sqrfr-dot(A, A); \n\
272 highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\
273 lowp vec4 result = vec4(0.0); \n\
274 if (det >= 0.0) { \n\
275 highp float detSqrt = sqrt(det); \n\
276 highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
277 if (bradius.y + w * bradius.z >= 0.0) \n\
278 result = texture2D(brushTexture, vec2(w, 0.5)); \n\
279 } \n\
280 return result; \n\
281 }\n";
282
283
284// Texture Brush
285static const char* const qglslPositionWithTextureBrushVertexShader = "\n\
286 attribute highp vec2 vertexCoordsArray; \n\
287 attribute highp vec3 pmvMatrix1; \n\
288 attribute highp vec3 pmvMatrix2; \n\
289 attribute highp vec3 pmvMatrix3; \n\
290 uniform mediump vec2 halfViewportSize; \n\
291 uniform highp vec2 invertedTextureSize; \n\
292 uniform highp mat3 brushTransform; \n\
293 varying highp vec2 brushTextureCoords; \n\
294 void setPosition(void) \n\
295 { \n\
296 highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
297 vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
298 gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
299 mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
300 mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
301 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
302 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
303 brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
304 }\n";
305
306static const char* const qglslAffinePositionWithTextureBrushVertexShader
307 = qglslPositionWithTextureBrushVertexShader;
308
309// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
310// we emulate GL_REPEAT by only taking the fractional part of the texture coords.
311// TODO: Special case POT textures which don't need this emulation
312static const char* const qglslTextureBrushSrcFragmentShader_ES = "\n\
313 varying highp vec2 brushTextureCoords; \n\
314 uniform sampler2D brushTexture; \n\
315 lowp vec4 srcPixel() { \n\
316 return texture2D(brushTexture, fract(brushTextureCoords)); \n\
317 }\n";
318
319static const char* const qglslTextureBrushSrcFragmentShader_desktop = "\n\
320 varying highp vec2 brushTextureCoords; \n\
321 uniform sampler2D brushTexture; \n\
322 lowp vec4 srcPixel() \n\
323 { \n\
324 return texture2D(brushTexture, brushTextureCoords); \n\
325 }\n";
326
327static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\
328 varying highp vec2 brushTextureCoords; \n\
329 uniform lowp vec4 patternColor; \n\
330 uniform sampler2D brushTexture; \n\
331 lowp vec4 srcPixel() \n\
332 { \n\
333 return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\
334 }\n";
335
336// Solid Fill Brush
337static const char* const qglslSolidBrushSrcFragmentShader = "\n\
338 uniform lowp vec4 fragmentColor; \n\
339 lowp vec4 srcPixel() \n\
340 { \n\
341 return fragmentColor; \n\
342 }\n";
343
344static const char* const qglslImageSrcFragmentShader = "\n\
345 varying highp vec2 textureCoords; \n\
346 uniform sampler2D imageTexture; \n\
347 lowp vec4 srcPixel() \n\
348 { \n"
349 "return texture2D(imageTexture, textureCoords); \n"
350 "}\n";
351
352static const char* const qglslCustomSrcFragmentShader = "\n\
353 varying highp vec2 textureCoords; \n\
354 uniform sampler2D imageTexture; \n\
355 lowp vec4 srcPixel() \n\
356 { \n\
357 return customShader(imageTexture, textureCoords); \n\
358 }\n";
359
360static const char* const qglslImageSrcWithPatternFragmentShader = "\n\
361 varying highp vec2 textureCoords; \n\
362 uniform lowp vec4 patternColor; \n\
363 uniform sampler2D imageTexture; \n\
364 lowp vec4 srcPixel() \n\
365 { \n\
366 return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\
367 }\n";
368
369static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\n\
370 varying highp vec2 textureCoords; \n\
371 uniform sampler2D imageTexture; \n\
372 lowp vec4 srcPixel() \n\
373 { \n\
374 lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\
375 sample.rgb = sample.rgb * sample.a; \n\
376 return sample; \n\
377 }\n";
378
379static const char* const qglslShockingPinkSrcFragmentShader = "\n\
380 lowp vec4 srcPixel() \n\
381 { \n\
382 return vec4(0.98, 0.06, 0.75, 1.0); \n\
383 }\n";
384
385static const char* const qglslMainFragmentShader_ImageArrays = "\n\
386 varying lowp float opacity; \n\
387 lowp vec4 srcPixel(); \n\
388 void main() \n\
389 { \n\
390 gl_FragColor = srcPixel() * opacity; \n\
391 }\n";
392
393static const char* const qglslMainFragmentShader_CMO = "\n\
394 uniform lowp float globalOpacity; \n\
395 lowp vec4 srcPixel(); \n\
396 lowp vec4 applyMask(lowp vec4); \n\
397 lowp vec4 compose(lowp vec4); \n\
398 void main() \n\
399 { \n\
400 gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
401 }\n";
402
403static const char* const qglslMainFragmentShader_CM = "\n\
404 lowp vec4 srcPixel(); \n\
405 lowp vec4 applyMask(lowp vec4); \n\
406 lowp vec4 compose(lowp vec4); \n\
407 void main() \n\
408 { \n\
409 gl_FragColor = applyMask(compose(srcPixel())); \n\
410 }\n";
411
412static const char* const qglslMainFragmentShader_MO = "\n\
413 uniform lowp float globalOpacity; \n\
414 lowp vec4 srcPixel(); \n\
415 lowp vec4 applyMask(lowp vec4); \n\
416 void main() \n\
417 { \n\
418 gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\
419 }\n";
420
421static const char* const qglslMainFragmentShader_M = "\n\
422 lowp vec4 srcPixel(); \n\
423 lowp vec4 applyMask(lowp vec4); \n\
424 void main() \n\
425 { \n\
426 gl_FragColor = applyMask(srcPixel()); \n\
427 }\n";
428
429static const char* const qglslMainFragmentShader_CO = "\n\
430 uniform lowp float globalOpacity; \n\
431 lowp vec4 srcPixel(); \n\
432 lowp vec4 compose(lowp vec4); \n\
433 void main() \n\
434 { \n\
435 gl_FragColor = compose(srcPixel()*globalOpacity); \n\
436 }\n";
437
438static const char* const qglslMainFragmentShader_C = "\n\
439 lowp vec4 srcPixel(); \n\
440 lowp vec4 compose(lowp vec4); \n\
441 void main() \n\
442 { \n\
443 gl_FragColor = compose(srcPixel()); \n\
444 }\n";
445
446static const char* const qglslMainFragmentShader_O = "\n\
447 uniform lowp float globalOpacity; \n\
448 lowp vec4 srcPixel(); \n\
449 void main() \n\
450 { \n\
451 gl_FragColor = srcPixel()*globalOpacity; \n\
452 }\n";
453
454static const char* const qglslMainFragmentShader = "\n\
455 lowp vec4 srcPixel(); \n\
456 void main() \n\
457 { \n\
458 gl_FragColor = srcPixel(); \n\
459 }\n";
460
461static const char* const qglslMaskFragmentShader = "\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.a; \n\
468 }\n";
469
470// For source over with subpixel antialiasing, the final color is calculated per component as follows
471// (.a is alpha component, .c is red, green or blue component):
472// alpha = src.a * mask.c * opacity
473// dest.c = dest.c * (1 - alpha) + src.c * alpha
474//
475// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
476// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
477//
478// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
479
480// For source composition with subpixel antialiasing, the final color is calculated per component as follows:
481// alpha = src.a * mask.c * opacity
482// dest.c = dest.c * (1 - mask.c) + src.c * alpha
483//
484
485static const char* const qglslRgbMaskFragmentShaderPass1 = "\n\
486 varying highp vec2 textureCoords;\n\
487 uniform sampler2D maskTexture;\n\
488 lowp vec4 applyMask(lowp vec4 src) \n\
489 { \n\
490 lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
491 return src.a * mask; \n\
492 }\n";
493
494static const char* const qglslRgbMaskFragmentShaderPass2 = "\n\
495 varying highp vec2 textureCoords;\n\
496 uniform sampler2D maskTexture;\n\
497 lowp vec4 applyMask(lowp vec4 src) \n\
498 { \n\
499 lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
500 return src * mask; \n\
501 }\n";
502
503/*
504 Left to implement:
505 RgbMaskFragmentShader,
506 RgbMaskWithGammaFragmentShader,
507
508 MultiplyCompositionModeFragmentShader,
509 ScreenCompositionModeFragmentShader,
510 OverlayCompositionModeFragmentShader,
511 DarkenCompositionModeFragmentShader,
512 LightenCompositionModeFragmentShader,
513 ColorDodgeCompositionModeFragmentShader,
514 ColorBurnCompositionModeFragmentShader,
515 HardLightCompositionModeFragmentShader,
516 SoftLightCompositionModeFragmentShader,
517 DifferenceCompositionModeFragmentShader,
518 ExclusionCompositionModeFragmentShader,
519*/
520
521QT_END_NAMESPACE
522
523#endif // GLGC_SHADER_SOURCE_H
524