X-Git-Url: https://git.lukelau.me/?p=opengl.git;a=blobdiff_plain;f=skybox.cpp;h=ab492ca9a330129a660421999ef7a330fe2c360b;hp=45ab4eacaa8ecf31d5ce50e92470d04d92186fbe;hb=9e43c799021b7bcca324b988aae44e98b05d10b4;hpb=a03f2bc751bbd7f91cbc2f52d2f0f6e753d6f776 diff --git a/skybox.cpp b/skybox.cpp index 45ab4ea..ab492ca 100644 --- a/skybox.cpp +++ b/skybox.cpp @@ -2,13 +2,17 @@ #include "skybox.hpp" #include +GLuint setupCubeVertices(GLuint progId, bool reverse = false); + Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") { - Program equiProg("equirectangularvert.glsl", "equirectangularfrag.glsl"); + Program equiProg("skyboxvert.glsl", "equirectangularfrag.glsl"); glUseProgram(equiProg.progId); - GLuint equiTexId; - glGenTextures(1, &equiTexId); - glBindTexture(GL_TEXTURE_2D, equiTexId); + GLuint allTexIds[3]; + glGenTextures(3, allTexIds); + hdrTexId = allTexIds[0], cubemapTexId = allTexIds[1], irradianceTexId = allTexIds[2]; + + glBindTexture(GL_TEXTURE_2D, hdrTexId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_SHORT, (unsigned short*)img.data()); @@ -27,9 +31,8 @@ Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") { 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); + // setup cubemap texture + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexId); 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); @@ -38,21 +41,8 @@ Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") { 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); - - GLuint vbo; - glGenBuffers(1, &vbo); - - 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); + // generate vertices + setupCubeVertices(equiProg.progId); // render the cube glm::mat4 captureProj = glm::perspective(glm::radians(90.f), 1.f, 0.1f, 10.f); @@ -68,36 +58,58 @@ Skybox::Skybox(const Image img): program("skyboxvert.glsl", "skyboxfrag.glsl") { 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); + glBindTexture(GL_TEXTURE_2D, hdrTexId); 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); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemapTexId, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 36); } + // setup irradiance map texture + glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceTexId); + for (GLuint i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, 32, 32, 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); - // switch back to regular skybox shader - glUseProgram(program.progId); - glDepthFunc(GL_LEQUAL); + // bind framebuffers for rendering irradiance map into + glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 32, 32); - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); + Program irradianceProg("skyboxvert.glsl", "irradiancefrag.glsl"); + glUseProgram(irradianceProg.progId); + glUniform1i(glGetUniformLocation(irradianceProg.progId, "environmentMap"), 0); + glUniformMatrix4fv(glGetUniformLocation(irradianceProg.progId, "projection"), 1, GL_FALSE, glm::value_ptr(captureProj)); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexId); - glGenBuffers(1, &vbo); + // generate vertices + setupCubeVertices(irradianceProg.progId); - // reverse so facing inside out - std::reverse(vertices.begin(), vertices.end()); + // render irradiance map + glViewport(0, 0, 32, 32); + glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + for (GLuint i = 0; i < 6; i++) { + glUniformMatrix4fv(glGetUniformLocation(irradianceProg.progId, "view"), 1, GL_FALSE, glm::value_ptr(captureViews[i])); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceTexId, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glDrawArrays(GL_TRIANGLES, 0, 36); + } - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); + // switch back to regular skybox shader + glUseProgram(program.progId); + glDepthFunc(GL_LEQUAL); - posLoc = glGetAttribLocation(program.progId, "pos"); - glEnableVertexAttribArray(posLoc); - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); + // reverse so facing inside out + vao = setupCubeVertices(program.progId, true); // restore default framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -116,12 +128,31 @@ void Skybox::draw(glm::mat4 proj, glm::mat4 view) const { glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, texId); + glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceTexId); glDrawArrays(GL_TRIANGLES, 0, 36); if (glGetError()) exit(1); } -GLuint Skybox::getTexture() const { - return texId; +GLuint setupCubeVertices(GLuint progId, bool reverse) { + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + GLuint vbo; + glGenBuffers(1, &vbo); + + auto vertices = cube(); + + if (reverse) + 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(progId, "pos"); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); + + return vao; }