diff --git a/CMakeLists.txt b/CMakeLists.txt index d70c85e..9f0a232 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ add_executable (pleascach ${SOURCES}) file(GLOB SHADER_SOURCE_FILES assets/shaders/*.frag assets/shaders/*.vert + assets/shaders/*.geom ) foreach(SHADER_SOURCE ${SHADER_SOURCE_FILES}) diff --git a/Input/Input.cpp b/Input/Input.cpp index 6136f43..1e8e5d8 100644 --- a/Input/Input.cpp +++ b/Input/Input.cpp @@ -77,7 +77,11 @@ void Input::handleMovementKeys(Renderer& ren) { if (ImGui::GetIO().WantCaptureKeyboard) return; - const auto forward = glm::vec3(glm::cos(ren.cam.phi), 0.0, glm::sin(ren.cam.phi)); + glm::vec3 forward; + if (ren.flycam) + forward = glm::vec3(glm::sin(ren.cam.theta)*glm::cos(ren.cam.phi), glm::cos(ren.cam.theta), glm::sin(ren.cam.theta)*glm::sin(ren.cam.phi)); + else + forward = glm::vec3(glm::cos(ren.cam.phi), 0.0, glm::sin(ren.cam.phi)); const auto right = glm::cross(forward, glm::vec3(0.0, 1.0, 0.0)); const auto speed = glfwGetKey(in, GLFW_KEY_LEFT_SHIFT)? 2.0f : 1.0f; diff --git a/Renderer/Pipeline.cpp b/Renderer/Pipeline.cpp index 33db072..d37e8f0 100644 --- a/Renderer/Pipeline.cpp +++ b/Renderer/Pipeline.cpp @@ -83,7 +83,7 @@ GraphicsPipeline::GraphicsPipeline(vk::Device dev, const std::vector& sh const auto raster_info = vk::PipelineRasterizationStateCreateInfo { .depthClampEnable = vk::False, .polygonMode = vk::PolygonMode::eFill, - .cullMode = vk::CullModeFlagBits::eBack, + .cullMode = vk::CullModeFlagBits::eNone, .frontFace = vk::FrontFace::eCounterClockwise, .depthBiasEnable = vk::False, .lineWidth = 1.0, diff --git a/Renderer/Renderer.cpp b/Renderer/Renderer.cpp index 9eab03b..466c164 100644 --- a/Renderer/Renderer.cpp +++ b/Renderer/Renderer.cpp @@ -122,10 +122,10 @@ Renderer::Renderer(Window& win) : win(win) { .pQueuePriorities = priorities, }; - /* enumerate available device features */ std::vector req_dev_extensions; req_dev_extensions.push_back("VK_KHR_swapchain"); req_dev_extensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); + auto dev_extentions = phys_dev.enumerateDeviceExtensionProperties(); Log::info("%zu available device extensions\n", dev_extentions.size()); for (const auto& ext : dev_extentions) { @@ -141,7 +141,11 @@ Renderer::Renderer(Window& win) : win(win) { "VK_LAYER_KHRONOS_validation" }; - auto dev_info = vk::DeviceCreateInfo{ + const auto features = vk::PhysicalDeviceFeatures { + .geometryShader = vk::True, + }; + + auto dev_info = vk::DeviceCreateInfo { .flags = vk::DeviceCreateFlagBits(0), .queueCreateInfoCount = 1, .pQueueCreateInfos = &queue_info, @@ -149,6 +153,7 @@ Renderer::Renderer(Window& win) : win(win) { .ppEnabledLayerNames = dev_layer_names.data(), .enabledExtensionCount = static_cast(req_dev_extensions.size()), .ppEnabledExtensionNames = req_dev_extensions.data(), + .pEnabledFeatures = &features, }; dev = phys_dev.createDevice(dev_info); @@ -181,6 +186,7 @@ Renderer::Renderer(Window& win) : win(win) { std::vector shaders = { { dev, "assets/shaders/basic.vert.spv", vk::ShaderStageFlagBits::eVertex }, + { dev, "assets/shaders/explode.geom.spv", vk::ShaderStageFlagBits::eGeometry }, { dev, "assets/shaders/basic.frag.spv", vk::ShaderStageFlagBits::eFragment }, }; @@ -191,17 +197,19 @@ Renderer::Renderer(Window& win) : win(win) { /* initialize models */ // models.push_back(std::make_shared(phys_dev, dev, "assets/models/dragon.gltf")); + Timer model_timer; models.push_back(std::make_shared(phys_dev, dev, "assets/models/dragon.gltf")); + auto t = model_timer.stop(); - Log::debug("#%zu vertex indices\n", models[0]->indices.size()); + Log::debug("Models loaded in %lf milliseconds\n", model_timer.read()); pipeline = std::make_unique(dev, shaders, swapchain->extent, *render_pass, bindings, *models[0]->vertex_buffer); pipeline->update(0, *uniform_buffer); pipeline->update(1, textures[0]); - shaders[0].cleanup(); - shaders[1].cleanup(); + for (auto& shader : shaders) + shader.cleanup(); ui = std::make_unique(this); } @@ -263,7 +271,7 @@ void Renderer::draw() { command_buffer->begin(); vk::ClearValue clear_values[] = { - vk::ClearColorValue(0.0f, 0.0f, 0.0f, 1.0f), + vk::ClearColorValue(1.0f, 1.0f, 1.0f, 1.0f), vk::ClearDepthStencilValue {.depth = 1.0f} }; diff --git a/Renderer/Renderer.hpp b/Renderer/Renderer.hpp index bdada14..78d4a13 100644 --- a/Renderer/Renderer.hpp +++ b/Renderer/Renderer.hpp @@ -63,4 +63,5 @@ struct Renderer { Camera cam {}; bool capture_mouse = false; + bool flycam = false; }; diff --git a/UI/UI.cpp b/UI/UI.cpp index 342cc4f..6bf1943 100644 --- a/UI/UI.cpp +++ b/UI/UI.cpp @@ -11,7 +11,7 @@ #include -UI::UI(Renderer* ren) : info{ .cam = ren->cam }, dev(ren->dev) { +UI::UI(Renderer* ren) : info{ .flycam = ren->flycam, .cam = ren->cam }, dev(ren->dev) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -90,6 +90,8 @@ void UI::newFrame() { ImGui::Begin("Rendering Info", nullptr); ImGui::Text("FPS: %f", info.fps); + ImGui::Checkbox("Fly Camera", &info.flycam); + ImGui::Text("Fly Camera mode: %b"); ImGui::SliderAngle("Theta", &info.cam.theta, 0.01, 179.9); ImGui::SliderAngle("Phi", &info.cam.phi, 0.0, 360.0, "%.0f def"); ImGui::SliderFloat("cam.x", &info.cam.pos.x, -1e2, 1e2); diff --git a/UI/UI.hpp b/UI/UI.hpp index a4fa466..c334c91 100644 --- a/UI/UI.hpp +++ b/UI/UI.hpp @@ -11,6 +11,7 @@ struct Camera; struct UI { struct UI_Info { float fps = 0.0; + bool& flycam; /* camera stuff */ Camera& cam; } info; diff --git a/Window/Window.cpp b/Window/Window.cpp index b71f9cd..b55aa82 100644 --- a/Window/Window.cpp +++ b/Window/Window.cpp @@ -2,7 +2,6 @@ #include -#define WINDOW_PTR GLFWwindow* #define INPUT_PTR GLFWwindow* #include #include diff --git a/Window/Window.hpp b/Window/Window.hpp index 5e51d6d..07b5b69 100644 --- a/Window/Window.hpp +++ b/Window/Window.hpp @@ -9,13 +9,11 @@ #include -#ifndef WINDOW_PTR -#define WINDOW_PTR void* -#endif - #define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS #include +#include + /* * Window class - abstracts away implementation/platform-specific realities of window * @@ -37,7 +35,7 @@ struct Window { vk::SurfaceKHR getSurface(vk::Instance& inst); std::unique_ptr getInput(); - WINDOW_PTR win = nullptr; + GLFWwindow* win = nullptr; private: u32 width, height; diff --git a/assets/shaders/basic.frag b/assets/shaders/basic.frag index f5f1c3b..1e64096 100644 --- a/assets/shaders/basic.frag +++ b/assets/shaders/basic.frag @@ -12,7 +12,5 @@ layout (set = 0, binding = 0) uniform Matrices { layout (set = 0, binding = 1) uniform sampler2D tex; void main() { - //FragColor = vec4(1.0); - FragColor = texture(tex, texCoord) * vec4(norm, 1.0); -// FragColor = vec4(texCoord, 0.0, 1.0); + FragColor = vec4(0.0, 0.0, 0.0, 1.0); } \ No newline at end of file diff --git a/assets/shaders/basic.frag.spv b/assets/shaders/basic.frag.spv index 671f15a..24651e1 100644 Binary files a/assets/shaders/basic.frag.spv and b/assets/shaders/basic.frag.spv differ diff --git a/assets/shaders/basic.vert b/assets/shaders/basic.vert index 9ef0cc5..df1816c 100644 --- a/assets/shaders/basic.vert +++ b/assets/shaders/basic.vert @@ -12,7 +12,8 @@ layout (set = 0, binding = 0) uniform Matrices { }; void main() { - gl_Position = mvp * vec4(aPos, 1.0); + //gl_Position = mvp * vec4(aPos, 1.0); + gl_Position = vec4(aPos, 1.0); texCoord = aTexCoord; norm = aNorm; } \ No newline at end of file diff --git a/assets/shaders/basic.vert.spv b/assets/shaders/basic.vert.spv index 076e37f..e9568b1 100644 Binary files a/assets/shaders/basic.vert.spv and b/assets/shaders/basic.vert.spv differ diff --git a/assets/shaders/explode.geom b/assets/shaders/explode.geom new file mode 100644 index 0000000..a9291ad --- /dev/null +++ b/assets/shaders/explode.geom @@ -0,0 +1,44 @@ +#version 450 core + +layout (triangles) in; +layout (triangle_strip) out; +layout (max_vertices = 3) out; + +layout (location = 0) in vec3 norm[]; +layout (location = 1) in vec2 texCoord[]; + +layout (location = 0) out vec3 _norm; +layout (location = 1) out vec2 _texCoord; + +layout (set = 0, binding = 0) uniform Matrices { + mat4 mvp; + float time; +}; + +vec4 explode(vec4 pos, vec3 n) { + float mag = 2.0; + vec3 dir = n * (time-3.0)/10.0 * mag; + return pos + vec4(dir, 0.0); +} + +void main(void) { + if (time < 3.0) { + for(int i = 0; i < gl_in.length(); i++) { + gl_Position = mvp * gl_in[i].gl_Position; + _norm = norm[i]; + _texCoord = texCoord[i]; + EmitVertex(); + } + EndPrimitive(); + return; + } + vec3 n = norm[0] + norm[1] + norm[2]; + n/=3; + for(int i = 0; i < gl_in.length(); i++) { + gl_Position = mvp * explode(gl_in[i].gl_Position, n); + _texCoord = texCoord[i]; + _norm = n; + EmitVertex(); + } + EndPrimitive(); +} \ No newline at end of file diff --git a/assets/shaders/explode.geom.spv b/assets/shaders/explode.geom.spv new file mode 100644 index 0000000..2f5eb55 Binary files /dev/null and b/assets/shaders/explode.geom.spv differ diff --git a/pléascach.cpp b/pléascach.cpp index 87b786a..d82bdb4 100644 --- a/pléascach.cpp +++ b/pléascach.cpp @@ -13,6 +13,11 @@ int main(int argc, char* argv[]) { try { Window win(argv[0], 256, 512); + + auto mon = glfwGetPrimaryMonitor(); + auto v = glfwGetVideoMode(mon); + glfwSetWindowMonitor(win.win, mon, 0, 0, v->width, v->height, v->refreshRate); + auto in = win.getInput(); Renderer ren(win); @@ -31,6 +36,16 @@ int main(int argc, char* argv[]) { /* no need to have a resize() function in the renderer, b/c swapchain images will be * automatically marked out-of-date, and recreation will be triggered in our code */ + /* but still block while waiting for window to be opened again */ + if (event.resize.height == 0 || event.resize.width == 0) { + int h = event.resize.height; + int w = event.resize.width; + do { + glfwPollEvents(); + glfwGetWindowSize(win.win, &w, &h); + } while (h * w == 0); + } + break; case InputEvent::Tag::eEXIT: win.close(); @@ -41,9 +56,15 @@ int main(int argc, char* argv[]) { case InputEvent::Tag::eBUTTON: break; case InputEvent::Tag::eKEY: - if (event.key.key == GLFW_KEY_ESCAPE && event.key.state == GLFW_PRESS) { + if (event.key.key == GLFW_KEY_Q) { + return 0; + } else if (event.key.key == GLFW_KEY_ESCAPE && event.key.state == GLFW_PRESS) { ren.capture_mouse = !ren.capture_mouse; in->setCursor(!ren.capture_mouse); + } else if (event.key.key == GLFW_KEY_R && event.key.state == GLFW_PRESS) { + ren.frame = 0; + } else if (event.key.key == GLFW_KEY_C && event.key.state == GLFW_PRESS) { + ren.flycam = !ren.flycam; } break; } diff --git a/util/Timer.hpp b/util/Timer.hpp index 3e548c8..638500d 100644 --- a/util/Timer.hpp +++ b/util/Timer.hpp @@ -21,6 +21,7 @@ struct Timer { start(); } + /* returns time in milliseconds */ inline double read() { if (running) { auto end = std::chrono::steady_clock::now();