diff --git a/src/QtAV/ConvolutionShader.h b/src/QtAV/ConvolutionShader.h new file mode 100644 index 000000000..a2e8fbc3f --- /dev/null +++ b/src/QtAV/ConvolutionShader.h @@ -0,0 +1,60 @@ +/****************************************************************************** + QtAV: Multimedia framework based on Qt and FFmpeg + Copyright (C) 2012-2016 Wang Bin + +* 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 + +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 diff --git a/src/QtAV/QtAV.h b/src/QtAV/QtAV.h index a60f7d8ca..c6ebef6a6 100644 --- a/src/QtAV/QtAV.h +++ b/src/QtAV/QtAV.h @@ -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 * This file is part of QtAV @@ -48,6 +48,7 @@ #include #include +#include #include #include diff --git a/src/libQtAV.pro b/src/libQtAV.pro index 3aa28897f..93ea04138 100644 --- a/src/libQtAV.pro +++ b/src/libQtAV.pro @@ -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 @@ -324,6 +325,7 @@ config_gl|config_opengl { OpenGLVideo.cpp \ VideoShader.cpp \ ShaderManager.cpp \ + opengl/ConvolutionShader.cpp \ utils/OpenGLHelper.cpp } config_openglwindow { diff --git a/src/opengl/ConvolutionShader.cpp b/src/opengl/ConvolutionShader.cpp new file mode 100644 index 000000000..ae6a37767 --- /dev/null +++ b/src/opengl/ConvolutionShader.cpp @@ -0,0 +1,124 @@ +/****************************************************************************** + QtAV: Multimedia framework based on Qt and FFmpeg + Copyright (C) 2012-2016 Wang Bin + +* 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 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