From bc118b0a20cd39d1792b8122a77dfce174d29e5e Mon Sep 17 00:00:00 2001 From: wuyize Date: Fri, 23 Feb 2024 23:43:22 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E7=BB=98=E5=88=B6=E9=83=A8?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ArchitectureColoredPainting.vcxproj | 4 + ...rchitectureColoredPainting.vcxproj.filters | 12 + .../res/Shaders/shadow_mapping.comp | 2 +- .../src/Renderer/Camera.cpp | 7 + .../src/Renderer/Camera.h | 2 + .../src/Renderer/Drawable.h | 13 +- .../src/Renderer/IblUtils.cpp | 243 ++++++------ .../src/Renderer/IblUtils.h | 18 +- .../src/Renderer/Light.h | 35 +- .../src/Renderer/Mesh.cpp | 29 +- .../src/Renderer/Mesh.h | 7 +- .../src/Renderer/Model.cpp | 46 +-- .../src/Renderer/Model.h | 17 +- .../src/Renderer/PaintingMesh.cpp | 29 +- .../src/Renderer/PaintingMesh.h | 7 +- .../src/Renderer/RenderPass.cpp | 261 +++++++++++++ .../src/Renderer/RenderPass.h | 132 +++++++ .../src/Renderer/RendererGLWidget.cpp | 353 ++---------------- .../src/Renderer/RendererGLWidget.h | 137 +++---- .../src/Renderer/Shader.cpp | 22 ++ .../src/Renderer/Shader.h | 15 + 21 files changed, 783 insertions(+), 608 deletions(-) create mode 100644 ArchitectureColoredPainting/src/Renderer/RenderPass.cpp create mode 100644 ArchitectureColoredPainting/src/Renderer/RenderPass.h create mode 100644 ArchitectureColoredPainting/src/Renderer/Shader.cpp create mode 100644 ArchitectureColoredPainting/src/Renderer/Shader.h diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 3f22455..013d882 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -171,6 +171,8 @@ + + @@ -265,6 +267,8 @@ + + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index 467cc18..7fad1bf 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -303,6 +303,12 @@ Source Files + + Source Files + + + Source Files + @@ -606,6 +612,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp index f65c5f6..95bd048 100644 --- a/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp +++ b/ArchitectureColoredPainting/res/Shaders/shadow_mapping.comp @@ -12,7 +12,7 @@ uniform samplerCube irradianceMap; uniform samplerCube prefilterMap; uniform sampler2D brdfLUT; -layout(rgba16f, binding = 1) uniform image2D gDirectLight; +//layout(rgba16f, binding = 1) uniform image2D gDirectLight; layout (std140, binding = 0) uniform LightSpaceMatrices { mat4 lightSpaceMatrices[16]; diff --git a/ArchitectureColoredPainting/src/Renderer/Camera.cpp b/ArchitectureColoredPainting/src/Renderer/Camera.cpp index 4875435..9514b41 100644 --- a/ArchitectureColoredPainting/src/Renderer/Camera.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Camera.cpp @@ -21,6 +21,13 @@ Camera::Camera(float posX, float posY, float posZ, float upX, float upY, float u updateCameraVectors(); } +QMatrix4x4 Camera::GetProjectionMatrix() +{ + QMatrix4x4 projection; + projection.perspective(Zoom, Ratio, NearPlane, FarPlane); + return projection; +} + // returns the view matrix calculated using Euler Angles and the LookAt Matrix QMatrix4x4 Camera::GetViewMatrix() { diff --git a/ArchitectureColoredPainting/src/Renderer/Camera.h b/ArchitectureColoredPainting/src/Renderer/Camera.h index cb29577..b8090cc 100644 --- a/ArchitectureColoredPainting/src/Renderer/Camera.h +++ b/ArchitectureColoredPainting/src/Renderer/Camera.h @@ -53,6 +53,8 @@ namespace Renderer // constructor with scalar values Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch); + QMatrix4x4 GetProjectionMatrix(); + // returns the view matrix calculated using Euler Angles and the LookAt Matrix QMatrix4x4 GetViewMatrix(); diff --git a/ArchitectureColoredPainting/src/Renderer/Drawable.h b/ArchitectureColoredPainting/src/Renderer/Drawable.h index 0e1f8ff..24f4802 100644 --- a/ArchitectureColoredPainting/src/Renderer/Drawable.h +++ b/ArchitectureColoredPainting/src/Renderer/Drawable.h @@ -1,10 +1,11 @@ #pragma once namespace Renderer { - class Drawable - { - public: - virtual void draw() = 0; - virtual void drawShadow() = 0; - }; + class Drawable + { + public: + virtual ~Drawable() = default; + virtual void draw(QOpenGLShaderProgram* shaderProgram) = 0; + virtual void drawShadow(QOpenGLShaderProgram* shadowProgram) = 0; + }; } diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp index d5d5a32..daed23d 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp @@ -1,3 +1,4 @@ +#include #include "IblUtils.h" #include #include @@ -9,7 +10,7 @@ #endif -void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc) +void Renderer::IblUtils::renderCube(GladGLContext* gl) { static GLuint cubeVAO = 0, cubeVBO = 0; // initialize (if necessary) @@ -59,39 +60,39 @@ void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc) -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left }; - glFunc->glGenVertexArrays(1, &cubeVAO); - glFunc->glGenBuffers(1, &cubeVBO); + gl->GenVertexArrays(1, &cubeVAO); + gl->GenBuffers(1, &cubeVBO); // fill buffer - glFunc->glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glFunc->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + gl->BindBuffer(GL_ARRAY_BUFFER, cubeVBO); + gl->BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // link vertex attributes - glFunc->glBindVertexArray(cubeVAO); - glFunc->glEnableVertexAttribArray(0); - glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); - glFunc->glEnableVertexAttribArray(1); - glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); - glFunc->glEnableVertexAttribArray(2); - glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); - glFunc->glBindBuffer(GL_ARRAY_BUFFER, 0); - glFunc->glBindVertexArray(0); + gl->BindVertexArray(cubeVAO); + gl->EnableVertexAttribArray(0); + gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + gl->EnableVertexAttribArray(1); + gl->VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + gl->EnableVertexAttribArray(2); + gl->VertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + gl->BindBuffer(GL_ARRAY_BUFFER, 0); + gl->BindVertexArray(0); } // render Cube - glFunc->glBindVertexArray(cubeVAO); - glFunc->glDrawArrays(GL_TRIANGLES, 0, 36); - glFunc->glBindVertexArray(0); + gl->BindVertexArray(cubeVAO); + gl->DrawArrays(GL_TRIANGLES, 0, 36); + gl->BindVertexArray(0); } -void Renderer::IblUtils::renderSphere(QOpenGLFunctions_4_5_Core* glFunc) +void Renderer::IblUtils::renderSphere(GladGLContext* gl) { static unsigned int sphereVAO = 0; static unsigned int indexCount; if (sphereVAO == 0) { - glFunc->glGenVertexArrays(1, &sphereVAO); + gl->GenVertexArrays(1, &sphereVAO); unsigned int vbo, ebo; - glFunc->glGenBuffers(1, &vbo); - glFunc->glGenBuffers(1, &ebo); + gl->GenBuffers(1, &vbo); + gl->GenBuffers(1, &ebo); std::vector positions; std::vector uv; @@ -158,35 +159,35 @@ void Renderer::IblUtils::renderSphere(QOpenGLFunctions_4_5_Core* glFunc) data.push_back(uv[i].y); } } - glFunc->glBindVertexArray(sphereVAO); - glFunc->glBindBuffer(GL_ARRAY_BUFFER, vbo); - glFunc->glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW); - glFunc->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glFunc->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); + gl->BindVertexArray(sphereVAO); + gl->BindBuffer(GL_ARRAY_BUFFER, vbo); + gl->BufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW); + gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + gl->BufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); unsigned int stride = (3 + 2 + 3) * sizeof(float); - glFunc->glEnableVertexAttribArray(0); - glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); - glFunc->glEnableVertexAttribArray(1); - glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); - glFunc->glEnableVertexAttribArray(2); - glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float))); + gl->EnableVertexAttribArray(0); + gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); + gl->EnableVertexAttribArray(1); + gl->VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float))); + gl->EnableVertexAttribArray(2); + gl->VertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float))); } - glFunc->glBindVertexArray(sphereVAO); - glFunc->glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); + gl->BindVertexArray(sphereVAO); + gl->DrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0); } -std::tuple Renderer::IblUtils::precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc) +std::tuple Renderer::IblUtils::precomputeCubemaps(GladGLContext* gl) { // pbr: setup framebuffer // ---------------------- unsigned int captureFBO; unsigned int captureRBO; - glFunc->glCreateFramebuffers(1, &captureFBO); - glFunc->glCreateRenderbuffers(1, &captureRBO); + gl->CreateFramebuffers(1, &captureFBO); + gl->CreateRenderbuffers(1, &captureRBO); - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); - glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); + gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO); + gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); // pbr: set up projection and view matrices for capturing data onto the 6 cubemap face directions // ---------------------------------------------------------------------------------------------- @@ -200,14 +201,14 @@ std::tuple Renderer::IblUtils::precomputeCubemap captureViews[4].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 0.0f, 1.0f), QVector3D(0.0f, -1.0f, 0.0f)); captureViews[5].lookAt(QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 0.0f, -1.0f), QVector3D(0.0f, -1.0f, 0.0f)); - GLuint envCubemap = generateCubemap(glFunc, captureFBO, captureRBO, captureProjection, captureViews); - GLuint irradianceMap = generateIrradianceMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap); - GLuint prefilterMap = generatePrefilterMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap); - GLuint brdfLut = gererateBrdfLut(glFunc); + GLuint envCubemap = generateCubemap(gl, captureFBO, captureRBO, captureProjection, captureViews); + GLuint irradianceMap = generateIrradianceMap(gl, captureFBO, captureRBO, captureProjection, captureViews, envCubemap); + GLuint prefilterMap = generatePrefilterMap(gl, captureFBO, captureRBO, captureProjection, captureViews, envCubemap); + GLuint brdfLut = gererateBrdfLut(gl); return { envCubemap, irradianceMap, prefilterMap, brdfLut }; } -GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews) +GLuint Renderer::IblUtils::generateCubemap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews) { // pbr: load the HDR environment map // --------------------------------- @@ -217,14 +218,14 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL unsigned int hdrTexture = 0; if (data) { - glFunc->glGenTextures(1, &hdrTexture); - glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture); - glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data); + gl->GenTextures(1, &hdrTexture); + gl->BindTexture(GL_TEXTURE_2D, hdrTexture); + gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_image_free(data); } @@ -234,17 +235,17 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL // pbr: setup cubemap to render to and attach to framebuffer // --------------------------------------------------------- unsigned int envCubemap; - glFunc->glGenTextures(1, &envCubemap); - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); + gl->GenTextures(1, &envCubemap); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); for (unsigned int i = 0; i < 6; ++i) { - glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, cubemapSize, cubemapSize, 0, GL_RGB, GL_FLOAT, nullptr); + gl->TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, cubemapSize, cubemapSize, 0, GL_RGB, GL_FLOAT, nullptr); } - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // enable pre-filter mipmap sampling (combatting visible dots artifact) - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // enable pre-filter mipmap sampling (combatting visible dots artifact) + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // pbr: convert HDR equirectangular environment map to cubemap equivalent @@ -259,52 +260,52 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL shader.bind(); shader.setUniformValue("equirectangularMap", 0); shader.setUniformValue("projection", captureProjection); - glFunc->glActiveTexture(GL_TEXTURE0); - glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture); + gl->ActiveTexture(GL_TEXTURE0); + gl->BindTexture(GL_TEXTURE_2D, hdrTexture); - glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); - glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize); - glFunc->glViewport(0, 0, cubemapSize, cubemapSize); - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO); + gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize); + gl->Viewport(0, 0, cubemapSize, cubemapSize); + gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { shader.setUniformValue("view", captureViews[i]); - glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); - glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0); + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - renderCube(glFunc); + renderCube(gl); } - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0); + gl->BindFramebuffer(GL_FRAMEBUFFER, 0); // then let OpenGL generate mipmaps from first mip face (combatting visible dots artifact) - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glFunc->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); + gl->GenerateMipmap(GL_TEXTURE_CUBE_MAP); return envCubemap; } -GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) +GLuint Renderer::IblUtils::generateIrradianceMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) { // pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale. // -------------------------------------------------------------------------------- unsigned int irradianceMap; - glFunc->glGenTextures(1, &irradianceMap); - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); + gl->GenTextures(1, &irradianceMap); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); for (unsigned int i = 0; i < 6; ++i) { - glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, irradianceMapSize, irradianceMapSize, 0, GL_RGB, GL_FLOAT, nullptr); + gl->TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, irradianceMapSize, irradianceMapSize, 0, GL_RGB, GL_FLOAT, nullptr); } - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); - glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); - glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, irradianceMapSize, irradianceMapSize); + gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO); + gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO); + gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, irradianceMapSize, irradianceMapSize); // pbr: solve diffuse integral by convolution to create an irradiance (cube)map. // ----------------------------------------------------------------------------- @@ -318,41 +319,41 @@ GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFu irradianceShader.bind(); irradianceShader.setUniformValue("environmentMap", 0); irradianceShader.setUniformValue("projection", captureProjection); - glFunc->glActiveTexture(GL_TEXTURE0); - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); + gl->ActiveTexture(GL_TEXTURE0); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glFunc->glViewport(0, 0, irradianceMapSize, irradianceMapSize); // don't forget to configure the viewport to the capture dimensions. - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + gl->Viewport(0, 0, irradianceMapSize, irradianceMapSize); // don't forget to configure the viewport to the capture dimensions. + gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO); for (unsigned int i = 0; i < 6; ++i) { irradianceShader.setUniformValue("view", captureViews[i]); - glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0); - glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0); + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - renderCube(glFunc); + renderCube(gl); } - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0); + gl->BindFramebuffer(GL_FRAMEBUFFER, 0); return irradianceMap; } -GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) +GLuint Renderer::IblUtils::generatePrefilterMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) { // pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale. // -------------------------------------------------------------------------------- unsigned int prefilterMap; - glFunc->glGenTextures(1, &prefilterMap); - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); + gl->GenTextures(1, &prefilterMap); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); for (unsigned int i = 0; i < 6; ++i) { - glFunc->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, prefilterMapSize, prefilterMapSize, 0, GL_RGB, GL_FLOAT, nullptr); + gl->TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, prefilterMapSize, prefilterMapSize, 0, GL_RGB, GL_FLOAT, nullptr); } - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // be sure to set minification filter to mip_linear - glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // be sure to set minification filter to mip_linear + gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // generate mipmaps for the cubemap so OpenGL automatically allocates the required memory. - glFunc->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + gl->GenerateMipmap(GL_TEXTURE_CUBE_MAP); // pbr: run a quasi monte-carlo simulation on the environment lighting to create a prefilter (cube)map. // ---------------------------------------------------------------------------------------------------- @@ -366,52 +367,52 @@ GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFun prefilterShader.bind(); prefilterShader.setUniformValue("environmentMap", 0); prefilterShader.setUniformValue("projection", captureProjection); - glFunc->glActiveTexture(GL_TEXTURE0); - glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); + gl->ActiveTexture(GL_TEXTURE0); + gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap); - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); + gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO); unsigned int maxMipLevels = 5; for (unsigned int mip = 0; mip < maxMipLevels; ++mip) { // reisze framebuffer according to mip-level size. unsigned int mipWidth = static_cast(prefilterMapSize * std::pow(0.5, mip)); unsigned int mipHeight = static_cast(prefilterMapSize * std::pow(0.5, mip)); - glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); - glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); - glFunc->glViewport(0, 0, mipWidth, mipHeight); + gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO); + gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); + gl->Viewport(0, 0, mipWidth, mipHeight); float roughness = (float)mip / (float)(maxMipLevels - 1); prefilterShader.setUniformValue("roughness", roughness); for (unsigned int i = 0; i < 6; ++i) { prefilterShader.setUniformValue("view", captureViews[i]); - glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilterMap, mip); + gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilterMap, mip); - glFunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - renderCube(glFunc); + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderCube(gl); } } - glFunc->glBindFramebuffer(GL_FRAMEBUFFER, 0); + gl->BindFramebuffer(GL_FRAMEBUFFER, 0); return prefilterMap; } -GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc) +GLuint Renderer::IblUtils::gererateBrdfLut(GladGLContext* gl) { constexpr int lutSize = 512; // pbr: generate a 2D LUT from the BRDF equations used. // ---------------------------------------------------- unsigned int brdfLUTTexture; - glFunc->glGenTextures(1, &brdfLUTTexture); + gl->GenTextures(1, &brdfLUTTexture); // pre-allocate enough memory for the LUT texture. - glFunc->glBindTexture(GL_TEXTURE_2D, brdfLUTTexture); - glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, lutSize, lutSize, 0, GL_RG, GL_FLOAT, 0); + gl->BindTexture(GL_TEXTURE_2D, brdfLUTTexture); + gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, lutSize, lutSize, 0, GL_RG, GL_FLOAT, 0); // be sure to set wrapping mode to GL_CLAMP_TO_EDGE - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); QOpenGLShaderProgram brdfShader; if (!brdfShader.addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/brdf_lut.comp")) @@ -419,8 +420,8 @@ GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc) if (!brdfShader.link()) qDebug() << "ERROR:" << brdfShader.log(); brdfShader.bind(); - glFunc->glBindImageTexture(0, brdfLUTTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG16F); - glFunc->glDispatchCompute(ceil(lutSize / 8.), ceil(lutSize / 8.), 1); + gl->BindImageTexture(0, brdfLUTTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG16F); + gl->DispatchCompute(ceil(lutSize / 8.), ceil(lutSize / 8.), 1); brdfShader.release(); return brdfLUTTexture; } diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.h b/ArchitectureColoredPainting/src/Renderer/IblUtils.h index 1f292fc..2db8ba9 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.h +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.h @@ -1,6 +1,6 @@ #pragma once #include - +struct GladGLContext; namespace Renderer { class IblUtils @@ -9,20 +9,20 @@ namespace Renderer static constexpr int cubemapSize = 1024; static constexpr int irradianceMapSize = 32; static constexpr int prefilterMapSize = 128; - static void renderCube(QOpenGLFunctions_4_5_Core* glFunc); - static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc); + static void renderCube(GladGLContext* gl); + static void renderSphere(GladGLContext* gl); /** - * @brief + * @brief * @return GLuint envCubemap * @return GLuint irradianceMap * @return GLuint prefilterMap * @return GLuint brdfLut */ - static std::tuple precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc); + static std::tuple precomputeCubemaps(GladGLContext* gl); private: - static GLuint generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews); - static GLuint generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap); - static GLuint generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap); - static GLuint gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc); + static GLuint generateCubemap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews); + static GLuint generateIrradianceMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap); + static GLuint generatePrefilterMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap); + static GLuint gererateBrdfLut(GladGLContext* gl); }; } diff --git a/ArchitectureColoredPainting/src/Renderer/Light.h b/ArchitectureColoredPainting/src/Renderer/Light.h index 679fc8b..e6f6db9 100644 --- a/ArchitectureColoredPainting/src/Renderer/Light.h +++ b/ArchitectureColoredPainting/src/Renderer/Light.h @@ -11,23 +11,24 @@ namespace Renderer { - class Light - { - public: - QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized(); - std::vector shadowCascadeLevels; - float blendRatio = 0.3; - std::vector frustumSizes; - Model* model = nullptr; - Light(Camera* camera); - void updateShadowCascadeLevels(); - std::vector getFrustumCornersWorldSpace(const QMatrix4x4& projview); - std::vector getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view); - QMatrix4x4 getLightSpaceMatrix(const float nearPlane, const float farPlane); - std::vector getLightSpaceMatrices(); - private: - Camera* camera; + class Light + { + public: + QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized(); + QVector3D radiance = QVector3D(0, 0, 0); + std::vector shadowCascadeLevels; + float blendRatio = 0.3; + std::vector frustumSizes; + Model* model = nullptr; + Light(Camera* camera); + void updateShadowCascadeLevels(); + std::vector getFrustumCornersWorldSpace(const QMatrix4x4& projview); + std::vector getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view); + QMatrix4x4 getLightSpaceMatrix(const float nearPlane, const float farPlane); + std::vector getLightSpaceMatrices(); + private: + Camera* camera; - }; + }; } diff --git a/ArchitectureColoredPainting/src/Renderer/Mesh.cpp b/ArchitectureColoredPainting/src/Renderer/Mesh.cpp index 59c0042..da1935a 100644 --- a/ArchitectureColoredPainting/src/Renderer/Mesh.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Mesh.cpp @@ -9,16 +9,14 @@ Renderer::Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, c { } -Mesh::Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model) +Mesh::Mesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model) : glFunc(glFunc) - , shaderProgram(shaderProgram) - , shadowProgram(shadowProgram) , VBO(QOpenGLBuffer::VertexBuffer) , EBO(QOpenGLBuffer::IndexBuffer) , model(model) { } -void Mesh::draw() +void Mesh::draw(QOpenGLShaderProgram* shaderProgram) { if (shaderProgram->bind()) { @@ -43,7 +41,7 @@ void Mesh::draw() shaderProgram->release(); } } -void Mesh::drawShadow() +void Mesh::drawShadow(QOpenGLShaderProgram* shadowProgram) { if (shadowProgram->bind()) { @@ -72,16 +70,17 @@ void Mesh::setupMesh() EBO.bind(); EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int)); - if (shaderProgram->bind()) - { - shaderProgram->enableAttributeArray(0); - shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(1); - shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(2); - shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex)); - shaderProgram->release(); - } + enum VertexAttribute : GLuint { + kPosition = 0, kNormal = 1, kTexCoords = 2 + }; + + glFunc->glEnableVertexAttribArray(kPosition); + glFunc->glVertexAttribPointer(kPosition, sizeof(Vertex::Position) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); + glFunc->glEnableVertexAttribArray(kNormal); + glFunc->glVertexAttribPointer(kNormal, sizeof(Vertex::Normal) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); + glFunc->glEnableVertexAttribArray(kTexCoords); + glFunc->glVertexAttribPointer(kTexCoords, sizeof(Vertex::TexCoords) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords)); + VAO.release(); } diff --git a/ArchitectureColoredPainting/src/Renderer/Mesh.h b/ArchitectureColoredPainting/src/Renderer/Mesh.h index 97d6243..879f112 100644 --- a/ArchitectureColoredPainting/src/Renderer/Mesh.h +++ b/ArchitectureColoredPainting/src/Renderer/Mesh.h @@ -48,11 +48,10 @@ namespace Renderer QMatrix4x4 model; QOpenGLFunctions_4_5_Core* glFunc; - QOpenGLShaderProgram* shaderProgram, * shadowProgram; - Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model); - void draw() override; - void drawShadow() override; + Mesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model); + void draw(QOpenGLShaderProgram* shaderProgram) override; + void drawShadow(QOpenGLShaderProgram* shadowProgram) override; void setupMesh(); private: diff --git a/ArchitectureColoredPainting/src/Renderer/Model.cpp b/ArchitectureColoredPainting/src/Renderer/Model.cpp index 97be668..dcd6996 100644 --- a/ArchitectureColoredPainting/src/Renderer/Model.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Model.cpp @@ -21,27 +21,28 @@ using namespace Renderer; using std::vector; -Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, - QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager) +Model::Model(QOpenGLContext* context, VirtualTextureManager* vtManager) : context(context) , glFunc(context->versionFunctions()) - , shaderProgram(shaderProgram) - , paintingProgram(paintingProgram) - , shadowProgram(shadowProgram) , vtManager(vtManager) { } -void Model::draw() { - for (auto& mesh : meshes) { - mesh->draw(); - } + +void Model::draw(QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram) +{ + for (auto& mesh : meshes) + mesh->draw(shaderProgram); + for (auto& mesh : paintingMeshes) + mesh->draw(paintingProgram); } -void Model::drawShadow() { - for (auto& mesh : meshes) { - mesh->drawShadow(); - } +void Model::drawShadow(QOpenGLShaderProgram* shadowProgram) +{ + for (auto& mesh : meshes) + mesh->drawShadow(shadowProgram); + for (auto& mesh : paintingMeshes) + mesh->drawShadow(shadowProgram); } void Renderer::Model::loadModel(QString path) @@ -121,19 +122,14 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4) { // 处理节点所有的网格(如果有的话) for (unsigned int i = 0; i < node->mNumMeshes; i++) - { - if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4)) - meshes.emplace_back(std::move(mesh)); + processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4); - } // 接下来对它的子节点重复这一过程 for (unsigned int i = 0; i < node->mNumChildren; i++) - { processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation); - } } -std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) +void Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) { QMatrix4x4 modelQ((float*)&model); @@ -157,7 +153,7 @@ std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, indices.insert(indices.end(), face->mIndices, face->mIndices + face->mNumIndices); if (vertices.empty() || indices.empty()) - return nullptr; + return; aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; @@ -165,11 +161,11 @@ std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, aiString str; material->GetTexture(aiTextureType_BASE_COLOR, 0, &str); return std::string(str.C_Str()); - }()); paintingProgram != nullptr && iter != paintingMap.end()) + }()); iter != paintingMap.end()) { qDebug() << iter->first.c_str() << "Replaced"; - auto mesh = std::make_unique(glFunc, paintingProgram, shadowProgram, modelQ); + auto& mesh = paintingMeshes.emplace_back(std::make_unique(glFunc, modelQ)); auto& [paintingPath, leftBottom, rightTop] = iter->second; auto [paintingId, ratio] = loadPainting(paintingPath); @@ -188,11 +184,10 @@ std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, mesh->indices = indices; mesh->setupMesh(); - return mesh; } else { - auto mesh = std::make_unique(glFunc, shaderProgram, shadowProgram, modelQ); + auto& mesh = meshes.emplace_back(std::make_unique(glFunc, modelQ)); mesh->vertices = vertices; mesh->indices = indices; @@ -214,7 +209,6 @@ std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, } mesh->setupMesh(); - return mesh; } } diff --git a/ArchitectureColoredPainting/src/Renderer/Model.h b/ArchitectureColoredPainting/src/Renderer/Model.h index 24eb8e1..22b69ad 100644 --- a/ArchitectureColoredPainting/src/Renderer/Model.h +++ b/ArchitectureColoredPainting/src/Renderer/Model.h @@ -4,15 +4,16 @@ #include "VirtualTextureManager.h" #include #include +#include "PaintingMesh.h" namespace Renderer { class Model { public: - Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager); - void draw(); - void drawShadow(); + Model(QOpenGLContext* context, VirtualTextureManager* vtManager); + void draw(QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram); + void drawShadow(QOpenGLShaderProgram* shadowProgram); void loadModel(QString path); void unloadModel(); const std::unordered_map>& getPaintingMap(); @@ -24,9 +25,6 @@ namespace Renderer private: QOpenGLContext* context = nullptr; QOpenGLFunctions_4_5_Core* glFunc = nullptr; - QOpenGLShaderProgram* shaderProgram = nullptr; - QOpenGLShaderProgram* paintingProgram = nullptr; - QOpenGLShaderProgram* shadowProgram = nullptr; VirtualTextureManager* vtManager = nullptr; /** @@ -36,17 +34,18 @@ namespace Renderer std::unordered_map> paintingMap; std::unordered_map> paintingLoaded; std::unordered_map texturesLoaded; - std::vector> meshes; + std::vector> meshes; + std::vector> paintingMeshes; QDir directory; /// 模型所在路径 QString name; /// 模型文件名 - + /// 递归遍历结点 void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4()); /// 加载网格 - std::unique_ptr processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); + void processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); /// 加载材质纹理 GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type); diff --git a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp index 98cc6d8..2982e15 100644 --- a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp +++ b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp @@ -1,15 +1,13 @@ #include "PaintingMesh.h" using namespace Renderer; -PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model) +PaintingMesh::PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model) : glFunc(glFunc) - , shaderProgram(shaderProgram) - , shadowProgram(shadowProgram) , VBO(QOpenGLBuffer::VertexBuffer) , EBO(QOpenGLBuffer::IndexBuffer) , model(model) { } -void PaintingMesh::draw() +void PaintingMesh::draw(QOpenGLShaderProgram* shaderProgram) { if (shaderProgram->bind()) { @@ -26,7 +24,7 @@ void PaintingMesh::draw() shaderProgram->release(); } } -void PaintingMesh::drawShadow() +void PaintingMesh::drawShadow(QOpenGLShaderProgram* shadowProgram) { if (shadowProgram->bind()) { @@ -54,16 +52,17 @@ void PaintingMesh::setupMesh() EBO.bind(); EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int)); - if (shaderProgram->bind()) - { - shaderProgram->enableAttributeArray(0); - shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(1); - shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex)); - shaderProgram->enableAttributeArray(2); - shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex)); - shaderProgram->release(); - } + enum VertexAttribute : GLuint { + kPosition = 0, kNormal = 1, kTexCoords = 2 + }; + + glFunc->glEnableVertexAttribArray(kPosition); + glFunc->glVertexAttribPointer(kPosition, sizeof(Vertex::Position) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); + glFunc->glEnableVertexAttribArray(kNormal); + glFunc->glVertexAttribPointer(kNormal, sizeof(Vertex::Normal) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); + glFunc->glEnableVertexAttribArray(kTexCoords); + glFunc->glVertexAttribPointer(kTexCoords, sizeof(Vertex::TexCoords) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords)); + VAO.release(); } diff --git a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h index 773a992..86c2201 100644 --- a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h +++ b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h @@ -24,12 +24,11 @@ namespace Renderer GLuint textureMetallicRoughness; QMatrix4x4 model; QOpenGLFunctions_4_5_Core* glFunc; - QOpenGLShaderProgram* shaderProgram, * shadowProgram; GLuint paintingId; - PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model); - void draw() override; - void drawShadow() override; + PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model); + void draw(QOpenGLShaderProgram* shaderProgram) override; + void drawShadow(QOpenGLShaderProgram* shadowProgram) override; void setupMesh(); private: diff --git a/ArchitectureColoredPainting/src/Renderer/RenderPass.cpp b/ArchitectureColoredPainting/src/Renderer/RenderPass.cpp new file mode 100644 index 0000000..e05760a --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/RenderPass.cpp @@ -0,0 +1,261 @@ +#include +#include "RenderPass.h" +#include "IblUtils.h" + +namespace Renderer +{ + ShadowMapPass::ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, Light& light, Model*& model) + : RenderPass(gl) + , modelShadowShader(":/Shaders/model_shadow.vert", ":/Shaders/model_shadow.frag", ":/Shaders/model_shadow.geom") + , shadowFboHandle(shadowFboHandle), shadowMapResolution(shadowMapResolution), light(light), model(model) + { + modelShadowShader.bind(); + gl->GenBuffers(1, &lightSpaceMatricesUBO); + gl->BindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO); + gl->BufferData(GL_UNIFORM_BUFFER, sizeof(QMatrix4x4) * 16, nullptr, GL_STATIC_DRAW); + gl->BindBufferBase(GL_UNIFORM_BUFFER, 0, lightSpaceMatricesUBO); + gl->BindBuffer(GL_UNIFORM_BUFFER, 0); + modelShadowShader.release(); + } + void ShadowMapPass::dispatch() + { + const std::vector lightMatrices = light.getLightSpaceMatrices(); + gl->BindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO); + for (size_t i = 0; i < lightMatrices.size(); i++) + { + gl->BufferSubData(GL_UNIFORM_BUFFER, i * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), lightMatrices[i].data()); + } + gl->BindBuffer(GL_UNIFORM_BUFFER, 0); + + gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); + gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution); + gl->Clear(GL_DEPTH_BUFFER_BIT); + //gl->CullFace(GL_FRONT); + if (model != nullptr) + model->drawShadow(&modelShadowShader); + //gl->CullFace(GL_BACK); + + gl->BindFramebuffer(GL_FRAMEBUFFER, 0); + } + + GeometryPass::GeometryPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, QOpenGLFramebufferObject*& fbo, Model*& model, QMatrix4x4& projection, QMatrix4x4& view) + : RenderPass(gl) + , modelShader(":/Shaders/model.vert", ":/Shaders/model.frag") + , paintingShader(":/Shaders/painting.vert", ":/Shaders/painting.frag") + , plainShader(":/Shaders/shader.vert", ":/Shaders/shader.frag") + , frameWidth(frameWidth) + , frameHeight(frameHeight) + , fbo(fbo) + , model(model) + , projection(projection) + , view(view) + { + } + void GeometryPass::dispatch() + { + if (fbo->bind()) + { + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl->Viewport(0, 0, frameWidth, frameHeight); + + modelShader.bind(); + modelShader.setUniformValue("projection", projection); + modelShader.setUniformValue("view", view); + modelShader.release(); + paintingShader.bind(); + paintingShader.setUniformValue("projection", projection); + paintingShader.setUniformValue("view", view); + paintingShader.release(); + if (model != nullptr) + model->draw(&modelShader, &paintingShader); + + /// Debug Lighting + if (false) + { + plainShader.bind(); + plainShader.setUniformValue("projection", projection); + plainShader.setUniformValue("view", view); + plainShader.setUniformValue("albedo", 0.5f, 0.5f, 0.5f); + QMatrix4x4 model; + int nrRows = 7, nrColumns = 7; + float spacing = 2.5; + for (int row = 0; row < nrRows; ++row) + { + plainShader.setUniformValue("metallic", (float)row / (float)nrRows); + for (int col = 0; col < nrColumns; ++col) + { + plainShader.setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); + + model.setToIdentity(); + model.scale(10); + model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing, + (float)(row - (nrRows / 2)) * spacing + 20, + -2.0f)); + plainShader.setUniformValue("model", model); + IblUtils::renderSphere(gl); + } + } + plainShader.release(); + } + + fbo->release(); + } + } + + PageIDCallbackPass::PageIDCallbackPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, QOpenGLFramebufferObject*& fbo, GLuint* gBuffers, GLuint& gPageID, VirtualTextureManager& vtManager) + : RenderPass(gl) + , pageIdDownsampleShader(":/Shaders/pageId_downsample.comp") + , frameWidth(frameWidth) + , frameHeight(frameHeight) + , fbo(fbo) + , gBuffers(gBuffers) + , gPageID(gPageID) + , vtManager(vtManager) + { + } + + void PageIDCallbackPass::dispatch() + { + if (fbo->bind()) + { + pageIdDownsampleShader.bind(); + gl->BindImageTexture(3, gPageID, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16UI); + gl->Uniform2ui(0, rand() % 8, rand() % 8); + gl->DispatchCompute(ceil(frameWidth / 8. / 8.), ceil(frameWidth / 8. / 8.), 1); + pageIdDownsampleShader.release(); + std::vector pixels; + pixels.resize(ceil(frameWidth / 8.) * ceil(frameHeight / 8.)); + //fboPtr->bind(); + gl->ReadBuffer(GL_COLOR_ATTACHMENT0 + (&gPageID - gBuffers)); + gl->ReadnPixels(0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); + //gl->GetTextureSubImage(gbuffers[4], 0, 0, 0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1, GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); + vtManager.tryUpdatePages(pixels); + fbo->release(); + } + } + + LightingPass::LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, QMatrix4x4& view, Camera& camera, Light& light, GLuint& gBaseColor, GLuint& gNormal, GLuint& gPosition, GLuint& gMetallicRoughness, GLuint& shadowGbuffer, GLuint& irradianceMap, GLuint& prefilterMap, GLuint& brdfLUTTexture) + : RenderPass(gl) + , pbrShader(":/Shaders/shadow_mapping.comp") + , frameWidth(frameWidth) + , frameHeight(frameHeight) + , view(view) + , camera(camera) + , light(light) + , gBaseColor(gBaseColor), gNormal(gNormal), gPosition(gPosition), gMetallicRoughness(gMetallicRoughness) + , shadowGbuffer(shadowGbuffer) + , irradianceMap(irradianceMap) + , prefilterMap(prefilterMap) + , brdfLUTTexture(brdfLUTTexture) + { + pbrShader.bind(); + pbrShader.setUniformValue("gNormal", gNormalBinding); + pbrShader.setUniformValue("gPosition", gPositionBinding); + pbrShader.setUniformValue("gMetallicRoughness", gMetallicRoughnessBinding); + pbrShader.setUniformValue("gShadowMap", gShadowMapBinding); + pbrShader.setUniformValue("irradianceMap", irradianceMapBinding); + pbrShader.setUniformValue("prefilterMap", prefilterMapBinding); + pbrShader.setUniformValue("brdfLUT", brdfLUTBinding); + pbrShader.release(); + } + + void LightingPass::dispatch() + { + pbrShader.bind(); + pbrShader.setUniformValue("view", view); + pbrShader.setUniformValue("farPlane", camera.FarPlane); + pbrShader.setUniformValueArray("shadowCascadePlaneDistances", light.shadowCascadeLevels.data(), light.shadowCascadeLevels.size(), 1); + pbrShader.setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1); + pbrShader.setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size()); + pbrShader.setUniformValue("shadowBlendRatio", light.blendRatio); + pbrShader.setUniformValue("camPos", camera.Position); + pbrShader.setUniformValue("mainLightDirection", light.lightDirection); + pbrShader.setUniformValue("mainLightRadiance", light.radiance); + + gl->BindTextureUnit(gNormalBinding, gNormal); + gl->BindTextureUnit(gPositionBinding, gPosition); + gl->BindTextureUnit(gMetallicRoughnessBinding, gMetallicRoughness); + gl->BindTextureUnit(gShadowMapBinding, shadowGbuffer); + gl->BindTextureUnit(irradianceMapBinding, irradianceMap); + gl->BindTextureUnit(prefilterMapBinding, prefilterMap); + gl->BindTextureUnit(brdfLUTBinding, brdfLUTTexture); + + gl->BindImageTexture(0, gBaseColor, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); + gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); + pbrShader.release(); + } + + FinalPass::FinalPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, GLuint& gBaseColor, float& exposure) + : RenderPass(gl) + , finalShader(":Shaders/final.vert", ":Shaders/final.frag") + , frameWidth(frameWidth) + , frameHeight(frameHeight) + , gBaseColor(gBaseColor) + , exposure(exposure) + { + finalShader.bind(); + finalShader.setUniformValue("gBaseColor", gBaseColorBinding); + finalShader.release(); + + quadVAO.create(); + QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); + + quadVBO.create(); + quadVBO.bind(); + GLfloat vertex[] = { + // positions // texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + quadVBO.allocate(vertex, sizeof(vertex)); + quadVBO.bind(); + gl->EnableVertexAttribArray(0); + gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), + nullptr); + gl->EnableVertexAttribArray(1); + gl->VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), + reinterpret_cast(3 * sizeof(GLfloat))); + quadVBO.release(); + } + + void FinalPass::dispatch() + { + gl->Viewport(0, 0, frameWidth, frameHeight); + gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + finalShader.bind(); + finalShader.setUniformValue("exposure", exposure); + gl->BindTextureUnit(gBaseColorBinding, gBaseColor); + quadVAO.bind(); + gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); + quadVAO.release(); + finalShader.release(); + } + + SkyboxPass::SkyboxPass(GladGLContext* gl, QMatrix4x4& projection, QMatrix4x4& view, float& exposure, GLuint& skyCubemap) + : RenderPass(gl) + , skyBoxShader(":Shaders/skybox.vert", ":Shaders/skybox.frag") + , projection(projection) + , view(view) + , exposure(exposure) + , skyCubemap(skyCubemap) + { + skyBoxShader.bind(); + skyBoxShader.setUniformValue("environmentMap", environmentMapBinding); + skyBoxShader.release(); + } + + void SkyboxPass::dispatch() + { + skyBoxShader.bind(); + gl->Disable(GL_CULL_FACE); + skyBoxShader.setUniformValue("view", view); + skyBoxShader.setUniformValue("projection", projection); + skyBoxShader.setUniformValue("exposure", exposure); + gl->BindTextureUnit(environmentMapBinding, skyCubemap); + IblUtils::renderCube(gl); + skyBoxShader.release(); + } +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/RenderPass.h b/ArchitectureColoredPainting/src/Renderer/RenderPass.h new file mode 100644 index 0000000..11685b0 --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/RenderPass.h @@ -0,0 +1,132 @@ +#pragma once +#include "Shader.h" +#include "Model.h" +#include "Light.h" +#include + +struct GladGLContext; + +namespace Renderer +{ + + class RenderPass + { + public: + RenderPass(GladGLContext* gl) : gl(gl) {}; + virtual ~RenderPass() = default; + virtual void dispatch() = 0; + protected: + GladGLContext* gl = nullptr; + }; + + class ShadowMapPass : public RenderPass + { + public: + ShadowMapPass(GladGLContext* gl, GLuint& shadowFboHandle, int& shadowMapResolution, Light& light, Model*& model); + void dispatch(); + private: + Shader modelShadowShader; + GLuint& shadowFboHandle; + int& shadowMapResolution; + Light& light; + Model*& model; + GLuint lightSpaceMatricesUBO; + }; + + class GeometryPass : public RenderPass + { + public: + GeometryPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, + QOpenGLFramebufferObject*& fbo, Model*& model, QMatrix4x4& projection, QMatrix4x4& view); + void dispatch(); + private: + Shader modelShader, paintingShader, plainShader; + unsigned int& frameWidth; + unsigned int& frameHeight; + QOpenGLFramebufferObject*& fbo; + Model*& model; + QMatrix4x4& projection; + QMatrix4x4& view; + }; + + class PageIDCallbackPass : public RenderPass + { + public: + PageIDCallbackPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, QOpenGLFramebufferObject*& fbo, + GLuint* gBuffers, GLuint& gPageID, VirtualTextureManager& vtManager); + void dispatch(); + private: + Shader pageIdDownsampleShader; + unsigned int& frameWidth; + unsigned int& frameHeight; + QOpenGLFramebufferObject*& fbo; + GLuint* gBuffers; + GLuint& gPageID; + VirtualTextureManager& vtManager; + }; + + class LightingPass : public RenderPass + { + public: + LightingPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, + QMatrix4x4& view, Camera& camera, Light& light, + GLuint& gBaseColor, GLuint& gNormal, GLuint& gPosition, GLuint& gMetallicRoughness, + GLuint& shadowGbuffer, GLuint& irradianceMap, GLuint& prefilterMap, GLuint& brdfLUTTexture); + void dispatch(); + private: + Shader pbrShader; + unsigned int& frameWidth; + unsigned int& frameHeight; + QMatrix4x4& view; + Camera& camera; + Light& light; + GLuint& gBaseColor; + GLuint& gNormal; + GLuint& gPosition; + GLuint& gMetallicRoughness; + GLuint& shadowGbuffer; + GLuint& irradianceMap; + GLuint& prefilterMap; + GLuint& brdfLUTTexture; + + constexpr static GLuint gNormalBinding = 1, + gPositionBinding = 2, + gMetallicRoughnessBinding = 3, + gShadowMapBinding = 4, + irradianceMapBinding = 5, + prefilterMapBinding = 6, + brdfLUTBinding = 7; + }; + + class FinalPass : public RenderPass + { + public: + FinalPass(GladGLContext* gl, unsigned int& frameWidth, unsigned int& frameHeight, GLuint& gBaseColor, float& exposure); + void dispatch(); + private: + Shader finalShader; + unsigned int& frameWidth; + unsigned int& frameHeight; + GLuint& gBaseColor; + float& exposure; + + QOpenGLBuffer quadVBO; + QOpenGLVertexArrayObject quadVAO; + constexpr static GLint gBaseColorBinding = 0; + }; + + class SkyboxPass : public RenderPass + { + public: + SkyboxPass(GladGLContext* gl, QMatrix4x4& projection, QMatrix4x4& view, float& exposure, GLuint& skyCubemap); + void dispatch(); + private: + Shader skyBoxShader; + QMatrix4x4& projection; + QMatrix4x4& view; + float& exposure; + GLuint& skyCubemap; + + constexpr static GLint environmentMapBinding = 0; + }; +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp index 3245753..1816768 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp @@ -14,7 +14,6 @@ using namespace Renderer; -QVector3D mainLightRadiance = 10 * QVector3D(0.7529, 0.7450, 0.6784).normalized(); static float sunPitch = 105, sunYaw = 80; static int sunSpeed = 10; @@ -24,7 +23,6 @@ RendererGLWidget::RendererGLWidget(QWidget* parent) , light(&camera) { //startTimer(); - lastFrame = std::clock(); setFocusPolicy(Qt::StrongFocus); //QSurfaceFormat format; //format.setProfile(QSurfaceFormat::CoreProfile); @@ -34,27 +32,6 @@ RendererGLWidget::RendererGLWidget(QWidget* parent) RendererGLWidget::~RendererGLWidget() { - if (modelProgramPtr != nullptr) - { - makeCurrent(); - delete modelProgramPtr; - modelProgramPtr = nullptr; - doneCurrent(); - } - if (paintingProgramPtr != nullptr) - { - makeCurrent(); - delete paintingProgramPtr; - paintingProgramPtr = nullptr; - doneCurrent(); - } - if (finalProgramPtr != nullptr) - { - makeCurrent(); - delete finalProgramPtr; - finalProgramPtr = nullptr; - doneCurrent(); - } } void RendererGLWidget::startTimer() @@ -95,7 +72,7 @@ void RendererGLWidget::setModel(QString path) void Renderer::RendererGLWidget::setMainLightRadiance(QVector3D radiance) { - mainLightRadiance = radiance; + light.radiance = radiance; } void RendererGLWidget::setMainLightPitch(float pitch) @@ -151,45 +128,16 @@ void RendererGLWidget::initializeGL() gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); gl->ClearColor(0, 0, 0, 1); - shadowProgramPtr = new QOpenGLShaderProgram; - if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert")) - qCritical() << "ERROR:" << shadowProgramPtr->log(); - if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Geometry, ":/Shaders/model_shadow.geom")) - qCritical() << "ERROR:" << shadowProgramPtr->log(); - if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model_shadow.frag")) - qCritical() << "ERROR:" << shadowProgramPtr->log(); - if (!shadowProgramPtr->link()) - qCritical() << "ERROR:" << shadowProgramPtr->log(); + vtManager = std::make_unique(gl.get()); + model = new Model(context(), vtManager.get()); - plainProgramPtr = new QOpenGLShaderProgram; - if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert")) - qCritical() << "ERROR:" << plainProgramPtr->log(); - if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag")) - qCritical() << "ERROR:" << plainProgramPtr->log(); - if (!plainProgramPtr->link()) - qCritical() << "ERROR:" << plainProgramPtr->log(); - - modelProgramPtr = new QOpenGLShaderProgram; - if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) - qCritical() << "ERROR:" << modelProgramPtr->log(); - if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag")) - qCritical() << "ERROR:" << modelProgramPtr->log(); - if (!modelProgramPtr->link()) - qCritical() << "ERROR:" << modelProgramPtr->log(); - - paintingProgramPtr = new QOpenGLShaderProgram; - if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert")) - qCritical() << "ERROR:" << paintingProgramPtr->log(); - if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag")) - qCritical() << "ERROR:" << paintingProgramPtr->log(); - if (!paintingProgramPtr->link()) - qCritical() << "ERROR:" << paintingProgramPtr->log(); - - pageIdDownsampleProgramPtr = new QOpenGLShaderProgram; - if (!pageIdDownsampleProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/pageId_downsample.comp")) - qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log(); - if (!pageIdDownsampleProgramPtr->link()) - qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log(); + shadowMapPass = std::make_unique(gl.get(), shadowFboHandle, shadowMapResolution, light, model); + geometryPass = std::make_unique(gl.get(), frameWidth, frameHeight, fboPtr, model, projection, view); + pageIDCallbackPass = std::make_unique(gl.get(), frameWidth, frameHeight, fboPtr, gbuffers, gPageID, *vtManager); + lightingPass = std::make_unique(gl.get(), frameWidth, frameHeight, view, camera, light, + gBaseColor, gNormal, gPosition, gMetallicRoughness, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture); + finalPass = std::make_unique(gl.get(), frameWidth, frameHeight, gBaseColor, exposure); + skyboxPass = std::make_unique(gl.get(), projection, view, exposure, skyCubemap); depthInitProgramPtr = new QOpenGLShaderProgram; if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp")) @@ -203,58 +151,16 @@ void RendererGLWidget::initializeGL() if (!depthMipmapProgramPtr->link()) qCritical() << "ERROR:" << depthMipmapProgramPtr->log(); - shadowMappingProgramPtr = new QOpenGLShaderProgram; - if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp")) - qCritical() << "ERROR:" << shadowMappingProgramPtr->log(); - if (!shadowMappingProgramPtr->link()) - qCritical() << "ERROR:" << shadowMappingProgramPtr->log(); - ssgiProgramPtr = new QOpenGLShaderProgram; if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp")) qCritical() << "ERROR:" << ssgiProgramPtr->log(); if (!ssgiProgramPtr->link()) qCritical() << "ERROR:" << ssgiProgramPtr->log(); - finalProgramPtr = new QOpenGLShaderProgram; - if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) - qCritical() << "ERROR:" << finalProgramPtr->log(); - if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag")) - qCritical() << "ERROR:" << finalProgramPtr->log(); - if (!finalProgramPtr->link()) - qCritical() << "ERROR:" << finalProgramPtr->log(); - - skyBoxProgramPtr = new QOpenGLShaderProgram; - if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert")) - qCritical() << "ERROR:" << skyBoxProgramPtr->log(); - if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag")) - qCritical() << "ERROR:" << skyBoxProgramPtr->log(); - if (!skyBoxProgramPtr->link()) - qCritical() << "ERROR:" << skyBoxProgramPtr->log(); - - shadowProgramPtr->bind(); - gl->GenBuffers(1, &lightSpaceMatricesUBO); - gl->BindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO); - gl->BufferData(GL_UNIFORM_BUFFER, sizeof(QMatrix4x4) * 16, nullptr, GL_STATIC_DRAW); - gl->BindBufferBase(GL_UNIFORM_BUFFER, 0, lightSpaceMatricesUBO); - gl->BindBuffer(GL_UNIFORM_BUFFER, 0); - shadowProgramPtr->release(); - - depthInitProgramPtr->bind(); depthInitProgramPtr->setUniformValue("depthBuffer", 0); depthInitProgramPtr->release(); - shadowMappingProgramPtr->bind(); - //shadowMappingProgramPtr->setUniformValue("gBaseColor", 0); - shadowMappingProgramPtr->setUniformValue("gNormal", 1); - shadowMappingProgramPtr->setUniformValue("gPosition", 2); - shadowMappingProgramPtr->setUniformValue("gMetallicRoughness", 3); - shadowMappingProgramPtr->setUniformValue("gShadowMap", 4); - shadowMappingProgramPtr->setUniformValue("irradianceMap", 5); - shadowMappingProgramPtr->setUniformValue("prefilterMap", 6); - shadowMappingProgramPtr->setUniformValue("brdfLUT", 7); - shadowMappingProgramPtr->release(); - ssgiProgramPtr->bind(); ssgiProgramPtr->setUniformValue("gBaseColor", 0); ssgiProgramPtr->setUniformValue("gNormal", 1); @@ -263,44 +169,21 @@ void RendererGLWidget::initializeGL() ssgiProgramPtr->setUniformValue("gDepth", 4); ssgiProgramPtr->setUniformValue("gDirectLight", 5); - finalProgramPtr->bind(); - finalProgramPtr->setUniformValue("gBaseColor", 0); - finalProgramPtr->release(); - - vtManager = std::make_unique(gl.get()); - model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, vtManager.get()); - - skyBoxProgramPtr->bind(); - skyBoxProgramPtr->setUniformValue("environmentMap", 0); - skyBoxProgramPtr->release(); - std::tie(skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture) = IblUtils::precomputeCubemaps(glFunc); - - quadVAO.create(); - QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); - - quadVBO.create(); - quadVBO.bind(); - GLfloat vertex[] = { - // positions // texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - - quadVBO.allocate(vertex, sizeof(vertex)); - quadVBO.bind(); - gl->EnableVertexAttribArray(0); - gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), - nullptr); - gl->EnableVertexAttribArray(1); - gl->VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), - reinterpret_cast(3 * sizeof(GLfloat))); - quadVBO.release(); + std::tie(skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture) = IblUtils::precomputeCubemaps(gl.get()); gl->GenQueries(1, &timeQuery); } +float calculateDeltaTime() +{ + using namespace std::chrono; + static steady_clock::time_point last = steady_clock::now(); + steady_clock::time_point current = steady_clock::now(); + auto d = duration_cast>(current - last); + last = current; + return d.count(); +} + void RendererGLWidget::paintGL() { QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions(); @@ -314,184 +197,24 @@ void RendererGLWidget::paintGL() light.lightDirection.setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw))); light.lightDirection.normalize(); - const std::vector lightMatrices = light.getLightSpaceMatrices(); - gl->BindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO); - for (size_t i = 0; i < lightMatrices.size(); i++) - { - gl->BufferSubData(GL_UNIFORM_BUFFER, i * 16 * sizeof(GLfloat), 16 * sizeof(GLfloat), lightMatrices[i].data()); - } - gl->BindBuffer(GL_UNIFORM_BUFFER, 0); + projection = camera.GetProjectionMatrix(); + view = camera.GetViewMatrix(); vtManager->commitMutex.lock(); - { - gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); - gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution); - gl->Clear(GL_DEPTH_BUFFER_BIT); - //gl->CullFace(GL_FRONT); - if (model != nullptr) - model->drawShadow(); - //gl->CullFace(GL_BACK); - - gl->BindFramebuffer(GL_FRAMEBUFFER, 0); - } - QMatrix4x4 projection; - projection.perspective(camera.Zoom, camera.Ratio, camera.NearPlane, camera.FarPlane); - QMatrix4x4 view = camera.GetViewMatrix(); - if (fboPtr->bind()) - { - gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - gl->Viewport(0, 0, frameWidth, frameHeight); - - modelProgramPtr->bind(); - modelProgramPtr->setUniformValue("projection", projection); - modelProgramPtr->setUniformValue("view", view); - modelProgramPtr->release(); - paintingProgramPtr->bind(); - paintingProgramPtr->setUniformValue("projection", projection); - paintingProgramPtr->setUniformValue("view", view); - paintingProgramPtr->release(); - if (model != nullptr) - model->draw(); - - /// Debug Lighting - if (false) - { - plainProgramPtr->bind(); - plainProgramPtr->setUniformValue("projection", projection); - plainProgramPtr->setUniformValue("view", view); - plainProgramPtr->setUniformValue("albedo", 0.5f, 0.5f, 0.5f); - QMatrix4x4 model; - int nrRows = 7, nrColumns = 7; - float spacing = 2.5; - for (int row = 0; row < nrRows; ++row) - { - plainProgramPtr->setUniformValue("metallic", (float)row / (float)nrRows); - for (int col = 0; col < nrColumns; ++col) - { - plainProgramPtr->setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); - - model.setToIdentity(); - model.scale(10); - model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing, - (float)(row - (nrRows / 2)) * spacing + 20, - -2.0f)); - plainProgramPtr->setUniformValue("model", model); - IblUtils::renderSphere(glFunc); - } - } - plainProgramPtr->release(); - } - - pageIdDownsampleProgramPtr->bind(); - gl->BindImageTexture(3, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16UI); - gl->Uniform2ui(0, rand() % 8, rand() % 8); - gl->DispatchCompute(ceil(frameWidth / 8. / 8.), ceil(frameWidth / 8. / 8.), 1); - pageIdDownsampleProgramPtr->release(); - std::vector pixels; - pixels.resize(ceil(frameWidth / 8.) * ceil(frameHeight / 8.)); - //fboPtr->bind(); - gl->ReadBuffer(GL_COLOR_ATTACHMENT4); - gl->ReadnPixels(0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); - //gl->GetTextureSubImage(gbuffers[4], 0, 0, 0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1, GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); - //fboPtr->release(); - vtManager->tryUpdatePages(pixels); - - fboPtr->release(); - } + shadowMapPass->dispatch(); + geometryPass->dispatch(); + pageIDCallbackPass->dispatch(); gl->Finish(); vtManager->commitMutex.unlock(); - - //depthInitProgramPtr->bind(); - //gl->ActiveTexture(GL_TEXTURE0); - //gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]); - //gl->BindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - //gl->DispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1); - //depthInitProgramPtr->release(); - - //depthMipmapProgramPtr->bind(); - //for (int i = 0; i <= 3; i++) - // gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - //gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1); - //for (int i = 0; i <= 3; i++) - // gl->BindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - //gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1); - //depthMipmapProgramPtr->release(); - - shadowMappingProgramPtr->bind(); - shadowMappingProgramPtr->setUniformValue("view", view); - shadowMappingProgramPtr->setUniformValue("farPlane", camera.FarPlane); - shadowMappingProgramPtr->setUniformValueArray("shadowCascadePlaneDistances", light.shadowCascadeLevels.data(), light.shadowCascadeLevels.size(), 1); - shadowMappingProgramPtr->setUniformValueArray("shadowBiases", light.frustumSizes.data(), light.frustumSizes.size(), 1); - //qDebug() << light.frustumSizes; - shadowMappingProgramPtr->setUniformValue("shadowCascadeCount", (GLint)light.shadowCascadeLevels.size()); - shadowMappingProgramPtr->setUniformValue("shadowBlendRatio", light.blendRatio); - shadowMappingProgramPtr->setUniformValue("camPos", camera.Position); - shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); - shadowMappingProgramPtr->setUniformValue("mainLightRadiance", mainLightRadiance); - - gl->BindTextureUnit(1, gbuffers[1]); - gl->BindTextureUnit(2, gbuffers[2]); - gl->BindTextureUnit(3, gbuffers[3]); - gl->BindTextureUnit(4, shadowGbuffer); - gl->BindTextureUnit(5, irradianceMap); - gl->BindTextureUnit(6, prefilterMap); - gl->BindTextureUnit(7, brdfLUTTexture); - - gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); - gl->BindImageTexture(1, gbuffers[8], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); - gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); - shadowMappingProgramPtr->release(); - - /*ssgiProgramPtr->bind(); - ssgiProgramPtr->setUniformValue("camPos", camera.Position); - ssgiProgramPtr->setUniformValue("cameraMatrix", projection * view); - ssgiProgramPtr->setUniformValue("projectionMatrix", projection); - ssgiProgramPtr->setUniformValue("viewMatrix", view); - ssgiProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); - ssgiProgramPtr->setUniformValue("mainLightRadiance", lightColors[0]); - ssgiProgramPtr->setUniformValue("rdSeed", QVector4D(rand(), rand(), rand(), rand())); - gl->ActiveTexture(GL_TEXTURE0); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]); - gl->ActiveTexture(GL_TEXTURE1); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]); - gl->ActiveTexture(GL_TEXTURE2); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]); - gl->ActiveTexture(GL_TEXTURE3); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]); - gl->ActiveTexture(GL_TEXTURE4); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[7]); - gl->ActiveTexture(GL_TEXTURE5); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[8]); - gl->BindImageTexture(1, gbuffers[9], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); - gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); - ssgiProgramPtr->release();*/ - - gl->Viewport(0, 0, frameWidth, frameHeight); - gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - finalProgramPtr->bind(); - finalProgramPtr->setUniformValue("exposure", exposure); - gl->BindTextureUnit(0, gbuffers[0]); - quadVAO.bind(); - gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); - quadVAO.release(); - finalProgramPtr->release(); - - skyBoxProgramPtr->bind(); - gl->Disable(GL_CULL_FACE); - skyBoxProgramPtr->setUniformValue("view", view); - skyBoxProgramPtr->setUniformValue("projection", projection); - skyBoxProgramPtr->setUniformValue("exposure", exposure); - gl->BindTextureUnit(0, skyCubemap); - IblUtils::renderCube(glFunc); - skyBoxProgramPtr->release(); + lightingPass->dispatch(); + finalPass->dispatch(); + skyboxPass->dispatch(); gl->EndQuery(GL_TIME_ELAPSED); GLuint frameDuration; gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration); - clock_t currentFrame = std::clock(); - deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC; - lastFrame = currentFrame; + float deltaTime = calculateDeltaTime(); static float accTime = 0, frameCnt = 0, averageDuration = 0; accTime += deltaTime; @@ -567,19 +290,19 @@ void RendererGLWidget::resizeGL(int width, int height) gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0); - //gPaintingIndex + //gPageID gl->BindTexture(GL_TEXTURE_2D, gbuffers[4]); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG16UI, frameWidth, frameHeight, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0); - //PaintingTexCoord + //PaintingTexCoord, Deprecated gl->BindTexture(GL_TEXTURE_2D, gbuffers[5]); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, frameWidth, frameHeight, 0, GL_RG, GL_FLOAT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0); - //Depth + //Depth, Deprecated gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, frameWidth, frameHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -596,7 +319,7 @@ void RendererGLWidget::resizeGL(int width, int height) if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) qDebug() << "Framebuffer not complete!"; - //HiZ, not bind to fbo + //HiZ, not bind to fbo, Deprecated depthWidth = ceil(frameWidth / 64.) * 64; depthHeight = ceil(frameHeight / 64.) * 64; qDebug() << depthWidth << depthHeight; @@ -610,12 +333,12 @@ void RendererGLWidget::resizeGL(int width, int height) gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); gl->TexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f })); - //DirectLight + //DirectLight, Deprecated gl->BindTexture(GL_TEXTURE_2D, gbuffers[8]); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //InDirectLight + //InDirectLight, Deprecated gl->BindTexture(GL_TEXTURE_2D, gbuffers[9]); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -624,9 +347,6 @@ void RendererGLWidget::resizeGL(int width, int height) fboPtr->release(); } - - - if (shadowFboHandle != 0) { gl->DeleteTextures(1, &shadowGbuffer); @@ -663,7 +383,6 @@ void RendererGLWidget::resizeGL(int width, int height) gl->BindFramebuffer(GL_FRAMEBUFFER, 0); } - std::cout << "\033[?25l"; } diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h index c75e931..dc5729e 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h @@ -9,79 +9,88 @@ #include "Camera.h" #include "Light.h" #include "Model.h" +#include "RenderPass.h" struct GladGLContext; namespace Renderer { - class VirtualTextureManager; + class VirtualTextureManager; - class RendererGLWidget : public QOpenGLWidget - { - Q_OBJECT - public: - RendererGLWidget(QWidget* parent = nullptr); - ~RendererGLWidget(); + class RendererGLWidget : public QOpenGLWidget + { + Q_OBJECT + public: + RendererGLWidget(QWidget* parent = nullptr); + ~RendererGLWidget(); - void startTimer(); - void stopTimer(); - const std::unordered_map>& getPaintingMap(); + void startTimer(); + void stopTimer(); + const std::unordered_map>& getPaintingMap(); - public slots: - void setModel(QString path); - void setMainLightRadiance(QVector3D radiance); - void setMainLightPitch(float pitch); - void setMainLightYaw(float yaw); - void setExposure(float exposure); - protected: - void initializeGL() override; - void paintGL() override; - void resizeGL(int width, int height) override; - void timerEvent(QTimerEvent* event) override; - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - void wheelEvent(QWheelEvent* event) override; - void focusInEvent(QFocusEvent* event) override; - void focusOutEvent(QFocusEvent* event) override; + public slots: + void setModel(QString path); + void setMainLightRadiance(QVector3D radiance); + void setMainLightPitch(float pitch); + void setMainLightYaw(float yaw); + void setExposure(float exposure); + protected: + void initializeGL() override; + void paintGL() override; + void resizeGL(int width, int height) override; + void timerEvent(QTimerEvent* event) override; + void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; + void wheelEvent(QWheelEvent* event) override; + void focusInEvent(QFocusEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; - private: - int timerId = -1; - int frameWidth, frameHeight; - int depthWidth, depthHeight; - QSet pressedKeys; - Camera camera; - Light light; - clock_t lastFrame; - float deltaTime; - int shadowMapResolution; - float exposure = 0.8; + private: + int timerId = -1; + unsigned int frameWidth, frameHeight; + int depthWidth, depthHeight; + QSet pressedKeys; + Camera camera; + Light light; + int shadowMapResolution; + float exposure = 0.8; - std::unique_ptr gl; - QOpenGLShaderProgram* shadowProgramPtr = nullptr; - QOpenGLShaderProgram* plainProgramPtr = nullptr; - QOpenGLShaderProgram* modelProgramPtr = nullptr; - QOpenGLShaderProgram* paintingProgramPtr = nullptr; - QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr; - QOpenGLShaderProgram* depthInitProgramPtr = nullptr; - QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr; - QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr; - QOpenGLShaderProgram* ssgiProgramPtr = nullptr; - QOpenGLShaderProgram* finalProgramPtr = nullptr; - QOpenGLShaderProgram* skyBoxProgramPtr = nullptr; - QOpenGLFramebufferObject* fboPtr = nullptr; - GLuint gbuffers[10]; - GLuint shadowFboHandle = 0; - GLuint shadowGbuffer; - GLuint lightSpaceMatricesUBO; - GLuint skyCubemap; - GLuint irradianceMap; - GLuint prefilterMap; - GLuint brdfLUTTexture; - QOpenGLBuffer quadVBO; - QOpenGLVertexArrayObject quadVAO; - Model* model = nullptr; - std::unique_ptr vtManager; + QMatrix4x4 projection; + QMatrix4x4 view; - GLuint timeQuery; - }; + std::unique_ptr gl; + + std::unique_ptr shadowMapPass; + std::unique_ptr geometryPass; + std::unique_ptr pageIDCallbackPass; + std::unique_ptr lightingPass; + std::unique_ptr finalPass; + std::unique_ptr skyboxPass; + + QOpenGLShaderProgram* depthInitProgramPtr = nullptr; + QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr; + QOpenGLShaderProgram* ssgiProgramPtr = nullptr; + + QOpenGLFramebufferObject* fboPtr = nullptr; + + GLuint gbuffers[10]; + GLuint& gBaseColor = gbuffers[0]; + GLuint& gNormal = gbuffers[1]; + GLuint& gPosition = gbuffers[2]; + GLuint& gMetallicRoughness = gbuffers[3]; + GLuint& gPageID = gbuffers[4]; + GLuint& gDirectLight = gbuffers[8]; + + GLuint shadowFboHandle = 0; + GLuint shadowGbuffer; + GLuint skyCubemap; + GLuint irradianceMap; + GLuint prefilterMap; + GLuint brdfLUTTexture; + + Model* model = nullptr; + std::unique_ptr vtManager; + + GLuint timeQuery; + }; } diff --git a/ArchitectureColoredPainting/src/Renderer/Shader.cpp b/ArchitectureColoredPainting/src/Renderer/Shader.cpp new file mode 100644 index 0000000..6c4a5aa --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/Shader.cpp @@ -0,0 +1,22 @@ +#include "Shader.h" +namespace Renderer +{ + Shader::Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath) + { + if (!addShaderFromSourceFile(QOpenGLShader::Vertex, vertexPath)) + qCritical() << "COMPILE ERROR:" << log(); + if (!addShaderFromSourceFile(QOpenGLShader::Fragment, fragmentPath)) + qCritical() << "COMPILE ERROR:" << log(); + if (geometryPath && !addShaderFromSourceFile(QOpenGLShader::Geometry, geometryPath)) + qCritical() << "COMPILE ERROR:" << log(); + if (!link()) + qCritical() << "LINK ERROR:" << log(); + } + Shader::Shader(const char* computePath) + { + if (!addShaderFromSourceFile(QOpenGLShader::Compute, computePath)) + qCritical() << "COMPILE ERROR:" << log(); + if (!link()) + qCritical() << "LINK ERROR:" << log(); + } +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Shader.h b/ArchitectureColoredPainting/src/Renderer/Shader.h new file mode 100644 index 0000000..93ed30d --- /dev/null +++ b/ArchitectureColoredPainting/src/Renderer/Shader.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace Renderer +{ + + class Shader : public QOpenGLShaderProgram + { + public: + Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr); + Shader(const char* computePath); + }; + +} \ No newline at end of file