重构绘制部分
parent
b15ddc0ecb
commit
bc118b0a20
|
@ -171,6 +171,8 @@
|
||||||
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
<ClCompile Include="src\Renderer\RendererWidget.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
<ClCompile Include="src\Renderer\Painting\ShortCutTree.cpp" />
|
||||||
<ClCompile Include="src\Renderer\Painting\StraightLine.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\Renderer\VirtualTextureManager.cpp" />
|
||||||
<ClCompile Include="src\SvgParser.cpp" />
|
<ClCompile Include="src\SvgParser.cpp" />
|
||||||
<ClCompile Include="src\Editor\EditorWidgetComponent\StrokeStyleWidget.cpp" />
|
<ClCompile Include="src\Editor\EditorWidgetComponent\StrokeStyleWidget.cpp" />
|
||||||
|
@ -265,6 +267,8 @@
|
||||||
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
<ClInclude Include="src\Renderer\Painting\Painting.h" />
|
||||||
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
|
<ClInclude Include="src\Renderer\Preview\ElementRenderer.h" />
|
||||||
<ClInclude Include="src\Renderer\Preview\PaintingRenderer.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\Renderer\VirtualTextureManager.h" />
|
||||||
<ClInclude Include="src\SvgParser.h" />
|
<ClInclude Include="src\SvgParser.h" />
|
||||||
<QtMoc Include="src\NavigationBarWidget.h" />
|
<QtMoc Include="src\NavigationBarWidget.h" />
|
||||||
|
|
|
@ -303,6 +303,12 @@
|
||||||
<ClCompile Include="src\FlowLayout.cpp">
|
<ClCompile Include="src\FlowLayout.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
<QtMoc Include="src\Renderer\RendererGLWidget.h">
|
||||||
|
@ -606,6 +612,12 @@
|
||||||
<ClInclude Include="src\FlowLayout.h">
|
<ClInclude Include="src\FlowLayout.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtRcc Include="res\MainWindow.qrc">
|
<QtRcc Include="res\MainWindow.qrc">
|
||||||
|
|
|
@ -12,7 +12,7 @@ uniform samplerCube irradianceMap;
|
||||||
uniform samplerCube prefilterMap;
|
uniform samplerCube prefilterMap;
|
||||||
uniform sampler2D brdfLUT;
|
uniform sampler2D brdfLUT;
|
||||||
|
|
||||||
layout(rgba16f, binding = 1) uniform image2D gDirectLight;
|
//layout(rgba16f, binding = 1) uniform image2D gDirectLight;
|
||||||
layout (std140, binding = 0) uniform LightSpaceMatrices
|
layout (std140, binding = 0) uniform LightSpaceMatrices
|
||||||
{
|
{
|
||||||
mat4 lightSpaceMatrices[16];
|
mat4 lightSpaceMatrices[16];
|
||||||
|
|
|
@ -21,6 +21,13 @@ Camera::Camera(float posX, float posY, float posZ, float upX, float upY, float u
|
||||||
updateCameraVectors();
|
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
|
// returns the view matrix calculated using Euler Angles and the LookAt Matrix
|
||||||
QMatrix4x4 Camera::GetViewMatrix()
|
QMatrix4x4 Camera::GetViewMatrix()
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace Renderer
|
||||||
// constructor with scalar values
|
// constructor with scalar values
|
||||||
Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch);
|
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
|
// returns the view matrix calculated using Euler Angles and the LookAt Matrix
|
||||||
QMatrix4x4 GetViewMatrix();
|
QMatrix4x4 GetViewMatrix();
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ namespace Renderer
|
||||||
class Drawable
|
class Drawable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void draw() = 0;
|
virtual ~Drawable() = default;
|
||||||
virtual void drawShadow() = 0;
|
virtual void draw(QOpenGLShaderProgram* shaderProgram) = 0;
|
||||||
|
virtual void drawShadow(QOpenGLShaderProgram* shadowProgram) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <glad/gl.h>
|
||||||
#include "IblUtils.h"
|
#include "IblUtils.h"
|
||||||
#include <QOpenGLShaderProgram>
|
#include <QOpenGLShaderProgram>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc)
|
void Renderer::IblUtils::renderCube(GladGLContext* gl)
|
||||||
{
|
{
|
||||||
static GLuint cubeVAO = 0, cubeVBO = 0;
|
static GLuint cubeVAO = 0, cubeVBO = 0;
|
||||||
// initialize (if necessary)
|
// 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, 1.0f, // top-left
|
||||||
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
||||||
};
|
};
|
||||||
glFunc->glGenVertexArrays(1, &cubeVAO);
|
gl->GenVertexArrays(1, &cubeVAO);
|
||||||
glFunc->glGenBuffers(1, &cubeVBO);
|
gl->GenBuffers(1, &cubeVBO);
|
||||||
// fill buffer
|
// fill buffer
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
gl->BindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||||
glFunc->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
gl->BufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
// link vertex attributes
|
// link vertex attributes
|
||||||
glFunc->glBindVertexArray(cubeVAO);
|
gl->BindVertexArray(cubeVAO);
|
||||||
glFunc->glEnableVertexAttribArray(0);
|
gl->EnableVertexAttribArray(0);
|
||||||
glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
|
gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
|
||||||
glFunc->glEnableVertexAttribArray(1);
|
gl->EnableVertexAttribArray(1);
|
||||||
glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
|
gl->VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||||
glFunc->glEnableVertexAttribArray(2);
|
gl->EnableVertexAttribArray(2);
|
||||||
glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
gl->VertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, 0);
|
gl->BindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glFunc->glBindVertexArray(0);
|
gl->BindVertexArray(0);
|
||||||
}
|
}
|
||||||
// render Cube
|
// render Cube
|
||||||
glFunc->glBindVertexArray(cubeVAO);
|
gl->BindVertexArray(cubeVAO);
|
||||||
glFunc->glDrawArrays(GL_TRIANGLES, 0, 36);
|
gl->DrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
glFunc->glBindVertexArray(0);
|
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 sphereVAO = 0;
|
||||||
static unsigned int indexCount;
|
static unsigned int indexCount;
|
||||||
if (sphereVAO == 0)
|
if (sphereVAO == 0)
|
||||||
{
|
{
|
||||||
glFunc->glGenVertexArrays(1, &sphereVAO);
|
gl->GenVertexArrays(1, &sphereVAO);
|
||||||
|
|
||||||
unsigned int vbo, ebo;
|
unsigned int vbo, ebo;
|
||||||
glFunc->glGenBuffers(1, &vbo);
|
gl->GenBuffers(1, &vbo);
|
||||||
glFunc->glGenBuffers(1, &ebo);
|
gl->GenBuffers(1, &ebo);
|
||||||
|
|
||||||
std::vector<glm::vec3> positions;
|
std::vector<glm::vec3> positions;
|
||||||
std::vector<glm::vec2> uv;
|
std::vector<glm::vec2> uv;
|
||||||
|
@ -158,35 +159,35 @@ void Renderer::IblUtils::renderSphere(QOpenGLFunctions_4_5_Core* glFunc)
|
||||||
data.push_back(uv[i].y);
|
data.push_back(uv[i].y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glFunc->glBindVertexArray(sphereVAO);
|
gl->BindVertexArray(sphereVAO);
|
||||||
glFunc->glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
gl->BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
glFunc->glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
|
gl->BufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
|
||||||
glFunc->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
glFunc->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
|
gl->BufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
|
||||||
unsigned int stride = (3 + 2 + 3) * sizeof(float);
|
unsigned int stride = (3 + 2 + 3) * sizeof(float);
|
||||||
glFunc->glEnableVertexAttribArray(0);
|
gl->EnableVertexAttribArray(0);
|
||||||
glFunc->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);
|
gl->VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);
|
||||||
glFunc->glEnableVertexAttribArray(1);
|
gl->EnableVertexAttribArray(1);
|
||||||
glFunc->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float)));
|
gl->VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)(3 * sizeof(float)));
|
||||||
glFunc->glEnableVertexAttribArray(2);
|
gl->EnableVertexAttribArray(2);
|
||||||
glFunc->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float)));
|
gl->VertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, stride, (void*)(6 * sizeof(float)));
|
||||||
}
|
}
|
||||||
|
|
||||||
glFunc->glBindVertexArray(sphereVAO);
|
gl->BindVertexArray(sphereVAO);
|
||||||
glFunc->glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0);
|
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
|
// pbr: setup framebuffer
|
||||||
// ----------------------
|
// ----------------------
|
||||||
unsigned int captureFBO;
|
unsigned int captureFBO;
|
||||||
unsigned int captureRBO;
|
unsigned int captureRBO;
|
||||||
glFunc->glCreateFramebuffers(1, &captureFBO);
|
gl->CreateFramebuffers(1, &captureFBO);
|
||||||
glFunc->glCreateRenderbuffers(1, &captureRBO);
|
gl->CreateRenderbuffers(1, &captureRBO);
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||||
glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO);
|
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
|
// 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[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));
|
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 envCubemap = generateCubemap(gl, captureFBO, captureRBO, captureProjection, captureViews);
|
||||||
GLuint irradianceMap = generateIrradianceMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
GLuint irradianceMap = generateIrradianceMap(gl, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
||||||
GLuint prefilterMap = generatePrefilterMap(glFunc, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
GLuint prefilterMap = generatePrefilterMap(gl, captureFBO, captureRBO, captureProjection, captureViews, envCubemap);
|
||||||
GLuint brdfLut = gererateBrdfLut(glFunc);
|
GLuint brdfLut = gererateBrdfLut(gl);
|
||||||
return { envCubemap, irradianceMap, prefilterMap, brdfLut };
|
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
|
// pbr: load the HDR environment map
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
@ -217,14 +218,14 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL
|
||||||
unsigned int hdrTexture = 0;
|
unsigned int hdrTexture = 0;
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
glFunc->glGenTextures(1, &hdrTexture);
|
gl->GenTextures(1, &hdrTexture);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture);
|
gl->BindTexture(GL_TEXTURE_2D, hdrTexture);
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data);
|
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);
|
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
gl->TexParameteri(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_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
stbi_image_free(data);
|
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
|
// pbr: setup cubemap to render to and attach to framebuffer
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
unsigned int envCubemap;
|
unsigned int envCubemap;
|
||||||
glFunc->glGenTextures(1, &envCubemap);
|
gl->GenTextures(1, &envCubemap);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(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)
|
gl->TexParameteri(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_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
|
||||||
// pbr: convert HDR equirectangular environment map to cubemap equivalent
|
// 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.bind();
|
||||||
shader.setUniformValue("equirectangularMap", 0);
|
shader.setUniformValue("equirectangularMap", 0);
|
||||||
shader.setUniformValue("projection", captureProjection);
|
shader.setUniformValue("projection", captureProjection);
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
gl->ActiveTexture(GL_TEXTURE0);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture);
|
gl->BindTexture(GL_TEXTURE_2D, hdrTexture);
|
||||||
|
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize);
|
gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize);
|
||||||
glFunc->glViewport(0, 0, cubemapSize, cubemapSize);
|
gl->Viewport(0, 0, cubemapSize, cubemapSize);
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||||
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
shader.setUniformValue("view", captureViews[i]);
|
shader.setUniformValue("view", captureViews[i]);
|
||||||
glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, envCubemap, 0);
|
gl->FramebufferTexture2D(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->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)
|
// then let OpenGL generate mipmaps from first mip face (combatting visible dots artifact)
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
||||||
glFunc->glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
gl->GenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||||
|
|
||||||
return envCubemap;
|
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.
|
// pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale.
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
unsigned int irradianceMap;
|
unsigned int irradianceMap;
|
||||||
glFunc->glGenTextures(1, &irradianceMap);
|
gl->GenTextures(1, &irradianceMap);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap);
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
gl->TexParameteri(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_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, irradianceMapSize, irradianceMapSize);
|
gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, irradianceMapSize, irradianceMapSize);
|
||||||
|
|
||||||
// pbr: solve diffuse integral by convolution to create an irradiance (cube)map.
|
// 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.bind();
|
||||||
irradianceShader.setUniformValue("environmentMap", 0);
|
irradianceShader.setUniformValue("environmentMap", 0);
|
||||||
irradianceShader.setUniformValue("projection", captureProjection);
|
irradianceShader.setUniformValue("projection", captureProjection);
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
gl->ActiveTexture(GL_TEXTURE0);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
||||||
|
|
||||||
glFunc->glViewport(0, 0, irradianceMapSize, irradianceMapSize); // don't forget to configure the viewport to the capture dimensions.
|
gl->Viewport(0, 0, irradianceMapSize, irradianceMapSize); // don't forget to configure the viewport to the capture dimensions.
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
irradianceShader.setUniformValue("view", captureViews[i]);
|
irradianceShader.setUniformValue("view", captureViews[i]);
|
||||||
glFunc->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradianceMap, 0);
|
gl->FramebufferTexture2D(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->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;
|
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.
|
// pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale.
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
unsigned int prefilterMap;
|
unsigned int prefilterMap;
|
||||||
glFunc->glGenTextures(1, &prefilterMap);
|
gl->GenTextures(1, &prefilterMap);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap);
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(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);
|
gl->TexParameteri(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
|
gl->TexParameteri(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_MAG_FILTER, GL_LINEAR);
|
||||||
// generate mipmaps for the cubemap so OpenGL automatically allocates the required memory.
|
// 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.
|
// 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.bind();
|
||||||
prefilterShader.setUniformValue("environmentMap", 0);
|
prefilterShader.setUniformValue("environmentMap", 0);
|
||||||
prefilterShader.setUniformValue("projection", captureProjection);
|
prefilterShader.setUniformValue("projection", captureProjection);
|
||||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
gl->ActiveTexture(GL_TEXTURE0);
|
||||||
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
gl->BindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
|
||||||
|
|
||||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||||
unsigned int maxMipLevels = 5;
|
unsigned int maxMipLevels = 5;
|
||||||
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
|
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
|
||||||
{
|
{
|
||||||
// reisze framebuffer according to mip-level size.
|
// reisze framebuffer according to mip-level size.
|
||||||
unsigned int mipWidth = static_cast<unsigned int>(prefilterMapSize * std::pow(0.5, mip));
|
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));
|
unsigned int mipHeight = static_cast<unsigned int>(prefilterMapSize * std::pow(0.5, mip));
|
||||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
gl->BindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
||||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight);
|
gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight);
|
||||||
glFunc->glViewport(0, 0, mipWidth, mipHeight);
|
gl->Viewport(0, 0, mipWidth, mipHeight);
|
||||||
|
|
||||||
float roughness = (float)mip / (float)(maxMipLevels - 1);
|
float roughness = (float)mip / (float)(maxMipLevels - 1);
|
||||||
prefilterShader.setUniformValue("roughness", roughness);
|
prefilterShader.setUniformValue("roughness", roughness);
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
prefilterShader.setUniformValue("view", captureViews[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);
|
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 prefilterMap;
|
return prefilterMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc)
|
GLuint Renderer::IblUtils::gererateBrdfLut(GladGLContext* gl)
|
||||||
{
|
{
|
||||||
constexpr int lutSize = 512;
|
constexpr int lutSize = 512;
|
||||||
|
|
||||||
// pbr: generate a 2D LUT from the BRDF equations used.
|
// pbr: generate a 2D LUT from the BRDF equations used.
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
unsigned int brdfLUTTexture;
|
unsigned int brdfLUTTexture;
|
||||||
glFunc->glGenTextures(1, &brdfLUTTexture);
|
gl->GenTextures(1, &brdfLUTTexture);
|
||||||
|
|
||||||
// pre-allocate enough memory for the LUT texture.
|
// pre-allocate enough memory for the LUT texture.
|
||||||
glFunc->glBindTexture(GL_TEXTURE_2D, brdfLUTTexture);
|
gl->BindTexture(GL_TEXTURE_2D, brdfLUTTexture);
|
||||||
glFunc->glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, lutSize, lutSize, 0, GL_RG, GL_FLOAT, 0);
|
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
|
// be sure to set wrapping mode to GL_CLAMP_TO_EDGE
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glFunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
gl->TexParameteri(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_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
QOpenGLShaderProgram brdfShader;
|
QOpenGLShaderProgram brdfShader;
|
||||||
if (!brdfShader.addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/brdf_lut.comp"))
|
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())
|
if (!brdfShader.link())
|
||||||
qDebug() << "ERROR:" << brdfShader.log();
|
qDebug() << "ERROR:" << brdfShader.log();
|
||||||
brdfShader.bind();
|
brdfShader.bind();
|
||||||
glFunc->glBindImageTexture(0, brdfLUTTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG16F);
|
gl->BindImageTexture(0, brdfLUTTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG16F);
|
||||||
glFunc->glDispatchCompute(ceil(lutSize / 8.), ceil(lutSize / 8.), 1);
|
gl->DispatchCompute(ceil(lutSize / 8.), ceil(lutSize / 8.), 1);
|
||||||
brdfShader.release();
|
brdfShader.release();
|
||||||
return brdfLUTTexture;
|
return brdfLUTTexture;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QOpenGLFunctions_4_5_Core>
|
#include <QOpenGLFunctions_4_5_Core>
|
||||||
|
struct GladGLContext;
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
class IblUtils
|
class IblUtils
|
||||||
|
@ -9,8 +9,8 @@ namespace Renderer
|
||||||
static constexpr int cubemapSize = 1024;
|
static constexpr int cubemapSize = 1024;
|
||||||
static constexpr int irradianceMapSize = 32;
|
static constexpr int irradianceMapSize = 32;
|
||||||
static constexpr int prefilterMapSize = 128;
|
static constexpr int prefilterMapSize = 128;
|
||||||
static void renderCube(QOpenGLFunctions_4_5_Core* glFunc);
|
static void renderCube(GladGLContext* gl);
|
||||||
static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc);
|
static void renderSphere(GladGLContext* gl);
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* @return GLuint envCubemap
|
* @return GLuint envCubemap
|
||||||
|
@ -18,11 +18,11 @@ namespace Renderer
|
||||||
* @return GLuint prefilterMap
|
* @return GLuint prefilterMap
|
||||||
* @return GLuint brdfLut
|
* @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:
|
private:
|
||||||
static GLuint generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews);
|
static GLuint generateCubemap(GladGLContext* gl, 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 generateIrradianceMap(GladGLContext* gl, 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 generatePrefilterMap(GladGLContext* gl, 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 gererateBrdfLut(GladGLContext* gl);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Renderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
|
QVector3D lightDirection = QVector3D(0.2, 4, 1).normalized();
|
||||||
|
QVector3D radiance = QVector3D(0, 0, 0);
|
||||||
std::vector<float> shadowCascadeLevels;
|
std::vector<float> shadowCascadeLevels;
|
||||||
float blendRatio = 0.3;
|
float blendRatio = 0.3;
|
||||||
std::vector<float> frustumSizes;
|
std::vector<float> frustumSizes;
|
||||||
|
|
|
@ -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)
|
: glFunc(glFunc)
|
||||||
, shaderProgram(shaderProgram)
|
|
||||||
, shadowProgram(shadowProgram)
|
|
||||||
, VBO(QOpenGLBuffer::VertexBuffer)
|
, VBO(QOpenGLBuffer::VertexBuffer)
|
||||||
, EBO(QOpenGLBuffer::IndexBuffer)
|
, EBO(QOpenGLBuffer::IndexBuffer)
|
||||||
, model(model)
|
, model(model)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void Mesh::draw()
|
void Mesh::draw(QOpenGLShaderProgram* shaderProgram)
|
||||||
{
|
{
|
||||||
if (shaderProgram->bind())
|
if (shaderProgram->bind())
|
||||||
{
|
{
|
||||||
|
@ -43,7 +41,7 @@ void Mesh::draw()
|
||||||
shaderProgram->release();
|
shaderProgram->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Mesh::drawShadow()
|
void Mesh::drawShadow(QOpenGLShaderProgram* shadowProgram)
|
||||||
{
|
{
|
||||||
if (shadowProgram->bind())
|
if (shadowProgram->bind())
|
||||||
{
|
{
|
||||||
|
@ -72,16 +70,17 @@ void Mesh::setupMesh()
|
||||||
EBO.bind();
|
EBO.bind();
|
||||||
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
||||||
|
|
||||||
if (shaderProgram->bind())
|
enum VertexAttribute : GLuint {
|
||||||
{
|
kPosition = 0, kNormal = 1, kTexCoords = 2
|
||||||
shaderProgram->enableAttributeArray(0);
|
};
|
||||||
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
|
|
||||||
shaderProgram->enableAttributeArray(1);
|
glFunc->glEnableVertexAttribArray(kPosition);
|
||||||
shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
|
glFunc->glVertexAttribPointer(kPosition, sizeof(Vertex::Position) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||||
shaderProgram->enableAttributeArray(2);
|
glFunc->glEnableVertexAttribArray(kNormal);
|
||||||
shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
|
glFunc->glVertexAttribPointer(kNormal, sizeof(Vertex::Normal) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
|
||||||
shaderProgram->release();
|
glFunc->glEnableVertexAttribArray(kTexCoords);
|
||||||
}
|
glFunc->glVertexAttribPointer(kTexCoords, sizeof(Vertex::TexCoords) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
|
||||||
|
|
||||||
VAO.release();
|
VAO.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,10 @@ namespace Renderer
|
||||||
|
|
||||||
QMatrix4x4 model;
|
QMatrix4x4 model;
|
||||||
QOpenGLFunctions_4_5_Core* glFunc;
|
QOpenGLFunctions_4_5_Core* glFunc;
|
||||||
QOpenGLShaderProgram* shaderProgram, * shadowProgram;
|
|
||||||
|
|
||||||
Mesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
|
Mesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model);
|
||||||
void draw() override;
|
void draw(QOpenGLShaderProgram* shaderProgram) override;
|
||||||
void drawShadow() override;
|
void drawShadow(QOpenGLShaderProgram* shadowProgram) override;
|
||||||
void setupMesh();
|
void setupMesh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -21,27 +21,28 @@
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
|
Model::Model(QOpenGLContext* context, VirtualTextureManager* vtManager)
|
||||||
QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager)
|
|
||||||
: context(context)
|
: context(context)
|
||||||
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Core>())
|
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Core>())
|
||||||
, shaderProgram(shaderProgram)
|
|
||||||
, paintingProgram(paintingProgram)
|
|
||||||
, shadowProgram(shadowProgram)
|
|
||||||
, vtManager(vtManager)
|
, vtManager(vtManager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::draw() {
|
|
||||||
for (auto& mesh : meshes) {
|
void Model::draw(QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram)
|
||||||
mesh->draw();
|
{
|
||||||
}
|
for (auto& mesh : meshes)
|
||||||
|
mesh->draw(shaderProgram);
|
||||||
|
for (auto& mesh : paintingMeshes)
|
||||||
|
mesh->draw(paintingProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::drawShadow() {
|
void Model::drawShadow(QOpenGLShaderProgram* shadowProgram)
|
||||||
for (auto& mesh : meshes) {
|
{
|
||||||
mesh->drawShadow();
|
for (auto& mesh : meshes)
|
||||||
}
|
mesh->drawShadow(shadowProgram);
|
||||||
|
for (auto& mesh : paintingMeshes)
|
||||||
|
mesh->drawShadow(shadowProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Model::loadModel(QString path)
|
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++)
|
for (unsigned int i = 0; i < node->mNumMeshes; i++)
|
||||||
{
|
processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4);
|
||||||
if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4))
|
|
||||||
meshes.emplace_back(std::move(mesh));
|
|
||||||
|
|
||||||
}
|
|
||||||
// 接下来对它的子节点重复这一过程
|
// 接下来对它的子节点重复这一过程
|
||||||
for (unsigned int i = 0; i < node->mNumChildren; i++)
|
for (unsigned int i = 0; i < node->mNumChildren; i++)
|
||||||
{
|
|
||||||
processNode(node->mChildren[i], scene, mat4 * node->mChildren[i]->mTransformation);
|
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);
|
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);
|
indices.insert(indices.end(), face->mIndices, face->mIndices + face->mNumIndices);
|
||||||
|
|
||||||
if (vertices.empty() || indices.empty())
|
if (vertices.empty() || indices.empty())
|
||||||
return nullptr;
|
return;
|
||||||
|
|
||||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||||
|
|
||||||
|
@ -165,11 +161,11 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
||||||
aiString str;
|
aiString str;
|
||||||
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
|
material->GetTexture(aiTextureType_BASE_COLOR, 0, &str);
|
||||||
return std::string(str.C_Str());
|
return std::string(str.C_Str());
|
||||||
}()); paintingProgram != nullptr && iter != paintingMap.end())
|
}()); iter != paintingMap.end())
|
||||||
{
|
{
|
||||||
qDebug() << iter->first.c_str() << "Replaced";
|
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& [paintingPath, leftBottom, rightTop] = iter->second;
|
||||||
auto [paintingId, ratio] = loadPainting(paintingPath);
|
auto [paintingId, ratio] = loadPainting(paintingPath);
|
||||||
|
@ -188,11 +184,10 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
||||||
mesh->indices = indices;
|
mesh->indices = indices;
|
||||||
|
|
||||||
mesh->setupMesh();
|
mesh->setupMesh();
|
||||||
return mesh;
|
|
||||||
}
|
}
|
||||||
else
|
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->vertices = vertices;
|
||||||
mesh->indices = indices;
|
mesh->indices = indices;
|
||||||
|
|
||||||
|
@ -214,7 +209,6 @@ std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh->setupMesh();
|
mesh->setupMesh();
|
||||||
return mesh;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,16 @@
|
||||||
#include "VirtualTextureManager.h"
|
#include "VirtualTextureManager.h"
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
#include "PaintingMesh.h"
|
||||||
|
|
||||||
namespace Renderer
|
namespace Renderer
|
||||||
{
|
{
|
||||||
class Model
|
class Model
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, VirtualTextureManager* vtManager);
|
Model(QOpenGLContext* context, VirtualTextureManager* vtManager);
|
||||||
void draw();
|
void draw(QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram);
|
||||||
void drawShadow();
|
void drawShadow(QOpenGLShaderProgram* shadowProgram);
|
||||||
void loadModel(QString path);
|
void loadModel(QString path);
|
||||||
void unloadModel();
|
void unloadModel();
|
||||||
const std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>>& getPaintingMap();
|
const std::unordered_map<std::string, std::tuple<std::string, glm::vec2, glm::vec2>>& getPaintingMap();
|
||||||
|
@ -24,9 +25,6 @@ namespace Renderer
|
||||||
private:
|
private:
|
||||||
QOpenGLContext* context = nullptr;
|
QOpenGLContext* context = nullptr;
|
||||||
QOpenGLFunctions_4_5_Core* glFunc = nullptr;
|
QOpenGLFunctions_4_5_Core* glFunc = nullptr;
|
||||||
QOpenGLShaderProgram* shaderProgram = nullptr;
|
|
||||||
QOpenGLShaderProgram* paintingProgram = nullptr;
|
|
||||||
QOpenGLShaderProgram* shadowProgram = nullptr;
|
|
||||||
VirtualTextureManager* vtManager = 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::tuple<std::string, glm::vec2, glm::vec2>> paintingMap;
|
||||||
std::unordered_map<std::string, std::pair<GLuint, float>> paintingLoaded;
|
std::unordered_map<std::string, std::pair<GLuint, float>> paintingLoaded;
|
||||||
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
|
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; /// 模型所在路径
|
QDir directory; /// 模型所在路径
|
||||||
QString name; /// 模型文件名
|
QString name; /// 模型文件名
|
||||||
|
@ -46,7 +45,7 @@ namespace Renderer
|
||||||
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
|
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);
|
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
#include "PaintingMesh.h"
|
#include "PaintingMesh.h"
|
||||||
using namespace Renderer;
|
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)
|
: glFunc(glFunc)
|
||||||
, shaderProgram(shaderProgram)
|
|
||||||
, shadowProgram(shadowProgram)
|
|
||||||
, VBO(QOpenGLBuffer::VertexBuffer)
|
, VBO(QOpenGLBuffer::VertexBuffer)
|
||||||
, EBO(QOpenGLBuffer::IndexBuffer)
|
, EBO(QOpenGLBuffer::IndexBuffer)
|
||||||
, model(model)
|
, model(model)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void PaintingMesh::draw()
|
void PaintingMesh::draw(QOpenGLShaderProgram* shaderProgram)
|
||||||
{
|
{
|
||||||
if (shaderProgram->bind())
|
if (shaderProgram->bind())
|
||||||
{
|
{
|
||||||
|
@ -26,7 +24,7 @@ void PaintingMesh::draw()
|
||||||
shaderProgram->release();
|
shaderProgram->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void PaintingMesh::drawShadow()
|
void PaintingMesh::drawShadow(QOpenGLShaderProgram* shadowProgram)
|
||||||
{
|
{
|
||||||
if (shadowProgram->bind())
|
if (shadowProgram->bind())
|
||||||
{
|
{
|
||||||
|
@ -54,16 +52,17 @@ void PaintingMesh::setupMesh()
|
||||||
EBO.bind();
|
EBO.bind();
|
||||||
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
EBO.allocate(indices.data(), indices.size() * sizeof(unsigned int));
|
||||||
|
|
||||||
if (shaderProgram->bind())
|
enum VertexAttribute : GLuint {
|
||||||
{
|
kPosition = 0, kNormal = 1, kTexCoords = 2
|
||||||
shaderProgram->enableAttributeArray(0);
|
};
|
||||||
shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(Vertex));
|
|
||||||
shaderProgram->enableAttributeArray(1);
|
glFunc->glEnableVertexAttribArray(kPosition);
|
||||||
shaderProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
|
glFunc->glVertexAttribPointer(kPosition, sizeof(Vertex::Position) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||||
shaderProgram->enableAttributeArray(2);
|
glFunc->glEnableVertexAttribArray(kNormal);
|
||||||
shaderProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(Vertex, TexCoords), 2, sizeof(Vertex));
|
glFunc->glVertexAttribPointer(kNormal, sizeof(Vertex::Normal) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
|
||||||
shaderProgram->release();
|
glFunc->glEnableVertexAttribArray(kTexCoords);
|
||||||
}
|
glFunc->glVertexAttribPointer(kTexCoords, sizeof(Vertex::TexCoords) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
|
||||||
|
|
||||||
VAO.release();
|
VAO.release();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,11 @@ namespace Renderer
|
||||||
GLuint textureMetallicRoughness;
|
GLuint textureMetallicRoughness;
|
||||||
QMatrix4x4 model;
|
QMatrix4x4 model;
|
||||||
QOpenGLFunctions_4_5_Core* glFunc;
|
QOpenGLFunctions_4_5_Core* glFunc;
|
||||||
QOpenGLShaderProgram* shaderProgram, * shadowProgram;
|
|
||||||
GLuint paintingId;
|
GLuint paintingId;
|
||||||
|
|
||||||
PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
|
PaintingMesh(QOpenGLFunctions_4_5_Core* glFunc, const QMatrix4x4& model);
|
||||||
void draw() override;
|
void draw(QOpenGLShaderProgram* shaderProgram) override;
|
||||||
void drawShadow() override;
|
void drawShadow(QOpenGLShaderProgram* shadowProgram) override;
|
||||||
void setupMesh();
|
void setupMesh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
using namespace Renderer;
|
using namespace Renderer;
|
||||||
|
|
||||||
QVector3D mainLightRadiance = 10 * QVector3D(0.7529, 0.7450, 0.6784).normalized();
|
|
||||||
static float sunPitch = 105, sunYaw = 80;
|
static float sunPitch = 105, sunYaw = 80;
|
||||||
static int sunSpeed = 10;
|
static int sunSpeed = 10;
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ RendererGLWidget::RendererGLWidget(QWidget* parent)
|
||||||
, light(&camera)
|
, light(&camera)
|
||||||
{
|
{
|
||||||
//startTimer();
|
//startTimer();
|
||||||
lastFrame = std::clock();
|
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
//QSurfaceFormat format;
|
//QSurfaceFormat format;
|
||||||
//format.setProfile(QSurfaceFormat::CoreProfile);
|
//format.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
|
@ -34,27 +32,6 @@ RendererGLWidget::RendererGLWidget(QWidget* parent)
|
||||||
|
|
||||||
RendererGLWidget::~RendererGLWidget()
|
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()
|
void RendererGLWidget::startTimer()
|
||||||
|
@ -95,7 +72,7 @@ void RendererGLWidget::setModel(QString path)
|
||||||
|
|
||||||
void Renderer::RendererGLWidget::setMainLightRadiance(QVector3D radiance)
|
void Renderer::RendererGLWidget::setMainLightRadiance(QVector3D radiance)
|
||||||
{
|
{
|
||||||
mainLightRadiance = radiance;
|
light.radiance = radiance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererGLWidget::setMainLightPitch(float pitch)
|
void RendererGLWidget::setMainLightPitch(float pitch)
|
||||||
|
@ -151,45 +128,16 @@ void RendererGLWidget::initializeGL()
|
||||||
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||||
gl->ClearColor(0, 0, 0, 1);
|
gl->ClearColor(0, 0, 0, 1);
|
||||||
|
|
||||||
shadowProgramPtr = new QOpenGLShaderProgram;
|
vtManager = std::make_unique<VirtualTextureManager>(gl.get());
|
||||||
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert"))
|
model = new Model(context(), vtManager.get());
|
||||||
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();
|
|
||||||
|
|
||||||
plainProgramPtr = new QOpenGLShaderProgram;
|
shadowMapPass = std::make_unique<ShadowMapPass>(gl.get(), shadowFboHandle, shadowMapResolution, light, model);
|
||||||
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert"))
|
geometryPass = std::make_unique<GeometryPass>(gl.get(), frameWidth, frameHeight, fboPtr, model, projection, view);
|
||||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
pageIDCallbackPass = std::make_unique<PageIDCallbackPass>(gl.get(), frameWidth, frameHeight, fboPtr, gbuffers, gPageID, *vtManager);
|
||||||
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag"))
|
lightingPass = std::make_unique<LightingPass>(gl.get(), frameWidth, frameHeight, view, camera, light,
|
||||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
gBaseColor, gNormal, gPosition, gMetallicRoughness, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
|
||||||
if (!plainProgramPtr->link())
|
finalPass = std::make_unique<FinalPass>(gl.get(), frameWidth, frameHeight, gBaseColor, exposure);
|
||||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
skyboxPass = std::make_unique<SkyboxPass>(gl.get(), projection, view, exposure, skyCubemap);
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
depthInitProgramPtr = new QOpenGLShaderProgram;
|
depthInitProgramPtr = new QOpenGLShaderProgram;
|
||||||
if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp"))
|
if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp"))
|
||||||
|
@ -203,58 +151,16 @@ void RendererGLWidget::initializeGL()
|
||||||
if (!depthMipmapProgramPtr->link())
|
if (!depthMipmapProgramPtr->link())
|
||||||
qCritical() << "ERROR:" << depthMipmapProgramPtr->log();
|
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;
|
ssgiProgramPtr = new QOpenGLShaderProgram;
|
||||||
if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp"))
|
if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp"))
|
||||||
qCritical() << "ERROR:" << ssgiProgramPtr->log();
|
qCritical() << "ERROR:" << ssgiProgramPtr->log();
|
||||||
if (!ssgiProgramPtr->link())
|
if (!ssgiProgramPtr->link())
|
||||||
qCritical() << "ERROR:" << ssgiProgramPtr->log();
|
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->bind();
|
||||||
depthInitProgramPtr->setUniformValue("depthBuffer", 0);
|
depthInitProgramPtr->setUniformValue("depthBuffer", 0);
|
||||||
depthInitProgramPtr->release();
|
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->bind();
|
||||||
ssgiProgramPtr->setUniformValue("gBaseColor", 0);
|
ssgiProgramPtr->setUniformValue("gBaseColor", 0);
|
||||||
ssgiProgramPtr->setUniformValue("gNormal", 1);
|
ssgiProgramPtr->setUniformValue("gNormal", 1);
|
||||||
|
@ -263,44 +169,21 @@ void RendererGLWidget::initializeGL()
|
||||||
ssgiProgramPtr->setUniformValue("gDepth", 4);
|
ssgiProgramPtr->setUniformValue("gDepth", 4);
|
||||||
ssgiProgramPtr->setUniformValue("gDirectLight", 5);
|
ssgiProgramPtr->setUniformValue("gDirectLight", 5);
|
||||||
|
|
||||||
finalProgramPtr->bind();
|
std::tie(skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture) = IblUtils::precomputeCubemaps(gl.get());
|
||||||
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();
|
|
||||||
|
|
||||||
gl->GenQueries(1, &timeQuery);
|
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()
|
void RendererGLWidget::paintGL()
|
||||||
{
|
{
|
||||||
QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
|
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.setZ(cos(qDegreesToRadians(sunPitch)) * sin(qDegreesToRadians(sunYaw)));
|
||||||
light.lightDirection.normalize();
|
light.lightDirection.normalize();
|
||||||
|
|
||||||
const std::vector<QMatrix4x4> lightMatrices = light.getLightSpaceMatrices();
|
projection = camera.GetProjectionMatrix();
|
||||||
gl->BindBuffer(GL_UNIFORM_BUFFER, lightSpaceMatricesUBO);
|
view = camera.GetViewMatrix();
|
||||||
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);
|
|
||||||
|
|
||||||
vtManager->commitMutex.lock();
|
vtManager->commitMutex.lock();
|
||||||
{
|
shadowMapPass->dispatch();
|
||||||
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
|
geometryPass->dispatch();
|
||||||
gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution);
|
pageIDCallbackPass->dispatch();
|
||||||
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();
|
|
||||||
}
|
|
||||||
gl->Finish();
|
gl->Finish();
|
||||||
vtManager->commitMutex.unlock();
|
vtManager->commitMutex.unlock();
|
||||||
|
lightingPass->dispatch();
|
||||||
//depthInitProgramPtr->bind();
|
finalPass->dispatch();
|
||||||
//gl->ActiveTexture(GL_TEXTURE0);
|
skyboxPass->dispatch();
|
||||||
//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();
|
|
||||||
|
|
||||||
gl->EndQuery(GL_TIME_ELAPSED);
|
gl->EndQuery(GL_TIME_ELAPSED);
|
||||||
GLuint frameDuration;
|
GLuint frameDuration;
|
||||||
gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration);
|
gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration);
|
||||||
|
|
||||||
clock_t currentFrame = std::clock();
|
float deltaTime = calculateDeltaTime();
|
||||||
deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC;
|
|
||||||
lastFrame = currentFrame;
|
|
||||||
|
|
||||||
static float accTime = 0, frameCnt = 0, averageDuration = 0;
|
static float accTime = 0, frameCnt = 0, averageDuration = 0;
|
||||||
accTime += deltaTime;
|
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_MIN_FILTER, GL_NEAREST);
|
||||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
|
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
|
||||||
//gPaintingIndex
|
//gPageID
|
||||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[4]);
|
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->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_MIN_FILTER, GL_NEAREST);
|
||||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
|
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0);
|
||||||
//PaintingTexCoord
|
//PaintingTexCoord, Deprecated
|
||||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[5]);
|
gl->BindTexture(GL_TEXTURE_2D, gbuffers[5]);
|
||||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, frameWidth, frameHeight, 0, GL_RG, GL_FLOAT, NULL);
|
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_MIN_FILTER, GL_NEAREST);
|
||||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
|
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_2D, gbuffers[5], 0);
|
||||||
//Depth
|
//Depth, Deprecated
|
||||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]);
|
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->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);
|
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)
|
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
qDebug() << "Framebuffer not complete!";
|
qDebug() << "Framebuffer not complete!";
|
||||||
|
|
||||||
//HiZ, not bind to fbo
|
//HiZ, not bind to fbo, Deprecated
|
||||||
depthWidth = ceil(frameWidth / 64.) * 64;
|
depthWidth = ceil(frameWidth / 64.) * 64;
|
||||||
depthHeight = ceil(frameHeight / 64.) * 64;
|
depthHeight = ceil(frameHeight / 64.) * 64;
|
||||||
qDebug() << depthWidth << depthHeight;
|
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_S, GL_CLAMP_TO_BORDER);
|
||||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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 }));
|
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->BindTexture(GL_TEXTURE_2D, gbuffers[8]);
|
||||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL);
|
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_MIN_FILTER, GL_NEAREST);
|
||||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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->BindTexture(GL_TEXTURE_2D, gbuffers[9]);
|
||||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL);
|
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_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -624,9 +347,6 @@ void RendererGLWidget::resizeGL(int width, int height)
|
||||||
fboPtr->release();
|
fboPtr->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (shadowFboHandle != 0)
|
if (shadowFboHandle != 0)
|
||||||
{
|
{
|
||||||
gl->DeleteTextures(1, &shadowGbuffer);
|
gl->DeleteTextures(1, &shadowGbuffer);
|
||||||
|
@ -663,7 +383,6 @@ void RendererGLWidget::resizeGL(int width, int height)
|
||||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << "\033[?25l";
|
std::cout << "\033[?25l";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Light.h"
|
#include "Light.h"
|
||||||
#include "Model.h"
|
#include "Model.h"
|
||||||
|
#include "RenderPass.h"
|
||||||
|
|
||||||
struct GladGLContext;
|
struct GladGLContext;
|
||||||
|
|
||||||
|
@ -46,39 +47,47 @@ namespace Renderer
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int timerId = -1;
|
int timerId = -1;
|
||||||
int frameWidth, frameHeight;
|
unsigned int frameWidth, frameHeight;
|
||||||
int depthWidth, depthHeight;
|
int depthWidth, depthHeight;
|
||||||
QSet<int> pressedKeys;
|
QSet<int> pressedKeys;
|
||||||
Camera camera;
|
Camera camera;
|
||||||
Light light;
|
Light light;
|
||||||
clock_t lastFrame;
|
|
||||||
float deltaTime;
|
|
||||||
int shadowMapResolution;
|
int shadowMapResolution;
|
||||||
float exposure = 0.8;
|
float exposure = 0.8;
|
||||||
|
|
||||||
|
QMatrix4x4 projection;
|
||||||
|
QMatrix4x4 view;
|
||||||
|
|
||||||
std::unique_ptr<GladGLContext> gl;
|
std::unique_ptr<GladGLContext> gl;
|
||||||
QOpenGLShaderProgram* shadowProgramPtr = nullptr;
|
|
||||||
QOpenGLShaderProgram* plainProgramPtr = nullptr;
|
std::unique_ptr<ShadowMapPass> shadowMapPass;
|
||||||
QOpenGLShaderProgram* modelProgramPtr = nullptr;
|
std::unique_ptr<GeometryPass> geometryPass;
|
||||||
QOpenGLShaderProgram* paintingProgramPtr = nullptr;
|
std::unique_ptr<PageIDCallbackPass> pageIDCallbackPass;
|
||||||
QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr;
|
std::unique_ptr<LightingPass> lightingPass;
|
||||||
|
std::unique_ptr<FinalPass> finalPass;
|
||||||
|
std::unique_ptr<SkyboxPass> skyboxPass;
|
||||||
|
|
||||||
QOpenGLShaderProgram* depthInitProgramPtr = nullptr;
|
QOpenGLShaderProgram* depthInitProgramPtr = nullptr;
|
||||||
QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr;
|
QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr;
|
||||||
QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr;
|
|
||||||
QOpenGLShaderProgram* ssgiProgramPtr = nullptr;
|
QOpenGLShaderProgram* ssgiProgramPtr = nullptr;
|
||||||
QOpenGLShaderProgram* finalProgramPtr = nullptr;
|
|
||||||
QOpenGLShaderProgram* skyBoxProgramPtr = nullptr;
|
|
||||||
QOpenGLFramebufferObject* fboPtr = nullptr;
|
QOpenGLFramebufferObject* fboPtr = nullptr;
|
||||||
|
|
||||||
GLuint gbuffers[10];
|
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 shadowFboHandle = 0;
|
||||||
GLuint shadowGbuffer;
|
GLuint shadowGbuffer;
|
||||||
GLuint lightSpaceMatricesUBO;
|
|
||||||
GLuint skyCubemap;
|
GLuint skyCubemap;
|
||||||
GLuint irradianceMap;
|
GLuint irradianceMap;
|
||||||
GLuint prefilterMap;
|
GLuint prefilterMap;
|
||||||
GLuint brdfLUTTexture;
|
GLuint brdfLUTTexture;
|
||||||
QOpenGLBuffer quadVBO;
|
|
||||||
QOpenGLVertexArrayObject quadVAO;
|
|
||||||
Model* model = nullptr;
|
Model* model = nullptr;
|
||||||
std::unique_ptr<VirtualTextureManager> vtManager;
|
std::unique_ptr<VirtualTextureManager> vtManager;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue