#include "UberShaderProgram.h" #include "vertex.h" #include "gl/VideoDriverGLES20.h" #include "gl/ShaderProgramGL.h" namespace oxygine { UberShaderProgramBase::UberShaderProgramBase() { } void UberShaderProgramBase::init(const std::vector& baseShader, const char* prepend, const char* append) { _data = baseShader; _data.insert(_data.begin(), prepend, prepend + strlen(prepend)); _data.insert(_data.end(), append, append + strlen(append)); _data.push_back(0); reg(CLOSURE(this, &UberShaderProgramBase::_restore), 0); } UberShaderProgramBase::~UberShaderProgramBase() { releaseShaders(); } void UberShaderProgramBase::_restore(Restorable*, void*) { } void UberShaderProgramBase::release() { releaseShaders(); unreg(); } UberShaderProgramBase::shader* UberShaderProgram::getShaderProgram(int flags) { shader& s = _shaders[flags]; if (!s.program) { bvertex_format bformat = vertexPCT2::FORMAT; s.flags = flags; const char* data = (const char*)&_data.front(); char prepend[255]; char append[255]; append[0] = 0; prepend[0] = 0; if (flags & ALPHA_PREMULTIPLY) strcat(prepend, "#define ALPHA_PREMULTIPLY\n"); if (flags & SEPARATE_ALPHA) strcat(prepend, "#define SEPARATE_ALPHA\n"); if (flags & MASK_R_CHANNEL) strcat(prepend, "#define MASK_R_CHANNEL\n"); if (flags & MASK) { strcat(prepend, "#define MASK\n"); } char* end = prepend + strlen(prepend); strcat(prepend, "#define program_main_ps main\n"); strcat(prepend, "#define PS\n"); int fs = ShaderProgramGL::createShader(GL_FRAGMENT_SHADER, data, prepend, append); *end = 0; strcat(prepend, "#define program_main_vs main\n"); strcat(prepend, "#define VS\n"); int vs = ShaderProgramGL::createShader(GL_VERTEX_SHADER, data, prepend, append); ShaderProgramGL* pgl = new ShaderProgramGL; VideoDriverGLES20* driver = ((VideoDriverGLES20*)IVideoDriver::instance); const VertexDeclarationGL* decl = driver->getVertexDeclaration(bformat); pgl->init(ShaderProgramGL::createProgram(vs, fs, decl)); CHECKGL(); driver->setShaderProgram(pgl); CHECKGL(); driver->setUniformInt("base_texture", UberShaderProgram::SAMPLER_BASE); driver->setUniformInt("alpha_texture", UberShaderProgram::SAMPLER_ALPHA); driver->setUniformInt("mask_texture", UberShaderProgram::SAMPLER_MASK); s.program = pgl; CHECKGL(); } return &s; } UberShaderProgram::UberShaderProgram() { } UberShaderProgram::~UberShaderProgram() { releaseShaders(); } void UberShaderProgram::releaseShaders() { for (int i = 0; i < SIZE; ++i) { shader& s = _shaders[i]; delete s.program; s.program = 0; } } }