added Shader, Program and ProgramManager classes.

This commit is contained in:
rachytski 2012-11-30 08:49:29 +03:00 committed by Alex Zolotarev
parent b0b5c08c71
commit 639d8eb242
7 changed files with 478 additions and 0 deletions

View file

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

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

View 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;
}
}
}

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

View 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;
}
}
}

View 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;
};
}
}