Changeset View
Changeset View
Standalone View
Standalone View
effects/blur/blurshader.cpp
Show All 15 Lines | |||||
16 | * along with this program; see the file COPYING. if not, write to | 16 | * along with this program; see the file COPYING. if not, write to | ||
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | * Boston, MA 02110-1301, USA. | 18 | * Boston, MA 02110-1301, USA. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "blurshader.h" | 21 | #include "blurshader.h" | ||
22 | 22 | | |||
23 | #include <kwineffects.h> | 23 | #include <kwineffects.h> | ||
24 | #include "kwinglutils.h" | | |||
25 | #include <kwinglplatform.h> | 24 | #include <kwinglplatform.h> | ||
25 | #include <kwinglutils.h> | ||||
26 | 26 | | |||
27 | #include <QByteArray> | 27 | #include <QByteArray> | ||
28 | #include <QMatrix4x4> | | |||
29 | #include <QTextStream> | 28 | #include <QTextStream> | ||
30 | #include <QVector2D> | | |||
31 | 29 | | |||
32 | #include <cmath> | 30 | namespace KWin | ||
33 | | ||||
34 | using namespace KWin; | | |||
35 | | ||||
36 | | ||||
37 | BlurShader::BlurShader() | | |||
38 | : mValid(false) | | |||
39 | { | | |||
40 | } | | |||
41 | | ||||
42 | BlurShader::~BlurShader() | | |||
43 | { | | |||
44 | } | | |||
45 | | ||||
46 | BlurShader *BlurShader::create() | | |||
47 | { | | |||
48 | return new GLSLBlurShader(); | | |||
49 | } | | |||
50 | | ||||
51 | // ---------------------------------------------------------------------------- | | |||
52 | | ||||
53 | | ||||
54 | | ||||
55 | GLSLBlurShader::GLSLBlurShader() | | |||
56 | { | | |||
57 | init(); | | |||
58 | } | | |||
59 | | ||||
60 | GLSLBlurShader::~GLSLBlurShader() | | |||
61 | { | | |||
62 | reset(); | | |||
63 | } | | |||
64 | | ||||
65 | void GLSLBlurShader::reset() | | |||
66 | { | 31 | { | ||
67 | delete m_shaderDownsample; | | |||
68 | m_shaderDownsample = nullptr; | | |||
69 | | ||||
70 | delete m_shaderUpsample; | | |||
71 | m_shaderUpsample = nullptr; | | |||
72 | | ||||
73 | delete m_shaderCopysample; | | |||
74 | m_shaderCopysample = nullptr; | | |||
75 | | ||||
76 | delete m_shaderNoisesample; | | |||
77 | m_shaderNoisesample = nullptr; | | |||
78 | 32 | | |||
79 | setIsValid(false); | 33 | BlurShader::BlurShader(QObject *parent) | ||
80 | } | 34 | : QObject(parent) | ||
81 | | ||||
82 | void GLSLBlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix) | | |||
83 | { | | |||
84 | if (!isValid()) | | |||
85 | return; | | |||
86 | | ||||
87 | switch (m_activeSampleType) { | | |||
88 | case CopySampleType: | | |||
89 | if (matrix == m_matrixCopysample) | | |||
90 | return; | | |||
91 | | ||||
92 | m_matrixCopysample = matrix; | | |||
93 | m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, matrix); | | |||
94 | break; | | |||
95 | | ||||
96 | case UpSampleType: | | |||
97 | if (matrix == m_matrixUpsample) | | |||
98 | return; | | |||
99 | | ||||
100 | m_matrixUpsample = matrix; | | |||
101 | m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, matrix); | | |||
102 | break; | | |||
103 | | ||||
104 | case DownSampleType: | | |||
105 | if (matrix == m_matrixDownsample) | | |||
106 | return; | | |||
107 | | ||||
108 | m_matrixDownsample = matrix; | | |||
109 | m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, matrix); | | |||
110 | break; | | |||
111 | | ||||
112 | case NoiseSampleType: | | |||
113 | if (matrix == m_matrixNoisesample) | | |||
114 | return; | | |||
115 | | ||||
116 | m_matrixNoisesample = matrix; | | |||
117 | m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, matrix); | | |||
118 | break; | | |||
119 | } | | |||
120 | } | | |||
121 | | ||||
122 | void GLSLBlurShader::setOffset(float offset) | | |||
123 | { | | |||
124 | if (!isValid()) | | |||
125 | return; | | |||
126 | | ||||
127 | switch (m_activeSampleType) { | | |||
128 | case UpSampleType: | | |||
129 | if (offset == m_offsetUpsample) | | |||
130 | return; | | |||
131 | | ||||
132 | m_offsetUpsample = offset; | | |||
133 | m_shaderUpsample->setUniform(m_offsetLocationUpsample, offset); | | |||
134 | break; | | |||
135 | | ||||
136 | case DownSampleType: | | |||
137 | if (offset == m_offsetDownsample) | | |||
138 | return; | | |||
139 | | ||||
140 | m_offsetDownsample = offset; | | |||
141 | m_shaderDownsample->setUniform(m_offsetLocationDownsample, offset); | | |||
142 | break; | | |||
143 | | ||||
144 | case NoiseSampleType: | | |||
145 | if (offset == m_offsetNoisesample) | | |||
146 | return; | | |||
147 | | ||||
148 | m_offsetNoisesample = offset; | | |||
149 | m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, offset); | | |||
150 | break; | | |||
151 | } | | |||
152 | } | | |||
153 | | ||||
154 | void GLSLBlurShader::setTargetTextureSize(QSize renderTextureSize) | | |||
155 | { | | |||
156 | if (!isValid()) | | |||
157 | return; | | |||
158 | | ||||
159 | QVector2D texSize = QVector2D(renderTextureSize.width(), renderTextureSize.height()); | | |||
160 | | ||||
161 | switch (m_activeSampleType) { | | |||
162 | case CopySampleType: | | |||
163 | m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, texSize); | | |||
164 | break; | | |||
165 | | ||||
166 | case UpSampleType: | | |||
167 | m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, texSize); | | |||
168 | m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | | |||
169 | break; | | |||
170 | | ||||
171 | case DownSampleType: | | |||
172 | m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, texSize); | | |||
173 | m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | | |||
174 | break; | | |||
175 | | ||||
176 | case NoiseSampleType: | | |||
177 | m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, texSize); | | |||
178 | m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | | |||
179 | break; | | |||
180 | } | | |||
181 | } | | |||
182 | | ||||
183 | void GLSLBlurShader::setNoiseTextureSize(QSize noiseTextureSize) | | |||
184 | { | | |||
185 | QVector2D noiseTexSize = QVector2D(noiseTextureSize.width(), noiseTextureSize.height()); | | |||
186 | | ||||
187 | if (noiseTexSize != m_noiseTextureSizeNoisesample) { | | |||
188 | m_noiseTextureSizeNoisesample = noiseTexSize; | | |||
189 | m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, noiseTexSize); | | |||
190 | } | | |||
191 | } | | |||
192 | | ||||
193 | void GLSLBlurShader::setTexturePosition(QPoint texPos) | | |||
194 | { | | |||
195 | m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(-texPos.x(), texPos.y())); | | |||
196 | } | | |||
197 | | ||||
198 | void GLSLBlurShader::setBlurRect(QRect blurRect, QSize screenSize) | | |||
199 | { | | |||
200 | if (!isValid()) | | |||
201 | return; | | |||
202 | | ||||
203 | QVector4D rect = QVector4D( | | |||
204 | blurRect.bottomLeft().x() / float(screenSize.width()), | | |||
205 | 1.0 - blurRect.bottomLeft().y() / float(screenSize.height()), | | |||
206 | blurRect.topRight().x() / float(screenSize.width()), | | |||
207 | 1.0 - blurRect.topRight().y() / float(screenSize.height()) | | |||
208 | ); | | |||
209 | | ||||
210 | m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect); | | |||
211 | } | | |||
212 | | ||||
213 | void GLSLBlurShader::bind(SampleType sampleType) | | |||
214 | { | | |||
215 | if (!isValid()) | | |||
216 | return; | | |||
217 | | ||||
218 | switch (sampleType) { | | |||
219 | case CopySampleType: | | |||
220 | ShaderManager::instance()->pushShader(m_shaderCopysample); | | |||
221 | break; | | |||
222 | | ||||
223 | case UpSampleType: | | |||
224 | ShaderManager::instance()->pushShader(m_shaderUpsample); | | |||
225 | break; | | |||
226 | | ||||
227 | case DownSampleType: | | |||
228 | ShaderManager::instance()->pushShader(m_shaderDownsample); | | |||
229 | break; | | |||
230 | | ||||
231 | case NoiseSampleType: | | |||
232 | ShaderManager::instance()->pushShader(m_shaderNoisesample); | | |||
233 | break; | | |||
234 | } | | |||
235 | | ||||
236 | m_activeSampleType = sampleType; | | |||
237 | } | | |||
238 | | ||||
239 | void GLSLBlurShader::unbind() | | |||
240 | { | | |||
241 | ShaderManager::instance()->popShader(); | | |||
242 | } | | |||
243 | | ||||
244 | void GLSLBlurShader::init() | | |||
245 | { | 35 | { | ||
246 | const bool gles = GLPlatform::instance()->isGLES(); | 36 | const bool gles = GLPlatform::instance()->isGLES(); | ||
247 | const bool glsl_140 = !gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(1, 40); | 37 | const bool glsl_140 = !gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(1, 40); | ||
248 | const bool core = glsl_140 || (gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(3, 0)); | 38 | const bool core = glsl_140 || (gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(3, 0)); | ||
249 | 39 | | |||
250 | QByteArray vertexSource; | 40 | QByteArray vertexSource; | ||
251 | QByteArray fragmentDownSource; | 41 | QByteArray fragmentDownSource; | ||
252 | QByteArray fragmentUpSource; | 42 | QByteArray fragmentUpSource; | ||
Show All 20 Lines | 62 | QString glUniformString = "uniform sampler2D texUnit;\n" | |||
273 | "uniform float offset;\n" | 63 | "uniform float offset;\n" | ||
274 | "uniform vec2 renderTextureSize;\n" | 64 | "uniform vec2 renderTextureSize;\n" | ||
275 | "uniform vec2 halfpixel;\n"; | 65 | "uniform vec2 halfpixel;\n"; | ||
276 | 66 | | |||
277 | if (core) { | 67 | if (core) { | ||
278 | glUniformString += "out vec4 fragColor;\n\n"; | 68 | glUniformString += "out vec4 fragColor;\n\n"; | ||
279 | } | 69 | } | ||
280 | 70 | | |||
281 | | ||||
282 | // Vertex shader | 71 | // Vertex shader | ||
283 | // =================================================================== | | |||
284 | QTextStream streamVert(&vertexSource); | 72 | QTextStream streamVert(&vertexSource); | ||
285 | 73 | | |||
286 | streamVert << glHeaderString; | 74 | streamVert << glHeaderString; | ||
287 | 75 | | |||
288 | streamVert << "uniform mat4 modelViewProjectionMatrix;\n"; | 76 | streamVert << "uniform mat4 modelViewProjectionMatrix;\n"; | ||
289 | streamVert << attribute << " vec4 vertex;\n\n"; | 77 | streamVert << attribute << " vec4 vertex;\n\n"; | ||
290 | streamVert << "\n"; | 78 | streamVert << "\n"; | ||
291 | streamVert << "void main(void)\n"; | 79 | streamVert << "void main(void)\n"; | ||
292 | streamVert << "{\n"; | 80 | streamVert << "{\n"; | ||
293 | streamVert << " gl_Position = modelViewProjectionMatrix * vertex;\n"; | 81 | streamVert << " gl_Position = modelViewProjectionMatrix * vertex;\n"; | ||
294 | streamVert << "}\n"; | 82 | streamVert << "}\n"; | ||
295 | 83 | | |||
296 | streamVert.flush(); | 84 | streamVert.flush(); | ||
297 | 85 | | |||
298 | // Fragment shader (Dual Kawase Blur) - Downsample | 86 | // Fragment shader (Dual Kawase Blur) - Downsample | ||
299 | // =================================================================== | | |||
300 | QTextStream streamFragDown(&fragmentDownSource); | 87 | QTextStream streamFragDown(&fragmentDownSource); | ||
301 | 88 | | |||
302 | streamFragDown << glHeaderString << glUniformString; | 89 | streamFragDown << glHeaderString << glUniformString; | ||
303 | 90 | | |||
304 | streamFragDown << "void main(void)\n"; | 91 | streamFragDown << "void main(void)\n"; | ||
305 | streamFragDown << "{\n"; | 92 | streamFragDown << "{\n"; | ||
306 | streamFragDown << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | 93 | streamFragDown << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | ||
307 | streamFragDown << " \n"; | 94 | streamFragDown << " \n"; | ||
308 | streamFragDown << " vec4 sum = " << texture2D << "(texUnit, uv) * 4.0;\n"; | 95 | streamFragDown << " vec4 sum = " << texture2D << "(texUnit, uv) * 4.0;\n"; | ||
309 | streamFragDown << " sum += " << texture2D << "(texUnit, uv - halfpixel.xy * offset);\n"; | 96 | streamFragDown << " sum += " << texture2D << "(texUnit, uv - halfpixel.xy * offset);\n"; | ||
310 | streamFragDown << " sum += " << texture2D << "(texUnit, uv + halfpixel.xy * offset);\n"; | 97 | streamFragDown << " sum += " << texture2D << "(texUnit, uv + halfpixel.xy * offset);\n"; | ||
311 | streamFragDown << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset);\n"; | 98 | streamFragDown << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset);\n"; | ||
312 | streamFragDown << " sum += " << texture2D << "(texUnit, uv - vec2(halfpixel.x, -halfpixel.y) * offset);\n"; | 99 | streamFragDown << " sum += " << texture2D << "(texUnit, uv - vec2(halfpixel.x, -halfpixel.y) * offset);\n"; | ||
313 | streamFragDown << " \n"; | 100 | streamFragDown << " \n"; | ||
314 | streamFragDown << " " << fragColor << " = sum / 8.0;\n"; | 101 | streamFragDown << " " << fragColor << " = sum / 8.0;\n"; | ||
315 | streamFragDown << "}\n"; | 102 | streamFragDown << "}\n"; | ||
316 | 103 | | |||
317 | streamFragDown.flush(); | 104 | streamFragDown.flush(); | ||
318 | 105 | | |||
319 | // Fragment shader (Dual Kawase Blur) - Upsample | 106 | // Fragment shader (Dual Kawase Blur) - Upsample | ||
320 | // =================================================================== | | |||
321 | QTextStream streamFragUp(&fragmentUpSource); | 107 | QTextStream streamFragUp(&fragmentUpSource); | ||
322 | 108 | | |||
323 | streamFragUp << glHeaderString << glUniformString; | 109 | streamFragUp << glHeaderString << glUniformString; | ||
324 | 110 | | |||
325 | streamFragUp << "void main(void)\n"; | 111 | streamFragUp << "void main(void)\n"; | ||
326 | streamFragUp << "{\n"; | 112 | streamFragUp << "{\n"; | ||
327 | streamFragUp << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | 113 | streamFragUp << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | ||
328 | streamFragUp << " \n"; | 114 | streamFragUp << " \n"; | ||
329 | streamFragUp << " vec4 sum = " << texture2D << "(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset);\n"; | 115 | streamFragUp << " vec4 sum = " << texture2D << "(texUnit, uv + vec2(-halfpixel.x * 2.0, 0.0) * offset);\n"; | ||
330 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; | 116 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; | ||
331 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset);\n"; | 117 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, halfpixel.y * 2.0) * offset);\n"; | ||
332 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; | 118 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, halfpixel.y) * offset) * 2.0;\n"; | ||
333 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset);\n"; | 119 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x * 2.0, 0.0) * offset);\n"; | ||
334 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | 120 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | ||
335 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n"; | 121 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n"; | ||
336 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | 122 | streamFragUp << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | ||
337 | streamFragUp << " \n"; | 123 | streamFragUp << " \n"; | ||
338 | streamFragUp << " " << fragColor << " = sum / 12.0;\n"; | 124 | streamFragUp << " " << fragColor << " = sum / 12.0;\n"; | ||
339 | streamFragUp << "}\n"; | 125 | streamFragUp << "}\n"; | ||
340 | 126 | | |||
341 | streamFragUp.flush(); | 127 | streamFragUp.flush(); | ||
342 | 128 | | |||
343 | // Fragment shader - Copy texture | 129 | // Fragment shader - Copy texture | ||
344 | // =================================================================== | | |||
345 | QTextStream streamFragCopy(&fragmentCopySource); | 130 | QTextStream streamFragCopy(&fragmentCopySource); | ||
346 | 131 | | |||
347 | streamFragCopy << glHeaderString; | 132 | streamFragCopy << glHeaderString; | ||
348 | 133 | | |||
349 | streamFragCopy << "uniform sampler2D texUnit;\n"; | 134 | streamFragCopy << "uniform sampler2D texUnit;\n"; | ||
350 | streamFragCopy << "uniform vec2 renderTextureSize;\n"; | 135 | streamFragCopy << "uniform vec2 renderTextureSize;\n"; | ||
351 | streamFragCopy << "uniform vec4 blurRect;\n"; | 136 | streamFragCopy << "uniform vec4 blurRect;\n"; | ||
352 | 137 | | |||
353 | if (core) | 138 | if (core) { | ||
354 | streamFragCopy << "out vec4 fragColor;\n\n"; | 139 | streamFragCopy << "out vec4 fragColor;\n\n"; | ||
140 | } | ||||
355 | 141 | | |||
356 | streamFragCopy << "void main(void)\n"; | 142 | streamFragCopy << "void main(void)\n"; | ||
357 | streamFragCopy << "{\n"; | 143 | streamFragCopy << "{\n"; | ||
358 | streamFragCopy << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | 144 | streamFragCopy << " vec2 uv = vec2(gl_FragCoord.xy / renderTextureSize);\n"; | ||
359 | streamFragCopy << " " << fragColor << " = " << texture2D << "(texUnit, clamp(uv, blurRect.xy, blurRect.zw));\n"; | 145 | streamFragCopy << " " << fragColor << " = " << texture2D << "(texUnit, clamp(uv, blurRect.xy, blurRect.zw));\n"; | ||
360 | streamFragCopy << "}\n"; | 146 | streamFragCopy << "}\n"; | ||
361 | 147 | | |||
362 | streamFragCopy.flush(); | 148 | streamFragCopy.flush(); | ||
363 | 149 | | |||
364 | // Fragment shader - Noise texture | 150 | // Fragment shader - Noise texture | ||
365 | // =================================================================== | | |||
366 | QTextStream streamFragNoise(&fragmentNoiseSource); | 151 | QTextStream streamFragNoise(&fragmentNoiseSource); | ||
367 | 152 | | |||
368 | streamFragNoise << glHeaderString << glUniformString; | 153 | streamFragNoise << glHeaderString << glUniformString; | ||
369 | 154 | | |||
370 | streamFragNoise << "uniform sampler2D noiseTexUnit;\n"; | 155 | streamFragNoise << "uniform sampler2D noiseTexUnit;\n"; | ||
371 | streamFragNoise << "uniform vec2 noiseTextureSize;\n"; | 156 | streamFragNoise << "uniform vec2 noiseTextureSize;\n"; | ||
372 | streamFragNoise << "uniform vec2 texStartPos;\n"; | 157 | streamFragNoise << "uniform vec2 texStartPos;\n"; | ||
373 | 158 | | |||
Show All 12 Lines | |||||
386 | streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n"; | 171 | streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(0.0, -halfpixel.y * 2.0) * offset);\n"; | ||
387 | streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | 172 | streamFragNoise << " sum += " << texture2D << "(texUnit, uv + vec2(-halfpixel.x, -halfpixel.y) * offset) * 2.0;\n"; | ||
388 | streamFragNoise << " \n"; | 173 | streamFragNoise << " \n"; | ||
389 | streamFragNoise << " " << fragColor << " = sum / 12.0 - (vec4(0.5, 0.5, 0.5, 0) - vec4(" << texture2D << "(noiseTexUnit, uvNoise).rrr, 0));\n"; | 174 | streamFragNoise << " " << fragColor << " = sum / 12.0 - (vec4(0.5, 0.5, 0.5, 0) - vec4(" << texture2D << "(noiseTexUnit, uvNoise).rrr, 0));\n"; | ||
390 | streamFragNoise << "}\n"; | 175 | streamFragNoise << "}\n"; | ||
391 | 176 | | |||
392 | streamFragNoise.flush(); | 177 | streamFragNoise.flush(); | ||
393 | 178 | | |||
179 | m_shaderDownsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource)); | ||||
180 | m_shaderUpsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource)); | ||||
181 | m_shaderCopysample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource)); | ||||
182 | m_shaderNoisesample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource)); | ||||
394 | 183 | | |||
395 | m_shaderDownsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource); | 184 | m_valid = m_shaderDownsample->isValid() && | ||
396 | m_shaderUpsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource); | | |||
397 | m_shaderCopysample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource); | | |||
398 | m_shaderNoisesample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource); | | |||
399 | | ||||
400 | bool areShadersValid = m_shaderDownsample->isValid() && | | |||
401 | m_shaderUpsample->isValid() && | 185 | m_shaderUpsample->isValid() && | ||
402 | m_shaderCopysample->isValid() && | 186 | m_shaderCopysample->isValid() && | ||
403 | m_shaderNoisesample->isValid(); | 187 | m_shaderNoisesample->isValid(); | ||
404 | setIsValid(areShadersValid); | | |||
405 | 188 | | |||
406 | if (areShadersValid) { | 189 | if (m_valid) { | ||
407 | m_mvpMatrixLocationDownsample = m_shaderDownsample->uniformLocation("modelViewProjectionMatrix"); | 190 | m_mvpMatrixLocationDownsample = m_shaderDownsample->uniformLocation("modelViewProjectionMatrix"); | ||
408 | m_offsetLocationDownsample = m_shaderDownsample->uniformLocation("offset"); | 191 | m_offsetLocationDownsample = m_shaderDownsample->uniformLocation("offset"); | ||
409 | m_renderTextureSizeLocationDownsample = m_shaderDownsample->uniformLocation("renderTextureSize"); | 192 | m_renderTextureSizeLocationDownsample = m_shaderDownsample->uniformLocation("renderTextureSize"); | ||
410 | m_halfpixelLocationDownsample = m_shaderDownsample->uniformLocation("halfpixel"); | 193 | m_halfpixelLocationDownsample = m_shaderDownsample->uniformLocation("halfpixel"); | ||
411 | 194 | | |||
412 | m_mvpMatrixLocationUpsample = m_shaderUpsample->uniformLocation("modelViewProjectionMatrix"); | 195 | m_mvpMatrixLocationUpsample = m_shaderUpsample->uniformLocation("modelViewProjectionMatrix"); | ||
413 | m_offsetLocationUpsample = m_shaderUpsample->uniformLocation("offset"); | 196 | m_offsetLocationUpsample = m_shaderUpsample->uniformLocation("offset"); | ||
414 | m_renderTextureSizeLocationUpsample = m_shaderUpsample->uniformLocation("renderTextureSize"); | 197 | m_renderTextureSizeLocationUpsample = m_shaderUpsample->uniformLocation("renderTextureSize"); | ||
Show All 10 Lines | |||||
425 | m_texStartPosLocationNoisesample = m_shaderNoisesample->uniformLocation("texStartPos"); | 208 | m_texStartPosLocationNoisesample = m_shaderNoisesample->uniformLocation("texStartPos"); | ||
426 | m_halfpixelLocationNoisesample = m_shaderNoisesample->uniformLocation("halfpixel"); | 209 | m_halfpixelLocationNoisesample = m_shaderNoisesample->uniformLocation("halfpixel"); | ||
427 | 210 | | |||
428 | QMatrix4x4 modelViewProjection; | 211 | QMatrix4x4 modelViewProjection; | ||
429 | const QSize screenSize = effects->virtualScreenSize(); | 212 | const QSize screenSize = effects->virtualScreenSize(); | ||
430 | modelViewProjection.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535); | 213 | modelViewProjection.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535); | ||
431 | 214 | | |||
432 | //Add default values to the uniforms of the shaders | 215 | //Add default values to the uniforms of the shaders | ||
433 | ShaderManager::instance()->pushShader(m_shaderDownsample); | 216 | ShaderManager::instance()->pushShader(m_shaderDownsample.data()); | ||
434 | m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, modelViewProjection); | 217 | m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, modelViewProjection); | ||
435 | m_shaderDownsample->setUniform(m_offsetLocationDownsample, float(1.0)); | 218 | m_shaderDownsample->setUniform(m_offsetLocationDownsample, float(1.0)); | ||
436 | m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, QVector2D(1.0, 1.0)); | 219 | m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, QVector2D(1.0, 1.0)); | ||
437 | m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(1.0, 1.0)); | 220 | m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(1.0, 1.0)); | ||
438 | ShaderManager::instance()->popShader(); | 221 | ShaderManager::instance()->popShader(); | ||
439 | 222 | | |||
440 | ShaderManager::instance()->pushShader(m_shaderUpsample); | 223 | ShaderManager::instance()->pushShader(m_shaderUpsample.data()); | ||
441 | m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, modelViewProjection); | 224 | m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, modelViewProjection); | ||
442 | m_shaderUpsample->setUniform(m_offsetLocationUpsample, float(1.0)); | 225 | m_shaderUpsample->setUniform(m_offsetLocationUpsample, float(1.0)); | ||
443 | m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, QVector2D(1.0, 1.0)); | 226 | m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, QVector2D(1.0, 1.0)); | ||
444 | m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(1.0, 1.0)); | 227 | m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(1.0, 1.0)); | ||
445 | ShaderManager::instance()->popShader(); | 228 | ShaderManager::instance()->popShader(); | ||
446 | 229 | | |||
447 | ShaderManager::instance()->pushShader(m_shaderCopysample); | 230 | ShaderManager::instance()->pushShader(m_shaderCopysample.data()); | ||
448 | m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, modelViewProjection); | 231 | m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, modelViewProjection); | ||
449 | m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, QVector2D(1.0, 1.0)); | 232 | m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, QVector2D(1.0, 1.0)); | ||
450 | m_shaderCopysample->setUniform(m_blurRectLocationCopysample, QVector4D(1.0, 1.0, 1.0, 1.0)); | 233 | m_shaderCopysample->setUniform(m_blurRectLocationCopysample, QVector4D(1.0, 1.0, 1.0, 1.0)); | ||
451 | ShaderManager::instance()->popShader(); | 234 | ShaderManager::instance()->popShader(); | ||
452 | 235 | | |||
453 | ShaderManager::instance()->pushShader(m_shaderNoisesample); | 236 | ShaderManager::instance()->pushShader(m_shaderNoisesample.data()); | ||
454 | m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, modelViewProjection); | 237 | m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, modelViewProjection); | ||
455 | m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, float(1.0)); | 238 | m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, float(1.0)); | ||
456 | m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, QVector2D(1.0, 1.0)); | 239 | m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, QVector2D(1.0, 1.0)); | ||
457 | m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, QVector2D(1.0, 1.0)); | 240 | m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, QVector2D(1.0, 1.0)); | ||
458 | m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(1.0, 1.0)); | 241 | m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(1.0, 1.0)); | ||
459 | m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(1.0, 1.0)); | 242 | m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(1.0, 1.0)); | ||
460 | 243 | | |||
461 | glUniform1i(m_shaderNoisesample->uniformLocation("texUnit"), 0); | 244 | glUniform1i(m_shaderNoisesample->uniformLocation("texUnit"), 0); | ||
462 | glUniform1i(m_shaderNoisesample->uniformLocation("noiseTexUnit"), 1); | 245 | glUniform1i(m_shaderNoisesample->uniformLocation("noiseTexUnit"), 1); | ||
463 | 246 | | |||
464 | ShaderManager::instance()->popShader(); | 247 | ShaderManager::instance()->popShader(); | ||
248 | } | ||||
249 | } | ||||
250 | | ||||
251 | BlurShader::~BlurShader() | ||||
252 | { | ||||
253 | } | ||||
254 | | ||||
255 | void BlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix) | ||||
256 | { | ||||
257 | if (!isValid()) { | ||||
258 | return; | ||||
259 | } | ||||
260 | | ||||
261 | switch (m_activeSampleType) { | ||||
262 | case CopySampleType: | ||||
263 | if (matrix == m_matrixCopysample) { | ||||
264 | return; | ||||
265 | } | ||||
266 | | ||||
267 | m_matrixCopysample = matrix; | ||||
268 | m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, matrix); | ||||
269 | break; | ||||
270 | | ||||
271 | case UpSampleType: | ||||
272 | if (matrix == m_matrixUpsample) { | ||||
273 | return; | ||||
274 | } | ||||
275 | | ||||
276 | m_matrixUpsample = matrix; | ||||
277 | m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, matrix); | ||||
278 | break; | ||||
279 | | ||||
280 | case DownSampleType: | ||||
281 | if (matrix == m_matrixDownsample) { | ||||
282 | return; | ||||
283 | } | ||||
284 | | ||||
285 | m_matrixDownsample = matrix; | ||||
286 | m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, matrix); | ||||
287 | break; | ||||
288 | | ||||
289 | case NoiseSampleType: | ||||
290 | if (matrix == m_matrixNoisesample) { | ||||
291 | return; | ||||
292 | } | ||||
293 | | ||||
294 | m_matrixNoisesample = matrix; | ||||
295 | m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, matrix); | ||||
296 | break; | ||||
297 | | ||||
298 | default: | ||||
299 | Q_UNREACHABLE(); | ||||
300 | break; | ||||
301 | } | ||||
302 | } | ||||
303 | | ||||
304 | void BlurShader::setOffset(float offset) | ||||
305 | { | ||||
306 | if (!isValid()) { | ||||
307 | return; | ||||
308 | } | ||||
309 | | ||||
310 | switch (m_activeSampleType) { | ||||
311 | case UpSampleType: | ||||
312 | if (offset == m_offsetUpsample) { | ||||
313 | return; | ||||
314 | } | ||||
315 | | ||||
316 | m_offsetUpsample = offset; | ||||
317 | m_shaderUpsample->setUniform(m_offsetLocationUpsample, offset); | ||||
318 | break; | ||||
319 | | ||||
320 | case DownSampleType: | ||||
321 | if (offset == m_offsetDownsample) { | ||||
322 | return; | ||||
323 | } | ||||
324 | | ||||
325 | m_offsetDownsample = offset; | ||||
326 | m_shaderDownsample->setUniform(m_offsetLocationDownsample, offset); | ||||
327 | break; | ||||
328 | | ||||
329 | case NoiseSampleType: | ||||
330 | if (offset == m_offsetNoisesample) { | ||||
331 | return; | ||||
332 | } | ||||
333 | | ||||
334 | m_offsetNoisesample = offset; | ||||
335 | m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, offset); | ||||
336 | break; | ||||
337 | | ||||
338 | default: | ||||
339 | Q_UNREACHABLE(); | ||||
340 | break; | ||||
341 | } | ||||
342 | } | ||||
343 | | ||||
344 | void BlurShader::setTargetTextureSize(const QSize &renderTextureSize) | ||||
345 | { | ||||
346 | if (!isValid()) { | ||||
347 | return; | ||||
348 | } | ||||
349 | | ||||
350 | const QVector2D texSize(renderTextureSize.width(), renderTextureSize.height()); | ||||
351 | | ||||
352 | switch (m_activeSampleType) { | ||||
353 | case CopySampleType: | ||||
354 | m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, texSize); | ||||
355 | break; | ||||
356 | | ||||
357 | case UpSampleType: | ||||
358 | m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, texSize); | ||||
359 | m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | ||||
360 | break; | ||||
361 | | ||||
362 | case DownSampleType: | ||||
363 | m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, texSize); | ||||
364 | m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | ||||
365 | break; | ||||
366 | | ||||
367 | case NoiseSampleType: | ||||
368 | m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, texSize); | ||||
369 | m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); | ||||
370 | break; | ||||
371 | | ||||
372 | default: | ||||
373 | Q_UNREACHABLE(); | ||||
374 | break; | ||||
375 | } | ||||
376 | } | ||||
377 | | ||||
378 | void BlurShader::setNoiseTextureSize(const QSize &noiseTextureSize) | ||||
379 | { | ||||
380 | const QVector2D noiseTexSize(noiseTextureSize.width(), noiseTextureSize.height()); | ||||
381 | | ||||
382 | if (noiseTexSize != m_noiseTextureSizeNoisesample) { | ||||
383 | m_noiseTextureSizeNoisesample = noiseTexSize; | ||||
384 | m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, noiseTexSize); | ||||
385 | } | ||||
386 | } | ||||
465 | 387 | | |||
466 | m_activeSampleType = -1; | 388 | void BlurShader::setTexturePosition(const QPoint &texPos) | ||
389 | { | ||||
390 | m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(-texPos.x(), texPos.y())); | ||||
391 | } | ||||
467 | 392 | | |||
468 | m_offsetDownsample = 0.0; | 393 | void BlurShader::setBlurRect(const QRect &blurRect, const QSize &screenSize) | ||
469 | m_matrixDownsample = QMatrix4x4(); | 394 | { | ||
395 | if (!isValid()) { | ||||
396 | return; | ||||
397 | } | ||||
470 | 398 | | |||
471 | m_offsetUpsample = 0.0; | 399 | const QVector4D rect( | ||
472 | m_matrixUpsample = QMatrix4x4(); | 400 | blurRect.left() / float(screenSize.width()), | ||
401 | 1.0 - blurRect.bottom() / float(screenSize.height()), | ||||
402 | blurRect.right() / float(screenSize.width()), | ||||
403 | 1.0 - blurRect.top() / float(screenSize.height()) | ||||
404 | ); | ||||
473 | 405 | | |||
474 | m_matrixCopysample = QMatrix4x4(); | 406 | m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect); | ||
407 | } | ||||
475 | 408 | | |||
476 | m_offsetNoisesample = 0.0; | 409 | void BlurShader::bind(SampleType sampleType) | ||
477 | m_noiseTextureSizeNoisesample = QVector2D(); | 410 | { | ||
478 | m_matrixNoisesample = QMatrix4x4(); | 411 | if (!isValid()) { | ||
412 | return; | ||||
479 | } | 413 | } | ||
414 | | ||||
415 | switch (sampleType) { | ||||
416 | case CopySampleType: | ||||
417 | ShaderManager::instance()->pushShader(m_shaderCopysample.data()); | ||||
418 | break; | ||||
419 | | ||||
420 | case UpSampleType: | ||||
421 | ShaderManager::instance()->pushShader(m_shaderUpsample.data()); | ||||
422 | break; | ||||
423 | | ||||
424 | case DownSampleType: | ||||
425 | ShaderManager::instance()->pushShader(m_shaderDownsample.data()); | ||||
426 | break; | ||||
427 | | ||||
428 | case NoiseSampleType: | ||||
429 | ShaderManager::instance()->pushShader(m_shaderNoisesample.data()); | ||||
430 | break; | ||||
431 | | ||||
432 | default: | ||||
433 | Q_UNREACHABLE(); | ||||
434 | break; | ||||
480 | } | 435 | } | ||
436 | | ||||
437 | m_activeSampleType = sampleType; | ||||
438 | } | ||||
439 | | ||||
440 | void BlurShader::unbind() | ||||
441 | { | ||||
442 | ShaderManager::instance()->popShader(); | ||||
443 | } | ||||
444 | | ||||
445 | } // namespace KWin |