forked from wang-bin/QtAV
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConvolutionShader.cpp
119 lines (101 loc) · 3.45 KB
/
ConvolutionShader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
* This file is part of QtAV (from 2016)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include "QtAV/ConvolutionShader.h"
#include "QtAV/private/VideoShader_p.h"
namespace QtAV {
class ConvolutionShaderPrivate : public VideoShaderPrivate
{
public:
ConvolutionShaderPrivate() : VideoShaderPrivate()
, u_Kernel(-1)
, radius(1)
{
kernel.resize((2*radius+1)*(2*radius+1));
updateShaderCode();
}
void updateShaderCode() {
const int ks = (2*radius+1)*(2*radius+1);
header = QStringLiteral("uniform float u_Kernel[%1];").arg(ks).toUtf8();
QString s = QStringLiteral("vec4 sample2d(sampler2D tex, vec2 pos, int p) { vec4 c = vec4(0.0);");
const int kd = 2*radius+1;
for (int i = 0; i < ks; ++i) {
const int x = i % kd - radius;
const int y = i / kd - radius;
s += QStringLiteral("c += texture(tex, pos + u_texelSize[p]*vec2(%1.0,%2.0))*u_Kernel[%3];")
.arg(x).arg(y).arg(i);
}
s += "c.a = texture(tex, pos).a;"
"return c;}\n";
sample_func = s.toUtf8();
}
int u_Kernel;
int radius;
QVector<float> kernel;
QByteArray header, sample_func;
};
ConvolutionShader::ConvolutionShader()
: VideoShader(*new ConvolutionShaderPrivate())
{}
ConvolutionShader::ConvolutionShader(ConvolutionShaderPrivate &d)
: VideoShader(d)
{}
int ConvolutionShader::kernelRadius() const
{
return d_func().radius;
}
void ConvolutionShader::setKernelRadius(int value)
{
DPTR_D(ConvolutionShader);
if (d.radius == value)
return;
d.radius = value;
d.kernel.resize(kernelSize());
d.updateShaderCode();
rebuildLater();
}
int ConvolutionShader::kernelSize() const
{
return (2*kernelRadius() + 1)*(2*kernelRadius() + 1);
}
const char* ConvolutionShader::userShaderHeader(QOpenGLShader::ShaderType t) const
{
if (t == QOpenGLShader::Vertex)
return 0;
return kernelUniformHeader().constData();
}
const char* ConvolutionShader::userSample() const
{
return kernelSample().constData();
}
bool ConvolutionShader::setUserUniformValues()
{
setKernelUniformValue();
return true;
}
const QByteArray& ConvolutionShader::kernelUniformHeader() const
{
return d_func().header;
}
const QByteArray& ConvolutionShader::kernelSample() const
{
return d_func().sample_func;
}
void ConvolutionShader::setKernelUniformValue()
{
program()->setUniformValueArray("u_Kernel", kernel(), kernelSize(), 1);
}
} //namespace QtAV