From 548c2b03f8184497a5306f4b4412e3120eaef211 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sun, 8 Jun 2014 15:40:35 +0300 Subject: Add shaderprogram class. --- src/CMakeLists.txt | 2 ++ src/Makefile.am | 2 ++ src/graphicsmanager.cpp | 1 + src/render/mgl.cpp | 1 + src/render/mgl.h | 1 + src/render/mgltypes.h | 2 ++ src/render/shaders/shader.h | 3 +++ src/render/shaders/shaderprogram.cpp | 49 +++++++++++++++++++++++++++++++++ src/render/shaders/shaderprogram.h | 48 +++++++++++++++++++++++++++++++++ src/render/shaders/shadersmanager.cpp | 51 +++++++++++++++++++++++++++++++++++ src/render/shaders/shadersmanager.h | 7 ++++- src/resources/resourcemanager.cpp | 27 +++++++++++++++++++ src/resources/resourcemanager.h | 3 +++ 13 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/render/shaders/shaderprogram.cpp create mode 100644 src/render/shaders/shaderprogram.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f9081b1f..ec19ed7d2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -939,6 +939,8 @@ SET(SRCS render/surfacegraphics.h render/shaders/shader.cpp render/shaders/shader.h + render/shaders/shaderprogram.cpp + render/shaders/shaderprogram.h render/shaders/shadersmanager.cpp render/shaders/shadersmanager.h text.cpp diff --git a/src/Makefile.am b/src/Makefile.am index c2aef8836..7a894c5ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1056,6 +1056,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ render/surfacegraphics.h \ render/shaders/shader.cpp \ render/shaders/shader.h \ + render/shaders/shaderprogram.cpp \ + render/shaders/shaderprogram.h \ render/shaders/shadersmanager.cpp \ render/shaders/shadersmanager.h \ text.cpp \ diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index 299255abe..4fa4744a6 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -985,6 +985,7 @@ void GraphicsManager::initOpenGLFunctions() assignFunction(glShaderSource, "glShaderSource"); assignFunction(glCompileShader, "glCompileShader"); assignFunction(glLinkProgram, "glLinkProgram"); + assignFunction(glGetProgramInfoLog, "glGetProgramInfoLog"); assignFunction(glDeleteProgram, "glDeleteProgram"); assignFunction(glCreateProgram, "glCreateProgram"); assignFunction(glAttachShader, "glAttachShader"); diff --git a/src/render/mgl.cpp b/src/render/mgl.cpp index 47d087325..d18763051 100644 --- a/src/render/mgl.cpp +++ b/src/render/mgl.cpp @@ -83,6 +83,7 @@ defName(glUniform2f); defName(glUniform3f); defName(glUniform4f); defName(glCheckFramebufferStatus); +defName(glGetProgramInfoLog); #ifdef WIN32 defName(wglGetExtensionsString); diff --git a/src/render/mgl.h b/src/render/mgl.h index 02122f88c..a72ef0331 100644 --- a/src/render/mgl.h +++ b/src/render/mgl.h @@ -86,6 +86,7 @@ defNameE(glUniform2f); defNameE(glUniform3f); defNameE(glUniform4f); defNameE(glCheckFramebufferStatus); +defNameE(glGetProgramInfoLog); #ifdef WIN32 defNameE(wglGetExtensionsString); diff --git a/src/render/mgltypes.h b/src/render/mgltypes.h index 497fa6afa..7e56941a9 100644 --- a/src/render/mgltypes.h +++ b/src/render/mgltypes.h @@ -121,6 +121,8 @@ typedef void (APIENTRY *glUniform3f_t) (GLint location, typedef void (APIENTRY *glUniform4f_t) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); typedef GLenum (APIENTRY *glCheckFramebufferStatus_t) (GLenum target); +typedef void (APIENTRY *glGetProgramInfoLog_t) (GLuint program, + GLsizei maxLength, GLsizei *length, GLchar *infoLog); // callback typedef void (APIENTRY *GLDEBUGPROC_t) (GLenum source, GLenum type, GLuint id, diff --git a/src/render/shaders/shader.h b/src/render/shaders/shader.h index 6ee964704..adcc29702 100644 --- a/src/render/shaders/shader.h +++ b/src/render/shaders/shader.h @@ -34,6 +34,9 @@ class Shader final : public Resource A_DELETE_COPY(Shader) + unsigned int getShaderId() const + { return mShaderId; } + protected: unsigned int mShaderId; }; diff --git a/src/render/shaders/shaderprogram.cpp b/src/render/shaders/shaderprogram.cpp new file mode 100644 index 000000000..7d79e5cb9 --- /dev/null +++ b/src/render/shaders/shaderprogram.cpp @@ -0,0 +1,49 @@ +/* + * The ManaPlus Client + * Copyright (C) 2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef USE_OPENGL + +#include "render/shaders/shaderprogram.h" + +#include "render/mgl.h" + +#include "render/shaders/shader.h" + +ShaderProgram::ShaderProgram(const unsigned int id, + Shader *const vertex, + Shader *const fragment) : + Resource(), + mProgramId(id), + mVertex(vertex), + mFragment(fragment) +{ +} + +ShaderProgram::~ShaderProgram() +{ + if (mProgramId) + mglDeleteProgram(mProgramId); + if (mVertex) + mVertex->decRef(); + if (mFragment) + mFragment->decRef(); +} + +#endif // USE_OPENGL diff --git a/src/render/shaders/shaderprogram.h b/src/render/shaders/shaderprogram.h new file mode 100644 index 000000000..bb01a4802 --- /dev/null +++ b/src/render/shaders/shaderprogram.h @@ -0,0 +1,48 @@ +/* + * The ManaPlus Client + * Copyright (C) 2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RENDER_SHADERPROGRAM_H +#define RENDER_SHADERPROGRAM_H + +#ifdef USE_OPENGL + +#include "resources/resource.h" + +class Shader; + +class ShaderProgram final : public Resource +{ + public: + ShaderProgram(const unsigned int id, + Shader *const vertex, + Shader *const fragment); + + ~ShaderProgram(); + + A_DELETE_COPY(ShaderProgram) + + protected: + unsigned int mProgramId; + Shader *mVertex; + Shader *mFragment; +}; + +#endif // USE_OPENGL +#endif // RENDER_SHADERPROGRAM_H diff --git a/src/render/shaders/shadersmanager.cpp b/src/render/shaders/shadersmanager.cpp index 85c5bf64e..e457ba473 100644 --- a/src/render/shaders/shadersmanager.cpp +++ b/src/render/shaders/shadersmanager.cpp @@ -28,6 +28,9 @@ #include "render/mgl.h" #include "render/shaders/shader.h" +#include "render/shaders/shaderprogram.h" + +#include "resources/resourcemanager.h" #include "utils/files.h" @@ -59,4 +62,52 @@ Shader *ShadersManager::createShader(const unsigned int type, return nullptr; } +ShaderProgram *ShadersManager::createProgram(const std::string &vertex, + const std::string &fragment) +{ + ResourceManager *const resman = ResourceManager::getInstance(); + Shader *const vertexShader = static_cast( + resman->getShader(GL_VERTEX_SHADER, vertex)); + if (!vertexShader) + return nullptr; + + Shader *const fragmentShader = static_cast( + resman->getShader(GL_FRAGMENT_SHADER, fragment)); + + if (!fragmentShader) + { + vertexShader->decRef(); + return nullptr; + } + + GLuint programId = mglCreateProgram(); + if (!programId) + { + vertexShader->decRef(); + fragmentShader->decRef(); + return nullptr; + } + + mglAttachShader(programId, vertexShader->getShaderId()); + mglAttachShader(programId, fragmentShader->getShaderId()); + mglLinkProgram(programId); + GLint isLinked = 0; + mglGetProgramiv(programId, GL_LINK_STATUS, &isLinked); + if (isLinked == GL_TRUE) + return new ShaderProgram(programId, vertexShader, fragmentShader); + + GLint len = 0; + mglGetProgramiv(programId, GL_INFO_LOG_LENGTH, &len); + char *buf = new char[len + 1]; + mglGetProgramInfoLog(programId, len, &len, buf); + buf[len] = 0; + logger->log("Program '%s, %s' compilation error: %s", + vertexShader->getIdPath().c_str(), + fragmentShader->getIdPath().c_str(), + buf); + delete [] buf; + mglDeleteProgram(programId); + return nullptr; +} + #endif diff --git a/src/render/shaders/shadersmanager.h b/src/render/shaders/shadersmanager.h index 0ad8556c8..ba7d26438 100644 --- a/src/render/shaders/shadersmanager.h +++ b/src/render/shaders/shadersmanager.h @@ -27,13 +27,18 @@ #include "localconsts.h" -struct Shader; +class Shader; +class ShaderProgram; class ShadersManager final { public: Shader *createShader(const unsigned int type, const std::string &fileName) A_WARN_UNUSED; + + ShaderProgram *createProgram(const std::string &vertex, + const std::string &fragment) + A_WARN_UNUSED; }; extern ShadersManager shaders; diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 8bce250fb..9fd445ffc 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -44,6 +44,7 @@ #include "utils/sdlcheckutils.h" #include "render/shaders/shader.h" +#include "render/shaders/shaderprogram.h" #include "render/shaders/shadersmanager.h" #include @@ -732,6 +733,32 @@ Resource *ResourceManager::getShader(const unsigned int type, ShaderLoader rl = { name, type }; return get("shader_" + name, &ShaderLoader::load, &rl); } + +struct ShaderProgramLoader final +{ + const std::string vertex; + const std::string fragment; + + static Resource *load(const void *const v) + { + if (!v) + return nullptr; + + const ShaderProgramLoader *const rl + = static_cast(v); + ShaderProgram *const resource = shaders.createProgram( + rl->vertex, rl->fragment); + return resource; + } +}; + +Resource *ResourceManager::getShaderProgram(const std::string &vertex, + const std::string &fragment) +{ + ShaderProgramLoader rl = { vertex, fragment }; + return get("program_" + vertex + " + " + fragment, + &ShaderProgramLoader::load, &rl); +} #endif struct WalkLayerLoader final diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index f7d901f09..88bae02db 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -178,6 +178,9 @@ class ResourceManager final Resource *getShader(const unsigned int type, const std::string &name) A_WARN_UNUSED; + + Resource *getShaderProgram(const std::string &vertex, + const std::string &fragment) A_WARN_UNUSED; #endif WalkLayer *getWalkLayer(const std::string &name, Map *const map); -- cgit v1.2.3-60-g2f50