void GLVertexBuffer::Resize(uint size) { m_Size = size; GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_Handle)); GLCall(glBufferData(GL_ARRAY_BUFFER, size, NULL, SPBufferUsageToOpenGL(m_Usage))); }
GLboolean Shader::checkErrors(GLuint shaderID, const std::string shader_type) { GLint success; GLCall( glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success) ); if (!success) { GLint length; GLCall( glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length) ); std::vector<char> error(length); GLCall( glGetShaderInfoLog(shaderID, length, &length, &error[0]) ); std::string errorMessage("[Shader]. Compile-time error: Type: "); errorMessage += shader_type; errorMessage += "\n"; errorMessage += &error[0]; XTEN_ERROR(errorMessage); //std::cout << "ERROR [Shader]. Compile-time error: Type: " << shader_type // << std::endl << errorMessage << std::endl // << "-- --------------------------------- --" << std::endl; return GL_FALSE; } else { return GL_TRUE; } }
bool ElysiumEngine::GLSLCompiler::compile(GLSLShader *shader) { unsigned int program = create(shader->vertexShader,shader->fragmentShader,shader->utilityShaders); if(program == -1) return false; shader->shaderProgram = program; //Bind our locations these are using the standard enumerated values //located in GLSLShader.h other vertex attributes can be found later GLCall(glLinkProgram(shader->shaderProgram)); GLint LinkFlag = 0; GLCall(glGetProgramiv(shader->shaderProgram,GL_LINK_STATUS,&LinkFlag)); if(!LinkFlag)//Linking failed { int LogLength = 0; GLsizei StringLength = 0; GLCall(glGetProgramiv(shader->shaderProgram, GL_INFO_LOG_LENGTH, &LogLength)); char *Log = new char[LogLength]; GLCall(glGetProgramInfoLog(shader->shaderProgram,LogLength,&StringLength,Log)); std::cout << "Could not link the specified program.\n" << Log << std::endl; return false; } //Bind up our uniforms std::stringstream str; for(int i = 0; i < shader->lights.size(); ++i) { char Array[100]; sprintf(Array,"uLightPositions[%i]",i); GLCall(shader->lights[i].postion = glGetUniformLocation(shader->shaderProgram,Array)); sprintf(Array,"uLightsDiffuse[%i]",i); GLCall(shader->lights[i].diffuse = glGetUniformLocation(shader->shaderProgram,Array)); sprintf(Array,"uLightsAmbient[%i]",i); GLCall(shader->lights[i].ambient = glGetUniformLocation(shader->shaderProgram,Array)); sprintf(Array,"uLightsSpecular[%i]",i); GLCall(shader->lights[i].specular = glGetUniformLocation(shader->shaderProgram,Array)); sprintf(Array,"uLightType[%i]",i); GLCall(shader->lights[i].type = glGetUniformLocation(shader->shaderProgram,Array)); sprintf(Array,"uLightsDirection[%i]",i); GLCall(shader->lights[i].direction = glGetUniformLocation(shader->shaderProgram,Array)); } return program != -1; }
Buffer::Buffer(float* data, uint count, uint componentCount) : m_ComponentCount(componentCount) { GLCall(glGenBuffers(1, &m_BufferID)); GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_BufferID)); GLCall(glBufferData(GL_ARRAY_BUFFER, count * sizeof(float), data, GL_STATIC_DRAW)); GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0)); }
void GLVertexBuffer::SetLayout(const BufferLayout& bufferLayout) { m_Layout = bufferLayout; const std::vector<BufferElement>& layout = bufferLayout.GetLayout(); for (uint i = 0; i < layout.size(); i++) { const BufferElement& element = layout[i]; GLCall(glEnableVertexAttribArray(i)); GLCall(glVertexAttribPointer(i, element.count, element.type, element.normalized, bufferLayout.GetStride(), (const void*)element.offset)); } }
GLuint Texture::Load() { BYTE* pixels = nullptr; if (m_FileName != "NULL") pixels = load_image(m_FileName.c_str(), &m_Width, &m_Height, &m_Bits); else m_Bits = 32; // Temporary GLuint result; GLCall(glGenTextures(1, &result)); GLCall(glBindTexture(GL_TEXTURE_2D, result)); GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLint)s_WrapMode)); GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLint)s_WrapMode)); if (m_Bits != 24 && m_Bits != 32) SPARKY_ERROR("[Texture] Unsupported image bit-depth! (", m_Bits, ")"); GLint internalFormat = m_Bits == 32 ? GL_RGBA : GL_RGB; GLenum format = m_Bits == 32 ? #ifdef SPARKY_PLATFORM_WEB GL_RGBA : GL_RGB; #else GL_BGRA : GL_BGR; #endif GLCall(glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_Width, m_Height, 0, format, GL_UNSIGNED_BYTE, pixels ? pixels : NULL)); GLCall(glBindTexture(GL_TEXTURE_2D, 0)); if (pixels != nullptr) delete[] pixels; return result; }
void ForwardRenderer::Present() { // TODO: Shader binding, texture sorting, visibility testing, etc. GLCall(glEnable(GL_DEPTH_TEST)); GLCall(glDepthFunc(GL_LEQUAL)); for (uint i = 0; i < m_CommandQueue.size(); i++) { const RenderCommand& command = m_CommandQueue[i]; command.mesh->GetMaterialInstance()->GetMaterial()->GetShader()->Bind(); SetRequiredUniforms(command.mesh->GetMaterialInstance()->GetMaterial()->GetShader(), command.uniforms); //SetSystemUniforms(command.mesh->GetMaterialInstance()->GetMaterial()->GetShader()); command.mesh->Render(*this); } }
void Renderer::draw(const Model& model, glm::mat4 modelMatrix, float t) { model.m_vao.bind(); for (auto mesh : model.m_meshes) { mesh.m_ebo.bind(); auto& shader = mesh.m_shaderProgram; shader.bind(); shader.setMaterial(MaterialSystem::getById(mesh.m_materialID)); GLCall(glUniform1f(shader.getUniformLocation("time"), t)); GLCall(glUniformMatrix4fv(shader.getUniformLocation("m2w"), 1, GL_FALSE, glm::value_ptr(modelMatrix))); GLCall(glDrawElements(GL_TRIANGLES, mesh.m_ebo.count(), GL_UNSIGNED_INT, nullptr)); } }
void Renderer::Draw(const VertexArray& va, const IndexBuffer& ib, const Shader& shader) const { shader.Bind(); ib.Bind(); va.Bind(); GLCall(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, 0)); }
UE_void PostEffectsPass::RenderPass(Framebuffer* target) { m_Shader->bind(); m_Shader->setUniformMat4("pr_matrix", maths::mat4::orthographic(0, target->GetWidth(), target->GetHeight(), 0, -1.0f, 1.0f)); GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL)); m_Shader->unbind(); }
void VertexArray::PushVertexBuffer(VertexBuffer* VB) { glBindVertexArray(m_VertexArray); VB->Bind(); const BufferLayout& layout = VB->GetLayout(); const auto& elements = layout.GetElements(); uint stride = layout.GetStride(); for (uint i = 0; i < elements.size(); i++) { GLCall(glEnableVertexAttribArray(i)); GLCall(glVertexAttribPointer(i, elements[i].count, elements[i].type, GL_FALSE, stride, (const void*)elements[i].offset)); } glBindVertexArray(0); }
//void Renderer::draw(const VertexArray& va, const ElementBuffer& eb, const ShaderProgram& shader) const void Renderer::draw(const VertexArray& va, const ElementBuffer& eb, const ShaderProgram& shader) { va.bind(); eb.bind(); shader.bind(); GLCall(glDrawElements(GL_TRIANGLES, eb.count(), GL_UNSIGNED_INT, nullptr)); // // UNBIND [optional]... discuss }
void Renderer::draw(const Model& model, glm::mat4 modelMatrix) { model.m_vao.bind(); for(auto& mesh: model.m_meshes) { mesh.m_ebo.bind(); mesh.m_shaderProgram.bind(); mesh.m_shaderProgram.setMaterial(MaterialSystem::getById(mesh.m_materialID)); GLint uniformModel = mesh.m_shaderProgram.getUniformLocation("model"); GLCall(glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(modelMatrix))); GLCall(glDrawElements(GL_TRIANGLES, mesh.m_ebo.count(), GL_UNSIGNED_INT, nullptr)); } // // UNBIND [optional]... discuss }
void Framebuffer2D::AttachDepth(Texture2D* texture) { FL_ASSERT(m_Width == texture->GetWidth() && m_Height == texture->GetHeight()); FL_ASSERT(texture->GetFormat() == TextureFormat::Depth); m_DepthAttachment = texture; Bind(); GLCall(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture->GetRendererID(), 0)); Unbind(); }
GLint Shader::getUniformLocation(const GLchar *name) { GLint result = GLCall( glGetUniformLocation(m_ID, name) ); if (result == -1) { std::string err = "[Shader]. Could not find uniform " + std::string(name) + " in shader."; XTEN_ERROR(err); } return result; }
GLboolean Shader::checkProgramErrors(GLuint shaderID, const std::string shader_type, const std::string type) { GLint success; if (type == "Link") { GLCall( glGetProgramiv(shaderID, GL_LINK_STATUS, &success) ); if (!success) { GLint length; GLCall( glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length) ); std::vector<char> error(length); GLCall( glGetShaderInfoLog(shaderID, length, &length, &error[0]) ); std::string errorMessage("[Shader]. "); errorMessage += type; errorMessage += "-time error: Type: "; errorMessage += shader_type; errorMessage += "\n"; errorMessage += &error[0]; XTEN_ERROR(errorMessage); //std::cout << "ERROR [Shader]. " << type << "-time error: Type: " << shader_type // << std::endl << errorMessage << std::endl // << "-- --------------------------------- --" << std::endl; return GL_FALSE; } else { return GL_TRUE; } } else if (type == "Validate") { GLCall( glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &success) ); if (!success) { GLint length; GLCall( glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &length) ); std::vector<char> error(length); GLCall( glGetShaderInfoLog(shaderID, length, &length, &error[0]) ); std::string errorMessage("[Shader]. "); errorMessage += type; errorMessage += "-time error: Type: "; errorMessage += shader_type; errorMessage += "\n"; errorMessage += &error[0]; XTEN_ERROR(errorMessage); //std::cout << "ERROR [Shader]. " << type << "-time error: Type: " << shader_type // << std::endl << errorMessage << std::endl // << "-- --------------------------------- --" << std::endl; return GL_FALSE; } else { return GL_TRUE; } } else { return GL_FALSE; } }
void Framebuffer2D::AttachColor(Texture2D* texture, uint index) { FL_ASSERT(m_Width == texture->GetWidth() && m_Height == texture->GetHeight()); if (m_ColorAttachments.size() <= index) m_ColorAttachments.resize(index + 1); m_ColorAttachments[index] = texture; Bind(); GLCall(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, GL_TEXTURE_2D, texture->GetRendererID(), 0)); Unbind(); }
UE_void Framebuffer::Create(UE_uint width, UE_uint height) { GLCall(glGenFramebuffers(1, &m_Data.framebufferID)); GLCall(glGenRenderbuffers(1, &m_Data.depthbufferID)); Texture::setFilter(TextureFilter::LINEAR); m_Texture = new Texture(width, height); GLCall(glBindRenderbuffer(GL_RENDERBUFFER, m_Data.depthbufferID)); GLCall(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height)); GLCall(glBindFramebuffer(GL_FRAMEBUFFER, m_Data.framebufferID)); GLCall(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_Texture->getID(), 0)); GLCall(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_Data.depthbufferID)); }
void Shader::setVector2f(const GLchar * name, const xmaths::vec2 & vector) { GLCall( glUniform2f(getUniformLocation(name), vector.x, vector.y) ); }
//TODO: Add in error handling unsigned int ElysiumEngine::GLSLCompiler::create(std::string vertexShader, std::string fragmentShader, std::vector<std::string> &utilityShaders) { //Create the two main shaders int vertex = -1; GLCall(vertex = glCreateShader(GL_VERTEX_SHADER)); int fragment = -1; GLCall(fragment = glCreateShader(GL_FRAGMENT_SHADER)); char *vertexText = nullptr; char *fragmentText = nullptr; char **utilityTexts; loadStringToFile(vertexShader.c_str(),vertexText); loadStringToFile(fragmentShader.c_str(), fragmentText); utilityTexts = new char*[utilityShaders.size() + 1]; for(int i = 0; i < utilityShaders.size(); ++i) { loadStringToFile(utilityShaders[i].c_str(), utilityTexts[i]); } utilityTexts[utilityShaders.size()] = vertexText; GLCall(glShaderSource(vertex,1+utilityShaders.size(),const_cast<const char**>(utilityTexts),nullptr)); GLCall(glCompileShader(vertex)); int CompiledFlag = 0; GLCall(glGetShaderiv(vertex,GL_COMPILE_STATUS,&CompiledFlag)); if(!CompiledFlag) { std::string Type; Type = "Vertex Shader"; int LogLength = 0; GLsizei StringLength = 0; //Get the length needed to store the log GLCall(glGetShaderiv(vertex, GL_INFO_LOG_LENGTH, &LogLength)); char *Log = new char[LogLength]; GLCall(glGetShaderInfoLog(vertex,LogLength,&StringLength,Log)); std::cout << "Could not compile " << Type << ": " << vertexShader << "\nLog:\n" << Log << std::endl; delete [] Log; return -1; } utilityTexts[utilityShaders.size()] = fragmentText; GLCall(glShaderSource(fragment,1+utilityShaders.size(),const_cast<const char **>(utilityTexts),nullptr)); GLCall(glCompileShader(fragment)); GLCall(glGetShaderiv(fragment,GL_COMPILE_STATUS,&CompiledFlag)); if(!CompiledFlag) { std::string Type; Type = "Fragment Shader"; int LogLength = 0; GLsizei StringLength = 0; //Get the length needed to store the log GLCall(glGetShaderiv(fragment, GL_INFO_LOG_LENGTH, &LogLength)); char *Log = new char[LogLength]; GLCall(glGetShaderInfoLog(fragment,LogLength,&StringLength,Log)); std::cout << "Could not compile " << Type << ": " << fragmentShader << "\nLog:\n" << Log << std::endl; delete [] Log; return -1; } int program = glCreateProgram(); GLCall(glAttachShader(program,vertex)); GLCall(glAttachShader(program,fragment)); //Free the char memory allocated by creating these shaders delete[] vertexText; delete[] fragmentText; for(int i = 0; i < utilityShaders.size(); ++i) { delete[] utilityTexts[i]; } delete[] utilityTexts; return program; }
void Shader::setMat4f(const GLchar * name, const xmaths::mat4 & matrix) { GLCall( glUniformMatrix4fv(getUniformLocation(name), 1, GL_FALSE, matrix.data) ); }
void Shader::setVector4f(const GLchar * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { GLCall( glUniform4f(getUniformLocation(name), x, y, z, w) ); }
void Shader::setVector4f(const GLchar * name, const xmaths::vec4 & vector) { GLCall( glUniform4f(getUniformLocation(name), vector.x, vector.y, vector.z, vector.w) ); }
void Shader::setVector3f(const GLchar * name, GLfloat x, GLfloat y, GLfloat z) { GLCall( glUniform3f(getUniformLocation(name), x, y, z) ); }
void Shader::setVector2f(const GLchar * name, GLfloat x, GLfloat y) { GLCall( glUniform2f(getUniformLocation(name), x, y) ); }
Shader::~Shader() { GLCall( glDeleteProgram(m_ID) ); }
void Shader::setUniform1iv(const GLchar * name, int count, int * value) { GLCall( glUniform1iv(getUniformLocation(name), count, value) ); }
void Shader::setInteger(const GLchar * name, int value) { GLCall( glUniform1i(getUniformLocation(name), value) ); }
void Shader::setFloat(const GLchar* name, float value) { GLCall( glUniform1f(getUniformLocation(name), value) ); }
GLboolean Shader::compile(const GLchar * vertexpath, const GLchar * fragpath, const GLchar * geompath) { GLuint vertexID = GLCall( glCreateShader(GL_VERTEX_SHADER) ); GLCall( glShaderSource(vertexID, 1, &vertexpath, NULL) ); GLCall( glCompileShader(vertexID) ); if (!checkErrors(vertexID, "VERTEX")) { GLCall( glDeleteShader(vertexID) ); return GL_FALSE; } GLuint fragID = GLCall( glCreateShader(GL_FRAGMENT_SHADER) ); GLCall( glShaderSource(fragID, 1, &fragpath, NULL) ); GLCall( glCompileShader(fragID) ); if (!checkErrors(fragID, "FRAGMENT")) { GLCall( glDeleteShader(vertexID) ); GLCall( glDeleteShader(fragID) ); return GL_FALSE; } GLuint geomID; if (geompath != nullptr) { geomID = GLCall( glCreateShader(GL_GEOMETRY_SHADER) ); GLCall( glShaderSource(geomID, 1, &geompath, NULL) ); GLCall( glCompileShader(geomID) ); if (!checkErrors(geomID, "GEOMETRY")) { GLCall( glDeleteShader(vertexID) ); GLCall( glDeleteShader(fragID) ); GLCall( glDeleteShader(geomID) ); return GL_FALSE; } } m_ID = GLCall( glCreateProgram() ); GLCall( glAttachShader(m_ID, vertexID) ); GLCall( glAttachShader(m_ID, fragID) ); if (geompath != nullptr) { GLCall( glAttachShader(m_ID, geomID) ); } GLCall( glLinkProgram(m_ID) ); if (!checkProgramErrors(m_ID, "PROGRAM", "Link")) { GLCall( glDetachShader(m_ID, vertexID) ); GLCall( glDeleteShader(vertexID) ); GLCall( glDetachShader(m_ID, fragID) ); GLCall( glDeleteShader(fragID) ); if (geompath != nullptr) { GLCall( glDetachShader(m_ID, geomID) ); GLCall( glDeleteShader(geomID) ); } return GL_FALSE; } GLCall( glValidateProgram(m_ID) ); if (!checkProgramErrors(m_ID, "PROGRAM", "Validate")) { GLCall( glDetachShader(m_ID, vertexID) ); GLCall( glDeleteShader(vertexID) ); GLCall( glDetachShader(m_ID, fragID) ); GLCall( glDeleteShader(fragID) ); if (geompath != nullptr) { GLCall( glDetachShader(m_ID, geomID) ); GLCall( glDeleteShader(geomID) ); } return GL_FALSE; } GLCall( glDetachShader(m_ID, vertexID) ); GLCall( glDeleteShader(vertexID) ); GLCall( glDetachShader(m_ID, fragID) ); GLCall( glDeleteShader(fragID) ); if (geompath != nullptr) { GLCall( glDetachShader(m_ID, geomID) ); GLCall( glDeleteShader(geomID) ); } return GL_TRUE; }