#include "graphics.h" #include "shapedata.h" #include #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" #include "stb_image.h" Graphics::Graphics(): m_textRenderer(std::make_shared()) { } Graphics::~Graphics(){ deleteFBOS(); } void Graphics::initializeGLEW(){ glewExperimental = GL_TRUE; std::cout<<"GLEWInit status: "<initialize(); std::cout<<"add shapes"<(rand()) / (static_cast (RAND_MAX/(ub-lb))); return random; } GLuint Graphics::loadCubeMap(std::vector textureFiles){ // create empty texture GLuint textureID; glGenTextures(1, &textureID); //glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); GLuint target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; for (int i=0; i<6; i++){ std::string filename = std::string(textureFiles[i]);//directory + '/' + filename; int width, height, nrChannels; unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0); if (data){ stbi_set_flip_vertically_on_load(false); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); stbi_image_free(data); } else { std::cout << "Texture failed to load at path: " << textureFiles[i] << std::endl; stbi_image_free(data); } } return textureID; } TextureData Graphics::loadTextureFromFile(const char *path) { std::string filename = std::string(path); GLuint textureID; glGenTextures(1, &textureID); int width, height, nrComponents; stbi_set_flip_vertically_on_load(true); unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0); stbi_set_flip_vertically_on_load(false); if (data) { GLenum format; if (nrComponents == 1) format = GL_RED; else if (nrComponents == 3) format = GL_RGB; else if (nrComponents == 4) format = GL_RGBA; glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_image_free(data); } else { std::cout << "Texture failed to load at path: " << path << std::endl; stbi_image_free(data); } TextureData newtex; newtex.textureID = textureID; newtex.height = height; newtex.width = width; return newtex; } TextureData Graphics::loadTextureFromFile_Repeat(const char *path) { std::string filename = std::string(path); GLuint textureID; glGenTextures(1, &textureID); int width, height, nrComponents; stbi_set_flip_vertically_on_load(true); unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0); stbi_set_flip_vertically_on_load(false); if (data) { GLenum format; if (nrComponents == 1) format = GL_RED; else if (nrComponents == 3) format = GL_RGB; else if (nrComponents == 4) format = GL_RGBA; glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_image_free(data); } else { std::cout << "Texture failed to load at path: " << path << std::endl; stbi_image_free(data); } TextureData newtex; newtex.textureID = textureID; newtex.height = height; newtex.width = width; return newtex; } GLuint Graphics::makeVAO(std::vector positions){ int numVertices = positions.size()/2; GLuint vao, vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, positions.size()*sizeof(float), positions.data(), GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0); // unbind glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); return vao; } void Graphics::clearScreen(GLbitfield mask){ glClear(mask); } void Graphics::setClearColor(glm::vec3 clearColor){ glClearColor(clearColor.r, clearColor.g, clearColor.b, 1); } void Graphics::setCameraData(std::shared_ptr camera){ m_active_shader->setCamera(camera); } void Graphics::addShader(std::string shaderName, std::vector shaderTypes, std::vector filepaths){ m_shaders.insert({shaderName, std::make_shared(shaderTypes, filepaths)}); } void Graphics::removeShader(std::string shaderName){ if(shaderName != "phong" && shaderName != "text"){ m_shaders.erase(shaderName); } } void Graphics::bindShader(std::string shaderName){ m_shaders.at(shaderName)->bind(); m_active_shader = m_shaders.at(shaderName); } GLuint Graphics::getShaderID(std::string shaderName){ return m_shaders.at(shaderName)->getHandle(); } std::shared_ptr Graphics::addShape(std::string shapeName, std::vector data, VAOAttrib attribs){ m_shapes.insert({shapeName, std::make_shared(std::make_shared(std::make_shared(data), attribs))}); return m_shapes.at(shapeName); } std::vector Graphics::addShape(std::string shapeName, std::string filepath, bool hasUV){ tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn, err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { throw std::runtime_error(warn + err); } int numTriangles = 0; for(size_t s = 0; s < shapes.size(); s++){ numTriangles += shapes[s].mesh.num_face_vertices.size(); } std::vector drawData; drawData.resize(numTriangles * 3 * 8); std::vector collisionData; collisionData.resize(numTriangles * 3); int i = 0; int j = 0; for(size_t s = 0; s < shapes.size(); s++) { size_t index_offset = 0; for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { unsigned int fv = shapes[s].mesh.num_face_vertices[f]; for(size_t v = 0; v < fv; v++) { tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; // Add position drawData[i] = attrib.vertices[3*idx.vertex_index]; drawData[i + 1] = attrib.vertices[3*idx.vertex_index + 1]; drawData[i + 2] = attrib.vertices[3*idx.vertex_index + 2]; // Add normal drawData[i + 3] = attrib.normals[3*idx.normal_index]; drawData[i + 4] = attrib.normals[3*idx.normal_index + 1]; drawData[i + 5] = attrib.normals[3*idx.normal_index + 2]; // Add uv drawData[i + 6] = 0; drawData[i + 7] = 0; if(hasUV){ drawData[i + 6] = attrib.texcoords[2*idx.texcoord_index]; drawData[i + 7] = attrib.texcoords[2*idx.texcoord_index + 1]; } // Add collision position data collisionData[j] = glm::vec3(attrib.vertices[3*idx.vertex_index], attrib.vertices[3*idx.vertex_index + 1], attrib.vertices[3*idx.vertex_index + 2]); i += 8; j += 1; } index_offset += fv; } } m_shapes.insert({shapeName, std::make_shared(std::make_shared(std::make_shared(drawData), VAOAttrib::POS | VAOAttrib::NORM | VAOAttrib::UV))}); std::cout << "coliision data size normal: " << collisionData.size() << std::endl; return collisionData; } std::vector Graphics::addShape_manual(std::string shapeName, const std::vector &verts, const std::vector &faces, bool hasUV){ std::pair, std::shared_ptr> info = makeVAOFromData(verts, faces, hasUV); m_shapes.insert({shapeName, std::make_shared(info.second)}); std::cout << "ADD SHAPE MANUAL" << std::endl; return info.first; } std::pair, std::shared_ptr> Graphics::makeVAOFromData(const std::vector &verts, const std::vector &faces, bool hasUV, bool needsCollisionData){ std::vector drawData; drawData.resize(faces.size() * 3 * 8); std::vector collisionData; collisionData.resize(faces.size() * 3); int i = 0; int j = 0; float uv = 0; size_t index_offset = 0; for(size_t f = 0; f < faces.size(); f++) { Eigen::Vector3i face = faces[f]; Eigen::Vector3f faceNormal = getFaceNormal(verts, face); for(int v = 0; v < 3; v++) { int idx = face[v]; Eigen::Vector3f vertexPos = verts[idx]; // Add position drawData[i] = vertexPos[0]; drawData[i + 1] = vertexPos[1]; drawData[i + 2] = vertexPos[2]; // Add normal drawData[i + 3] = 0.f; drawData[i + 4] = 1.f; drawData[i + 5] = 0.f; // Add uv drawData[i + 6] = 0; drawData[i + 7] = 0; if(hasUV){ drawData[i + 6] = uv; drawData[i + 7] = uv; uv += .01; } if (needsCollisionData){ // Add collision position data collisionData[j] = glm::vec3(vertexPos[0], vertexPos[1], vertexPos[2]); } i += 8; j += 1; } } std::shared_ptr vao = std::make_shared(std::make_shared(drawData), VAOAttrib::POS | VAOAttrib::NORM | VAOAttrib::UV); return std::make_pair(collisionData, vao); } Eigen::Vector3f Graphics::getFaceNormal(const std::vector &verts, const Eigen::Vector3i& face) { Eigen::Vector3f v1 = verts[face[0]]; Eigen::Vector3f v2 = verts[face[1]]; Eigen::Vector3f v3 = verts[face[2]]; Eigen::Vector3f e1 = v2 - v1; Eigen::Vector3f e2 = v3 - v1; Eigen::Vector3f n = e1.cross(e2); return n.normalized(); } // MATERIALSS std::vector Graphics::addShape_withMaterial(std::string shapeName, std::string filepath, std::string mtl_file, bool hasUV){ tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn, err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str(), mtl_file.c_str())) { throw std::runtime_error(warn + err); } int numTriangles = 0; for(size_t s = 0; s < shapes.size(); s++){ numTriangles += shapes[s].mesh.num_face_vertices.size(); } std::cout << "materials size: " << materials.size() << std::endl; for (auto m : materials){ std::cout << "material: " << m.name << std::endl; } std::vector shape_names; std::vector collisionData; std::cout << "---- NUM Triangles: " << numTriangles * 3 << std::endl; collisionData.resize(numTriangles * 3); int j = 0; for(size_t s = 0; s < shapes.size(); s++) { int i = 0; bool hasMaterial = true; std::shared_ptr shape_material; std::vector drawData; drawData.resize(shapes[s].mesh.num_face_vertices.size() * 3 * 8); size_t index_offset = 0; int shape_material_id = shapes[s].mesh.material_ids[0]; if (shape_material_id < 0) hasMaterial = false; if (hasMaterial){ std::string shape_material_name = materials[shape_material_id].name; //std::cout << "load: " << shape_material_name << std::endl; std::string shape_material_path = "/Users/jesswan/Desktop/cs1950u/cs1950u-jjesswan/Resources/Images/" + shape_material_name + ".png"; shape_material = addMaterial(shape_material_name, shape_material_path, 1.f); } // std::cout << "shape name:" << shapes[s].name << std::endl; // std::cout << "mesh material id sample:" << shapes[s].mesh.material_ids[0] << std::endl; // std::cout << "mesh material id sample2:" << shapes[s].mesh.material_ids[5] << std::endl; // std::cout << "mesh material id size:" << shapes[s].mesh.material_ids.size() << std::endl; // std::cout << "num faces:" << shapes[s].mesh.num_face_vertices.size() << std::endl; for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { unsigned int fv = shapes[s].mesh.num_face_vertices[f]; for(size_t v = 0; v < fv; v++) { tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; // Add position drawData[i] = attrib.vertices[3*idx.vertex_index]; drawData[i + 1] = attrib.vertices[3*idx.vertex_index + 1]; drawData[i + 2] = attrib.vertices[3*idx.vertex_index + 2]; // Add normal drawData[i + 3] = attrib.normals[3*idx.normal_index]; drawData[i + 4] = attrib.normals[3*idx.normal_index + 1]; drawData[i + 5] = attrib.normals[3*idx.normal_index + 2]; // Add uv drawData[i + 6] = 0; drawData[i + 7] = 0; if(hasUV){ drawData[i + 6] = attrib.texcoords[2*idx.texcoord_index]; drawData[i + 7] = attrib.texcoords[2*idx.texcoord_index + 1]; } // Add collision position data collisionData[j] = glm::vec3(attrib.vertices[3*idx.vertex_index], attrib.vertices[3*idx.vertex_index + 1], attrib.vertices[3*idx.vertex_index + 2]); i += 8; j += 1; } index_offset += fv; } if (hasMaterial){ m_shapes.insert({shapeName + std::to_string(s), std::make_shared(std::make_shared(std::make_shared(drawData), VAOAttrib::POS | VAOAttrib::NORM | VAOAttrib::UV), shape_material)}); } else { m_shapes.insert({shapeName + std::to_string(s), std::make_shared(std::make_shared(std::make_shared(drawData), VAOAttrib::POS | VAOAttrib::NORM | VAOAttrib::UV))}); } shape_names.push_back(shapeName + std::to_string(s)); } std::cout << "DONE LOADING MTL" << std::endl; m_shape_groups.insert({shapeName, shape_names}); std::cout << "collision data size: " << collisionData.size() << std::endl; return collisionData; } std::pair, std::vector> Graphics::getNavmeshData(std::string filepath){ tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn, err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { throw std::runtime_error(warn + err); } int numTriangles = 0; for(size_t s = 0; s < shapes.size(); s++){ numTriangles += shapes[s].mesh.num_face_vertices.size(); } std::vector positions; std::vector faces; for(int i = 0; i Graphics::getShape(std::string shapeName){ return m_shapes.at(shapeName); } std::vector> Graphics::getShapeGroup(std::string shapeName){ std::vector shape_ids = m_shape_groups.at(shapeName); std::vector> all_shapes; for (std::string id : shape_ids){ all_shapes.push_back(m_shapes.at(id)); } return all_shapes; } void Graphics::drawShape(std::shared_ptr myShape, std::shared_ptr modelTransform, std::shared_ptr material){ if(material == nullptr){ m_active_shader->setMaterial(getMaterial("default")); } else{ m_active_shader->setMaterial(material); } m_active_shader->setModelTransform(modelTransform); myShape->draw(); } void Graphics::drawShape(std::shared_ptr myShape, glm::mat4 modelMatrix, std::shared_ptr material){ if(material == nullptr){ m_active_shader->setMaterial(getMaterial("default")); } else{ m_active_shader->setMaterial(material); } m_active_shader->setModelTransform(modelMatrix); myShape->draw(); } std::vector Graphics::getObjData(std::string filepath){ tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn, err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { throw std::runtime_error(warn + err); } std::vector faces; std::vector vertices; for(size_t s = 0; s < shapes.size(); s++) { size_t index_offset = 0; for(size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) { unsigned int fv = shapes[s].mesh.num_face_vertices[f]; glm::vec3 face; for(size_t v = 0; v < fv; v++) { tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v]; face[v] = idx.vertex_index; } faces.push_back(face); index_offset += fv; } } for (size_t i = 0; i < attrib.vertices.size(); i += 3) { vertices.emplace_back(attrib.vertices[i], attrib.vertices[i + 1], attrib.vertices[i + 2]); } std::vector data; data.resize(18 * faces.size()); for(int i = 0; i(faces[i].x)]; glm::vec3 v1 = vertices[static_cast(faces[i].y)]; glm::vec3 v2 = vertices[static_cast(faces[i].z)]; glm::vec3 normal = glm::normalize(glm::cross(v1 - v0, v2 - v0)); data[18*i] = v0.x; data[18*i+1] = v0.y; data[18*i+2] = v0.z; data[18*i+3] = normal.x; data[18*i+4] = normal.y; data[18*i+5] = normal.z; data[18*i+6] = v1.x; data[18*i+7] = v1.y; data[18*i+8] = v1.z; data[18*i+9] = normal.x; data[18*i+10] = normal.y; data[18*i+11] = normal.z; data[18*i+12] = v2.x; data[18*i+13] = v2.y; data[18*i+14] = v2.z; data[18*i+15] = normal.x; data[18*i+16] = normal.y; data[18*i+17] = normal.z; } return data; } std::shared_ptr Graphics::addMaterial(std::string materialName, glm::vec3 color, float shininess){ std::shared_ptr newMaterial = std::make_shared(color, shininess); m_materials.insert({materialName, newMaterial}); return m_materials.at(materialName); } std::shared_ptr Graphics::addMaterial(std::string materialName, float shininess){ std::shared_ptr newMaterial = std::make_shared(shininess); m_materials.insert({materialName, newMaterial}); return m_materials.at(materialName); } std::shared_ptr Graphics::addMaterial(std::string materialName, std::string filePath, float shininess){ std::shared_ptr newTexture = std::make_shared(filePath); std::shared_ptr newMaterial = std::make_shared(newTexture, shininess); m_materials.insert({materialName, newMaterial}); return m_materials.at(materialName); } void Graphics::removeMaterial(std::string materialName){ if(materialName != "default"){ m_materials.erase(materialName); } } std::shared_ptr Graphics::getMaterial(std::string materialName){ return m_materials.at(materialName); } std::shared_ptr Graphics::addFont(std::string fontName, std::string filepath){ std::shared_ptr newFont = std::make_shared(filepath); m_fonts.insert({fontName, newFont}); return m_fonts.at(fontName); } void Graphics::removeFont(std::string fontName){ m_fonts.erase(fontName); } std::shared_ptr Graphics::getFont(std::string fontName){ return m_fonts.at(fontName); } void Graphics::drawUIText(std::shared_ptr font, std::string text, glm::vec2 anchorPosition, AnchorPoint anchorPoint, float textBoxWidth, float fontSize, float lineSpacing, glm::vec3 textColor){ m_active_shader->setTextUniforms(m_windowSize.x, m_windowSize.y, textColor); m_textRenderer->renderUIText(font, text, anchorPosition, anchorPoint, textBoxWidth, fontSize, lineSpacing, textColor); } void Graphics::setGlobalData(glm::vec3 globalCoeffs){ m_active_shader->setGlobalCoeffs(globalCoeffs); } void Graphics::setLights(std::vector> lights){ m_active_shader->setLights(lights); } void Graphics::clearLights(){ m_active_shader->clearLights(); } void Graphics::setWindowSize(glm::ivec2 windowSize){ m_windowSize = windowSize; } glm::ivec2 Graphics::getWindowSize(){ return m_windowSize; } void Graphics::setFramebufferSize(glm::ivec2 framebufferSize){ m_framebufferSize = framebufferSize; glViewport(0, 0, m_framebufferSize.x, m_framebufferSize.y); } glm::ivec2 Graphics::getFramebufferSize(){ return m_framebufferSize; } // WATERRRR ////// void Graphics::setWaterHeight(float height){ m_water_height = height; } float Graphics::getWaterHeight(){ return m_water_height; } void Graphics::bindReflection(){ Debug::checkGLError(); bindFBO(reflectionFBO, REFLECTION_W, REFLECTION_H); Debug::checkGLError(); } void Graphics::bindRefraction(){ Debug::checkGLError(); bindFBO(refractionFBO, REFRACTION_W, REFRACTION_H); Debug::checkGLError(); } GLuint Graphics::getReflectionTexture(){ return reflectionTexture; } GLuint Graphics::getRefractionTexture(){ return refractionTexture; } GLuint Graphics::getReflectionRBO(){ return reflectionDepthBuffer; } GLuint Graphics::getRefractionDepth(){ return refractionDepthTexture; } void Graphics::initializeReflectionFBO(){ Debug::checkGLError(); reflectionFBO = createFBO(); Debug::checkGLError(); reflectionTexture = createTextureAttachment(REFLECTION_W, REFLECTION_H); Debug::checkGLError(); reflectionDepthBuffer = createDepthBuffer(REFLECTION_W, REFLECTION_H); Debug::checkGLError(); unbindFBO(); Debug::checkGLError(); } void Graphics::initializeRefractionFBO(){ Debug::checkGLError(); refractionFBO = createFBO(); Debug::checkGLError(); refractionTexture = createTextureAttachment(REFRACTION_W, REFRACTION_H); Debug::checkGLError(); // glDrawBuffer(GL_NONE); refractionDepthTexture = createDepthTextureAttachment(REFRACTION_W, REFRACTION_H); Debug::checkGLError(); unbindFBO(); Debug::checkGLError(); } void Graphics::bindFBO(GLuint fbo, int width, int height){ // make sure texture isnt already bound Debug::checkGLError(); glBindTexture(GL_TEXTURE_2D, 0); Debug::checkGLError(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); Debug::checkGLError(); glViewport(0, 0, width, height); Debug::checkGLError(); auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (fboStatus != GL_FRAMEBUFFER_COMPLETE){ std::cout << "Framebuffer not complete: " << fboStatus << std::endl; } Debug::checkGLError(); } void Graphics::unbindFBO(){ Debug::checkGLError(); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, m_framebufferSize.x, m_framebufferSize.y); } GLuint Graphics::createFBO(){ GLuint fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_COLOR_ATTACHMENT0); return fbo; } GLuint Graphics::createTextureAttachment(int width, int height){ GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // adds texture attachement to currently bound fbo std::cout << "Color buffer: " << texture << std::endl; //glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); return texture; } GLuint Graphics::createDepthTextureAttachment(int width, int height){ GLuint texture; glBindTexture(GL_TEXTURE_2D, 0); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); Debug::checkGLError(); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); Debug::checkGLError(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); std::cout << "Depth texture: " << texture << std::endl; Debug::checkGLError(); glBindTexture(GL_TEXTURE_2D, 0); Debug::checkGLError(); // adds texture attachement to currently bound fbo glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0); Debug::checkGLError(); return texture; } GLuint Graphics::createDepthBuffer(int width, int height){ GLuint depthBuffer; glGenRenderbuffers(1, &depthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); std::cout << "Depth buffer: " << depthBuffer << std::endl; glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer); return depthBuffer; } void Graphics::deleteFBOS(){ glDeleteFramebuffers(1, &reflectionFBO); glDeleteFramebuffers(1, &refractionFBO); glDeleteTextures(1, &reflectionTexture); glDeleteTextures(1, &refractionTexture); glDeleteTextures(1, &refractionDepthTexture); glDeleteRenderbuffers(1, &reflectionDepthBuffer); }