WE BE RENDERING BABY
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <destrum/FS/AssetFS.h>
|
||||
|
||||
#include "glm/gtx/transform.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
App::App(): renderer{meshCache} {
|
||||
@@ -49,6 +50,11 @@ void App::init(const AppParams& params) {
|
||||
float aspectRatio = static_cast<float>(params.renderSize.x) / static_cast<float>(params.renderSize.y);
|
||||
camera.setAspectRatio(aspectRatio);
|
||||
|
||||
//Look 90 deg to the right
|
||||
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
|
||||
|
||||
inputManager.Init();
|
||||
|
||||
}
|
||||
|
||||
void App::run() {
|
||||
@@ -84,6 +90,7 @@ void App::run() {
|
||||
}
|
||||
|
||||
while (accumulator >= dt) {
|
||||
inputManager.BeginFrame();
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
@@ -99,28 +106,68 @@ void App::run() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
inputManager.ProcessEvent(event);
|
||||
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_W)) {
|
||||
camera.m_position += camera.GetForward() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_S)) {
|
||||
camera.m_position -= camera.GetForward() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_A)) {
|
||||
camera.m_position -= camera.GetRight() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_D)) {
|
||||
camera.m_position += camera.GetRight() * dt * 5.f;
|
||||
}
|
||||
|
||||
// rotation
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_LEFT)) {
|
||||
camera.SetRotation(camera.GetYaw() - glm::radians(90.f) * dt, camera.GetPitch());
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_RIGHT)) {
|
||||
camera.SetRotation(camera.GetYaw() + glm::radians(90.f) * dt, camera.GetPitch());
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_UP)) {
|
||||
camera.SetRotation(camera.GetYaw(), camera.GetPitch() + glm::radians(90.f) * dt);
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_DOWN)) {
|
||||
camera.SetRotation(camera.GetYaw(), camera.GetPitch() - glm::radians(90.f) * dt);
|
||||
}
|
||||
|
||||
camera.Update(dt);
|
||||
|
||||
}
|
||||
|
||||
if (gfxDevice.needsSwapchainRecreate()) {
|
||||
spdlog::info("Recreating swapchain to size: {}x{}", m_params.windowSize.x, m_params.windowSize.y);
|
||||
gfxDevice.recreateSwapchain(m_params.windowSize.x, m_params.windowSize.y);
|
||||
renderer.resize(gfxDevice, { m_params.windowSize.x, m_params.windowSize.y });
|
||||
float aspectRatio = float(m_params.windowSize.x) / float(m_params.windowSize.y);
|
||||
camera.setAspectRatio(aspectRatio);
|
||||
}
|
||||
|
||||
accumulator -= dt;
|
||||
}
|
||||
|
||||
if (!gfxDevice.needsSwapchainRecreate()) {
|
||||
glm::mat4 objMatrix = glm::mat4(1.f);
|
||||
objMatrix = glm::translate(objMatrix, glm::vec3(0.f, -3.0f, 0.f));
|
||||
renderer.beginDrawing(gfxDevice);
|
||||
renderer.drawMesh(testMeshID, glm::mat4(1.f), 0);
|
||||
renderer.drawMesh(testMeshID, objMatrix, 0);
|
||||
renderer.endDrawing();
|
||||
|
||||
|
||||
auto cmd = gfxDevice.beginFrame();
|
||||
const auto& drawImage = renderer.getDrawImage(gfxDevice);
|
||||
renderer.draw(cmd, gfxDevice, camera, GameRenderer::SceneData{
|
||||
camera, glm::vec3(0.1f), 0.5f, glm::vec3(0.5f), 0.01f
|
||||
});
|
||||
gfxDevice.endFrame(cmd, GPUImage{}, {});
|
||||
gfxDevice.endFrame(cmd, drawImage, {
|
||||
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
|
||||
.drawImageBlitRect = glm::ivec4{}}
|
||||
);
|
||||
}
|
||||
if (frameLimit) {
|
||||
// Delay to not overload the CPU
|
||||
|
||||
@@ -193,3 +193,28 @@ void Camera::Target(const glm::vec3& target) {
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
|
||||
void Camera::SetRotation(float yawRadians, float pitchRadians) {
|
||||
m_yaw = yawRadians;
|
||||
m_pitch = glm::clamp(
|
||||
pitchRadians,
|
||||
-glm::half_pi<float>() + 0.001f,
|
||||
glm::half_pi<float>() - 0.001f
|
||||
);
|
||||
|
||||
// Yaw around world Y, pitch around local Z (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
|
||||
// Forward is +X in your camera space
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0)));
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_useTarget = false; // rotation overrides target mode
|
||||
}
|
||||
|
||||
void Camera::SetRotation(const glm::vec2& yawPitchRadians) {
|
||||
SetRotation(yawPitchRadians.x, yawPitchRadians.y);
|
||||
}
|
||||
|
||||
@@ -160,49 +160,49 @@ void GfxDevice::endFrame(VkCommandBuffer cmd, const GPUImage& drawImage, const E
|
||||
auto swapchainLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
{
|
||||
// clear swapchain image
|
||||
VkImageSubresourceRange clearRange =
|
||||
vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
VkImageSubresourceRange clearRange =vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
vkutil::transitionImage(cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_GENERAL);
|
||||
swapchainLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
|
||||
const auto clearValue = props.clearColor;
|
||||
vkCmdClearColorImage(cmd, swapchainImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange);
|
||||
}
|
||||
|
||||
// if (props.copyImageIntoSwapchain) {
|
||||
if (true) {
|
||||
// copy from draw image into swapchain
|
||||
// vkutil::transitionImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
vkutil::transitionImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
vkutil::transitionImage(
|
||||
cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
swapchainLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
// const auto filter = props.drawImageLinearBlit ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
const auto filter = VK_FILTER_LINEAR;
|
||||
// // if (props.drawImageBlitRect != glm::ivec4{}) {
|
||||
// vkutil::copyImageToImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// swapchainImage,
|
||||
// drawImage.getExtent2D(),
|
||||
// props.drawImageBlitRect.x,
|
||||
// props.drawImageBlitRect.y,
|
||||
// props.drawImageBlitRect.z,
|
||||
// props.drawImageBlitRect.w,
|
||||
// filter);
|
||||
// } else {
|
||||
// // will stretch image to swapchain
|
||||
// vkutil::copyImageToImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// swapchainImage,
|
||||
// drawImage.getExtent2D(),
|
||||
// getSwapchainExtent(),
|
||||
// filter);
|
||||
// }
|
||||
auto filter = false ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
filter = VK_FILTER_NEAREST;
|
||||
if (false) {
|
||||
vkutil::copyImageToImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
swapchainImage,
|
||||
drawImage.getExtent2D(),
|
||||
props.drawImageBlitRect.x,
|
||||
props.drawImageBlitRect.y,
|
||||
props.drawImageBlitRect.z,
|
||||
props.drawImageBlitRect.w,
|
||||
filter);
|
||||
} else {
|
||||
// will stretch image to swapchain
|
||||
vkutil::copyImageToImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
swapchainImage,
|
||||
drawImage.getExtent2D(),
|
||||
getSwapchainExtent(),
|
||||
filter);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare for present
|
||||
vkutil::transitionImage(cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <destrum/Graphics/Util.h>
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
GameRenderer::GameRenderer(MeshCache& meshCache): meshCache{meshCache} {
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
.colorImageView = drawImage.imageView,
|
||||
.colorImageClearValue = glm::vec4{0.f, 0.f, 0.f, 1.f},
|
||||
.depthImageView = depthImage.imageView,
|
||||
.depthImageClearValue = 0.f,
|
||||
.depthImageClearValue = 1.f,
|
||||
});
|
||||
|
||||
vkCmdBeginRendering(cmd, &renderInfo.renderingInfo);
|
||||
@@ -99,6 +101,10 @@ void GameRenderer::drawMesh(MeshID id, const glm::mat4& transform, MaterialId ma
|
||||
});
|
||||
}
|
||||
|
||||
const GPUImage& GameRenderer::getDrawImage(const GfxDevice& gfx_device) const {
|
||||
return gfx_device.getImage(drawImageId);
|
||||
}
|
||||
|
||||
void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
||||
const glm::ivec2& drawImageSize,
|
||||
bool firstCreate)
|
||||
@@ -144,6 +150,7 @@ void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
||||
};
|
||||
|
||||
depthImageId = gfxDevice.createImage(createInfo, "depth image", nullptr, depthImageId);
|
||||
spdlog::info("Created depth image with id {}", depthImageId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ void Swapchain::createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint
|
||||
|
||||
// TODO: if re-creation of swapchain is supported, don't forget to call
|
||||
// vkutil::initSwapchainViews here.
|
||||
|
||||
extent = m_swapchain.extent;
|
||||
}
|
||||
|
||||
void Swapchain::recreateSwapchain(const GfxDevice& gfxDevice, VkFormat format, std::uint32_t width, std::uint32_t height, bool vSync) {
|
||||
@@ -98,6 +100,7 @@ void Swapchain::recreateSwapchain(const GfxDevice& gfxDevice, VkFormat format, s
|
||||
imageViews = m_swapchain.get_image_views().value();
|
||||
|
||||
dirty = false;
|
||||
extent = m_swapchain.extent;
|
||||
}
|
||||
|
||||
void Swapchain::cleanup() {
|
||||
|
||||
148
destrum/src/Input/InputManager.cpp
Normal file
148
destrum/src/Input/InputManager.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include <destrum/Input/InputManager.h>
|
||||
|
||||
void InputManager::Init() {
|
||||
// Nothing mandatory here. You can also enable relative mouse mode, etc.
|
||||
// SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
}
|
||||
|
||||
void InputManager::BeginFrame() {
|
||||
m_keysPressed.clear();
|
||||
m_keysReleased.clear();
|
||||
m_mousePressed.clear();
|
||||
m_mouseReleased.clear();
|
||||
|
||||
m_wheelX = 0;
|
||||
m_wheelY = 0;
|
||||
|
||||
m_textInput.clear();
|
||||
|
||||
// Update mouse delta based on last known position
|
||||
m_mouseDX = m_mouseX - m_prevMouseX;
|
||||
m_mouseDY = m_mouseY - m_prevMouseY;
|
||||
m_prevMouseX = m_mouseX;
|
||||
m_prevMouseY = m_mouseY;
|
||||
}
|
||||
|
||||
void InputManager::ProcessEvent(const SDL_Event& e) {
|
||||
switch (e.type) {
|
||||
case SDL_KEYDOWN: {
|
||||
if (e.key.repeat) break; // avoid repeat spam for "Pressed"
|
||||
SDL_Scancode sc = e.key.keysym.scancode;
|
||||
m_keysDown.insert(sc);
|
||||
m_keysPressed.insert(sc);
|
||||
} break;
|
||||
|
||||
case SDL_KEYUP: {
|
||||
SDL_Scancode sc = e.key.keysym.scancode;
|
||||
m_keysDown.erase(sc);
|
||||
m_keysReleased.insert(sc);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN: {
|
||||
Uint8 b = e.button.button;
|
||||
m_mouseDown.insert(b);
|
||||
m_mousePressed.insert(b);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP: {
|
||||
Uint8 b = e.button.button;
|
||||
m_mouseDown.erase(b);
|
||||
m_mouseReleased.insert(b);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEMOTION: {
|
||||
m_mouseX = e.motion.x;
|
||||
m_mouseY = e.motion.y;
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEWHEEL: {
|
||||
// Accumulate wheel per frame
|
||||
m_wheelX += e.wheel.x;
|
||||
m_wheelY += e.wheel.y;
|
||||
} break;
|
||||
|
||||
case SDL_TEXTINPUT: {
|
||||
// text typed this frame
|
||||
m_textInput += e.text.text;
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputManager::IsKeyDown(SDL_Scancode sc) const {
|
||||
return m_keysDown.find(sc) != m_keysDown.end();
|
||||
}
|
||||
bool InputManager::WasKeyPressed(SDL_Scancode sc) const {
|
||||
return m_keysPressed.find(sc) != m_keysPressed.end();
|
||||
}
|
||||
bool InputManager::WasKeyReleased(SDL_Scancode sc) const {
|
||||
return m_keysReleased.find(sc) != m_keysReleased.end();
|
||||
}
|
||||
|
||||
bool InputManager::IsMouseDown(Uint8 button) const {
|
||||
return m_mouseDown.find(button) != m_mouseDown.end();
|
||||
}
|
||||
bool InputManager::WasMousePressed(Uint8 button) const {
|
||||
return m_mousePressed.find(button) != m_mousePressed.end();
|
||||
}
|
||||
bool InputManager::WasMouseReleased(Uint8 button) const {
|
||||
return m_mouseReleased.find(button) != m_mouseReleased.end();
|
||||
}
|
||||
|
||||
void InputManager::StartTextInput() {
|
||||
if (!m_textInputActive) {
|
||||
SDL_StartTextInput();
|
||||
m_textInputActive = true;
|
||||
}
|
||||
}
|
||||
void InputManager::StopTextInput() {
|
||||
if (m_textInputActive) {
|
||||
SDL_StopTextInput();
|
||||
m_textInputActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::BindAction(const std::string& action, const Binding& binding) {
|
||||
m_bindings[action].push_back(binding);
|
||||
}
|
||||
|
||||
bool InputManager::QueryBinding(const Binding& b, ButtonState state) const {
|
||||
switch (b.device) {
|
||||
case Device::Keyboard: {
|
||||
auto sc = static_cast<SDL_Scancode>(b.code);
|
||||
if (state == ButtonState::Down) return IsKeyDown(sc);
|
||||
if (state == ButtonState::Pressed) return WasKeyPressed(sc);
|
||||
if (state == ButtonState::Released) return WasKeyReleased(sc);
|
||||
} break;
|
||||
|
||||
case Device::MouseButton: {
|
||||
auto mb = static_cast<Uint8>(b.code);
|
||||
if (state == ButtonState::Down) return IsMouseDown(mb);
|
||||
if (state == ButtonState::Pressed) return WasMousePressed(mb);
|
||||
if (state == ButtonState::Released) return WasMouseReleased(mb);
|
||||
} break;
|
||||
|
||||
case Device::MouseWheel: {
|
||||
// Encoding:
|
||||
// +1/-1 => wheel Y (up/down), +2/-2 => wheel X (right/left)
|
||||
const int c = b.code;
|
||||
if (state != ButtonState::Pressed) return false; // wheel is "impulse"
|
||||
if (c == 1) return m_wheelY > 0;
|
||||
if (c == -1) return m_wheelY < 0;
|
||||
if (c == 2) return m_wheelX > 0;
|
||||
if (c == -2) return m_wheelX < 0;
|
||||
} break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputManager::GetAction(const std::string& action, ButtonState state) const {
|
||||
auto it = m_bindings.find(action);
|
||||
if (it == m_bindings.end()) return false;
|
||||
|
||||
for (const auto& b : it->second) {
|
||||
if (QueryBinding(b, state)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user