improved environment mapping for specular IBL

This commit is contained in:
devZoGok
2021-11-27 14:27:34 +02:00
parent 5ca6e8b16f
commit 4b25859338
6 changed files with 80 additions and 32 deletions
+1
View File
@@ -17,6 +17,7 @@ namespace vb01{
inline Vector3 getUp(){return up;} inline Vector3 getUp(){return up;}
inline void setNearPlane(float near){this->nearPlane = near;} inline void setNearPlane(float near){this->nearPlane = near;}
inline void setFarPlane(float far){this->farPlane = far;} inline void setFarPlane(float far){this->farPlane = far;}
inline void setFov(float fov){this->fov = fov;}
inline float getFov(){return fov;} inline float getFov(){return fov;}
inline float getNearPlane(){return nearPlane;} inline float getNearPlane(){return nearPlane;}
inline float getFarPlane(){return farPlane;} inline float getFarPlane(){return farPlane;}
+55 -20
View File
@@ -64,11 +64,13 @@ namespace vb01{
environmentShader = new Shader(libPath + "environmentPreFilter"); environmentShader = new Shader(libPath + "environmentPreFilter");
brdfIntegrationShader = new Shader(libPath + "brdfIntegration"); brdfIntegrationShader = new Shader(libPath + "brdfIntegration");
environmentMap = new Texture(reflectionSize, false, 5); prefilterMap = new Texture(reflectionSize, false);
postfilterMap = new Texture(reflectionSize, false, 5);
brdfIntegrationMap = new Texture(reflectionSize, reflectionSize, false); brdfIntegrationMap = new Texture(reflectionSize, reflectionSize, false);
int width = reflectionSize; int width = reflectionSize;
initFramebuffer(preFilterFramebuffer, preFilterRenderbuffer, reflectionSize); initFramebuffer(preFilterFramebuffer, preFilterRenderbuffer, reflectionSize);
initFramebuffer(postFilterFramebuffer, postFilterRenderbuffer, reflectionSize);
initFramebuffer(brdfFramebuffer, brdfRenderbuffer, reflectionSize); initFramebuffer(brdfFramebuffer, brdfRenderbuffer, reflectionSize);
initMesh(); initMesh();
@@ -87,7 +89,7 @@ namespace vb01{
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "Mesh framebuffer not complete\n"; cout << "Mesh framebuffer not complete\n";
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, *Root::getSingleton()->getFBO());
} }
void Mesh::initMesh(){ void Mesh::initMesh(){
@@ -241,7 +243,7 @@ namespace vb01{
} }
} }
void Mesh::updatePrefilterMap(Vector3 pos){ void Mesh::updatePrefilterMap(Vector3 pos, mat4 &proj, vec3 dirs[6]){
/* /*
Node *rootNode = root->getRootNode(); Node *rootNode = root->getRootNode();
vector<Node*> descendants; vector<Node*> descendants;
@@ -274,23 +276,50 @@ namespace vb01{
} }
} }
*/ */
glBindFramebuffer(GL_FRAMEBUFFER, preFilterFramebuffer);
glViewport(0, 0, reflectionSize, reflectionSize);
Root *root = Root::getSingleton(); Root *root = Root::getSingleton();
Mesh *skybox = root->getSkybox(); Mesh *skybox = root->getSkybox();
Texture *skyboxTex = ((Material::TextureUniform*)skybox->getMaterial()->getUniform("skybox"))->value; Material *mat = skybox->getMaterial();
mat->update();
glBindFramebuffer(GL_FRAMEBUFFER, preFilterFramebuffer); Shader *shader = mat->getShader();
glBindRenderbuffer(GL_RENDERBUFFER, preFilterRenderbuffer); shader->setMat4(proj, "proj");
for(int i = 0; i < 6; i++){
vec3 upVec = (fabs(dirs[i].y) == 1 ? vec3(0, 0, -1) : vec3(0, 1, 0));
shader->setMat4(lookAt(vec3(0.0), dirs[i], upVec), "view");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, *prefilterMap->getTexture(), 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(skybox) {
glDepthMask(GL_FALSE);
glCullFace(GL_FRONT);
skybox->render();
glDepthMask(GL_TRUE);
glCullFace(GL_BACK);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, *root->getFBO());
glViewport(0, 0, root->getWidth(), root->getHeight());
}
void Mesh::updatePostfilterMap(mat4 &proj, vec3 dirs[6]){
glBindFramebuffer(GL_FRAMEBUFFER, postFilterFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, postFilterRenderbuffer);
skyboxTex->select();
environmentShader->use(); environmentShader->use();
environmentShader->setInt(0, "environmentMap");
mat4 proj = perspective(radians(90.f), 1.f, .1f, 100.f);
environmentShader->setMat4(proj, "proj"); environmentShader->setMat4(proj, "proj");
environmentShader->setMat4(mat4(1.f), "model"); environmentShader->setInt(0, "environmentMap");
int numMipmaps = environmentMap->getMipmapLevel(); prefilterMap->select(0);
vec3 dirs[]{vec3(1, 0, 0), vec3(-1, 0, 0), vec3(0, 1, 0), vec3(0, -1, 0), vec3(0, 0, 1), vec3(0, 0, -1)};
Root *root = Root::getSingleton();
int numMipmaps = postfilterMap->getMipmapLevel();
for(int i = 0; i < numMipmaps; ++i){ for(int i = 0; i < numMipmaps; ++i){
u32 width = reflectionSize * pow(0.5, i); u32 width = reflectionSize * pow(0.5, i);
@@ -300,15 +329,17 @@ namespace vb01{
environmentShader->setFloat((float)i / numMipmaps, "roughness"); environmentShader->setFloat((float)i / numMipmaps, "roughness");
for(int j = 0; j < 6; j++){ for(int j = 0; j < 6; j++){
vec3 v = vec3(pos.x, pos.y, pos.z);
vec3 upVec = (fabs(dirs[j].y) == 1 ? vec3(0, 0, -1) : vec3(0, 1, 0)); vec3 upVec = (fabs(dirs[j].y) == 1 ? vec3(0, 0, -1) : vec3(0, 1, 0));
environmentShader->setMat4(lookAt(v, v + dirs[j], upVec), "view"); environmentShader->setMat4(lookAt(vec3(0.0), dirs[j], upVec), "view");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, *environmentMap->getTexture(), i); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, *postfilterMap->getTexture(), i);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(skybox) glDepthMask(GL_FALSE);
skybox->render(); glCullFace(GL_FRONT);
root->getPostfilterBox()->render();
glDepthMask(GL_TRUE);
glCullFace(GL_BACK);
} }
} }
@@ -336,7 +367,11 @@ namespace vb01{
} }
void Mesh::updateReflection(Vector3 pos){ void Mesh::updateReflection(Vector3 pos){
updatePrefilterMap(pos); vec3 dirs[]{ vec3(1, 0, 0), vec3(-1, 0, 0), vec3(0, 1, 0), vec3(0, -1, 0), vec3(0, 0, 1), vec3(0, 0, -1) };
mat4 proj = perspective(radians(90.f), 1.0f, 0.1f, 100.0f);
updatePrefilterMap(pos, proj, dirs);
updatePostfilterMap(proj, dirs);
updateBrdfLut(); updateBrdfLut();
Shader *shader = material->getShader(); Shader *shader = material->getShader();
@@ -347,7 +382,7 @@ namespace vb01{
shader->setInt(preFilterId, "preFilterMap"); shader->setInt(preFilterId, "preFilterMap");
shader->setInt(brdfId, "brdfIntegrationMap"); shader->setInt(brdfId, "brdfIntegrationMap");
environmentMap->select(preFilterId); postfilterMap->select(preFilterId);
brdfIntegrationMap->select(brdfId); brdfIntegrationMap->select(brdfId);
} }
+6 -4
View File
@@ -57,21 +57,23 @@ namespace vb01{
inline u32* getIndices(){return indices;} inline u32* getIndices(){return indices;}
inline ShapeKey& getShapeKey(int i){return shapeKeys[i];} inline ShapeKey& getShapeKey(int i){return shapeKeys[i];}
inline int getNumShapeKeys(){return numShapeKeys;} inline int getNumShapeKeys(){return numShapeKeys;}
inline Texture* getEnvironmentMap(){return environmentMap;} inline Texture* getPrefilterMap(){return prefilterMap;}
inline Texture* getPostfilterMap(){return postfilterMap;}
inline Texture* getBrdfIntegrationMap(){return brdfIntegrationMap;} inline Texture* getBrdfIntegrationMap(){return brdfIntegrationMap;}
private: private:
void initMesh(); void initMesh();
void initFramebuffer(u32&, u32&, int); void initFramebuffer(u32&, u32&, int);
void updateSkeleton(Shader*); void updateSkeleton(Shader*);
void updatePrefilterMap(Vector3); void updatePrefilterMap(Vector3, glm::mat4&, glm::vec3[6]);
void updatePostfilterMap(glm::mat4&, glm::vec3[6]);
void updateBrdfLut(); void updateBrdfLut();
void updateReflection(Vector3); void updateReflection(Vector3);
void updateShapeKeys(Shader*); void updateShapeKeys(Shader*);
int reflectionSize = 512; int reflectionSize = 512;
Texture *environmentMap = nullptr, *brdfIntegrationMap = nullptr; Texture *prefilterMap = nullptr, *postfilterMap = nullptr, *brdfIntegrationMap = nullptr;
Shader *environmentShader = nullptr, *brdfIntegrationShader = nullptr; Shader *environmentShader = nullptr, *brdfIntegrationShader = nullptr;
u32 preFilterFramebuffer, preFilterRenderbuffer, brdfFramebuffer, brdfRenderbuffer; u32 preFilterFramebuffer, preFilterRenderbuffer, postFilterFramebuffer, postFilterRenderbuffer, brdfFramebuffer, brdfRenderbuffer;
Material *material = nullptr; Material *material = nullptr;
Node *node = nullptr; Node *node = nullptr;
std::vector<Mesh*> meshes; std::vector<Mesh*> meshes;
+11 -3
View File
@@ -8,6 +8,7 @@
#include "glad.h" #include "glad.h"
#include <glfw3.h> #include <glfw3.h>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
@@ -46,6 +47,7 @@ namespace vb01{
initWindow(name); initWindow(name);
brdfLutPlane = new Quad(Vector3::VEC_IJK); brdfLutPlane = new Quad(Vector3::VEC_IJK);
postfilterBox = new Box(Vector3::VEC_IJK);
Texture *fragTexture = new Texture(width, height, false); Texture *fragTexture = new Texture(width, height, false);
Texture *brightTexture = new Texture(width, height, false); Texture *brightTexture = new Texture(width, height, false);
@@ -57,19 +59,25 @@ namespace vb01{
void Root::initWindow(string name){ void Root::initWindow(string name){
glfwSetErrorCallback(error_callback); glfwSetErrorCallback(error_callback);
if (GL_TRUE != glfwInit()) if (GL_TRUE != glfwInit())
std::cerr << "Error initialising glfw" << std::endl; std::cerr << "Error initialising glfw" << std::endl;
window = glfwCreateWindow(width, height, name.c_str(), NULL, NULL); window = glfwCreateWindow(width, height, name.c_str(), NULL, NULL);
if(window == NULL){ if(window == NULL){
cout << "Failed to load window...\n"; cout << "Failed to load window...\n";
exit(-1); exit(-1);
} }
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, foo); glfwSetFramebufferSizeCallback(window, foo);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
cout << "Failed to load GLAD.\n"; cout << "Failed to load GLAD.\n";
exit(-1); exit(-1);
} }
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@@ -92,8 +100,8 @@ namespace vb01{
glGenRenderbuffers(1, &RBO); glGenRenderbuffers(1, &RBO);
glBindRenderbuffer(GL_RENDERBUFFER, RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, RBO);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "Not complete\n"; cout << "Not complete\n";
@@ -199,7 +207,7 @@ namespace vb01{
skybox = new Box(Vector3(1, 1, 1) * 10); skybox = new Box(Vector3(1, 1, 1) * 10);
Material *skyboxMat = new Material(libPath + "skybox"); Material *skyboxMat = new Material(libPath + "skybox");
Texture *texture = new Texture(paths, 6, true); Texture *texture = new Texture(paths, 6, true);
skyboxMat->addTexUniform("skybox", texture, true); skyboxMat->addTexUniform("tex", texture, true);
skybox->setMaterial(skyboxMat); skybox->setMaterial(skyboxMat);
} }
+4 -2
View File
@@ -28,7 +28,8 @@ namespace vb01{
inline Node* getGuiNode(){return guiNode;} inline Node* getGuiNode(){return guiNode;}
inline int getWidth(){return width;} inline int getWidth(){return width;}
inline int getHeight(){return height;} inline int getHeight(){return height;}
inline unsigned int* getFBO(){return &FBO;} inline u32* getFBO(){return &FBO;}
inline u32* getRBO(){return &RBO;}
inline GLFWwindow* getWindow(){return window;} inline GLFWwindow* getWindow(){return window;}
inline void setHDREnabled(bool hdr){this->hdr = hdr;} inline void setHDREnabled(bool hdr){this->hdr = hdr;}
inline void setExposure(float exposure){this->exposure = exposure;} inline void setExposure(float exposure){this->exposure = exposure;}
@@ -36,6 +37,7 @@ namespace vb01{
inline void setBloom(bool bloom){this->bloom = bloom;} inline void setBloom(bool bloom){this->bloom = bloom;}
inline void setBlurLevel(bool level){this->blurLevel = level;} inline void setBlurLevel(bool level){this->blurLevel = level;}
inline Box* getSkybox(){return skybox;} inline Box* getSkybox(){return skybox;}
inline Box* getPostfilterBox(){return postfilterBox;}
inline Quad* getBrdfLutPlane(){return brdfLutPlane;} inline Quad* getBrdfLutPlane(){return brdfLutPlane;}
void createSkybox(std::string[6]); void createSkybox(std::string[6]);
void removeSkybox(); void removeSkybox();
@@ -47,7 +49,7 @@ namespace vb01{
int numLights = 0; int numLights = 0;
bool bloom = false, hdr = false; bool bloom = false, hdr = false;
float exposure = 1, gamma = 1; float exposure = 1, gamma = 1;
Box *skybox = nullptr; Box *skybox = nullptr, *postfilterBox = nullptr;
Quad *guiPlane = nullptr, *brdfLutPlane = nullptr; Quad *guiPlane = nullptr, *brdfLutPlane = nullptr;
int width, height, blurLevel = 10; int width, height, blurLevel = 10;
u32 FBO, RBO, pingpongBuffers[2]; u32 FBO, RBO, pingpongBuffers[2];
+3 -3
View File
@@ -41,7 +41,6 @@ namespace vb01{
} }
Texture::Texture(string paths[], int numPaths, bool cubemap, int mipmapLevel, bool flip){ Texture::Texture(string paths[], int numPaths, bool cubemap, int mipmapLevel, bool flip){
this->numFrames = numPaths;
this->cubemap = cubemap; this->cubemap = cubemap;
this->paths = new string[numPaths]; this->paths = new string[numPaths];
@@ -53,6 +52,7 @@ namespace vb01{
createCubemap(false, flip, true); createCubemap(false, flip, true);
} }
else{ else{
this->numFrames = numPaths;
texture = new u32[numPaths]; texture = new u32[numPaths];
create2DTexture(flip); create2DTexture(flip);
} }
@@ -116,7 +116,7 @@ namespace vb01{
} }
} }
else else
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, width, 0, GL_RGB, GL_FLOAT, NULL); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_INT, NULL);
} }
else{ else{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, width, width, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, width, width, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
@@ -126,7 +126,7 @@ namespace vb01{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 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_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_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 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_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
} }