forked from organicmaps/organicmaps
added Shader, Program and ProgramManager classes.
This commit is contained in:
parent
b0b5c08c71
commit
639d8eb242
7 changed files with 478 additions and 0 deletions
|
@ -23,7 +23,10 @@ SOURCES += \
|
|||
opengl/vertex.cpp \
|
||||
opengl/clipper.cpp \
|
||||
opengl/geometry_renderer.cpp \
|
||||
opengl/shader.cpp \
|
||||
opengl/program.cpp \
|
||||
opengl/defines_conv.cpp \
|
||||
opengl/program_manager.cpp \
|
||||
opengl/gl_render_context.cpp \
|
||||
opengl/storage.cpp \
|
||||
blitter.cpp \
|
||||
|
@ -81,7 +84,10 @@ HEADERS += \
|
|||
opengl/geometry_renderer.hpp \
|
||||
opengl/data_traits.hpp \
|
||||
opengl/storage.hpp \
|
||||
opengl/shader.hpp \
|
||||
opengl/program.hpp \
|
||||
opengl/defines_conv.hpp \
|
||||
opengl/program_manager.hpp \
|
||||
blitter.hpp \
|
||||
resource_manager.hpp \
|
||||
skin.hpp \
|
||||
|
|
199
graphics/opengl/program.cpp
Normal file
199
graphics/opengl/program.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include "program.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "buffer_object.hpp"
|
||||
#include "defines_conv.hpp"
|
||||
#include "../../base/thread.hpp"
|
||||
|
||||
#include "../../std/bind.hpp"
|
||||
#include "../vertex_decl.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
Program::Program(shared_ptr<Shader> const & vxShader,
|
||||
shared_ptr<Shader> const & frgShader)
|
||||
{
|
||||
m_handle = glCreateProgramFn();
|
||||
OGLCHECKAFTER;
|
||||
|
||||
if (!m_handle)
|
||||
throw Exception("CreateProgram error", "could not create Program!");
|
||||
|
||||
OGLCHECK(glAttachShaderFn(m_handle, vxShader->id()));
|
||||
OGLCHECK(glAttachShaderFn(m_handle, frgShader->id()));
|
||||
|
||||
OGLCHECK(glLinkProgramFn(m_handle));
|
||||
|
||||
int linkStatus = GL_FALSE;
|
||||
OGLCHECK(glGetProgramivFn(m_handle, GL_LINK_STATUS, &linkStatus));
|
||||
|
||||
if (linkStatus != GL_TRUE)
|
||||
{
|
||||
int bufLength = 0;
|
||||
OGLCHECK(glGetProgramivFn(m_handle, GL_INFO_LOG_LENGTH, &bufLength));
|
||||
if (bufLength)
|
||||
{
|
||||
vector<char> v;
|
||||
v.resize(bufLength);
|
||||
glGetProgramInfoLogFn(m_handle, bufLength, NULL, &v[0]);
|
||||
|
||||
throw LinkException("Could not link program: ", &v[0]);
|
||||
}
|
||||
|
||||
throw LinkException("Could not link program: ", "Unknown link error");
|
||||
}
|
||||
}
|
||||
|
||||
Program::~Program()
|
||||
{
|
||||
OGLCHECK(glDeleteProgramFn(m_handle));
|
||||
}
|
||||
|
||||
GLuint Program::getParam(char const * name)
|
||||
{
|
||||
GLuint res = glGetUniformLocationFn(m_handle, name);
|
||||
OGLCHECKAFTER;
|
||||
return res;
|
||||
}
|
||||
|
||||
GLuint Program::getAttribute(char const * name)
|
||||
{
|
||||
GLuint res = glGetAttribLocationFn(m_handle, name);
|
||||
OGLCHECKAFTER;
|
||||
return res;
|
||||
}
|
||||
|
||||
void setParamImpl(GLuint prgID, char const * name, function<void(GLint)> fn)
|
||||
{
|
||||
GLuint res = glGetUniformLocationFn(prgID, name);
|
||||
OGLCHECKAFTER;
|
||||
OGLCHECK(fn(res));
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, float v0)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform1f, _1, v0);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, float v0, float v1)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform2f, _1, v0, v1);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, float v0, float v1, float v2)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform3f, _1, v0, v1, v2);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, float v0, float v1, float v2, float v3)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform4f, _1, v0, v1, v2, v3);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, int v0)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform1i, _1, v0);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, int v0, int v1)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform2i, _1, v0, v1);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, int v0, int v1, int v2)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform3i, _1, v0, v1, v2);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, int v0, int v1, int v2, int v3)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniform4i, _1, v0, v1, v2, v3);
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, math::Matrix<float, 2, 2> const & m)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniformMatrix2fv, _1, 1, 0, &m(0, 0));
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, math::Matrix<float, 3, 3> const & m)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniformMatrix3fv, _1, 1, 0, &m(0, 0));
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void Program::setParam(char const * name, math::Matrix<float, 4, 4> const & m)
|
||||
{
|
||||
function<void(GLint)> fn = bind(&glUniformMatrix4fv, _1, 1, 0, &m(0, 0));
|
||||
m_uniforms[name] = bind(&setParamImpl, m_handle, name, fn);
|
||||
}
|
||||
|
||||
void enableAndSetVertexAttrib(GLuint id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, void * ptr)
|
||||
{
|
||||
OGLCHECK(glEnableVertexAttribArray(id));
|
||||
OGLCHECK(glVertexAttribPointer(id, size, type, normalized, stride, ptr));
|
||||
}
|
||||
|
||||
void Program::setAttribute(GLuint id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, void *ptr)
|
||||
{
|
||||
function<void()> fn = bind(&enableAndSetVertexAttrib, id, size, type, normalized, stride, ptr);
|
||||
m_attributes[id] = fn;
|
||||
}
|
||||
|
||||
void Program::setVertexDecl(VertexDecl const * decl)
|
||||
{
|
||||
for (size_t i = 0; i < decl->size(); ++i)
|
||||
{
|
||||
VertexAttrib const * va = decl->getAttr(i);
|
||||
GLuint attrID = getAttribute(va->m_name.c_str());
|
||||
GLenum glType;
|
||||
convert(va->m_elemType, glType);
|
||||
setAttribute(attrID,
|
||||
va->m_elemCount,
|
||||
glType,
|
||||
false,
|
||||
va->m_stride,
|
||||
(void*)((unsigned char*)m_storage.m_vertices->glPtr() + va->m_offset));
|
||||
}
|
||||
}
|
||||
|
||||
void Program::setStorage(Storage const & storage)
|
||||
{
|
||||
m_storage = storage;
|
||||
}
|
||||
|
||||
void Program::makeCurrent()
|
||||
{
|
||||
OGLCHECK(glUseProgramFn(m_handle));
|
||||
|
||||
m_storage.m_vertices->makeCurrent();
|
||||
|
||||
/// setting all attributes streams;
|
||||
for (TAttributes::const_iterator it = m_attributes.begin();
|
||||
it != m_attributes.end();
|
||||
++it)
|
||||
{
|
||||
it->second();
|
||||
}
|
||||
|
||||
m_storage.m_indices->makeCurrent();
|
||||
|
||||
/// setting all uniforms
|
||||
for (TUniforms::const_iterator it = m_uniforms.begin();
|
||||
it != m_uniforms.end();
|
||||
++it)
|
||||
it->second();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
70
graphics/opengl/program.hpp
Normal file
70
graphics/opengl/program.hpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include "opengl.hpp"
|
||||
#include "storage.hpp"
|
||||
|
||||
#include "../../base/matrix.hpp"
|
||||
#include "../../base/exception.hpp"
|
||||
|
||||
#include "../../std/shared_ptr.hpp"
|
||||
#include "../../std/function.hpp"
|
||||
#include "../../std/string.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
class VertexDecl;
|
||||
namespace gl
|
||||
{
|
||||
class Shader;
|
||||
|
||||
class Program
|
||||
{
|
||||
private:
|
||||
|
||||
GLuint m_handle;
|
||||
|
||||
typedef map<string, function<void()> > TUniforms;
|
||||
TUniforms m_uniforms;
|
||||
|
||||
typedef map<GLuint, function<void()> > TAttributes;
|
||||
TAttributes m_attributes;
|
||||
|
||||
Storage m_storage;
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_EXCEPTION(Exception, RootException);
|
||||
DECLARE_EXCEPTION(LinkException, Exception);
|
||||
|
||||
Program(shared_ptr<Shader> const & vxShader,
|
||||
shared_ptr<Shader> const & frgShader);
|
||||
|
||||
~Program();
|
||||
|
||||
unsigned getParam(char const * name);
|
||||
|
||||
void setParam(char const * name, float v0);
|
||||
void setParam(char const * name, float v0, float v1);
|
||||
void setParam(char const * name, float v0, float v1, float v2);
|
||||
void setParam(char const * name, float v0, float v1, float v2, float v3);
|
||||
|
||||
void setParam(char const * name, int v0);
|
||||
void setParam(char const * name, int v0, int v1);
|
||||
void setParam(char const * name, int v0, int v1, int v2);
|
||||
void setParam(char const * name, int v0, int v1, int v2, int v3);
|
||||
|
||||
void setParam(char const * name, math::Matrix<float, 2, 2> const & m);
|
||||
void setParam(char const * name, math::Matrix<float, 3, 3> const & m);
|
||||
void setParam(char const * name, math::Matrix<float, 4, 4> const & m);
|
||||
|
||||
GLuint getAttribute(char const * name);
|
||||
void setAttribute(GLuint id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, void * ptr);
|
||||
|
||||
void setVertexDecl(VertexDecl const * decl);
|
||||
|
||||
void setStorage(Storage const & storage);
|
||||
|
||||
void makeCurrent();
|
||||
};
|
||||
}
|
||||
}
|
95
graphics/opengl/program_manager.cpp
Normal file
95
graphics/opengl/program_manager.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "program_manager.hpp"
|
||||
#include "opengl.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
#if defined(OMIM_GL_ES)
|
||||
#define PRECISION "lowp"
|
||||
#else
|
||||
#define PRECISION ""
|
||||
#endif
|
||||
|
||||
ProgramManager::ProgramManager()
|
||||
{
|
||||
/// Vertex Shader Source
|
||||
static const char vxSrc[] =
|
||||
"attribute vec4 Position;\n"
|
||||
"attribute vec2 Normal;\n"
|
||||
"attribute vec2 TexCoordIn;\n"
|
||||
"uniform mat4 ProjM;\n"
|
||||
"uniform mat4 ModelViewM;\n"
|
||||
"varying vec2 TexCoordOut;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = (vec4(Normal, 0.0, 0.0) + Position * ModelViewM) * ProjM;\n"
|
||||
" TexCoordOut = TexCoordIn;\n"
|
||||
"}\n";
|
||||
|
||||
m_vxShaders["basic"].reset(new Shader(vxSrc, EVertexShader));
|
||||
|
||||
/// Sharp Vertex Shader Source
|
||||
|
||||
static const char sharpVxSrc[] =
|
||||
"attribute vec4 Position;\n"
|
||||
"attribute vec2 Normal;\n"
|
||||
"attribute vec2 TexCoordIn;\n"
|
||||
"uniform mat4 ProjM;\n"
|
||||
"uniform mat4 ModelViewM;\n"
|
||||
"varying vec2 TexCoordOut;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = floor(vec4(Normal, 0.0, 0.0) + Position * ModelViewM) * ProjM;\n"
|
||||
" TexCoordOut = TexCoordIn;\n"
|
||||
"}\n";
|
||||
|
||||
m_vxShaders["sharp"].reset(new Shader(sharpVxSrc, EVertexShader));
|
||||
|
||||
/// Fragment Shader with alphaTest
|
||||
|
||||
static const char alphaTestFrgSrc [] =
|
||||
"uniform sampler2D Texture;\n"
|
||||
"varying " PRECISION " vec2 TexCoordOut;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_FragColor = texture2D(Texture, TexCoordOut);\n"
|
||||
" if (gl_FragColor.a == 0.0)\n"
|
||||
" discard;\n"
|
||||
"}\n";
|
||||
|
||||
m_frgShaders["alphatest"].reset(new Shader(alphaTestFrgSrc, EFragmentShader));
|
||||
|
||||
/// Fragment shader without alphaTest
|
||||
|
||||
static const char noAlphaTestFrgSrc[] =
|
||||
"uniform sampler2D Texture;\n"
|
||||
"varying " PRECISION " vec2 TexCoordOut;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_FragColor = texture2D(Texture, TexCoordOut);\n"
|
||||
"}\n";
|
||||
m_frgShaders["noalphatest"].reset(new Shader(noAlphaTestFrgSrc, EFragmentShader));
|
||||
|
||||
getProgram("basic", "alphatest");
|
||||
getProgram("basic", "noalphatest");
|
||||
|
||||
getProgram("sharp", "alphatest");
|
||||
getProgram("sharp", "noalphatest");
|
||||
}
|
||||
|
||||
shared_ptr<Program> const ProgramManager::getProgram(char const * vxName,
|
||||
char const * frgName)
|
||||
{
|
||||
string prgName(string(vxName) + ":" + frgName);
|
||||
|
||||
map<string, shared_ptr<Program> >::const_iterator it = m_programs.find(prgName);
|
||||
if (it != m_programs.end())
|
||||
return it->second;
|
||||
|
||||
shared_ptr<Program> program(new Program(m_vxShaders[vxName], m_frgShaders[frgName]));
|
||||
|
||||
m_programs[prgName] = program;
|
||||
|
||||
LOG(LINFO, (this, ", ", vxName, ", ", frgName, ", ", program));
|
||||
|
||||
return program;
|
||||
}
|
||||
}
|
||||
}
|
30
graphics/opengl/program_manager.hpp
Normal file
30
graphics/opengl/program_manager.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "program.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
#include "../../std/shared_ptr.hpp"
|
||||
#include "../../std/map.hpp"
|
||||
#include "../../std/string.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
class ProgramManager
|
||||
{
|
||||
private:
|
||||
|
||||
map<string, shared_ptr<Shader> > m_vxShaders;
|
||||
map<string, shared_ptr<Shader> > m_frgShaders;
|
||||
map<string, shared_ptr<Program> > m_programs;
|
||||
|
||||
public:
|
||||
|
||||
ProgramManager();
|
||||
|
||||
shared_ptr<Program> const getProgram(char const * vxName,
|
||||
char const * frgName);
|
||||
};
|
||||
}
|
||||
}
|
48
graphics/opengl/shader.cpp
Normal file
48
graphics/opengl/shader.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "shader.hpp"
|
||||
|
||||
#include "defines_conv.hpp"
|
||||
#include "opengl.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
Shader::Shader(const char *src, EShaderType type)
|
||||
{
|
||||
GLenum glType;
|
||||
convert(type, glType);
|
||||
|
||||
m_handle = glCreateShaderFn(glType);
|
||||
OGLCHECKAFTER;
|
||||
|
||||
if (!m_handle)
|
||||
throw Exception("CreateShader error", "could not create Shader!");
|
||||
|
||||
int len = strlen(src);
|
||||
|
||||
OGLCHECK(glShaderSource(m_handle, 1, &src, &len));
|
||||
|
||||
OGLCHECK(glCompileShaderFn(m_handle));
|
||||
|
||||
GLint compileRes;
|
||||
OGLCHECK(glGetShaderivFn(m_handle, GL_COMPILE_STATUS, &compileRes));
|
||||
|
||||
if (compileRes == GL_FALSE)
|
||||
{
|
||||
GLchar msg[256];
|
||||
OGLCHECK(glGetShaderInfoLogFn(m_handle, sizeof(msg), 0, msg));
|
||||
throw CompileException("Couldn't compile shader: ", msg);
|
||||
}
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
OGLCHECK(glDeleteShaderFn(m_handle));
|
||||
}
|
||||
|
||||
GLuint Shader::id() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
}
|
||||
}
|
30
graphics/opengl/shader.hpp
Normal file
30
graphics/opengl/shader.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../base/exception.hpp"
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
#include "opengl.hpp"
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
class Shader
|
||||
{
|
||||
private:
|
||||
GLuint m_handle;
|
||||
public:
|
||||
|
||||
DECLARE_EXCEPTION(Exception, RootException);
|
||||
DECLARE_EXCEPTION(CompileException, Exception);
|
||||
|
||||
/// Constructor.
|
||||
Shader(char const * src, EShaderType type);
|
||||
/// Destructor.
|
||||
~Shader();
|
||||
/// Handle to the program.
|
||||
GLuint id() const;
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue