Skip to content

Commit

Permalink
gl: add ConvolutionShader for convenience
Browse files Browse the repository at this point in the history
bug: shader program does not update if setKernelRadius
  • Loading branch information
wang-bin committed Mar 13, 2016
1 parent ee4a989 commit efae65c
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 1 deletion.
60 changes: 60 additions & 0 deletions src/QtAV/ConvolutionShader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/******************************************************************************
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
******************************************************************************/
#ifndef QTAV_CONVOLUTIONSHADER_H
#define QTAV_CONVOLUTIONSHADER_H
#include <QtAV/VideoShader.h>

namespace QtAV {
class ConvolutionShaderPrivate;
/*!
* \brief The ConvolutionShader class
* Uniform u_Kernel is used
*/
class Q_AV_EXPORT ConvolutionShader : public VideoShader
{
DPTR_DECLARE_PRIVATE(ConvolutionShader)
public:
ConvolutionShader();
/*!
* \brief kernelRadius
* Default is 1, i.e. 3x3 kernel
* kernelSize is (2*kernelRadius()+1)^2
* \return
*/
int kernelRadius() const;
/// TODO: update shader program if radius is changed. mark dirty program
void setKernelRadius(int value);
int kernelSize() const;

/// default implementions
const char* userShaderHeader(QOpenGLShader::ShaderType t) const Q_DECL_OVERRIDE;
const char* userSample() const Q_DECL_OVERRIDE;
void setUserUniformValues() Q_DECL_OVERRIDE;

protected:
virtual const float* kernel() const = 0;
const QByteArray& kernelUniformHeader() const; //can be used in your userFragmentShaderHeader();
const QByteArray& kernelSample() const; //can be in your userSample();
void setKernelUniformValue(); // can be used in your setUserUniformValues()
ConvolutionShader(ConvolutionShaderPrivate &d);
};
} //namespace QtAV
#endif // QTAV_CONVOLUTIONSHADER_H
3 changes: 2 additions & 1 deletion src/QtAV/QtAV.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -48,6 +48,7 @@

#include <QtAV/VideoShader.h>
#include <QtAV/OpenGLVideo.h>
#include <QtAV/ConvolutionShader.h>

#include <QtAV/VideoCapture.h>
#include <QtAV/VideoEncoder.h>
Expand Down
2 changes: 2 additions & 0 deletions src/libQtAV.pro
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ config_gl|config_opengl {
SDK_HEADERS *= \
QtAV/OpenGLRendererBase.h \
QtAV/OpenGLVideo.h \
QtAV/ConvolutionShader.h \
QtAV/VideoShader.h
SDK_PRIVATE_HEADERS = \
QtAV/private/OpenGLRendererBase_p.h
Expand All @@ -324,6 +325,7 @@ config_gl|config_opengl {
OpenGLVideo.cpp \
VideoShader.cpp \
ShaderManager.cpp \
opengl/ConvolutionShader.cpp \
utils/OpenGLHelper.cpp
}
config_openglwindow {
Expand Down
124 changes: 124 additions & 0 deletions src/opengl/ConvolutionShader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/******************************************************************************
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 = QByteArray("uniform float u_Kernel[")
.append(QByteArray::number(ks))
.append("];");
QByteArray s("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 += "c += texture(tex, pos + u_texelSize[p]*vec2(";
s += QByteArray::number((float)x, 'f', 1);
s += ",";
s += QByteArray::number((float)y, 'f', 1);
s += "))*u_Kernel[";
s += QByteArray::number(i);
s += "];\n";
}
s += "c.a = texture(tex, pos).a;"
"return c;}\n";
sample_func = s;
}

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();
}

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();
}

void ConvolutionShader::setUserUniformValues()
{
setKernelUniformValue();
}

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

0 comments on commit efae65c

Please sign in to comment.