X-Git-Url: https://git.lukelau.me/?a=blobdiff_plain;ds=sidebyside;f=skybox.cpp;h=45ab4eacaa8ecf31d5ce50e92470d04d92186fbe;hb=a03f2bc751bbd7f91cbc2f52d2f0f6e753d6f776;hp=bd097cb473dc85f92189a354325de78f6b4c4ba5;hpb=c44e69ec78367fb2957324026894aef970f2481a;p=opengl.git diff --git a/skybox.cpp b/skybox.cpp index bd097cb..45ab4ea 100644 --- a/skybox.cpp +++ b/skybox.cpp @@ -1,27 +1,44 @@ #include "shapes.hpp" #include "skybox.hpp" -#include "image.hpp" -#include #include -Skybox::Skybox(const std::vector faces): program("skyboxvert.glsl", "skyboxfrag.glsl") { - glUseProgram(program.progId); - glGenTextures(1, &texId); - glBindTexture(GL_TEXTURE_CUBE_MAP, texId); +Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") { + Program equiProg("equirectangularvert.glsl", "equirectangularfrag.glsl"); + glUseProgram(equiProg.progId); - int width, height, numChans; - for (int i = 0; i < faces.size(); i++) { - Image img(faces[i]); + GLuint equiTexId; + glGenTextures(1, &equiTexId); + glBindTexture(GL_TEXTURE_2D, equiTexId); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data()); - } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_SHORT, (unsigned short*)img.data()); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // generate framebuffers to store cubemap in + GLuint captureFBO, captureRBO; + glGenFramebuffers(1, &captureFBO); + glGenRenderbuffers(1, &captureRBO); + + glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureFBO); + + // generate and setup cubemap texture + glGenTextures(1, &texId); + glBindTexture(GL_TEXTURE_CUBE_MAP, texId); + for (GLuint i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr); 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); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // generate cube to render glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -36,27 +53,60 @@ Skybox::Skybox(const std::vector faces): program("skyboxvert.glsl", GLuint posLoc = glGetAttribLocation(program.progId, "pos"); glEnableVertexAttribArray(posLoc); glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); + + // render the cube + glm::mat4 captureProj = glm::perspective(glm::radians(90.f), 1.f, 0.1f, 10.f); + glm::mat4 captureViews[] = { + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 1, 0, 0), glm::vec3(0, -1, 0)), + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(-1, 0, 0), glm::vec3(0, -1, 0)), + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 1, 0), glm::vec3(0, 0, 1)), + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, -1, 0), glm::vec3(0, 0, -1)), + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 0, 1), glm::vec3(0, -1, 0)), + glm::lookAt(glm::vec3(0, 0, 0), glm::vec3( 0, 0, -1), glm::vec3(0, -1, 0)) + }; + + glUniform1i(glGetUniformLocation(equiProg.progId, "equirectangularMap"), 0); + glUniformMatrix4fv(glGetUniformLocation(equiProg.progId, "projection"), 1, GL_FALSE, glm::value_ptr(captureProj)); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, equiTexId); + + glViewport(0, 0, 512, 512); + glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + for (GLuint i = 0; i < 6; i++) { + glUniformMatrix4fv(glGetUniformLocation(equiProg.progId, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, texId, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDrawArrays(GL_TRIANGLES, 0, 36); } -void validatePrograms(GLuint progId) { - glValidateProgram(progId); - - GLint success; - glGetProgramiv(progId, GL_VALIDATE_STATUS, &success); - if (!success) { - GLchar log[1024]; - glGetProgramInfoLog(progId, sizeof(log), NULL, log); - fprintf(stderr, "error: %s\n", log); - exit(1); - } + + + // switch back to regular skybox shader + glUseProgram(program.progId); + glDepthFunc(GL_LEQUAL); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &vbo); + + // reverse so facing inside out + std::reverse(vertices.begin(), vertices.end()); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); + + posLoc = glGetAttribLocation(program.progId, "pos"); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); + + // restore default framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Skybox::draw(glm::mat4 proj, glm::mat4 view) const { glUseProgram(program.progId); - glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); glBindVertexArray(vao); - validatePrograms(program.progId); GLuint projLoc = glGetUniformLocation(program.progId, "projection"); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj)); @@ -65,8 +115,13 @@ void Skybox::draw(glm::mat4 proj, glm::mat4 view) const { view = glm::mat4(glm::mat3(view)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, texId); glDrawArrays(GL_TRIANGLES, 0, 36); - glEnable(GL_CULL_FACE); - glDepthMask(GL_TRUE); + + if (glGetError()) exit(1); +} + +GLuint Skybox::getTexture() const { + return texId; }