添加MainWIndow类

main
wuyize 2023-04-16 18:34:50 +08:00
parent b06f08cd84
commit 6234a31673
5 changed files with 315 additions and 289 deletions

View File

@ -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" />

View File

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

View File

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

View File

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

View File

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