void TileMapRenderer::render(void* _sprites) { BaseSprite sprites = (BaseSprite)_sprites; if(!verts.buffer) { glGenBuffers(1, &verts.buffer); glGenBuffers(1, &texs.buffer); } if(!program) { program = get_program(standard_program_loader); } gl_check(program->use()); if(sprites) { nverts = basespritelist_set(sprites, &verts, &texs); texture = sprites->texture; } else { spritelist_set_texs_and_verts_gl(nverts, &verts, &texs); texture->bind(); } gl_check(glUniform1i(program->requireUniform(UNIFORM_TEX0), 0)); gl_check(glUniformMatrix4fv(program->requireUniform(UNIFORM_MVP), 1, GL_FALSE, GIGGLE->renderer->orthographic_projection.data)); gl_check(glDrawArrays(GL_TRIANGLES, 0, nverts)); }
unsigned int ShaderProgram::linkProgram() { if (!checkBuilt()) { // this ShaderProgram has already been built. return 0; } if (m_stages.empty()) { Err() << "When linking program, there were no shaders to link! Cannot " "create shader program."; return 0; } if (m_programId != 0) { Dbg() << "Relinking shader program id=" << m_programId; } else { // have GL make a program and bail out if no success. createNewProgram(); if (m_programId == 0) return 0; Dbg() << "Linking shader program id=" << m_programId; } gl_check(glLinkProgram(m_programId)); // Check the program int InfoLogLength{ 0 }; GLint result{ GL_FALSE }; gl_check(glGetProgramiv(m_programId, GL_LINK_STATUS, &result)); gl_check(glGetProgramiv(m_programId, GL_INFO_LOG_LENGTH, &InfoLogLength)); Dbg() << "GL Link Status for shader program " << m_programId << ": " << (result == GL_FALSE ? "GL_FALSE" : "GL_TRUE") << "."; if (InfoLogLength > 1) { std::vector<char> programErrorMessage(InfoLogLength + 1); gl_check(glGetProgramInfoLog(m_programId, InfoLogLength, nullptr, &programErrorMessage[0])); Dbg() << &programErrorMessage[0]; } return m_programId; }
void ShaderProgram::setUniform(const char* param, int val) { unsigned int loc = getUniformLocation(param); // gl_check(glUniform1f(m_programId, loc, val)); gl_check(glProgramUniform1i(m_programId, loc, val)); }
void ShaderProgram::setUniform(const char* param, const glm::vec3& val) { unsigned int loc = getUniformLocation(param); // gl_check(glUniform3fv(m_programId, loc, 1, glm::value_ptr(val))); gl_check(glProgramUniform3fv(m_programId, loc, 1, glm::value_ptr(val))); }
void ShaderProgram::setUniform(const char* param, const glm::mat4& val) { unsigned int loc = getUniformLocation(param); // gl_check(glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val))); gl_check(glProgramUniformMatrix4fv(m_programId, loc, 1, GL_FALSE, glm::value_ptr(val))); }
Program* Program::create(const char* vertexname, const char* fragmentname, ...) { char* vertex_source = filename_slurp(vertexname); char* fragment_source = filename_slurp(fragmentname); LOGI("renderer_load_shader: %s", vertexname); int vertex = renderer_load_shader(vertex_source, GL_VERTEX_SHADER); LOGI("renderer_load_shader: %s", fragmentname); int fragment = renderer_load_shader(fragment_source, GL_FRAGMENT_SHADER); free(vertex_source); free(fragment_source); // uniform bindings are deferred until the program is linked const char* uniform_bindings[UNIFORM_MAX]; memset(uniform_bindings, 0, sizeof(uniform_bindings)); int program = glCreateProgram(); Program* p = new Program(); p->program = program; gl_check(glAttachShader(program, vertex)); gl_check(glAttachShader(program, fragment)); int mode = BINDING_INVALID; va_list ap; va_start(ap, fragmentname); while(1) { unsigned arg = va_arg(ap, int); // are we done? if(arg == BINDING_DONE) break; // if mode switch, do it now if(arg == BINDING_ATTRIBUTES || arg == BINDING_UNIFORMS) { mode = arg; continue; } // if there is no mode then error if(mode == BINDING_INVALID) { fail_exit("mode not defined before first binding"); } if(mode == BINDING_ATTRIBUTES) { ProgramParameters param = (ProgramParameters)arg; const char* name = va_arg(ap, char*); gl_check(glBindAttribLocation(program, param, name)); } else if(mode == BINDING_UNIFORMS) {
bool ShaderProgram::validateProgram() { unsigned int id{ m_programId }; GLint val{ GL_FALSE }; gl_check(glValidateProgram(id)); gl_check(glGetProgramiv(id, GL_VALIDATE_STATUS, &val)); int logLength{ 0 }; gl_check(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &logLength)); if (logLength > 0) { std::vector<char> msg(logLength); gl_check(glGetProgramInfoLog(id, logLength, NULL, &msg[0])); Dbg() << &msg[0]; } return val == GL_TRUE; }
unsigned int Shader::create() { GLenum gl_type{ gl_target[ordinal<ShaderType>(m_type)] }; GLuint shaderId = gl_check(glCreateShader(gl_type)); Dbg() << "glCreateShader for type=" << bd::gl_to_string(gl_type) << " returned id=" << shaderId; return m_id = shaderId; }
unsigned int ShaderProgram::createNewProgram() { GLuint programId = gl_check(glCreateProgram()); if (programId == 0) { Err() << "Unable to create shader program with glCreateProgram(). " "Returned id was 0."; } else { Dbg() << "Created program id: " << programId; for (const Shader* stage : m_stages) { gl_check(glAttachShader(programId, stage->id())); } } return m_programId = programId; }
GLuint load(const char *filename, unsigned int flags) { auto lti = loaded_textures.find(filename); if(lti != loaded_textures.end()) { return lti->second.name; } common::image::Image img; if(!img.read(filename)) { goto fail; } GLenum internal_format = GL_RGBA; GLenum format = GL_RGBA; GLenum type = GL_UNSIGNED_BYTE; if(img.channel_format == common::image::ChannelFmt::R && img.data_format == common::image::DataFmt::FLOAT) { internal_format = GL_R32F; format = GL_RED; type = GL_FLOAT; } loaded_texture lt; glGenTextures(1, <.name); glBindTexture(GL_TEXTURE_2D, lt.name); glTexImage2D(GL_TEXTURE_2D, 0, internal_format, img.width, img.height, 0, format, type, img.data); gl_check(); if(flags & IMG_MIPMAPS) { glGenerateMipmap(GL_TEXTURE_2D); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); } if(flags & IMG_NO_WRAP) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } lt.sequence = sequence; loaded_textures[filename] = lt; img.release(); return lt.name; fail: return 0; }
unsigned int ShaderProgram::getUniformLocation(const char* param) { int rval{ 0 }; ParamTable::iterator found = m_params.find(param); if (found != m_params.end()) { rval = (*found).second; } else { rval = gl_check(glGetUniformLocation(m_programId, param)); // put the uniform location in params table for faster lookup next time. m_params[param] = rval; } return static_cast<unsigned int>(rval); }
bool Compiler::compile(Shader& shader, const char* code) { unsigned int shaderId = shader.id(); gl_check(glShaderSource(shaderId, 1, &code, nullptr)); gl_check(glCompileShader(shaderId)); // Check for errors. GLint result{ GL_FALSE }; int infoLogLength; gl_check(glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result)); gl_check(glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLength)); if (infoLogLength > 1) { std::vector<char> msg(infoLogLength + 1); gl_check(glGetShaderInfoLog(shaderId, infoLogLength, nullptr, &msg[0])); Dbg() << &msg[0]; } return result == GL_TRUE; }
void RenderState::draw() { gl_check(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); switch (m_vao->method()) { case VertexArrayObject::Method::ELEMENTS: drawElementArrays(); break; case VertexArrayObject::Method::ARRAYS: drawArrays(); break; default: break; } }
void ShaderProgram::bind() { // static const std::array<GLenum, 3> targets // { // GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D // }; gl_check(glUseProgram(m_programId)); // int i = 0; // pair is (glsl sampler location, Texture) // for (auto &pair : m_textures) { // gl_check(glActiveTexture(GL_TEXTURE0 + i)); // const Texture &tex = *(pair.second); // GLenum target = targets.at(static_cast<int>(tex.type())); // gl_check(glBindTexture(target, tex.id())); // gl_check(glUniform1f(pair.first, tex.id())); // // i += 1; // } //gl_check(glActiveTexture(GL_TEXTURE0)); }
void RenderState::drawElementArrays() { gl_check(glDrawElements(GL_TRIANGLE_STRIP, m_vao->numElements(), GL_UNSIGNED_SHORT, 0)); }
void GradientScreenRectRenderer::render(void *args) { if(!program) { program = get_program(standard_color_program_loader); } GradientScreenRectParams* params = (GradientScreenRectParams*)args; GLfloat verts[] = { params->corners[0].x, params->corners[0].y, 0.0f, // bl params->corners[1].x, params->corners[1].y, 0.0f, // br params->corners[2].x, params->corners[2].y, 0.0f, // tr params->corners[2].x, params->corners[2].y, 0.0f, // tr params->corners[3].x, params->corners[3].y, 0.0f, // tl params->corners[0].x, params->corners[0].y, 0.0f // bl }; GLfloat colors[] = { params->colors[0].r, params->colors[0].g, params->colors[0].b, params->colors[0].a, params->colors[1].r, params->colors[1].g, params->colors[1].b, params->colors[1].a, params->colors[2].r, params->colors[2].g, params->colors[2].b, params->colors[2].a, params->colors[2].r, params->colors[2].g, params->colors[2].b, params->colors[2].a, params->colors[3].r, params->colors[3].g, params->colors[3].b, params->colors[3].a, params->colors[0].r, params->colors[0].g, params->colors[0].b, params->colors[0].a, }; GLfloat texs[] = { params->texture->u0, params->texture->v0, params->texture->u1, params->texture->v0, params->texture->u1, params->texture->v1, params->texture->u1, params->texture->v1, params->texture->u0, params->texture->v1, params->texture->u0, params->texture->v0 }; gl_check(program->use()); GLuint vert_buffer = next_buffer(); gl_check(glEnableVertexAttribArray(GLPARAM_VERTEX)); gl_check(glBindBuffer(GL_ARRAY_BUFFER, vert_buffer)); gl_check(glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_DYNAMIC_DRAW)); gl_check(glVertexAttribPointer(GLPARAM_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0)); GLuint tex_buffer = next_buffer(); gl_check(glEnableVertexAttribArray(GLPARAM_TEXCOORD0)); gl_check(glBindBuffer(GL_ARRAY_BUFFER, tex_buffer)); gl_check(glBufferData(GL_ARRAY_BUFFER, sizeof(texs), texs, GL_DYNAMIC_DRAW)); gl_check(glVertexAttribPointer(GLPARAM_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 0, 0)); GLuint color_buffer = next_buffer(); gl_check(glEnableVertexAttribArray(GLPARAM_OTHER0)); gl_check(glBindBuffer(GL_ARRAY_BUFFER, color_buffer)); gl_check(glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 6, colors, GL_DYNAMIC_DRAW)); gl_check(glVertexAttribPointer(GLPARAM_OTHER0, 4, GL_FLOAT, GL_FALSE, 0, 0)); params->texture->texture->bind(); gl_check(glUniform1i(program->requireUniform(UNIFORM_TEX0), 0)); gl_check(glUniformMatrix4fv(program->requireUniform(UNIFORM_MVP), 1, GL_FALSE, GIGGLE->renderer->orthographic_projection.data)); gl_check(glDrawArrays(GL_TRIANGLES, 0, 6)); }
void ShaderProgram::unbind() { gl_check(glUseProgram(0)); }