X-Git-Url: http://git.lukelau.me/?p=opengl.git;a=blobdiff_plain;f=skybox.cpp;fp=skybox.cpp;h=45ab4eacaa8ecf31d5ce50e92470d04d92186fbe;hp=79ce9d022029cf121fc51c02f1cf05e67026382a;hb=a03f2bc751bbd7f91cbc2f52d2f0f6e753d6f776;hpb=210d1b08cec40845d849e89baea8a9cc96917f60 diff --git a/skybox.cpp b/skybox.cpp index 79ce9d0..45ab4ea 100644 --- a/skybox.cpp +++ b/skybox.cpp @@ -1,26 +1,44 @@ #include "shapes.hpp" #include "skybox.hpp" -#include "image.hpp" #include -Skybox::Skybox(const std::vector faces): program("skyboxvert.glsl", "skyboxfrag.glsl") { - glGenTextures(1, &texId); - glBindTexture(GL_TEXTURE_CUBE_MAP, texId); - glDepthFunc(GL_LEQUAL); +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); @@ -29,15 +47,60 @@ Skybox::Skybox(const std::vector faces): program("skyboxvert.glsl", auto vertices = cube(); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); + + 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); + } + + + // 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); - GLuint posLoc = glGetAttribLocation(program.progId, "pos"); + 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 { @@ -55,6 +118,8 @@ void Skybox::draw(glm::mat4 proj, glm::mat4 view) const { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, texId); glDrawArrays(GL_TRIANGLES, 0, 36); + + if (glGetError()) exit(1); } GLuint Skybox::getTexture() const {