Allow changing present mode

This commit is contained in:
bailehuni 2024-04-26 23:31:34 +01:00
parent 5b60668f71
commit e9e78966be
13 changed files with 308 additions and 107 deletions

View File

@ -29,23 +29,24 @@ enum class MSAALevel {
k16X,
};
enum class PresentMode {
kDoubleBufferedNoVsync,
kDoubleBufferedVsync,
kTripleBuffered,
};
struct GraphicsSettings {
GraphicsSettings()
{
// sane defaults
enable_validation = true;
vsync = true;
// not all GPUs/drivers support immediate present with V-sync enabled
wait_for_present = true;
enable_validation = false;
present_mode = PresentMode::kDoubleBufferedVsync;
msaa_level = MSAALevel::kOff;
enable_anisotropy = false; // anisotropic filtering can severely affect performance on intel iGPUs
}
bool enable_validation;
bool vsync;
// idle CPU after render until the frame has been presented
// (no affect with V-sync disabled)
bool wait_for_present;
PresentMode present_mode;
MSAALevel msaa_level;
bool enable_anisotropy;
};

View File

@ -19,6 +19,9 @@ class GFXDevice {
void GetViewportSize(uint32_t* w, uint32_t* h);
void ChangePresentMode(gfx::PresentMode mode);
gfx::PresentMode GetPresentMode();
void SetupImguiBackend();
void ShutdownImguiBackend();
void CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);

View File

@ -118,8 +118,9 @@ void main() {
lighting *= (1.0 - shadow);
const vec3 ambient_light = vec3(0.09082, 0.13281, 0.18164) * 2.4;
lighting += mix(ambient_light, texture(globalSetSkybox, R).rgb, metallic) * ao * diffuse_brdf; // this is NOT physically-based, it just looks cool
const vec3 ambient_light = vec3(0.09082, 0.13281, 0.18164) * 2.4 * 0.1;
//lighting += mix(ambient_light, texture(globalSetSkybox, R).rgb, metallic) * ao * diffuse_brdf; // this is NOT physically-based, it just looks cool
lighting += (ambient_light * ao * diffuse_brdf);
// tone mapping
const vec3 hdr_color = emission + lighting;

View File

@ -75,6 +75,39 @@ static std::filesystem::path getResourcesPath()
return resourcesPath;
}
#ifdef _WIN32
static std::string openGLTFDialog() {
OPENFILENAMEA ofn; // common dialog box structure
CHAR szFile[260] = { 0 }; // if using TCHAR macros, use TCHAR array
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "GLTF Files (*.gltf;*.glb)\0*.gltf;*.glb\0All Files (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
// Display the Open dialog box
if (GetOpenFileNameA(&ofn) == TRUE)
{
return ofn.lpstrFile;
}
else
{
return ""; // User cancelled the dialog
}
}
#endif
static auto frametimeFromFPS(int fps) { return std::chrono::nanoseconds(1'000'000'000 / fps); }
Application::Application(const char* appName, const char* appVersion, gfx::GraphicsSettings graphicsSettings, Configuration configuration)
: app_name(appName), app_version(appVersion), configuration_(configuration)
{
@ -184,11 +217,6 @@ void Application::GameLoop()
{
LOG_DEBUG("Begin game loop...");
constexpr int FPS_LIMIT = 240;
constexpr auto FRAMETIME_LIMIT = std::chrono::nanoseconds(1000000000 / FPS_LIMIT);
auto beginFrame = std::chrono::steady_clock::now();
auto endFrame = beginFrame + FRAMETIME_LIMIT;
auto lastTick = window_->GetNanos();
std::array<float, 20> delta_times{};
@ -196,8 +224,29 @@ void Application::GameLoop()
bool menu_active = false;
bool show_entity_boxes = false;
bool show_bounding_volumes = false;
bool enable_frame_limiter = false;
bool triple_buffering = false;
bool vsync = false;
bool show_info_window = false;
} debug_menu_state;
debug_menu_state.enable_frame_limiter = configuration_.enable_frame_limiter;
switch (renderer_->GetDevice()->GetPresentMode()) {
case gfx::PresentMode::kDoubleBufferedNoVsync:
debug_menu_state.triple_buffering = false;
debug_menu_state.vsync = false;
break;
case gfx::PresentMode::kDoubleBufferedVsync:
debug_menu_state.triple_buffering = false;
debug_menu_state.vsync = true;
break;
case gfx::PresentMode::kTripleBuffered:
debug_menu_state.triple_buffering = true;
debug_menu_state.vsync = false;
}
int fps_limit = 240;
auto beginFrame = std::chrono::steady_clock::now();
auto endFrame = beginFrame + frametimeFromFPS(fps_limit);
// single-threaded game loop
while (window_->IsRunning()) {
@ -225,16 +274,71 @@ void Application::GameLoop()
debug_menu_state.show_info_window = !debug_menu_state.show_info_window;
}
if (window_->GetKeyPress(inputs::Key::K_L)) {
debug_menu_state.enable_frame_limiter ^= true;
}
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
//ImGui::ShowDemoWindow();
// Stop mouse from moving the camera when the settings menu is open
input_manager_->SetDeviceActive(InputDevice::kMouse, !debug_menu_state.menu_active);
if (debug_menu_state.menu_active) {
if (ImGui::Begin("debugMenu", 0)) {
ImGui::Text("Test!");
if (ImGui::Begin("Settings", 0)) {
ImGui::Text("FPS: %.3f", std::roundf(avg_fps));
ImGui::Checkbox("Show entity hitboxes?", &debug_menu_state.show_entity_boxes);
ImGui::Checkbox("Show bounding volumes?", &debug_menu_state.show_bounding_volumes);
ImGui::Checkbox("Enable FPS limiter", &debug_menu_state.enable_frame_limiter);
if (debug_menu_state.enable_frame_limiter) {
ImGui::SliderInt("FPS limit", &fps_limit, 10, 360);
}
if (debug_menu_state.triple_buffering) {
ImGui::BeginDisabled();
}
if (ImGui::Checkbox("Enable vsync", &debug_menu_state.vsync)) {
if (debug_menu_state.vsync) {
renderer_->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync);
}
else {
renderer_->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync);
}
}
if (debug_menu_state.triple_buffering) {
ImGui::EndDisabled();
}
if (ImGui::Checkbox("Triple buffering", &debug_menu_state.triple_buffering)) {
if (debug_menu_state.triple_buffering) {
debug_menu_state.vsync = false;
renderer_->GetDevice()->ChangePresentMode(gfx::PresentMode::kTripleBuffered);
}
else {
if (debug_menu_state.vsync) {
renderer_->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedVsync);
}
else {
renderer_->GetDevice()->ChangePresentMode(gfx::PresentMode::kDoubleBufferedNoVsync);
}
}
}
ImGui::Separator();
ImGui::Checkbox("Show entity hitboxes", &debug_menu_state.show_entity_boxes);
ImGui::Checkbox("Show bounding volumes", &debug_menu_state.show_bounding_volumes);
ImGui::Separator();
#ifndef _WIN32
ImGui::BeginDisabled();
#endif
// load gltf file dialog
if (ImGui::Button("Load glTF")) {
#ifdef _WIN32
std::string path = std::filesystem::path(openGLTFDialog()).string();
#endif
}
#ifndef _WIN32
ImGui::EndDisabled();
#endif
}
ImGui::End();
}
@ -281,62 +385,86 @@ void Application::GameLoop()
for (const auto& node : colsys->bvh_) {
if (node.type1 == CollisionSystem::BiTreeNode::Type::Entity) {
const glm::vec3 col =
(node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
Line line1{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
(node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{1.0f, 0.0f, 0.0f} : glm::vec3{0.0f, 1.0f, 0.0f};
Line line1{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col};
debug_lines.push_back(line1);
Line line2{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
Line line2{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col};
debug_lines.push_back(line2);
Line line3{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
Line line3{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col};
debug_lines.push_back(line3);
Line line4{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
Line line4{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col};
debug_lines.push_back(line4);
Line line5{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, col };
Line line5{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line5);
Line line6{ glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line6{glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line6);
Line line7{ glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line7{glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line7);
Line line8{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, col };
Line line8{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line8);
Line line9{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line9{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line9);
Line line10{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line10{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line10);
Line line11{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line11{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line11);
Line line12{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line12{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line12);
}
if (node.type2 == CollisionSystem::BiTreeNode::Type::Entity) {
const glm::vec3 col =
(node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
Line line1{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
(node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{1.0f, 0.0f, 0.0f} : glm::vec3{0.0f, 1.0f, 0.0f};
Line line1{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col};
debug_lines.push_back(line1);
Line line2{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
Line line2{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col};
debug_lines.push_back(line2);
Line line3{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
Line line3{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col};
debug_lines.push_back(line3);
Line line4{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
Line line4{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col};
debug_lines.push_back(line4);
Line line5{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, col };
Line line5{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line5);
Line line6{ glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line6{glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line6);
Line line7{ glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line7{glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line7);
Line line8{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, col };
Line line8{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line8);
Line line9{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line9{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line9);
Line line10{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line10{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line10);
Line line11{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line11{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line11);
Line line12{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line12{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line12);
}
}
@ -347,62 +475,86 @@ void Application::GameLoop()
for (const auto& node : colsys->bvh_) {
if (node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) {
const glm::vec3 col =
(node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
Line line1{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
(node.type1 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{1.0f, 0.0f, 0.0f} : glm::vec3{0.0f, 1.0f, 0.0f};
Line line1{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col};
debug_lines.push_back(line1);
Line line2{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
Line line2{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col};
debug_lines.push_back(line2);
Line line3{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col };
Line line3{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, col};
debug_lines.push_back(line3);
Line line4{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col };
Line line4{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, col};
debug_lines.push_back(line4);
Line line5{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, col };
Line line5{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line5);
Line line6{ glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line6{glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line6);
Line line7{ glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line7{glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line7);
Line line8{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z}, glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, col };
Line line8{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.min.z},
glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line8);
Line line9{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line9{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line9);
Line line10{ glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line10{glm::vec3{node.box1.min.x, node.box1.min.y, node.box1.max.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line10);
Line line11{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col };
Line line11{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z},
glm::vec3{node.box1.max.x, node.box1.min.y, node.box1.max.z}, col};
debug_lines.push_back(line11);
Line line12{ glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z}, glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col };
Line line12{glm::vec3{node.box1.max.x, node.box1.max.y, node.box1.max.z},
glm::vec3{node.box1.min.x, node.box1.max.y, node.box1.max.z}, col};
debug_lines.push_back(line12);
}
if (node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) {
const glm::vec3 col =
(node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{ 1.0f, 0.0f, 0.0f } : glm::vec3{ 0.0f, 1.0f, 0.0f };
Line line1{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
(node.type2 == CollisionSystem::BiTreeNode::Type::BoundingVolume) ? glm::vec3{1.0f, 0.0f, 0.0f} : glm::vec3{0.0f, 1.0f, 0.0f};
Line line1{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col};
debug_lines.push_back(line1);
Line line2{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
Line line2{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col};
debug_lines.push_back(line2);
Line line3{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col };
Line line3{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, col};
debug_lines.push_back(line3);
Line line4{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col };
Line line4{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, col};
debug_lines.push_back(line4);
Line line5{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, col };
Line line5{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line5);
Line line6{ glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line6{glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line6);
Line line7{ glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line7{glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line7);
Line line8{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z}, glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, col };
Line line8{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.min.z},
glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line8);
Line line9{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line9{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line9);
Line line10{ glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line10{glm::vec3{node.box2.min.x, node.box2.min.y, node.box2.max.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line10);
Line line11{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col };
Line line11{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z},
glm::vec3{node.box2.max.x, node.box2.min.y, node.box2.max.z}, col};
debug_lines.push_back(line11);
Line line12{ glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z}, glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col };
Line line12{glm::vec3{node.box2.max.x, node.box2.max.y, node.box2.max.z},
glm::vec3{node.box2.min.x, node.box2.max.y, node.box2.max.z}, col};
debug_lines.push_back(line12);
}
}
@ -420,11 +572,22 @@ void Application::GameLoop()
window_->GetInputAndEvents();
/* fps limiter */
if (configuration_.enable_frame_limiter != debug_menu_state.enable_frame_limiter) {
if (debug_menu_state.enable_frame_limiter) {
configuration_.enable_frame_limiter = true;
// reset beginFrame and endFrame so the limiter doesn't hang for ages
beginFrame = std::chrono::steady_clock::now();
endFrame = beginFrame;
}
else {
configuration_.enable_frame_limiter = false;
}
}
if (configuration_.enable_frame_limiter) {
std::this_thread::sleep_until(endFrame);
}
beginFrame = endFrame;
endFrame = beginFrame + FRAMETIME_LIMIT;
endFrame = beginFrame + frametimeFromFPS(fps_limit);
delta_times[window_->GetFrameCount() % delta_times.size()] = window_->dt();
}

View File

@ -474,8 +474,7 @@ GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* wi
pimpl->swapchainInfo.physicalDevice = pimpl->device.physicalDevice;
pimpl->swapchainInfo.surface = pimpl->surface;
pimpl->swapchainInfo.window = pimpl->window;
pimpl->swapchainInfo.vsync = pimpl->graphicsSettings.vsync;
pimpl->swapchainInfo.waitForPresent = pimpl->graphicsSettings.wait_for_present;
pimpl->swapchainInfo.requested_present_mode = pimpl->graphicsSettings.present_mode;
createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo);
/* make synchronisation primitives for rendering and allocate command buffers
@ -577,6 +576,26 @@ void GFXDevice::GetViewportSize(uint32_t* w, uint32_t* h)
}
}
void GFXDevice::ChangePresentMode(gfx::PresentMode mode)
{
pimpl->swapchainInfo.requested_present_mode = mode;
// need to recreate swapchain to apply changes
pimpl->swapchainIsOutOfDate = true;
}
gfx::PresentMode GFXDevice::GetPresentMode() {
switch (pimpl->swapchain.presentMode) {
case VK_PRESENT_MODE_FIFO_KHR:
return gfx::PresentMode::kDoubleBufferedVsync;
case VK_PRESENT_MODE_IMMEDIATE_KHR:
return gfx::PresentMode::kDoubleBufferedNoVsync;
case VK_PRESENT_MODE_MAILBOX_KHR:
return gfx::PresentMode::kTripleBuffered;
default:
throw std::runtime_error("Unknown present mode");
}
}
void GFXDevice::SetupImguiBackend()
{
auto loaderFunc = [](const char* function_name, void* user_data) -> PFN_vkVoidFunction {

View File

@ -4,6 +4,7 @@
#include "application_component.h"
#include "util/files.h"
#include "log.h"
#include <glm/mat4x4.hpp>
#include <glm/trigonometric.hpp>

View File

@ -89,6 +89,8 @@ static glm::mat4 MatFromDoubleArray(const std::vector<double>& arr)
engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
{
LOG_INFO("Loading gltf file: {}", path);
tg::TinyGLTF loader;
tg::Model model;
std::string err, warn;
@ -407,6 +409,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
std::vector<uint32_t> indices;
indices.reserve(num_indices);
// TODO: natively support indices of these sizes instead of having to convert to uint32
if (indices_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) {
for (size_t i = 0; i < num_indices; ++i) {
indices.push_back(*reinterpret_cast<const uint8_t*>(&indices_data_start[i * 1]));
@ -630,7 +633,6 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
if (node.mesh != -1) {
const auto& primitives = primitive_arrays.at(node.mesh);
int i = 0;
if (primitives.size() == 1) {
auto meshren = scene.AddComponent<MeshRenderableComponent>(e);
meshren->mesh = primitives.front().mesh;
@ -639,12 +641,14 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
collider->aabb = primitives.front().aabb;
}
else {
int i = 0;
for (const EnginePrimitive& prim : primitives) {
auto prim_entity = scene.CreateEntity(std::string("_mesh") + std::to_string(i), e);
scene.GetTransform(prim_entity)->is_static = isStatic;
auto meshren = scene.AddComponent<MeshRenderableComponent>(prim_entity);
meshren->mesh = prim.mesh;
meshren->material = prim.material;
auto collider = scene.AddComponent<ColliderComponent>(e);
auto collider = scene.AddComponent<ColliderComponent>(prim_entity);
collider->aabb = prim.aabb;
++i;
}
@ -660,7 +664,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
generateEntities(parent, model.nodes.at(i));
}
LOG_DEBUG("Loaded glTF model: {}", path);
LOG_DEBUG("Loaded glTF file: {}", path);
return parent;
}

View File

@ -53,21 +53,23 @@ namespace engine {
res = vkGetPhysicalDeviceSurfacePresentModesKHR(info.physicalDevice, info.surface, &surfacePresentModeCount, presentModes.data());
assert(res == VK_SUCCESS);
VkPresentModeKHR present_mode_requested;
switch (info.requested_present_mode) {
case gfx::PresentMode::kDoubleBufferedNoVsync:
present_mode_requested = VK_PRESENT_MODE_IMMEDIATE_KHR;
break;
case gfx::PresentMode::kDoubleBufferedVsync:
present_mode_requested = VK_PRESENT_MODE_FIFO_KHR;
break;
case gfx::PresentMode::kTripleBuffered:
present_mode_requested = VK_PRESENT_MODE_MAILBOX_KHR;
}
sc->presentMode = VK_PRESENT_MODE_FIFO_KHR; // This mode is always available
if (info.vsync == true) {
if (info.waitForPresent == false) {
for (const auto& presMode : presentModes) {
if (presMode == VK_PRESENT_MODE_MAILBOX_KHR) {
sc->presentMode = presMode; // this mode allows V-sync without fixing FPS to refresh rate
}
}
}
}
else {
for (const auto& presMode : presentModes) {
if (presMode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
sc->presentMode = presMode; // V-sync off
}
// check requested mode is available
for (VkPresentModeKHR mode : presentModes) {
if (mode == present_mode_requested) {
sc->presentMode = mode;
break;
}
}

View File

@ -9,6 +9,8 @@
#include <vk_mem_alloc.h>
#include "gfx.h"
namespace engine {
struct DepthStencil {
@ -38,8 +40,7 @@ namespace engine {
VkSurfaceKHR surface;
SDL_Window* window;
VmaAllocator allocator;
bool vsync;
bool waitForPresent;
gfx::PresentMode requested_present_mode;
};
void createSwapchain(Swapchain* sc, const SwapchainInfo& info);

View File

@ -169,8 +169,9 @@ void Window::OnMouseMotionEvent(SDL_MouseMotionEvent& e)
else {
mouse_.x = e.x;
mouse_.y = e.y;
mouse_.dx = e.xrel;
mouse_.dy = e.yrel;
// mouse motion events can occur multiple times per frame when FPS drops, these need to be accumulated
mouse_.dx += e.xrel;
mouse_.dy += e.yrel;
}
}
@ -289,6 +290,7 @@ bool Window::SetRelativeMouseMode(bool enabled)
int code = SDL_SetRelativeMouseMode(static_cast<SDL_bool>(enabled));
if (code != 0) {
throw std::runtime_error("Unable to set relative mouse mode");
// return false;
}
else {
return true;

View File

@ -202,6 +202,10 @@ void CameraControllerSystem::OnUpdate(float ts)
scene_->app()->scene_manager()->SetActiveScene(next_scene_);
}
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_Q)) {
c->noclip ^= true;
}
if (scene_->app()->window()->GetButtonPress(engine::inputs::MouseButton::M_LEFT)) {
engine::Ray ray{};
ray.origin = t->position;

View File

@ -8,7 +8,7 @@
struct CameraControllerComponent {
// looking
static constexpr float kCameraSensitivity = 0.007f;
static constexpr float kCameraSensitivity = 0.001f;
static constexpr float kMaxPitch = glm::pi<float>();
static constexpr float kMinPitch = 0.0f;
@ -16,7 +16,7 @@ struct CameraControllerComponent {
static constexpr float kSpeedForwardBack = 4.0f;
static constexpr float kSpeedStrafe = 4.0f;
static constexpr float kSprintMultiplier = 2.0f;
static constexpr float kJumpVelocity = 4.4f;
static constexpr float kJumpVelocity = 4.4f * 2.0f;
// collision
static constexpr float kPlayerHeight = 2.0f; // 71.0f * 25.4f / 1000.0f;
@ -31,7 +31,8 @@ struct CameraControllerComponent {
bool noclip = false;
float yaw = 0.0f;
float pitch = glm::half_pi<float>();
//float pitch = glm::half_pi<float>();
float pitch = 0.0f;
glm::vec3 vel{0.0f, 0.0f, 0.0f};
bool grounded = false;

View File

@ -46,8 +46,7 @@ void PlayGame(GameSettings settings)
engine::gfx::GraphicsSettings graphics_settings{};
graphics_settings.enable_validation = settings.enable_validation;
graphics_settings.vsync = false;
graphics_settings.wait_for_present = false;
graphics_settings.present_mode = engine::gfx::PresentMode::kTripleBuffered;
graphics_settings.msaa_level = engine::gfx::MSAALevel::kOff;
graphics_settings.enable_anisotropy = true;
@ -66,12 +65,12 @@ void PlayGame(GameSettings settings)
/* as of right now, the entity with tag 'camera' is used to build the view
* matrix */
engine::Entity sponza = engine::util::LoadGLTF(*start_scene, app.GetResourcePath("models/tree.glb"), true);
start_scene->GetPosition(sponza).z += 90.0f;
//engine::Entity temple = engine::util::LoadGLTF(*start_scene, "C:/games/temple.glb", true);
start_scene->RegisterComponent<CameraControllerComponent>();
start_scene->RegisterSystem<CameraControllerSystem>();
start_scene->AddComponent<CameraControllerComponent>(camera)->noclip = true;
start_scene->GetPosition(camera).z += 10.0f;
}
engine::Scene* main_scene = app.scene_manager()->CreateEmptyScene();
@ -107,7 +106,7 @@ void PlayGame(GameSettings settings)
// main_scene->GetComponent<engine::TransformComponent>(bottle)->position.z += 5.0f;
engine::Entity helmet = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/DamagedHelmet.glb"), true);
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 1.0f};
main_scene->GetPosition(helmet) += glm::vec3{5.0f, 5.0f, 5.0f};
main_scene->GetScale(helmet) *= 3.0f;
main_scene->GetRotation(helmet) = glm::angleAxis(glm::pi<float>(), glm::vec3{ 0.0f, 0.0f, 1.0f });
main_scene->GetRotation(helmet) *= glm::angleAxis(glm::half_pi<float>(), glm::vec3{ 1.0f, 0.0f, 0.0f });