From 2de32140be5057e410c99465293ac496bccfcca7 Mon Sep 17 00:00:00 2001 From: lachrymaLF Date: Thu, 23 May 2024 03:18:24 -0400 Subject: [PATCH] asdfafs --- Keishiki/CMakeLists.txt | 2 +- Keishiki/Graphics.cpp | 75 +++++-- Keishiki/Keishiki.cpp | 55 +---- Keishiki/UI.cpp | 194 +++++++++++------- Keishiki/include/Graphics.h | 85 +++++++- Keishiki/include/Keishiki.h | 12 +- Keishiki/include/UI.h | 6 +- Keishiki/include/VisualTrack.h | 44 +++- Keishiki/shader.py | 23 ++- .../BinaryComposite/BinaryComposite.frag | 144 ++++++++++++- .../BinaryComposite/BinaryComposite.vert | 11 + .../shaders/Checkerboard/Checkerboard.frag | 8 +- README.md | 2 +- TODO.md | 4 +- 14 files changed, 497 insertions(+), 168 deletions(-) diff --git a/Keishiki/CMakeLists.txt b/Keishiki/CMakeLists.txt index a8e8b4a..8d9e20e 100644 --- a/Keishiki/CMakeLists.txt +++ b/Keishiki/CMakeLists.txt @@ -10,7 +10,7 @@ add_executable (Keishiki "ext/imgui/imgui_demo.cpp" "ext/imgui/imgui_draw.cpp" "ext/imgui/imgui_tables.cpp" "ext/imgui/imgui_widgets.cpp" "ext/imgui/misc/cpp/imgui_stdlib.cpp" - "Keishiki.cpp" "Graphics.cpp" "UI.cpp" "ShaderGraph.cpp" "include/ShaderGraph.h" "include/ShaderNodes.h") + "Keishiki.cpp" "Graphics.cpp" "UI.cpp" "ShaderGraph.cpp") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET Keishiki PROPERTY CXX_STANDARD 20) diff --git a/Keishiki/Graphics.cpp b/Keishiki/Graphics.cpp index 5e0033f..c23be9e 100644 --- a/Keishiki/Graphics.cpp +++ b/Keishiki/Graphics.cpp @@ -20,7 +20,6 @@ namespace { switch (bgfx::getRendererType()) { case bgfx::RendererType::Noop: -// case bgfx::RendererType::Direct3D9: shaderPath = "shaders/dx9/"; break; case bgfx::RendererType::Direct3D11: case bgfx::RendererType::Direct3D12: shaderPath = "shaders/dx11/"; break; case bgfx::RendererType::Gnm: shaderPath = "shaders/pssl/"; break; @@ -55,7 +54,7 @@ namespace { f32 v; }; - static PosUVVertex quad_vert[] = + PosUVVertex quad_vert[] = { { 0.f, 0.f, 0.0f, 0.0f, 0.0f }, { 0.f, 1.f, 0.0f, 0.0f, 1.0f }, @@ -63,7 +62,7 @@ namespace { { 1.f, 1.f, 0.0f, 1.0f, 1.0f } }; - static const u16 quad_indices[] = + const u16 quad_indices[] = { 0, 2, 1, 1, 2, 3 @@ -182,7 +181,8 @@ namespace { } Font regular, bold; - bgfx::ProgramHandle a_program, imga_program; + bgfx::ProgramHandle imga_program; + bgfx::ProgramHandle a_program; bgfx::UniformHandle s_texColor; bgfx::UniformHandle imga_opacity; @@ -192,6 +192,10 @@ namespace { bgfx::VertexLayout pcvDecl; Dict imgs; + + f32 composite_view[16]; + bgfx::UniformHandle composite_A, composite_B, composite_mode; + bgfx::ProgramHandle composite_pg; } namespace K::Graphics { @@ -225,6 +229,11 @@ namespace K::Graphics { s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler); mmaker = Graphics::GetImageTextureFromFile("mmaker.png"); + bx::mtxTranslate(composite_view, 0.f, 0.f, 1.0f); + composite_A = bgfx::createUniform("v_A", bgfx::UniformType::Sampler); + composite_B = bgfx::createUniform("v_B", bgfx::UniformType::Sampler); + composite_pg = load_shader_program("BinaryComposite"); + composite_mode = bgfx::createUniform("f_mode", bgfx::UniformType::Vec4); return true; } @@ -246,28 +255,37 @@ namespace K::Graphics { bgfx::destroy(s_texColor); bgfx::destroy(imga_opacity); - } + + bgfx::destroy(composite_A); + bgfx::destroy(composite_B); + bgfx::destroy(composite_pg); + bgfx::destroy(composite_mode); + } // Draws quad with texture on Z = 0 - void DrawTexture(u32 view_id, const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h, u64 state, const bgfx::ProgramHandle& pg) { - f32 mtx1[16], mtx2[16], mtx3[16]; + void DrawTextureWithTransform(u32 view_id, const bgfx::TextureHandle& tex, f32 mtx[16], u64 state, const bgfx::ProgramHandle& pg) { + bgfx::setTransform(mtx); + + bgfx::setVertexBuffer(0, vbh); + bgfx::setIndexBuffer(ibh); + + bgfx::setTexture(0, s_texColor, tex); + + bgfx::setState(state); + bgfx::submit(view_id, pg); + } + + void DrawTexture(u32 view_id, const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h, u64 state, const bgfx::ProgramHandle& pg) { + static f32 mtx1[16], mtx2[16], mtx3[16]; bx::mtxTranslate(mtx1, pos_x, pos_y, 0.0f); bx::mtxScale(mtx2, w, h, 1.0f); bx::mtxMul(mtx3, mtx2, mtx1); - bgfx::setTransform(mtx3); - - bgfx::setVertexBuffer(0, vbh); - bgfx::setIndexBuffer(ibh); - - bgfx::setTexture(0, s_texColor, tex); - - bgfx::setState(state); - bgfx::submit(view_id, pg); + DrawTextureWithTransform(view_id, tex, mtx3, state, pg); } void DrawTextureImageAlpha(u32 view_id, const ImageTexture& img, i32 pos_x, i32 pos_y, f32 alpha) { - f32 pack[4]{}; + static f32 pack[4]{}; pack[0] = alpha; bgfx::setUniform(imga_opacity, pack); DrawTexture(view_id, img.tx, pos_x, pos_y, img.w, img.h, (BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) & ~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS), imga_program); @@ -371,7 +389,7 @@ namespace K::Graphics { pos_x = reset_x; pos_y -= f->face->size->metrics.height / 64; } - if (last >= halt) { + if (last >= halt) { WalkString(view_id, last_copy, pos, copy_x, copy_y); return copy_x; }; @@ -413,4 +431,25 @@ namespace K::Graphics { } return pos_x; } + + void Composite(bgfx::FrameBufferHandle fb, bgfx::TextureHandle composite, bgfx::TextureHandle from, Blending mode, u16 w, u16 h, f32 proj[16], f32 transform[16]) { + static f32 pack[4]{}; + pack[0] = static_cast(mode); + + bgfx::touch(K::Graphics::K_VIEW_DRAW); + bgfx::setViewMode(K::Graphics::K_VIEW_DRAW, bgfx::ViewMode::Sequential); + bgfx::setViewClear(K::Graphics::K_VIEW_DRAW, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); + bgfx::setViewFrameBuffer(K::Graphics::K_VIEW_COMP_COMPOSITE, fb); + bgfx::setViewTransform(K::Graphics::K_VIEW_COMP_COMPOSITE, composite_view, proj); + bgfx::setViewRect(K::Graphics::K_VIEW_COMP_COMPOSITE, 0, 0, w, h); + + bgfx::setTransform(transform); + bgfx::setVertexBuffer(0, vbh); + bgfx::setIndexBuffer(ibh); + bgfx::setTexture(0, composite_A, composite); + bgfx::setTexture(0, composite_B, from); + bgfx::setUniform(composite_mode, pack); + bgfx::setState((BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) & ~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS)); + bgfx::submit(K::Graphics::K_VIEW_COMP_COMPOSITE, composite_pg); + } } diff --git a/Keishiki/Keishiki.cpp b/Keishiki/Keishiki.cpp index b349aaa..5ee6c3e 100644 --- a/Keishiki/Keishiki.cpp +++ b/Keishiki/Keishiki.cpp @@ -9,9 +9,8 @@ #include #include -#include #include "backends/imgui_impl_sdl2.h" -#include "imgui_impl_bgfx.h" +#include namespace { SDL_Window* window; @@ -22,13 +21,9 @@ namespace { bool running = false; K::CompState state; - bgfx::FrameBufferHandle fb = BGFX_INVALID_HANDLE; - K::Graphics::ImageTexture* mm; } namespace K { - const char* BlendingToString[] = { "Normal", "Additive", "Invalid Blending" }; - bool Init() { if (SDL_Init(SDL_INIT_VIDEO)) { LogError(SDL_GetError()); @@ -75,25 +70,14 @@ namespace K { if (!bgfx::init(bgfxInit)) { LogError("bgfx initialization failed"); return false; - }; + } - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; -// io.Fonts->AddFontFromFileTTF("SourceHanSans-Regular.ttc", 17); - ImGui_Implbgfx_Init(K::Graphics::K_VIEW_TOP); bgfx::setDebug(BGFX_DEBUG_TEXT); bgfx::setViewClear(K::Graphics::K_VIEW_TOP, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0); bgfx::setViewRect(K::Graphics::K_VIEW_TOP, 0, 0, window_width, window_height); -#if BX_PLATFORM_WINDOWS - ImGui_ImplSDL2_InitForD3D(window); -#elif BX_PLATFORM_OSX - ImGui_ImplSDL2_InitForMetal(window); -#elif BX_PLATFORM_LINUX || BX_PLATFORM_EMSCRIPTEN - ImGui_ImplSDL2_InitForOpenGL(window, nullptr); -#endif + K::UI::Init(window); if (!K::Graphics::Init(window_width, window_height)) { LogError("Graphics init failed"); @@ -102,29 +86,19 @@ namespace K { state.width = 800; state.height = 600; - fb = bgfx::createFrameBuffer(state.width, state.height, bgfx::TextureFormat::RGBA8); - state.layers.push_back(Layer{ - VisualTrack{}, - "garfield", - true, - false, - K_V_Normal - }); + K::UI::SetupViewport(state); return true; } void Render() { -// ImGui::ShowDemoWindow(); - UI::Draw(state, mm, fb); - ImGui::Render(); - ImGui_Implbgfx_RenderDrawLists(ImGui::GetDrawData()); + UI::Draw(state); - const bgfx::Stats* stat = bgfx::getStats(); - bgfx::dbgTextClear(); - bgfx::dbgTextPrintf(0, window_height/16 - 3, 0xf8, " %u FPS", stat->cpuTimerFreq / stat->cpuTimeFrame); - bgfx::dbgTextPrintf(0, window_height/16 - 2, 0xf8, " Project Keishiki :: %s :: Build %s %s", BX_COMPILER_NAME, __DATE__, __TIME__); - bgfx::dbgTextPrintf(0, window_height/16 - 1, 0xf8, " SDL %i.%i.%i :: bgfx 1.%i :: Dear ImGui %s :: %s", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL, BGFX_API_VERSION, ImGui::GetVersion(), bgfx::getRendererName(bgfx::getRendererType())); + const bgfx::Stats* stat = bgfx::getStats(); + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, window_height/16 - 3, 0xf8, " %u FPS", stat->cpuTimerFreq / stat->cpuTimeFrame); + bgfx::dbgTextPrintf(0, window_height/16 - 2, 0xf8, " Project Keishiki :: %s :: Build %s %s", BX_COMPILER_NAME, __DATE__, __TIME__); + bgfx::dbgTextPrintf(0, window_height/16 - 1, 0xf8, " SDL %i.%i.%i :: bgfx 1.%i :: Dear ImGui %s :: %s", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL, BGFX_API_VERSION, ImGui::GetVersion(), bgfx::getRendererName(bgfx::getRendererType())); bgfx::frame(); } @@ -137,10 +111,6 @@ namespace K { current_time = SDL_GetTicks64(); delta_t = current_time - last_time; - ImGui_ImplSDL2_NewFrame(); - ImGui_Implbgfx_NewFrame(); - ImGui::NewFrame(); - for (SDL_Event current_event; SDL_PollEvent(¤t_event) != 0;) { ImGui_ImplSDL2_ProcessEvent(¤t_event); if (current_event.type == SDL_QUIT) { @@ -156,11 +126,8 @@ namespace K { } void Shutdown() { - bgfx::destroy(fb); K::Graphics::Shutdown(); - ImGui_Implbgfx_Shutdown(); - ImGui_ImplSDL2_Shutdown(); - ImGui::DestroyContext(); + K::UI::Shutdown(state); bgfx::shutdown(); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/Keishiki/UI.cpp b/Keishiki/UI.cpp index 4b16d91..31dc82c 100644 --- a/Keishiki/UI.cpp +++ b/Keishiki/UI.cpp @@ -5,18 +5,23 @@ #include #include #include -#include namespace { bool draw_viewport = true; bool draw_sequencer = true; bool draw_nodes = true; + + // Viewport + bgfx::FrameBufferHandle composite_fb = BGFX_INVALID_HANDLE, render_fb = BGFX_INVALID_HANDLE; + K::VisualTrack bg{}; + f32 proj[16], transform[16]; } + namespace ImGui { inline ImTextureID toId(bgfx::TextureHandle _handle, uint8_t _flags, uint8_t _mip) { - union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID id; } tex; + union { struct { bgfx::TextureHandle handle; uint8_t flags; uint8_t mip; } s; ImTextureID id; } tex{}; tex.s.handle = _handle; tex.s.flags = _flags; tex.s.mip = _mip; @@ -46,24 +51,74 @@ namespace K::UI { } ImGui::EndMainMenuBar(); } - void Viewport(CompState& s, Graphics::ImageTexture* mm, bgfx::FrameBufferHandle fb) { + + void SetupViewport(CompState& s) { + composite_fb = bgfx::createFrameBuffer(s.width, s.height, bgfx::TextureFormat::RGBA8); + render_fb = bgfx::createFrameBuffer(s.width, s.height, bgfx::TextureFormat::RGBA8); + + bg.pg = K::Graphics::load_shader_program("Checkerboard"); + bg.add_uniform("f_hw", ShaderGraph::Type::T_XYZ); + + bx::mtxOrtho(proj, 0.0f, static_cast(s.width), 0.0f, static_cast(s.height), + 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth); + f32 mtx1[16], mtx2[16]; + bx::mtxTranslate(mtx1, 0, 0, 0.0f); + bx::mtxScale(mtx2, s.width, s.height, 1.0f); + bx::mtxMul(transform, mtx2, mtx1); + } + + void DestroyViewport(CompState& s) { + bgfx::destroy(composite_fb); + bgfx::destroy(render_fb); + + bgfx::destroy(bg.pg); + bgfx::destroy(bg.uniforms.begin()->second.first); + bg.uniforms.erase(bg.uniforms.begin()); + + for (auto& layer : s.layers) { + if (bgfx::isValid(layer.track.pg)) + bgfx::destroy(layer.track.pg); + for (auto& uniform : layer.track.uniforms) { + bgfx::destroy(uniform.second.first); + } + } + } + + void Viewport(CompState& s) { if (ImGui::Begin("Viewport", &draw_viewport)) { ImTextureID idx = nullptr; - // If we need new frame + + bgfx::TextureHandle composite = bg.get_frame(composite_fb, s.width, s.height); for (auto& layer : s.layers) { if (!layer.enabled) continue; - bgfx::TextureHandle tx = layer.track.get_frame(0, mm, fb, s.width, s.height); - idx = ImGui::toId(tx, 0, 0); + Graphics::Composite(composite_fb, composite, layer.track.get_frame(render_fb, s.width, s.height), + &layer == &s.layers.front() ? Graphics::K_V_AlphaOver : layer.mode, s.width, s.height, proj, transform); } + idx = ImGui::toId(composite, 0, 0); if (idx != nullptr) - ImGui::Image(idx, ImVec2{ 800, 600 }); + ImGui::Image(idx, ImVec2{ static_cast(s.width), static_cast(s.height) }); ImGui::Text("Comp Size: %ux%u", s.width, s.height); } ImGui::End(); } + void Sequencer(CompState& s){ if (ImGui::Begin("Sequencer", &draw_sequencer)) { + static String name{}; + if (ImGui::Button("Add Layer") && !name.empty()) { + s.layers.push_back(Layer{ + VisualTrack{}, + name, + true, + false, + Graphics::K_V_AlphaOver + }); + } + ImGui::SameLine(); + ImGui::InputText("##UniformName", &name); + + if (ImGui::BeginTable("Layers", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) { ImGui::TableSetupColumn("#", ImGuiTableColumnFlags_NoSort); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoSort); @@ -76,18 +131,19 @@ namespace K::UI { ImGui::TableNextColumn(); ImGui::Text("%u", i); ImGui::TableNextColumn(); - if (ImGui::Selectable(s.layers[i].name.c_str(), &s.layers[i].selected)) { - s.active = s.layers[i].selected ? &s.layers[i] : nullptr; -// if (s.active != nullptr && ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held -// layers[i].selected = !layers[i].selected; + if (ImGui::Selectable((s.layers[i].name + "##" + std::to_string(i)).c_str(), &s.layers[i].selected)) { + s.active = s.layers[i].selected ? i : -1; + if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held + for (u32 j = 0; j < s.layers.size(); j++) + s.layers[j].selected = j == i && s.layers[j].selected; } ImGui::TableNextColumn(); ImGui::SetNextItemWidth(100.0f); - if (ImGui::BeginCombo(("##Blending" + std::to_string(i)).c_str(), BlendingToString[s.layers[i].mode])) { - for (i32 b = K_V_Normal; b != K_V_Count; b++) { - const bool is_selected = ((Blending)b == s.layers[i].mode); - if (ImGui::Selectable(BlendingToString[b], is_selected)) - s.layers[i].mode = (Blending)b; + if (ImGui::BeginCombo(("##Blending" + std::to_string(i)).c_str(), Graphics::BlendingToString[s.layers[i].mode])) { + for (i32 b = Graphics::K_V_AlphaOver; b != Graphics::K_V_Count; b++) { + const bool is_selected = (static_cast(b) == s.layers[i].mode); + if (ImGui::Selectable(Graphics::BlendingToString[b], is_selected)) + s.layers[i].mode = static_cast(b); if (is_selected) ImGui::SetItemDefaultFocus(); } @@ -101,6 +157,7 @@ namespace K::UI { } ImGui::End(); } + /*void Nodegraph(CompState& s) { Layer* active = nullptr; u32 active_index = 0; @@ -246,18 +303,19 @@ namespace K::UI { } ImGui::End(); }*/ + void Shader(CompState& s) { if (ImGui::Begin("Shader", &draw_nodes)) { - if (s.active == nullptr) + if (s.active == -1) ImGui::Text("No active layer."); else { static int type_current = 0; - static char text[8] = ""; - if (ImGui::Button("Add Uniform") && text[0] != '\0') { // todo LEAK!! - s.active->track.add_uniform(text, ShaderGraph::expand_type(static_cast(type_current))); + static String name{}; + if (ImGui::Button("Add Uniform") && !name.empty()) { + s.layers[s.active].track.add_uniform(name, ShaderGraph::expand_type(static_cast(type_current))); } ImGui::SameLine(); - ImGui::InputText("##UniformName", text, IM_ARRAYSIZE(text)); + ImGui::InputText("##UniformName", &name); ImGui::SameLine(); ImGui::Combo("Type", &type_current, ShaderGraph::Type_To_Str, ShaderGraph::T_Count); @@ -268,7 +326,7 @@ namespace K::UI { ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoSort); ImGui::TableSetupColumn("##del", ImGuiTableColumnFlags_NoSort); ImGui::TableHeadersRow(); - for (auto it = s.active->track.uniforms.begin(); it != s.active->track.uniforms.end();) { + for (auto it = s.layers[s.active].track.uniforms.begin(); it != s.layers[s.active].track.uniforms.end();) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%s", it->first.c_str()); @@ -286,71 +344,65 @@ namespace K::UI { else if constexpr (std::is_same_v::type>) ImGui::InputFloat4(("##" + it->first).c_str(), &arg.r); else if constexpr (std::is_same_v::type>) - ImGui::InputFloat3(("##" + it->first).c_str(), &arg.x);; + ImGui::InputFloat3(("##" + it->first).c_str(), &arg.x); }, it->second.second); ImGui::TableNextColumn(); if (ImGui::Button("Delete Uniform")) { bgfx::destroy(it->second.first); - it = s.active->track.uniforms.erase(it); + it = s.layers[s.active].track.uniforms.erase(it); } else it++; } ImGui::EndTable(); } - ImGui::Text("Editing Layer %u: %s", 0, s.active->name.c_str()); - ImGuiIO& io = ImGui::GetIO(); - ImGui::InputTextMultiline("##source", &s.active->track.shader, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 24), ImGuiInputTextFlags_AllowTabInput); - if (ImGui::Button("Submit Shader")) { - // Compile shader and assign - std::ofstream f("temp.frag"); - f << s.active->track.shader; - f.close(); - if (std::system( -#if BX_PLATFORM_WINDOWS - "./ext/bgfx/cmake/bgfx/shaderc " - "-f temp.frag " - "--type fragment " - "--platform windows " - "--profile " "ps_5_0" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "dx11" "/temp.frag.bin" -#elif BX_PLATFORM_LINUX - "./ext/bgfx/cmake/bgfx/shaderc " - "-f temp.frag " - "--type fragment " - "--platform windows " - "--profile " "spirv" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "spirv" "/temp.frag.bin" -#elif BX_PLATFORM_OSX - "./ext/bgfx/cmake/bgfx/shaderc " - "-f temp.frag " - "--type fragment " - "--platform osx " - "--profile " "metal" " " - "--varyingdef temp.varying.def.sc " - "-i ./ " - "-o shaders/" "metal" "/temp.frag.bin" -#endif - ) == 0) { - if (isValid( s.layers[0].track.pg)) bgfx::destroy(s.layers[0].track.pg); - s.layers[0].track.pg = Graphics::load_shader_program("temp"); // todo LEAK!!! - } - else - Log("User shader compilation failed"); - } + ImGui::Text("Editing Layer %u: %s", s.active, s.layers[s.active].name.c_str()); + ImGui::InputTextMultiline("##source", &s.layers[s.active].track.shader, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 40), ImGuiInputTextFlags_AllowTabInput); + if (ImGui::Button("Submit Shader")) + s.layers[s.active].track.compile(); } } ImGui::End(); } - void Draw(CompState& s, Graphics::ImageTexture* mm, bgfx::FrameBufferHandle fb) { + + void Draw(CompState& s) { + ImGui_ImplSDL2_NewFrame(); + ImGui_Implbgfx_NewFrame(); + ImGui::NewFrame(); + +// ImGui::ShowDemoWindow(); static ImGuiStyle& style = ImGui::GetStyle(); - style.GrabRounding = style.FrameRounding = 15.0f; + style.GrabRounding = style.FrameRounding = 5.0f; MainMenuBar(s); - if (draw_viewport) Viewport(s, mm, fb); + if (draw_viewport) Viewport(s); if (draw_nodes) Shader(s); if (draw_sequencer) Sequencer(s); + + ImGui::Render(); + ImGui_Implbgfx_RenderDrawLists(ImGui::GetDrawData()); + } + + void Init(SDL_Window* window) { + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; +// io.Fonts->AddFontFromFileTTF("SourceHanSans-Regular.ttc", 17); + ImGui_Implbgfx_Init(K::Graphics::K_VIEW_TOP); + +#if BX_PLATFORM_WINDOWS + ImGui_ImplSDL2_InitForD3D(window); +#elif BX_PLATFORM_OSX + ImGui_ImplSDL2_InitForMetal(window); +#elif BX_PLATFORM_LINUX || BX_PLATFORM_EMSCRIPTEN + ImGui_ImplSDL2_InitForVulkan(window); +#endif + + } + + void Shutdown(CompState& s) { + + DestroyViewport(s); + ImGui_Implbgfx_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); } } diff --git a/Keishiki/include/Graphics.h b/Keishiki/include/Graphics.h index 7c9066f..3c2fee8 100644 --- a/Keishiki/include/Graphics.h +++ b/Keishiki/include/Graphics.h @@ -8,7 +8,8 @@ namespace K::Graphics { enum VIEW_ID { K_VIEW_TOP = 0, - K_VIEW_DRAW = 5 + K_VIEW_COMP_COMPOSITE, + K_VIEW_DRAW }; bool Init(u16 width, u16 height); @@ -23,6 +24,7 @@ namespace K::Graphics { }; ImageTexture* GetImageTextureFromFile(const std::string& file); + void DrawTextureWithTransform(u32 view_id, const bgfx::TextureHandle& tex, f32 mtx[16], u64 state, const bgfx::ProgramHandle& pg); void DrawTexture(u32 view_id, const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h, u64 state, const bgfx::ProgramHandle& pg); void DrawTextureImageAlpha(u32 view_id, const ImageTexture& img, i32 pos_x, i32 pos_y, f32 alpha); void DrawTextureStencilAlpha(u32 view_id, const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h); @@ -39,5 +41,86 @@ namespace K::Graphics { i32 RenderSubstringBox(u32 view_id, const String& s, i32& pos_x, i32& pos_y, i32 reset_x, u32 w, u32 col, size_t s_end = String::npos); + enum Blending { + K_V_AlphaOver = 0, + + K_V_Dissolve, + + K_V_Add, + K_V_Subtract, + K_V_Difference, + K_V_Exclusion, + K_V_Multiply, + K_V_Divide, + + K_V_Lighten, + K_V_Darken, + K_V_LighterColour, + K_V_DarkerColour, + + K_V_Screen, + K_V_Overlay, + + K_V_HardLight, + K_V_SoftLight, + + K_V_VividLight, + K_V_LinearLight, + + K_V_ColourBurn, + K_V_LinearBurn, + K_V_ColourDodge, + K_V_LinearDodge, + + K_V_Hue, + K_V_Saturation, + K_V_Color, + K_V_Luminosity, + + K_V_Count + }; + static const char* BlendingToString[] = { + "Alpha Over", + + "Dissolve", + + "Add", + "Subtract", + "Difference", + "Exclusion", + "Multiply", + "Divide", + + "Lighten", + "Darken", + "Lighter Colour", + "Darker Colour", + + "Screen", + "Overlay", + + "Hard Light", + "Soft Light", + + "Vivid Light", + "Linear Light", + + "Pin Light", + + "Colour Burn", + "Linear Burn", + "Colour Dodge", + "Linear Dodge", + + "Hue", + "Saturation", + "Color", + "Luminosity", + + "Invalid" + }; + + void Composite(bgfx::FrameBufferHandle fb, bgfx::TextureHandle composite, bgfx::TextureHandle from, Blending mode, u16 w, u16 h, f32 proj[16], f32 transform[16]); + extern Graphics::ImageTexture* mmaker; } diff --git a/Keishiki/include/Keishiki.h b/Keishiki/include/Keishiki.h index d9176c6..7c85406 100644 --- a/Keishiki/include/Keishiki.h +++ b/Keishiki/include/Keishiki.h @@ -9,19 +9,11 @@ namespace K { void Render(); - extern const char* BlendingToString[]; - - enum Blending { - K_V_Normal = 0, - K_V_Additive, - K_V_Count - }; - struct Layer { VisualTrack track; String name; bool enabled, selected; - Blending mode; + Graphics::Blending mode; }; struct CompState { @@ -30,6 +22,6 @@ namespace K { u32 fps; u32 width, height; Vector layers; - Layer* active = nullptr; + i32 active = -1; }; } diff --git a/Keishiki/include/UI.h b/Keishiki/include/UI.h index 0537fae..ddceb8a 100644 --- a/Keishiki/include/UI.h +++ b/Keishiki/include/UI.h @@ -8,6 +8,8 @@ #include "imgui_impl_bgfx.h" namespace K::UI { - void Draw(CompState& s, Graphics::ImageTexture* mm, bgfx::FrameBufferHandle fb); - + void Init(SDL_Window* window); + void Draw(CompState& s); + void Shutdown(CompState& s); + void SetupViewport(CompState& s); } diff --git a/Keishiki/include/VisualTrack.h b/Keishiki/include/VisualTrack.h index 2b0bbaa..d954947 100644 --- a/Keishiki/include/VisualTrack.h +++ b/Keishiki/include/VisualTrack.h @@ -4,6 +4,7 @@ #include "ShaderGraph.h" #include #include +#include namespace K { template @@ -21,7 +22,8 @@ namespace K { bgfx::ProgramHandle pg = BGFX_INVALID_HANDLE; String shader{}; Dict::type>> uniforms; - bgfx::TextureHandle get_frame(u64 time, Graphics::ImageTexture* mm, bgfx::FrameBufferHandle fb, u32 w, u32 h) const { +// Vector samplers; + bgfx::TextureHandle get_frame(bgfx::FrameBufferHandle fb, u32 w, u32 h) const { bgfx::touch(K::Graphics::K_VIEW_DRAW); bgfx::setViewMode(K::Graphics::K_VIEW_DRAW, bgfx::ViewMode::Sequential); bgfx::setViewClear(K::Graphics::K_VIEW_DRAW, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0); @@ -66,6 +68,46 @@ namespace K { if (!uniforms.contains(s)) uniforms.emplace(s, std::make_pair(bgfx::createUniform(s.c_str(), bgfx::UniformType::Vec4), std::move(val))); } + void compile() { + std::ofstream f("temp.frag"); + f << shader; + f.close(); + if (std::system( +#if BX_PLATFORM_WINDOWS + "./ext/bgfx/cmake/bgfx/shaderc " + "-f temp.frag " + "--type fragment " + "--platform windows " + "--profile " "ps_5_0" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "dx11" "/temp.frag.bin" +#elif BX_PLATFORM_LINUX + "./ext/bgfx/cmake/bgfx/shaderc " + "-f temp.frag " + "--type fragment " + "--platform windows " + "--profile " "spirv" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "spirv" "/temp.frag.bin" +#elif BX_PLATFORM_OSX + "./ext/bgfx/cmake/bgfx/shaderc " + "-f temp.frag " + "--type fragment " + "--platform osx " + "--profile " "metal" " " + "--varyingdef temp.varying.def.sc " + "-i ./ " + "-o shaders/" "metal" "/temp.frag.bin" +#endif + ) == 0) { + if (isValid(pg)) bgfx::destroy(pg); + pg = Graphics::load_shader_program("temp"); + } + else + Log("User shader compilation failed"); + } }; void Composite(); diff --git a/Keishiki/shader.py b/Keishiki/shader.py index 6fa7f42..a060ed8 100644 --- a/Keishiki/shader.py +++ b/Keishiki/shader.py @@ -1,16 +1,19 @@ import subprocess, os #SHADERC = "..\\out\\install\\x64-Debug\\bin\\shaderc" -SHADERC = "/Users/lachrymal/Projects/NouVeL/build/ADVect/ext/bgfx/Debug/shaderc" +# SHADERC = "/Users/lachrymal/Projects/NouVeL/build/ADVect/ext/bgfx/Debug/shaderc" +SHADERC = "/home/lach/Projects/Keishiki/cmake-build-debug/Keishiki/ext/bgfx/cmake/bgfx/shaderc" #OUT = "..\\out\\build\\x64-Debug\\ADVect\\shaders\\" # OUT = "..\\build\\ADVect\\shaders\\" -OUT = "/Users/lachrymal/Projects/NouVeL/ADVect/runtime/shaders/" +# OUT = "/Users/lachrymal/Projects/NouVeL/ADVect/runtime/shaders/" +OUT = "/home/lach/Projects/Keishiki/cmake-build-debug/Keishiki/shaders/" +I = "/home/lach/Projects/Keishiki/cmake-build-debug/Keishiki/" P = lambda location, platform, frag, vert: { 'location': location, 'platform': platform, 'frag': frag, 'vert': vert } plats = [ -# P('glsl', 'windows', '140', '140'), -# P('dx11', 'windows', 'ps_5_0', 'vs_5_0'), -# P('spirv', 'windows', 'spirv', 'spirv'), + P('glsl', 'windows', '140', '140'), + # P('dx11', 'windows', 's_5_0', 's_5_0'), + P('spirv', 'windows', 'spirv', 'spirv'), P('metal', 'osx', 'metal', 'metal') ] @@ -22,15 +25,13 @@ for root, dirs, _ in os.walk('shaders'): "--platform", config['platform'], "--profile", config['frag'], "--varyingdef", os.path.join(root, name, "varying.def.sc"), - "-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common", - "-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src", - "-o", OUT + config['location'] + "\\" + name + ".frag.bin"]) + "-i", I, + "-o", OUT + config['location'] + "/" + name + ".frag.bin"]) subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.vert'), "--type", "vertex", "--platform", config['platform'], "--profile", config['vert'], "--varyingdef", os.path.join(root, name, "varying.def.sc"), - "-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common", - "-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src", - "-o", OUT + config['location'] + "\\" + name + ".vert.bin"]) + "-i", I, + "-o", OUT + config['location'] + "/" + name + ".vert.bin"]) diff --git a/Keishiki/shaders/BinaryComposite/BinaryComposite.frag b/Keishiki/shaders/BinaryComposite/BinaryComposite.frag index 0aeb332..c11ec15 100644 --- a/Keishiki/shaders/BinaryComposite/BinaryComposite.frag +++ b/Keishiki/shaders/BinaryComposite/BinaryComposite.frag @@ -3,11 +3,149 @@ $input v_texcoord0 #include #include -SAMPLER2D(A, 0); -SAMPLER2D(B, 0); +uniform vec4 f_mode; +SAMPLER2D(v_A, 0); +SAMPLER2D(v_B, 0); void main() { vec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y); - gl_FragColor = texture2D(A, uv) + texture2D(B, uv).a; + vec4 _A = texture2D(v_A, uv); + vec4 _B = texture2D(v_B, uv); + + if (f_mode.x == 0.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 1.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 2.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 3.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 4.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 5.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 6.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 7.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 8.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 9.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 10.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 11.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 12.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 13.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 14.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 15.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 16.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 17.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 18.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 19.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 20.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 21.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 22.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 23.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 24.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 25.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } + else if (f_mode.x == 26.0f) { + float alpha_b = _A.a * (1.0f - _B.a); + float alpha = _A.a + alpha_b; + gl_FragColor = vec4((_A.rgb * _A.a + _B.rgb * alpha_b)/alpha, alpha); + } } diff --git a/Keishiki/shaders/BinaryComposite/BinaryComposite.vert b/Keishiki/shaders/BinaryComposite/BinaryComposite.vert index e69de29..f0be38e 100644 --- a/Keishiki/shaders/BinaryComposite/BinaryComposite.vert +++ b/Keishiki/shaders/BinaryComposite/BinaryComposite.vert @@ -0,0 +1,11 @@ +$input a_position, a_texcoord0 +$output v_texcoord0 + +#include +#include + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0)); + v_texcoord0 = a_texcoord0; +} diff --git a/Keishiki/shaders/Checkerboard/Checkerboard.frag b/Keishiki/shaders/Checkerboard/Checkerboard.frag index 48e840c..e4514c8 100644 --- a/Keishiki/shaders/Checkerboard/Checkerboard.frag +++ b/Keishiki/shaders/Checkerboard/Checkerboard.frag @@ -3,8 +3,12 @@ $input v_texcoord0 #include #include +uniform vec4 f_hw; + void main() { - vec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y) * 100.0f; - gl_FragColor = ceil((uv - floor(uv)) - 0.5f); + vec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y) * 20.0f; + vec2 uvv = ceil(uv- floor(uv) - 0.5f); + float b = 0.8f - mod((uvv.x + uvv.y), 2.0f) * 0.2; + gl_FragColor = vec4(b, b, b, 1.0f); } diff --git a/README.md b/README.md index 56d5248..f9befa3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Logo -# Keishiki Compositor-Sequencer +# Keishiki: GPU Compositor-Sequencer ## Libraries - [SDL2](https://www.libsdl.org/) diff --git a/TODO.md b/TODO.md index 50724f0..8953b16 100644 --- a/TODO.md +++ b/TODO.md @@ -1,12 +1,10 @@ ## Compositor -- BinaryComposite - Manage Samplers - Data model for comps -- Dump state, non-POD needs serialization!!! +- Dump and read back state, (de)serialization!!! ## UI - Sequencer timeline init -- Node editor - Viewport Gizmos (https://github.com/CedricGuillemet/ImGuizmo) - Shader nodes (https://github.com/CedricGuillemet/ImGuizmo)