重构绘制部分

main
wuyize 2024-02-23 23:43:22 +08:00
parent b15ddc0ecb
commit bc118b0a20
21 changed files with 783 additions and 608 deletions

View File

@ -171,6 +171,8 @@
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
<ClCompile Include="src\Renderer\Painting\StraightLine.cpp" />
<ClCompile Include="src\Renderer\RenderPass.cpp" />
<ClCompile Include="src\Renderer\Shader.cpp" />
<ClCompile Include="src\Renderer\VirtualTextureManager.cpp" />
<ClCompile Include="src\SvgParser.cpp" />
<ClCompile Include="src\Editor\EditorWidgetComponent\StrokeStyleWidget.cpp" />
@ -265,6 +267,8 @@
<ClInclude Include="src\Renderer\Painting\Painting.h" />
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
<ClInclude Include="src\Renderer\Preview\PaintingRenderer.h" />
<ClInclude Include="src\Renderer\RenderPass.h" />
<ClInclude Include="src\Renderer\Shader.h" />
<ClInclude Include="src\Renderer\VirtualTextureManager.h" />
<ClInclude Include="src\SvgParser.h" />
<QtMoc Include="src\NavigationBarWidget.h" />

View File

@ -303,6 +303,12 @@
<ClCompile Include="src\FlowLayout.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\RenderPass.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Renderer\Shader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -606,6 +612,12 @@
<ClInclude Include="src\FlowLayout.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\RenderPass.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Renderer\Shader.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<QtRcc Include="res\MainWindow.qrc">

View File

@ -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];

View File

@ -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()
{

View File

@ -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();

View File

@ -4,7 +4,8 @@ namespace Renderer
class Drawable
{
public:
virtual void draw() = 0;
virtual void drawShadow() = 0;
virtual ~Drawable() = default;
virtual void draw(QOpenGLShaderProgram* shaderProgram) = 0;
virtual void drawShadow(QOpenGLShaderProgram* shadowProgram) = 0;
};
}

View File

@ -1,3 +1,4 @@
#include <glad/gl.h>
#include "IblUtils.h"
#include <QOpenGLShaderProgram>
#include <QDebug>
@ -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<glm::vec3> positions;
std::vector<glm::vec2> 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<GLuint, GLuint, GLuint, GLuint> Renderer::IblUtils::precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc)
std::tuple<GLuint, GLuint, GLuint, GLuint> 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<GLuint, GLuint, GLuint, GLuint> 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<QMatrix4x4, 6>& captureViews)
GLuint Renderer::IblUtils::generateCubemap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& 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<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
GLuint Renderer::IblUtils::generateIrradianceMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& 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<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
GLuint Renderer::IblUtils::generatePrefilterMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& 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<unsigned int>(prefilterMapSize * std::pow(0.5, mip));
unsigned int mipHeight = static_cast<unsigned int>(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;
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <QOpenGLFunctions_4_5_Core>
struct GladGLContext;
namespace Renderer
{
class IblUtils
@ -9,8 +9,8 @@ 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
* @return GLuint envCubemap
@ -18,11 +18,11 @@ namespace Renderer
* @return GLuint prefilterMap
* @return GLuint brdfLut
*/
static std::tuple<GLuint, GLuint, GLuint, GLuint> precomputeCubemaps(QOpenGLFunctions_4_5_Core* glFunc);
static std::tuple<GLuint, GLuint, GLuint, GLuint> precomputeCubemaps(GladGLContext* gl);
private:
static GLuint generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews);
static GLuint generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap);
static GLuint generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& 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<QMatrix4x4, 6>& captureViews);
static GLuint generateIrradianceMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap);
static GLuint generatePrefilterMap(GladGLContext* gl, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap);
static GLuint gererateBrdfLut(GladGLContext* gl);
};
}

View File

@ -15,6 +15,7 @@ namespace Renderer
{
public:
QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
QVector3D radiance = QVector3D(0, 0, 0);
std::vector<float> shadowCascadeLevels;
float blendRatio = 0.3;
std::vector<float> frustumSizes;

View File

@ -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();
}

View File

@ -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:

View File

@ -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<QOpenGLFunctions_4_5_Core>())
, 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<Drawable> 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<Drawable> 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<Drawable> 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<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
auto& mesh = paintingMeshes.emplace_back(std::make_unique<PaintingMesh>(glFunc, modelQ));
auto& [paintingPath, leftBottom, rightTop] = iter->second;
auto [paintingId, ratio] = loadPainting(paintingPath);
@ -188,11 +184,10 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
mesh->indices = indices;
mesh->setupMesh();
return mesh;
}
else
{
auto mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
auto& mesh = meshes.emplace_back(std::make_unique<Mesh>(glFunc, modelQ));
mesh->vertices = vertices;
mesh->indices = indices;
@ -214,7 +209,6 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
}
mesh->setupMesh();
return mesh;
}
}

View File

@ -4,15 +4,16 @@
#include "VirtualTextureManager.h"
#include <QDir>
#include <assimp/scene.h>
#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<std::string, std::tuple<std::string, glm::vec2, glm::vec2>>& 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,7 +34,8 @@ namespace Renderer
std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
std::unordered_map<std::string, std::pair<GLuint, float>> paintingLoaded;
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
std::vector<std::unique_ptr<Drawable>> meshes;
std::vector<std::unique_ptr<Mesh>> meshes;
std::vector<std::unique_ptr<PaintingMesh>> paintingMeshes;
QDir directory; /// 模型所在路径
QString name; /// 模型文件名
@ -46,7 +45,7 @@ namespace Renderer
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
/// 加载网格
std::unique_ptr<Drawable> processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
void processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
/// 加载材质纹理
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);

View File

@ -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();
}

View File

@ -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:

View File

@ -0,0 +1,261 @@
#include <glad/gl.h>
#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<QMatrix4x4> 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<glm::u16vec2> 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<void*>(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();
}
}

View File

@ -0,0 +1,132 @@
#pragma once
#include "Shader.h"
#include "Model.h"
#include "Light.h"
#include <QOpenGLFramebufferObject>
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;
};
}

View File

@ -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<VirtualTextureManager>(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<ShadowMapPass>(gl.get(), shadowFboHandle, shadowMapResolution, light, model);
geometryPass = std::make_unique<GeometryPass>(gl.get(), frameWidth, frameHeight, fboPtr, model, projection, view);
pageIDCallbackPass = std::make_unique<PageIDCallbackPass>(gl.get(), frameWidth, frameHeight, fboPtr, gbuffers, gPageID, *vtManager);
lightingPass = std::make_unique<LightingPass>(gl.get(), frameWidth, frameHeight, view, camera, light,
gBaseColor, gNormal, gPosition, gMetallicRoughness, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
finalPass = std::make_unique<FinalPass>(gl.get(), frameWidth, frameHeight, gBaseColor, exposure);
skyboxPass = std::make_unique<SkyboxPass>(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<VirtualTextureManager>(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<void*>(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<duration<float>>(current - last);
last = current;
return d.count();
}
void RendererGLWidget::paintGL()
{
QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
@ -314,184 +197,24 @@ void RendererGLWidget::paintGL()
light.lightDirection.setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw)));
light.lightDirection.normalize();
const std::vector<QMatrix4x4> 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<glm::u16vec2> 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";
}

View File

@ -9,6 +9,7 @@
#include "Camera.h"
#include "Light.h"
#include "Model.h"
#include "RenderPass.h"
struct GladGLContext;
@ -46,39 +47,47 @@ namespace Renderer
private:
int timerId = -1;
int frameWidth, frameHeight;
unsigned int frameWidth, frameHeight;
int depthWidth, depthHeight;
QSet<int> pressedKeys;
Camera camera;
Light light;
clock_t lastFrame;
float deltaTime;
int shadowMapResolution;
float exposure = 0.8;
QMatrix4x4 projection;
QMatrix4x4 view;
std::unique_ptr<GladGLContext> gl;
QOpenGLShaderProgram* shadowProgramPtr = nullptr;
QOpenGLShaderProgram* plainProgramPtr = nullptr;
QOpenGLShaderProgram* modelProgramPtr = nullptr;
QOpenGLShaderProgram* paintingProgramPtr = nullptr;
QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr;
std::unique_ptr<ShadowMapPass> shadowMapPass;
std::unique_ptr<GeometryPass> geometryPass;
std::unique_ptr<PageIDCallbackPass> pageIDCallbackPass;
std::unique_ptr<LightingPass> lightingPass;
std::unique_ptr<FinalPass> finalPass;
std::unique_ptr<SkyboxPass> skyboxPass;
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& 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 lightSpaceMatricesUBO;
GLuint skyCubemap;
GLuint irradianceMap;
GLuint prefilterMap;
GLuint brdfLUTTexture;
QOpenGLBuffer quadVBO;
QOpenGLVertexArrayObject quadVAO;
Model* model = nullptr;
std::unique_ptr<VirtualTextureManager> vtManager;

View File

@ -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();
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <QOpenGLShaderProgram>
namespace Renderer
{
class Shader : public QOpenGLShaderProgram
{
public:
Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr);
Shader(const char* computePath);
};
}