/** * Updates all vertex attributes. * This is used when BindingLocation changes after a shader recompile. */ void GLVertexAttributeArray::UpdateVertexAttributes() { OGL_CALL(glBindBuffer, GL_ARRAY_BUFFER, v_buffer); OGL_CALL(glBindVertexArray, vao); OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, i_buffer); for (const auto& desc : v_desc) { if (desc.location->iBinding > 0) { OGL_CALL(glEnableVertexAttribArray, desc.location->iBinding); switch (desc.shaderType) { case VAShaderType::FLOAT: OGL_CALL(glVertexAttribPointer, desc.location->iBinding, desc.size, desc.type, desc.normalized, desc.stride, (static_cast<char*> (nullptr)) + desc.offset); break; case VAShaderType::INTEGER: OGL_CALL(glVertexAttribIPointer, desc.location->iBinding, desc.size, desc.type, desc.stride, (static_cast<char*> (nullptr)) + desc.offset); break; case VAShaderType::DOUBLE: OGL_CALL(glVertexAttribLPointer, desc.location->iBinding, desc.size, desc.type, desc.stride, (static_cast<char*> (nullptr)) + desc.offset); break; } } } OGL_CALL(glBindVertexArray, 0); OGL_CALL(glBindBuffer, GL_ARRAY_BUFFER, 0); }
/** Disables all vertex attributes in the array. */ void GLVertexAttributeArray::DisableAttributes() { OGL_CALL(glBindVertexArray, vao); OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0); for (const auto& desc : v_desc) { if (desc.location->iBinding > 0) { OGL_CALL(glDisableVertexAttribArray, desc.location->iBinding); } } OGL_CALL(glBindVertexArray, 0); }
/** * Adds a new double attribute to the vertex. * @param location the binding location * @param size the number of components in the attribute * @param type the type in which the data is stored in the vertex buffer * @param stride the difference in bytes between of this attributes * @param offset the offset into the buffer to the first of this attributes */ void GLVertexAttributeArray::AddVertexAttributeL(BindingLocation location, int size, GLenum type, GLsizei stride, unsigned int offset) { vertex_attribute_desc desc; desc.shaderType = VAShaderType::DOUBLE; desc.location = location; desc.size = size; desc.type = type; desc.stride = stride; desc.offset = offset; v_desc.push_back(std::move(desc)); OGL_CALL(glEnableVertexAttribArray, location->iBinding); OGL_CALL(glVertexAttribLPointer, location->iBinding, size, type, stride, (static_cast<char*> (nullptr)) + offset); }
void Shader::UnloadLocal() { if (this->shader != 0) { OGL_CALL(glDeleteShader, shader); shader = 0; } }
void ForwardRenderer::Render() { auto totalObjects = scene->GetTotalObjects(); auto totalLights = scene->GetTotalLights(); auto totalRenderingPasses = totalLights + 2; // Render passes: // 0 - Depth Prepass // 1 - Global Light for the Objects (Ambient, Emissive) // Rest - Diffuse/Specular/etc Lighting for Objects for (decltype(totalRenderingPasses) p = 0; p < totalRenderingPasses; ++p) { OGL_CALL(glDepthMask((p == 0) ? GL_TRUE : GL_FALSE)); bool writeToColor = (p == 0) ? GL_FALSE: GL_TRUE; OGL_CALL(glColorMask(writeToColor, writeToColor, writeToColor, writeToColor)); for (decltype(totalObjects) i = 0; i < totalObjects; ++i) { const SceneObject& sceneObject = scene->GetSceneObject(i); auto totalRenderObjects = sceneObject.GetTotalRenderObjects(); for (decltype(totalRenderObjects) r = 0; r < totalRenderObjects; ++r) { const RenderingObject* renderObject = sceneObject.GetRenderObject(r); if (!renderObject) { continue; } const ShaderProgram* shaderToUse = renderObject->GetShaderProgramRaw(); assert(shaderToUse); shaderToUse->StartUseShader(); renderObject->BeginRender(); // Make the scene object setup its shader with any data its shader might need. // Start from the end because the very 'last' light handles the global lighting for the object. // A light that is a nullptr will cause the shader to perform default behavior, whatever that may be. const Light* lightObject = scene->GetLightObject(totalRenderingPasses - p - 1); if (shaderToUse->IsAffectedByLight(lightObject)) { sceneObject.PrepareShaderForRendering(shaderToUse, camera.get(), lightObject); renderObject->Render(); } renderObject->EndRender(); shaderToUse->StopUseShader(); } } } OGL_CALL(glDepthMask(GL_TRUE)); }
Texture2D::Texture2D(GLubyte* rawData, int width, int height): Texture(GL_TEXTURE_2D), texWidth(width), texHeight(height) { OGL_CALL(glGenTextures(1, &glTexture)); OGL_CALL(glBindTexture(GL_TEXTURE_2D, glTexture)); OGL_CALL(glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, texWidth, texHeight)); OGL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, rawData)); // Would be useful to expose these settings! OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)); OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)); OGL_CALL(glGenerateMipmap(GL_TEXTURE_2D)); OGL_CALL(glBindTexture(GL_TEXTURE_2D, 0)); }
/** * Constructor. * @param vertexBuffer the vertex buffer used to create the attributes. * @param indexBuffer the index buffer to bind */ GLVertexAttributeArray::GLVertexAttributeArray(GLuint vertexBuffer, GLuint indexBuffer) : vao(0), i_buffer(indexBuffer), v_buffer(vertexBuffer), v_desc() { OGL_CALL(glGenVertexArrays, 1, &vao); }
void BlinnPhongShader::UpdateMaterialBlock() const { StartUseShader(); memcpy((void*)(materialStorage.data() + materialOffsets[0]), glm::value_ptr(diffuse), sizeof(glm::vec4)); memcpy((void*)(materialStorage.data() + materialOffsets[1]), glm::value_ptr(specular), sizeof(glm::vec4)); memcpy((void*)(materialStorage.data() + materialOffsets[2]), &shininess, sizeof(float)); memcpy((void*)(materialStorage.data() + materialOffsets[3]), glm::value_ptr(ambient), sizeof(glm::vec4)); if (materialBuffer && materialBlockLocation != GL_INVALID_INDEX) { OGL_CALL(glBindBuffer(GL_UNIFORM_BUFFER, materialBuffer)); OGL_CALL(glBufferData(GL_UNIFORM_BUFFER, materialBlockSize, materialStorage.data(), GL_STATIC_DRAW)); OGL_CALL(glBindBufferBase(GL_UNIFORM_BUFFER, MATERIAL_BINDING_POINT, materialBuffer)); OGL_CALL(glUniformBlockBinding(shaderProgram, materialBlockLocation, MATERIAL_BINDING_POINT)); OGL_CALL(glBindBuffer(GL_UNIFORM_BUFFER, 0)); } StopUseShader(); }
void EpicShader::SetupShaderMaterials() const { // Need to make sure the material buffer is bound. OGL_CALL(glBindBufferBase(GL_UNIFORM_BUFFER, MATERIAL_BINDING_POINT, materialBuffer)); // Make sure the right textures are bound. const Texture* diffuseTexture = defaultTexture.get(); if (textureSlotMapping.find(TextureSlots::DIFFUSE) != textureSlotMapping.end()) { diffuseTexture = textureSlotMapping.at(TextureSlots::DIFFUSE).get(); } assert(diffuseTexture); diffuseTexture->BeginRender(static_cast<int>(TextureSlots::DIFFUSE)); // While we're here, also setup the textures too. SetShaderUniform("diffuseTexture", static_cast<int>(TextureSlots::DIFFUSE)); }
void MediaLayer::InitializeOpenGL() { if (!sdlInitialized) { std::cerr << "ERROR: Can not initialize OpenGL before setting up SDL." << std::endl; return; } glContext = SDL_GL_CreateContext(sdlWindow); if (glContext == NULL) { std::cerr << "ERROR: SDL failed to create an OpenGL context" << std::endl; return; } // 0 - Disables Vsync, 1 - Enables Vsync // More information: https://www.opengl.org/wiki/Swap_Interval // Documentation: https://wiki.libsdl.org/SDL_GL_SetSwapInterval SDL_GL_SetSwapInterval(0); // Initialize GLEW glewExperimental = GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { std::cerr << "ERROR: GLEW failed to initialize." << std::endl; return; } // At this point we want to flush out all of the OpenGL errors that might have been caused by GLEW. while ((err = glGetError()) != GL_NO_ERROR); openglInitialized = true; // Sane default settings for OpenGL rendering OGL_CALL(glEnable(GL_DEPTH_TEST)); OGL_CALL(glDepthFunc(GL_LEQUAL)); OGL_CALL(glEnable(GL_BLEND)); OGL_CALL(glBlendFunc(GL_ONE, GL_ONE)); OGL_CALL(glEnable(GL_CULL_FACE)); OGL_CALL(glCullFace(GL_BACK)); OGL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); }
/** * Loads a shader from file and compiles it. * @param filename the shaders file name * @param type the shaders type * @param strType the shaders type as string * @return the compiled shader if successful */ GLuint Shader::CompileShader(const std::string& filename, const std::vector<std::string>& defines, GLenum type, const std::string& strType) const { unsigned int firstFileId = 0; if (!boost::filesystem::exists(filename)) { LOG(ERROR) << "Cannot open shader file \"" << filename.c_str() << "\"."; throw resource_loading_error() << ::boost::errinfo_file_name(filename) << fileid_info(firstFileId) << resid_info(id) << errdesc_info("Cannot open shader file."); } auto shaderText = LoadShaderFile(filename, defines, firstFileId, 0); auto shader = OGL_CALL(glCreateShader, type); if (shader == 0) { LOG(ERROR) << L"Could not create shader!"; throw std::runtime_error("Could not create shader!"); } auto shaderTextArray = shaderText.c_str(); auto shaderLength = static_cast<int>(shaderText.length()); OGL_CALL(glShaderSource, shader, 1, &shaderTextArray, &shaderLength); OGL_CALL(glCompileShader, shader); GLint status; OGL_CALL(glGetShaderiv, shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint infoLogLength; OGL_CALL(glGetShaderiv, shader, GL_INFO_LOG_LENGTH, &infoLogLength); auto strInfoLog = new GLchar[infoLogLength + 1]; OGL_CALL(glGetShaderInfoLog, shader, infoLogLength, NULL, strInfoLog); std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; LOG(ERROR) << L"Compile failure in " << converter.from_bytes(strType) << L" shader (" << filename.c_str() << "): " << std::endl << strInfoLog; std::string infoLog = strInfoLog; delete[] strInfoLog; OGL_CALL(glDeleteShader, shader); throw shader_compiler_error() << ::boost::errinfo_file_name(filename) << compiler_error_info(infoLog) << resid_info(id) << errdesc_info("Shader compilation failed."); } return shader; }
BlinnPhongShader::~BlinnPhongShader() { OGL_CALL(glDeleteBuffers(1, &materialBuffer)); }
/** Disables the vertex attribute array. */ void GLVertexAttributeArray::DisableVertexAttributeArray() const { OGL_CALL(glBindVertexArray, 0); }
/** Enables the vertex attribute array. */ void GLVertexAttributeArray::EnableVertexAttributeArray() const { OGL_CALL(glBindVertexArray, vao); }
/** Ends the vertex attribute setup. */ void GLVertexAttributeArray::EndAttributeSetup() const { OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, i_buffer); OGL_CALL(glBindVertexArray, 0); OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0); }
GLVertexAttributeArray::~GLVertexAttributeArray() { if (vao != 0) { OGL_CALL(glDeleteVertexArrays, 1, &vao); } }
EpicShader::~EpicShader() { OGL_CALL(glDeleteBuffers(1, &materialBuffer)); }
/** Initializes the vertex attribute setup. */ void GLVertexAttributeArray::StartAttributeSetup() const { OGL_CALL(glBindVertexArray, vao); OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0); }