添加MainWIndow类
parent
b06f08cd84
commit
6234a31673
|
@ -26,6 +26,7 @@
|
|||
<ClInclude Include="src\Camera.h" />
|
||||
<ClInclude Include="src\IblUtils.h" />
|
||||
<ClInclude Include="src\Light.h" />
|
||||
<ClInclude Include="src\MainWindow.h" />
|
||||
<ClInclude Include="src\Mesh.h" />
|
||||
<ClInclude Include="src\Model.h" />
|
||||
<ClInclude Include="src\RenderPass.h" />
|
||||
|
@ -41,6 +42,7 @@
|
|||
<ClCompile Include="src\IblUtils.cpp" />
|
||||
<ClCompile Include="src\Light.cpp" />
|
||||
<ClCompile Include="src\main.cpp" />
|
||||
<ClCompile Include="src\MainWindow.cpp" />
|
||||
<ClCompile Include="src\Mesh.cpp" />
|
||||
<ClCompile Include="src\Model.cpp" />
|
||||
<ClCompile Include="src\RenderPass.cpp" />
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
<ClInclude Include="src\Actor.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\MainWindow.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\gl.c">
|
||||
|
@ -89,6 +92,9 @@
|
|||
<ClCompile Include="src\Actor.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\MainWindow.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Shaders\brdf_lut.comp">
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
#include "MainWindow.h"
|
||||
#include "IblUtils.h"
|
||||
#include "RenderPass.h"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: camera(glm::vec3(0.0f, 0.0f, 3.0f))
|
||||
, light(&camera)
|
||||
{
|
||||
}
|
||||
|
||||
void MainWindow::processInput(GLFWwindow* window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.processKeyboard(FORWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.processKeyboard(BACKWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.processKeyboard(LEFT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.processKeyboard(RIGHT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
|
||||
camera.processKeyboard(UP, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
|
||||
camera.processKeyboard(DOWN, deltaTime);
|
||||
|
||||
glm::mat4 transform(1);
|
||||
float speed = 1;
|
||||
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, speed)));
|
||||
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, -speed)));
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(-speed, 0, 0)));
|
||||
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(speed, 0, 0)));
|
||||
}
|
||||
|
||||
void MainWindow::framebufferSizeCallback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
frameWidth = width;
|
||||
frameHeight = height;
|
||||
camera.Ratio = (float)frameWidth / (float)frameHeight;
|
||||
if (fbo)
|
||||
{
|
||||
gl->DeleteRenderbuffers(1, &rboDepth);
|
||||
gl->DeleteTextures(gbuffers.size(), gbuffers.data());
|
||||
gl->DeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
|
||||
gl->CreateFramebuffers(1, &fbo);
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
{
|
||||
gl->GenTextures(gbuffers.size(), gbuffers.data());
|
||||
//BaseColor
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameWidth, frameHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gbuffers[0], 0);
|
||||
//Normal
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gbuffers[1], 0);
|
||||
//Position
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0);
|
||||
//MetallicRoughness
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG8, frameWidth, frameHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
|
||||
|
||||
std::array<GLenum, 4> attachments = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
|
||||
gl->DrawBuffers(attachments.size(), attachments.data());
|
||||
gl->GenRenderbuffers(1, &rboDepth);
|
||||
gl->BindRenderbuffer(GL_RENDERBUFFER, rboDepth);
|
||||
gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, frameWidth, frameHeight);
|
||||
gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cerr << "Framebuffer not complete!\n";
|
||||
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
if (shadowFboHandle != 0)
|
||||
{
|
||||
gl->DeleteTextures(1, &shadowGbuffer);
|
||||
gl->DeleteFramebuffers(1, &shadowFboHandle);
|
||||
}
|
||||
|
||||
shadowMapResolution = 2048;
|
||||
gl->GenFramebuffers(1, &shadowFboHandle);
|
||||
{
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
|
||||
gl->GenTextures(1, &shadowGbuffer);
|
||||
//Depth
|
||||
gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
|
||||
gl->TexImage3D(
|
||||
GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, (int)light.shadowCascadeLevels.size(),
|
||||
0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
|
||||
gl->FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowGbuffer, 0);
|
||||
gl->DrawBuffer(GL_NONE);
|
||||
gl->ReadBuffer(GL_NONE);
|
||||
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cerr << "ShadowFramebuffer not complete!\n";
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::mouseCallback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
static bool firstMouse = true;
|
||||
static float lastX;
|
||||
static float lastY;
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
if (firstMouse)
|
||||
{
|
||||
firstMouse = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
|
||||
{
|
||||
float speed = 0.2f;
|
||||
glm::mat4 rotate(1);
|
||||
rotate = glm::rotate(rotate, glm::radians(glm::length(glm::vec2(xoffset, yoffset)) * speed), glm::vec3(glm::vec2(-yoffset, xoffset), 0.0));
|
||||
modelPtr->setTransform(rotate);
|
||||
}
|
||||
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
|
||||
camera.processMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void MainWindow::scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.processMouseScroll(yoffset);
|
||||
}
|
||||
|
||||
MainWindow& MainWindow::instance()
|
||||
{
|
||||
static MainWindow window;
|
||||
return window;
|
||||
}
|
||||
|
||||
int MainWindow::exec()
|
||||
{
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
float xscale, yscale;
|
||||
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||
GLFWwindow* window = glfwCreateWindow(kWindowWidth * xscale, kWindowHeight * yscale, "RenderModel", NULL, NULL);
|
||||
MainWindow& m = *this;
|
||||
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
|
||||
MainWindow::instance().framebufferSizeCallback(window, width, height);
|
||||
});
|
||||
glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos) {
|
||||
MainWindow::instance().mouseCallback(window, xpos, ypos);
|
||||
});
|
||||
glfwSetScrollCallback(window, [](GLFWwindow* window, double xoffset, double yoffset) {
|
||||
MainWindow::instance().scrollCallback(window, xoffset, yoffset);
|
||||
});
|
||||
int xpos, ypos, width, height;
|
||||
glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
|
||||
glfwSetWindowPos(window, xpos + (width - (kWindowWidth * xscale)) / 2, ypos + (height - kWindowHeight * yscale) / 2);
|
||||
glfwMakeContextCurrent(window);
|
||||
gl = std::make_unique<GladGLContext>();
|
||||
if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); }))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
gl->Enable(GL_DEBUG_OUTPUT);
|
||||
//gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
gl->DebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
|
||||
if (type == GL_DEBUG_TYPE_ERROR)
|
||||
std::cerr << std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}", type, severity, message);
|
||||
}, 0);
|
||||
gl->ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
gl->Enable(GL_DEPTH_TEST);
|
||||
gl->DepthFunc(GL_LEQUAL);
|
||||
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
|
||||
std::string modelFilePath;
|
||||
//modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj";
|
||||
//modelFilePath = "E:\\3D Objects\\plane\\plane.gltf";
|
||||
modelFilePath = "E:\\3D Objects\\vampire/gltf/vampire.gltf";
|
||||
//modelFilePath = "E:\\3D Objects\\cup\\cup.gltf";
|
||||
//modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf";
|
||||
|
||||
Model model(gl.get(), modelFilePath);
|
||||
modelPtr = &model;
|
||||
light.model = &model;
|
||||
|
||||
Animation danceAnimation(modelFilePath, &model);
|
||||
Animator animator(&danceAnimation);
|
||||
|
||||
glm::mat4 projection, view;
|
||||
auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get());
|
||||
|
||||
ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, model, light);
|
||||
GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, model, projection, view, animator);
|
||||
LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance,
|
||||
gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
|
||||
FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure);
|
||||
SkyboxPass skyboxPass(gl.get(), projection, view, exposure, skyCubemap);
|
||||
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
framebufferSizeCallback(window, w, h);
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
processInput(window);
|
||||
|
||||
animator.UpdateAnimation(deltaTime);
|
||||
|
||||
projection = camera.getProjectionMatrix();
|
||||
view = camera.getViewMatrix();
|
||||
|
||||
shadowMapPass.dispatch();
|
||||
geometryPass.dispatch();
|
||||
lightingPass.dispatch();
|
||||
finalPass.dispatch();
|
||||
skyboxPass.dispatch();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include "Model.h"
|
||||
#include "Camera.h"
|
||||
#include "Light.h"
|
||||
#include <array>
|
||||
#include <glad/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
class MainWindow
|
||||
{
|
||||
public:
|
||||
static MainWindow& instance();
|
||||
int exec();
|
||||
|
||||
private:
|
||||
MainWindow();
|
||||
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
||||
void mouseCallback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow* window);
|
||||
|
||||
static constexpr int kWindowWidth = 1200;
|
||||
static constexpr int kWindowHeight = 675;
|
||||
unsigned int frameWidth;
|
||||
unsigned int frameHeight;
|
||||
|
||||
Model* modelPtr = nullptr;
|
||||
Camera camera;
|
||||
Light light;
|
||||
glm::vec3 mainLightRadiance = 40.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
|
||||
float exposure = 1;
|
||||
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
std::unique_ptr<GladGLContext> gl;
|
||||
|
||||
GLuint fbo = 0;
|
||||
std::array<GLuint, 4> gbuffers;
|
||||
GLuint rboDepth = 0;
|
||||
GLuint shadowFboHandle = 0;
|
||||
GLuint shadowGbuffer;
|
||||
int shadowMapResolution;
|
||||
};
|
||||
|
|
@ -1,299 +1,12 @@
|
|||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#include <glad/gl.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include "Shader.h"
|
||||
#include "camera.h"
|
||||
#include "Model.h"
|
||||
#include "IblUtils.h"
|
||||
#include "Light.h"
|
||||
#include "RenderPass.h"
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <format>
|
||||
#include "Animation.h"
|
||||
#include "Animator.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
extern "C" {
|
||||
_declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
||||
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
||||
void mouseCallback(GLFWwindow* window, double xpos, double ypos);
|
||||
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void processInput(GLFWwindow* window);
|
||||
|
||||
constexpr int windowWidth = 1200;
|
||||
constexpr int windowHeight = 675;
|
||||
unsigned int frameWidth;
|
||||
unsigned int frameHeight;
|
||||
|
||||
Model* modelPtr = nullptr;
|
||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||
Light light(&camera);
|
||||
glm::vec3 mainLightRadiance = 40.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
|
||||
float exposure = 1;
|
||||
|
||||
float deltaTime = 0.0f;
|
||||
float lastFrame = 0.0f;
|
||||
|
||||
std::unique_ptr<GladGLContext> gl;
|
||||
|
||||
GLuint fbo = 0;
|
||||
std::array<GLuint, 4> gbuffers;
|
||||
GLuint rboDepth = 0;
|
||||
GLuint shadowFboHandle = 0;
|
||||
GLuint shadowGbuffer;
|
||||
int shadowMapResolution;
|
||||
|
||||
void GLAPIENTRY messageCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
const void* userParam)
|
||||
{
|
||||
if (type == GL_DEBUG_TYPE_ERROR)
|
||||
std::cerr << std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}",
|
||||
type, severity, message);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
float xscale, yscale;
|
||||
glfwGetMonitorContentScale(monitor, &xscale, &yscale);
|
||||
GLFWwindow* window = glfwCreateWindow(windowWidth * xscale, windowHeight * yscale, "RenderModel", NULL, NULL);
|
||||
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
|
||||
glfwSetCursorPosCallback(window, mouseCallback);
|
||||
glfwSetScrollCallback(window, scrollCallback);
|
||||
int xpos, ypos, width, height;
|
||||
glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
|
||||
glfwSetWindowPos(window, xpos + (width - (windowWidth * xscale)) / 2, ypos + (height - windowHeight * yscale) / 2);
|
||||
glfwMakeContextCurrent(window);
|
||||
gl = std::make_unique<GladGLContext>();
|
||||
if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)glfwGetProcAddress(name); }))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
gl->Enable(GL_DEBUG_OUTPUT);
|
||||
//gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
gl->DebugMessageCallback(messageCallback, 0);
|
||||
gl->ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
gl->Enable(GL_DEPTH_TEST);
|
||||
gl->DepthFunc(GL_LEQUAL);
|
||||
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
|
||||
std::string modelFilePath;
|
||||
//modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj";
|
||||
//modelFilePath = "E:\\3D Objects\\plane\\plane.gltf";
|
||||
modelFilePath = "E:\\3D Objects\\vampire/gltf/vampire.gltf";
|
||||
//modelFilePath = "E:\\3D Objects\\cup\\cup.gltf";
|
||||
//modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf";
|
||||
|
||||
Model model(gl.get(), modelFilePath);
|
||||
modelPtr = &model;
|
||||
light.model = &model;
|
||||
|
||||
Animation danceAnimation(modelFilePath, &model);
|
||||
Animator animator(&danceAnimation);
|
||||
|
||||
glm::mat4 projection, view;
|
||||
auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get());
|
||||
|
||||
ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, model, light);
|
||||
GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, model, projection, view, animator);
|
||||
LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance,
|
||||
gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
|
||||
FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure);
|
||||
SkyboxPass skyboxPass(gl.get(), projection, view, exposure, skyCubemap);
|
||||
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
framebufferSizeCallback(window, w, h);
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
processInput(window);
|
||||
|
||||
animator.UpdateAnimation(deltaTime);
|
||||
|
||||
projection = camera.getProjectionMatrix();
|
||||
view = camera.getViewMatrix();
|
||||
|
||||
shadowMapPass.dispatch();
|
||||
geometryPass.dispatch();
|
||||
lightingPass.dispatch();
|
||||
finalPass.dispatch();
|
||||
skyboxPass.dispatch();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void processInput(GLFWwindow* window)
|
||||
{
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
camera.processKeyboard(FORWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
camera.processKeyboard(BACKWARD, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
camera.processKeyboard(LEFT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
camera.processKeyboard(RIGHT, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
|
||||
camera.processKeyboard(UP, deltaTime);
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
|
||||
camera.processKeyboard(DOWN, deltaTime);
|
||||
|
||||
glm::mat4 transform(1);
|
||||
float speed = 1;
|
||||
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, speed)));
|
||||
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(0, 0, -speed)));
|
||||
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(-speed, 0, 0)));
|
||||
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
|
||||
modelPtr->setTransform(glm::translate(transform, glm::vec3(speed, 0, 0)));
|
||||
}
|
||||
|
||||
void framebufferSizeCallback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
frameWidth = width;
|
||||
frameHeight = height;
|
||||
camera.Ratio = (float)frameWidth / (float)frameHeight;
|
||||
if (fbo)
|
||||
{
|
||||
gl->DeleteRenderbuffers(1, &rboDepth);
|
||||
gl->DeleteTextures(gbuffers.size(), gbuffers.data());
|
||||
gl->DeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
|
||||
gl->CreateFramebuffers(1, &fbo);
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
{
|
||||
gl->GenTextures(gbuffers.size(), gbuffers.data());
|
||||
//BaseColor
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frameWidth, frameHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gbuffers[0], 0);
|
||||
//Normal
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gbuffers[1], 0);
|
||||
//Position
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, frameWidth, frameHeight, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gbuffers[2], 0);
|
||||
//MetallicRoughness
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG8, frameWidth, frameHeight, 0, GL_RG, GL_UNSIGNED_BYTE, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
|
||||
|
||||
std::array<GLenum, 4> attachments = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
|
||||
gl->DrawBuffers(attachments.size(), attachments.data());
|
||||
gl->GenRenderbuffers(1, &rboDepth);
|
||||
gl->BindRenderbuffer(GL_RENDERBUFFER, rboDepth);
|
||||
gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, frameWidth, frameHeight);
|
||||
gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cerr << "Framebuffer not complete!\n";
|
||||
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
if (shadowFboHandle != 0)
|
||||
{
|
||||
gl->DeleteTextures(1, &shadowGbuffer);
|
||||
gl->DeleteFramebuffers(1, &shadowFboHandle);
|
||||
}
|
||||
|
||||
shadowMapResolution = 2048;
|
||||
gl->GenFramebuffers(1, &shadowFboHandle);
|
||||
{
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
|
||||
gl->GenTextures(1, &shadowGbuffer);
|
||||
//Depth
|
||||
gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
|
||||
gl->TexImage3D(
|
||||
GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, shadowMapResolution, shadowMapResolution, (int)light.shadowCascadeLevels.size(),
|
||||
0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
|
||||
gl->FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowGbuffer, 0);
|
||||
gl->DrawBuffer(GL_NONE);
|
||||
gl->ReadBuffer(GL_NONE);
|
||||
|
||||
if (gl->CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
std::cerr << "ShadowFramebuffer not complete!\n";
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mouseCallback(GLFWwindow* window, double xpos, double ypos)
|
||||
{
|
||||
static bool firstMouse = true;
|
||||
static float lastX;
|
||||
static float lastY;
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos;
|
||||
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
|
||||
if (firstMouse)
|
||||
{
|
||||
firstMouse = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
|
||||
{
|
||||
float speed = 0.2f;
|
||||
glm::mat4 rotate(1);
|
||||
rotate = glm::rotate(rotate, glm::radians(glm::length(glm::vec2(xoffset, yoffset)) * speed), glm::vec3(glm::vec2(-yoffset, xoffset), 0.0));
|
||||
modelPtr->setTransform(rotate);
|
||||
}
|
||||
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
|
||||
camera.processMouseMovement(xoffset, yoffset);
|
||||
}
|
||||
|
||||
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
camera.processMouseScroll(yoffset);
|
||||
return MainWindow::instance().exec();
|
||||
}
|
Loading…
Reference in New Issue