New ShaderManager
The ShaderManager provides the built-in shaders for scene and effects. Scene and effects can simply push one of those built-in shaders or a custom one on a stack ensuring that the previously bound shader will be rebound when the shader is poped again. The class will be extended to not only have built-in shaders but also to load custom shaders and being the only way to bind a shader at all.
This commit is contained in:
parent
1911a81cd7
commit
3c6e7309f2
2 changed files with 332 additions and 0 deletions
|
@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QVector4D>
|
||||
#include <QMatrix4x4>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DEBUG_GLRENDERTARGET 0
|
||||
|
||||
|
@ -1081,6 +1082,221 @@ void GLShader::bindAttributeLocation(int index, const char* name)
|
|||
// TODO: relink the shader
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// ShaderManager
|
||||
//****************************************
|
||||
ShaderManager *ShaderManager::s_shaderManager = NULL;
|
||||
|
||||
ShaderManager *ShaderManager::instance()
|
||||
{
|
||||
if (!s_shaderManager) {
|
||||
s_shaderManager = new ShaderManager();
|
||||
}
|
||||
return s_shaderManager;
|
||||
}
|
||||
|
||||
void ShaderManager::cleanup()
|
||||
{
|
||||
delete s_shaderManager;
|
||||
}
|
||||
|
||||
ShaderManager::ShaderManager()
|
||||
: m_orthoShader(NULL)
|
||||
, m_genericShader(NULL)
|
||||
, m_colorShader(NULL)
|
||||
, m_inited(false)
|
||||
, m_valid(false)
|
||||
{
|
||||
initShaders();
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager()
|
||||
{
|
||||
while (!m_boundShaders.isEmpty()) {
|
||||
popShader();
|
||||
}
|
||||
delete m_orthoShader;
|
||||
delete m_genericShader;
|
||||
delete m_colorShader;
|
||||
}
|
||||
|
||||
GLShader *ShaderManager::getBoundShader() const
|
||||
{
|
||||
if (m_boundShaders.isEmpty()) {
|
||||
return NULL;
|
||||
} else {
|
||||
return m_boundShaders.top();
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderManager::isShaderBound() const
|
||||
{
|
||||
return !m_boundShaders.isEmpty();
|
||||
}
|
||||
|
||||
bool ShaderManager::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
GLShader *ShaderManager::pushShader(ShaderType type, bool reset)
|
||||
{
|
||||
if (m_inited && !m_valid) {
|
||||
return NULL;
|
||||
}
|
||||
GLShader *shader;
|
||||
switch (type) {
|
||||
case SimpleShader:
|
||||
shader = m_orthoShader;
|
||||
break;
|
||||
case GenericShader:
|
||||
shader = m_genericShader;
|
||||
break;
|
||||
case ColorShader:
|
||||
shader = m_colorShader;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pushShader(shader);
|
||||
if (reset) {
|
||||
resetShader(type);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void ShaderManager::pushShader(GLShader *shader)
|
||||
{
|
||||
// only bind shader if it is not already bound
|
||||
if (shader != getBoundShader()) {
|
||||
shader->bind();
|
||||
}
|
||||
m_boundShaders.push(shader);
|
||||
}
|
||||
|
||||
void ShaderManager::popShader()
|
||||
{
|
||||
if (m_boundShaders.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
GLShader *shader = m_boundShaders.pop();
|
||||
if (m_boundShaders.isEmpty()) {
|
||||
// no more shader bound - unbind
|
||||
shader->unbind();
|
||||
} else if (shader != m_boundShaders.top()) {
|
||||
// only rebind if a different shader is on top of stack
|
||||
m_boundShaders.top()->bind();
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManager::initShaders()
|
||||
{
|
||||
m_orthoShader = new GLShader(":/resources/scene-vertex.glsl", ":/resources/scene-fragment.glsl");
|
||||
if (m_orthoShader->isValid()) {
|
||||
pushShader(SimpleShader, true);
|
||||
popShader();
|
||||
kDebug(1212) << "Ortho Shader is valid";
|
||||
}
|
||||
else {
|
||||
delete m_orthoShader;
|
||||
m_orthoShader = NULL;
|
||||
kDebug(1212) << "Orho Shader is not valid";
|
||||
return;
|
||||
}
|
||||
m_genericShader = new GLShader( ":/resources/scene-generic-vertex.glsl", ":/resources/scene-fragment.glsl" );
|
||||
if (m_genericShader->isValid()) {
|
||||
pushShader(GenericShader, true);
|
||||
popShader();
|
||||
kDebug(1212) << "Generic Shader is valid";
|
||||
}
|
||||
else {
|
||||
delete m_genericShader;
|
||||
m_genericShader = NULL;
|
||||
delete m_orthoShader;
|
||||
m_orthoShader = NULL;
|
||||
kDebug(1212) << "Generic Shader is not valid";
|
||||
return;
|
||||
}
|
||||
m_colorShader = new GLShader(":/resources/scene-color-vertex.glsl", ":/resources/scene-color-fragment.glsl");
|
||||
if (m_colorShader->isValid()) {
|
||||
pushShader(ColorShader, true);
|
||||
popShader();
|
||||
kDebug(1212) << "Color Shader is valid";
|
||||
} else {
|
||||
delete m_genericShader;
|
||||
m_genericShader = NULL;
|
||||
delete m_orthoShader;
|
||||
m_orthoShader = NULL;
|
||||
delete m_colorShader;
|
||||
m_colorShader = NULL;
|
||||
kDebug(1212) << "Color Scene Shader is not valid";
|
||||
return;
|
||||
}
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
void ShaderManager::resetShader(ShaderType type)
|
||||
{
|
||||
// resetShader is either called from init or from push, we know that a built-in shader is bound
|
||||
GLShader *shader = getBoundShader();
|
||||
switch (type) {
|
||||
case SimpleShader:
|
||||
shader->setUniform("displaySize", QVector2D(displayWidth(), displayHeight()));
|
||||
// TODO: has to become offset
|
||||
shader->setUniform("geometry", QVector4D(0, 0, 0, 0));
|
||||
shader->setUniform("debug", 0);
|
||||
shader->setUniform("sample", 0);
|
||||
// TODO: has to become textureSize
|
||||
shader->setUniform("textureWidth", 1.0f);
|
||||
shader->setUniform("textureHeight", 1.0f);
|
||||
// TODO: has to become colorManiuplation
|
||||
shader->setUniform("opacity", 1.0f);
|
||||
shader->setUniform("brightness", 1.0f);
|
||||
shader->setUniform("saturation", 1.0f);
|
||||
break;
|
||||
case GenericShader: {
|
||||
shader->setUniform("debug", 0);
|
||||
shader->setUniform("sample", 0);
|
||||
QMatrix4x4 projection;
|
||||
float fovy = 60.0f;
|
||||
float aspect = 1.0f;
|
||||
float zNear = 0.1f;
|
||||
float zFar = 100.0f;
|
||||
float ymax = zNear * tan(fovy * M_PI / 360.0f);
|
||||
float ymin = -ymax;
|
||||
float xmin = ymin * aspect;
|
||||
float xmax = ymax * aspect;
|
||||
projection.frustum(xmin, xmax, ymin, ymax, zNear, zFar);
|
||||
shader->setUniform("projection", projection);
|
||||
QMatrix4x4 modelview;
|
||||
float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax;
|
||||
modelview.translate(xmin*scaleFactor, ymax*scaleFactor, -1.1);
|
||||
modelview.scale((xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001);
|
||||
shader->setUniform("modelview", modelview);
|
||||
const QMatrix4x4 identity;
|
||||
shader->setUniform("screenTransformation", identity);
|
||||
shader->setUniform("windowTransformation", identity);
|
||||
// TODO: has to become textureSize
|
||||
shader->setUniform("textureWidth", 1.0f);
|
||||
shader->setUniform("textureHeight", 1.0f);
|
||||
// TODO: has to become colorManiuplation
|
||||
shader->setUniform("opacity", 1.0f);
|
||||
shader->setUniform("brightness", 1.0f);
|
||||
shader->setUniform("saturation", 1.0f);
|
||||
break;
|
||||
}
|
||||
case ColorShader:
|
||||
shader->setUniform("displaySize", QVector2D(displayWidth(), displayHeight()));
|
||||
// TODO: has to become offset
|
||||
shader->setUniform("geometry", QVector4D(0, 0, 0, 0));
|
||||
shader->setUniform("geometryColor", QVector4D(0, 0, 0, 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*** GLRenderTarget ***/
|
||||
bool GLRenderTarget::mSupported = false;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <QtGui/QImage>
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QSharedData>
|
||||
#include <QtCore/QStack>
|
||||
|
||||
/** @addtogroup kwineffects */
|
||||
/** @{ */
|
||||
|
@ -293,6 +294,121 @@ class KWIN_EXPORT GLShader
|
|||
float mTextureHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Manager for Shaders.
|
||||
*
|
||||
* This class provides some built-in shaders to be used by both compositing scene and effects.
|
||||
* The ShaderManager provides methods to bind a built-in or a custom shader and keeps track of
|
||||
* the shaders which have been bound. When a shader is unbound the previously bound shader
|
||||
* will be rebound.
|
||||
*
|
||||
* @author Martin Gräßlin <kde@martin-graesslin.com>
|
||||
* @since 4.7
|
||||
**/
|
||||
class KWIN_EXPORT ShaderManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Identifiers for built-in shaders available for effects and scene
|
||||
**/
|
||||
enum ShaderType {
|
||||
/**
|
||||
* An orthographic projection shader able to render textured geometries.
|
||||
* Expects a @c vec2 uniform @c offset describing the offset from top-left corner
|
||||
* and defaults to @c (0/0). Expects a @c vec2 uniform @c textureSize to calculate
|
||||
* normalized texture coordinates. Defaults to @c (1.0/1.0). And expects a @c vec3
|
||||
* uniform @c colorManiuplation, with @c x being opacity, @c y being brightness and
|
||||
* @c z being saturation. All three values default to @c 1.0.
|
||||
* The sampler uniform is @c sample and defaults to @c 0.
|
||||
* The shader uses two vertex attributes @c vertex and @c texCoord.
|
||||
**/
|
||||
SimpleShader,
|
||||
/**
|
||||
* A generic shader able to render transformed, textured geometries.
|
||||
* This shader is mostly needed by the scene and not of much interest for effects.
|
||||
* Effects can influence this shader through @link ScreenPaintData and @link WindowPaintData.
|
||||
* The shader expects four @c mat4 uniforms @c projection, @c modelview,
|
||||
* @c screenTransformation and @c windowTransformation. The fragment shader expect the
|
||||
* same uniforms as the SimpleShader and the same vertex attributes are used.
|
||||
**/
|
||||
GenericShader,
|
||||
/**
|
||||
* An orthographic shader to render simple colored geometries without texturing.
|
||||
* Expects a @c vec2 uniform @c offset describing the offset from top-left corner
|
||||
* and defaults to @c (0/0). The fragment shader expects a single @c vec4 uniform
|
||||
* @c geometryColor, which defaults to fully opaque black.
|
||||
* The Shader uses one vertex attribute @c vertex.
|
||||
**/
|
||||
ColorShader
|
||||
};
|
||||
|
||||
/**
|
||||
* @return The currently bound shader or @c null if no shader is bound.
|
||||
**/
|
||||
GLShader *getBoundShader() const;
|
||||
|
||||
/**
|
||||
* @return @c true if a shader is bound, @c false otherwise
|
||||
**/
|
||||
bool isShaderBound() const;
|
||||
/**
|
||||
* @return @c true if the built-in shaders are valid, @c false otherwise
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Binds the shader of specified @p type.
|
||||
* To unbind the shader use @link popShader. A previous bound shader will be rebound.
|
||||
* @param type The built-in shader to bind
|
||||
* @param reset Whether all uniforms should be reset to their default values
|
||||
* @return The bound shader or @c NULL if shaders are not valid
|
||||
* @see popShader
|
||||
**/
|
||||
GLShader *pushShader(ShaderType type, bool reset = false);
|
||||
/**
|
||||
* Binds the @p shader.
|
||||
* To unbind the shader use @link popShader. A previous bound shader will be rebound.
|
||||
* To bind a built-in shader use the more specific method.
|
||||
* @param shader The shader to be bound
|
||||
* @see popShader
|
||||
**/
|
||||
void pushShader(GLShader *shader);
|
||||
|
||||
/**
|
||||
* Unbinds the currently bound shader and rebinds a previous stored shader.
|
||||
* If there is no previous shader, no shader will be rebound.
|
||||
* It is not safe to call this method if there is no bound shader.
|
||||
* @see pushShader
|
||||
* @see getBoundShader
|
||||
**/
|
||||
void popShader();
|
||||
|
||||
/**
|
||||
* @return a pointer to the ShaderManager instance
|
||||
**/
|
||||
static ShaderManager *instance();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
**/
|
||||
static void cleanup();
|
||||
|
||||
private:
|
||||
ShaderManager();
|
||||
~ShaderManager();
|
||||
|
||||
void initShaders();
|
||||
void resetShader(ShaderType type);
|
||||
|
||||
QStack<GLShader*> m_boundShaders;
|
||||
GLShader *m_orthoShader;
|
||||
GLShader *m_genericShader;
|
||||
GLShader *m_colorShader;
|
||||
bool m_inited;
|
||||
bool m_valid;
|
||||
static ShaderManager *s_shaderManager;
|
||||
};
|
||||
|
||||
/**
|
||||
* @short Render target object
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue