gg blend modes

This commit is contained in:
lachrymaLF 2024-06-06 15:23:00 -04:00
parent 30735c4f78
commit facd0d7022
10 changed files with 264 additions and 244 deletions

View file

@ -225,10 +225,10 @@ namespace K::Graphics {
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_A = bgfx::createUniform("s_A", bgfx::UniformType::Sampler);
composite_B = bgfx::createUniform("s_B", bgfx::UniformType::Sampler);
composite_pg = load_shader_program("BinaryComposite");
composite_mode = bgfx::createUniform("f_mode", bgfx::UniformType::Vec4);
composite_mode = bgfx::createUniform("u_mode", bgfx::UniformType::Vec4);
return true;
}
@ -427,24 +427,23 @@ 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]) {
void Composite(u32 view_id, 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<f32>(mode);
pack[3] = pack[2] = pack[1] = pack[0] = static_cast<f32>(mode);
bgfx::touch(K::Graphics::K_VIEW_COMP_COMPOSITE);
bgfx::setViewMode(K::Graphics::K_VIEW_COMP_COMPOSITE, bgfx::ViewMode::Sequential);
bgfx::setViewClear(K::Graphics::K_VIEW_COMP_COMPOSITE, 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::setViewMode(view_id, bgfx::ViewMode::Sequential);
bgfx::setViewClear(view_id, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL);
bgfx::setViewFrameBuffer(view_id, fb);
bgfx::setViewTransform(view_id, composite_view, proj);
bgfx::setViewRect(view_id, 0, 0, w, h);
bgfx::setTransform(transform);
bgfx::setVertexBuffer(0, vbh);
bgfx::setIndexBuffer(ibh);
bgfx::setTexture(0, composite_A, composite);
bgfx::setTexture(1, 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);
bgfx::setTexture(0, composite_A, from); // A
bgfx::setTexture(1, composite_B, composite); // B
bgfx::setUniform(composite_mode, pack); // A over B
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
bgfx::submit(view_id, composite_pg);
}
}

View file

@ -13,19 +13,13 @@
#include <imgui.h>
namespace {
SDL_Window *window;
u16 window_width = 1920;
u16 window_height = 1080;
u64 init_time, last_time, current_time, delta_t;
u32 frame;
bool running = false;
K::CompState state;
K::Graphics::ImageTexture *logo;
}
namespace K {
K::AppState app_state;
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCompFrame(const CompState& s, const PlugboardGraph::NodeInstance& n) {
return PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type{static_cast<i32>(s.current_frame)};
}
@ -42,28 +36,28 @@ namespace K {
return false;
}
window = SDL_CreateWindow("Keishiki",
app_state.window = SDL_CreateWindow("Keishiki",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
window_width, window_height,
app_state.window_width, app_state.window_height,
SDL_WINDOW_SHOWN);
if (window == nullptr) {
if (app_state.window == nullptr) {
LogError(SDL_GetError());
return false;
}
bgfx::Init bgfxInit;
bgfxInit.type = bgfx::RendererType::Count; // Automatically choose a renderer.
bgfxInit.resolution.width = window_width;
bgfxInit.resolution.height = window_height;
bgfxInit.resolution.width = app_state.window_width;
bgfxInit.resolution.height = app_state.window_height;
bgfxInit.resolution.reset = BGFX_RESET_VSYNC;
#if !BX_PLATFORM_EMSCRIPTEN
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if (!SDL_GetWindowWMInfo(window, &wmi)) {
if (!SDL_GetWindowWMInfo(app_state.window, &wmi)) {
LogError(SDL_GetError());
}
#endif
@ -85,16 +79,16 @@ namespace K {
}
bgfx::setDebug(BGFX_DEBUG_TEXT);
bgfx::setViewRect(K::Graphics::K_VIEW_LOGO, 0, 0, window_width, window_height);
bgfx::setViewRect(K::Graphics::K_VIEW_LOGO, 0, 0, app_state.window_width, app_state.window_height);
float view[16];
bx::mtxTranslate(view, 0.f, 0.f, 1.0f);
float proj[16];
bx::mtxOrtho(proj, 0.0f, window_width, 0.0f, window_height, 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth);
bx::mtxOrtho(proj, 0.0f, app_state.window_width, 0.0f, app_state.window_height, 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth);
bgfx::setViewTransform(K::Graphics::K_VIEW_LOGO, view, proj);
K::UI::Init(window);
K::UI::Init(app_state.window);
if (!K::Graphics::Init(window_width, window_height)) {
if (!K::Graphics::Init(app_state.window_width, app_state.window_height)) {
LogError("Graphics init failed");
return false;
}
@ -105,7 +99,7 @@ namespace K {
state.height = 550;
state.current_frame = 0;
state.fps = 30.0f;
state.frame_max = 50;
state.frame_max = 200;
state.plugboard.comp_in = PlugboardGraph::Node{
"Composition In",
{},
@ -128,46 +122,47 @@ namespace K {
}
void Render() {
K::Graphics::DrawTextureImageAlpha(K::Graphics::K_VIEW_LOGO, *logo, window_width - logo->w + 10, 0, .4f);
K::Graphics::DrawTextureImageAlpha(K::Graphics::K_VIEW_LOGO, *logo, app_state.window_width - logo->w + 10, 0, .4f);
UI::Draw(frame, state);
UI::Draw(app_state.bgfx_frame, state);
const bgfx::Stats *stat = bgfx::getStats();
const bgfx::Caps *caps = bgfx::getCaps();
bgfx::dbgTextClear();
bgfx::dbgTextPrintf(0, window_height/16 - 4, 0xf8,
bgfx::dbgTextPrintf(0, app_state.window_height/16 - 4, 0xf8,
" lachrymal.net :: %s Renderer :: Max Views %u :: Max FBs %u :: Max Texture Samplers %u :: Blitting %s :: %u FPS",
caps->supported & BGFX_CAPS_RENDERER_MULTITHREADED ? "Multithreaded" : "Singlethreaded",
caps->limits.maxViews, caps->limits.maxFrameBuffers,
caps->limits.maxTextureSamplers, caps->supported & BGFX_CAPS_TEXTURE_BLIT ? "OK" : "NO",
stat->cpuTimerFreq / stat->cpuTimeFrame);
bgfx::dbgTextPrintf(0, window_height/16 - 3, 0xf8,
bgfx::dbgTextPrintf(0, app_state.window_height/16 - 3, 0xf8,
" Project Keishiki :: %s :: Build %s %s :: SDL %i.%i.%i :: bgfx 1.%i :: Dear ImGui %s :: %s",
BX_COMPILER_NAME, __DATE__, __TIME__, SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
BGFX_API_VERSION, ImGui::GetVersion(), bgfx::getRendererName(bgfx::getRendererType()));
frame = bgfx::frame();
app_state.bgfx_frame = bgfx::frame();
}
void Run() {
last_time = init_time = SDL_GetTicks64();
app_state.init_time = SDL_GetTicks64();
app_state.last_time = app_state.init_time;
running = true;
while (running) {
current_time = SDL_GetTicks64();
delta_t = current_time - last_time;
app_state.running = true;
while (app_state.running) {
app_state.current_time = SDL_GetTicks64();
app_state.delta_t = app_state.current_time - app_state.last_time;
for (SDL_Event current_event; SDL_PollEvent(&current_event) != 0;) {
ImGui_ImplSDL2_ProcessEvent(&current_event);
if (current_event.type == SDL_QUIT) {
running = false;
app_state.running = false;
break;
}
}
Render();
last_time = current_time;
app_state.last_time = app_state.current_time;
}
}
@ -175,7 +170,7 @@ namespace K {
K::Graphics::Shutdown();
K::UI::Shutdown(state);
bgfx::shutdown();
SDL_DestroyWindow(window);
SDL_DestroyWindow(app_state.window);
SDL_Quit();
}
}

View file

@ -29,11 +29,12 @@ namespace {
const f32 row_height = 20.0f;
// Viewport
bgfx::TextureHandle composite = BGFX_INVALID_HANDLE,
composite_blit = BGFX_INVALID_HANDLE,
bool playing;
u64 last_frame_tick;
bgfx::TextureHandle composite[2] = { BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE },
render = BGFX_INVALID_HANDLE,
save = BGFX_INVALID_HANDLE;
bgfx::FrameBufferHandle composite_fb = BGFX_INVALID_HANDLE,
bgfx::FrameBufferHandle composite_fb[2] = { BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE },
render_fb = BGFX_INVALID_HANDLE;
K::VisualTrack bg{};
f32 proj[16], transform[16], view[16];
@ -55,6 +56,53 @@ namespace ImGui {
}
namespace K::UI {
void AddTransformLayer(CompState& s, const std::string& name) {
auto l = Layer{
VisualTrack{},
name,
Graphics::K_V_AlphaOver,
0UL,
s.frame_max
};
l.track.add_uniform("aspect_ratio", ShaderGraph::expand_type(ShaderGraph::T_XY));
if (s.width > s.height)
l.track.uniforms["aspect_ratio"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(static_cast<f32>(s.width)/static_cast<f32>(s.height), 1.0f);
else
l.track.uniforms["aspect_ratio"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(1.0f, static_cast<f32>(s.height)/static_cast<f32>(s.width));
l.track.add_uniform("opacity", ShaderGraph::expand_type(ShaderGraph::T_Float));
l.track.uniforms["opacity"].val = ShaderGraph::T_Map<ShaderGraph::T_Float>::type(1.0f);
l.track.add_uniform("rot", ShaderGraph::expand_type(ShaderGraph::T_Float));
l.track.uniforms["rot"].val = ShaderGraph::T_Map<ShaderGraph::T_Float>::type(.0f);
l.track.add_uniform("scale", ShaderGraph::expand_type(ShaderGraph::T_XY));
l.track.uniforms["scale"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(1.0f, 1.0f);
l.track.add_uniform("translate", ShaderGraph::expand_type(ShaderGraph::T_XY));
l.track.uniforms["translate"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(.0f, .0f);
l.track.shader = "void main() {\n"
"\tfloat angle = -rot * M_PI / 180.0f;\n"
"\tvec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y) - .5f;\n"
"\tuv = uv * aspect_ratio;\n"
"\tuv = uv - translate;\n"
"\tuv = vec2(cos(angle)*uv.x - sin(angle)*uv.y, sin(angle)*uv.x + cos(angle)*uv.y);\n"
"\tuv = uv / scale;\n"
"\tuv = uv + .5f;\n\n"
"\tvec4 tx = texture2D(s_texColor, uv);\n"
"\tgl_FragColor = vec4(tx.rgb, tx.a * opacity);\n"
"}\n";
l.track.compile();
l.track.expose_uniform(s, "aspect_ratio");
l.track.expose_uniform(s, "opacity");
l.track.expose_uniform(s, "rot");
l.track.expose_uniform(s, "scale");
l.track.expose_uniform(s, "translate");
s.layers.push_back(std::move(l));
}
void MainMenuBar(const CompState& s) {
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("Edit")) {
@ -78,13 +126,15 @@ namespace K::UI {
}
void SetupViewport(CompState& s) {
composite = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
composite_blit = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_BLIT_DST);
composite[0] = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
composite[1] = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
render = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT);
bgfx::Attachment comp{}, ren{};
comp.init(composite, bgfx::Access::Write); // DX 11 requires Write only
bgfx::Attachment comp{}, comp2{}, ren{};
comp.init(composite[0], bgfx::Access::Write); // DX 11 requires Write only
comp2.init(composite[1], bgfx::Access::Write); // DX 11 requires Write only
ren.init(render, bgfx::Access::ReadWrite);
composite_fb = bgfx::createFrameBuffer(1, &comp);
composite_fb[0] = bgfx::createFrameBuffer(1, &comp);
composite_fb[1] = bgfx::createFrameBuffer(1, &comp2);
render_fb = bgfx::createFrameBuffer(1, &ren);
save = bgfx::createTexture2D(s.width, s.height, false, 1, bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_READ_BACK | BGFX_TEXTURE_BLIT_DST);
@ -104,9 +154,10 @@ namespace K::UI {
}
void DestroyViewport(CompState& s) {
bgfx::destroy(composite_fb);
bgfx::destroy(composite);
bgfx::destroy(composite_blit);
bgfx::destroy(composite_fb[0]);
bgfx::destroy(composite_fb[1]);
bgfx::destroy(composite[0]);
bgfx::destroy(composite[1]);
bgfx::destroy(render_fb);
bgfx::destroy(render);
@ -268,29 +319,64 @@ namespace K::UI {
}
void Viewport(CompState& s) {
if (ImGui::Begin("Viewport", &draw_viewport)) {
ImTextureID idx;
if (playing) {
if (static_cast<f32>(app_state.current_time - last_frame_tick) >= 1000.0f / s.fps) {
f32 delta = static_cast<f32>(app_state.current_time - last_frame_tick);
f32 frames_passed = delta / (1000.0f / s.fps);
s.current_frame = (s.current_frame + static_cast<u64>(std::floor(frames_passed))) % (s.frame_max + 1);
last_frame_tick = app_state.current_time - static_cast<u64>(std::fmod(delta, 1000.0f / s.fps));
}
}
if (ImGui::Begin("Viewport", &draw_viewport)) {
u32 view_count = 0, layers_done = 0;
bgfx::setViewFrameBuffer(Graphics::K_VIEW_COMP_COMPOSITE + view_count, composite_fb[0]); // the other fb will be cleared in composite
bgfx::setViewClear(Graphics::K_VIEW_COMP_COMPOSITE + view_count, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, 0x00000000);
bgfx::setViewRect(Graphics::K_VIEW_COMP_COMPOSITE + view_count, 0, 0, s.width, s.height);
bgfx::touch(Graphics::K_VIEW_COMP_COMPOSITE + view_count);
view_count++;
bg.get_frame(s, composite_fb, s.width, s.height, proj, view, transform);
bgfx::blit(Graphics::K_VIEW_COMP_COMPOSITE, composite_blit, 0, 0, composite);
for (u32 i = s.layers.size() - 1; i != u32(-1); i--) {
if (s.disabled.contains(i)) continue;
if (s.current_frame > s.layers[i].out || s.current_frame < s.layers[i].in) continue;
Graphics::Composite( composite_fb, composite_blit, s.layers[i].track.get_frame(s, render_fb, s.width, s.height, proj, view, transform),
i == s.layers.size() - 1 ? Graphics::K_V_AlphaOver : s.layers[i].mode, s.width, s.height, proj, transform);
bgfx::blit(Graphics::K_VIEW_COMP_COMPOSITE, composite_blit, 0, 0, composite);
s.layers[i].track.get_frame(s, Graphics::K_VIEW_COMP_COMPOSITE + view_count++, render_fb, s.width, s.height, proj, view, transform);
Graphics::Composite(Graphics::K_VIEW_COMP_COMPOSITE + view_count++, composite_fb[(layers_done + 1) % 2], composite[layers_done % 2], render, s.layers[i].mode, s.width, s.height, proj, transform);
layers_done++;
}
idx = ImGui::toId(composite, 0, 0);
if (layers_done != 0) {
bg.get_frame(s, Graphics::K_VIEW_COMP_COMPOSITE + view_count++, render_fb, s.width, s.height, proj, view,
transform);
Graphics::Composite(Graphics::K_VIEW_COMP_COMPOSITE + view_count++, composite_fb[(layers_done + 1) % 2],
render, composite[layers_done % 2], Graphics::K_V_AlphaOver, s.width, s.height,
proj, transform);
layers_done++;
}
else {
bg.get_frame(s, Graphics::K_VIEW_COMP_COMPOSITE + view_count++, composite_fb[0], s.width, s.height, proj, view,
transform);
}
Vector<bgfx::ViewId> views;
for (u32 i = 0; i < view_count; i++)
views.push_back(Graphics::K_VIEW_COMP_COMPOSITE + i);
views.push_back(Graphics::K_VIEW_COMP_SAVE);
views.push_back(Graphics::K_VIEW_UI);
views.push_back(Graphics::K_VIEW_LOGO);
bgfx::setViewOrder(0, views.size(), views.data());
ImTextureID idx = ImGui::toId(composite[layers_done % 2], 0, 0);
if (idx != nullptr)
ImGui::Image(idx, ImVec2{ static_cast<f32>(s.width), static_cast<f32>(s.height) });
ImGui::Text("Composition Size: %ux%u", s.width, s.height);
ImGui::SameLine();
ImGui::DragFloat("FPS", &s.fps, 1.0f, 1.0f, 120.0f);
ImGui::SameLine();
ImGui::BeginDisabled(save_called);
if (ImGui::Button("Save to frame.png")) {
bgfx::blit(Graphics::K_VIEW_COMP_SAVE, save, 0, 0, composite);
bgfx::blit(Graphics::K_VIEW_COMP_SAVE, save, 0, 0, composite[layers_done % 2]);
ready_frame = bgfx::readTexture(save, save_buffer);
save_called = true;
}
@ -339,6 +425,13 @@ namespace K::UI {
ImGui::EndCombo();
}
ImGui::SameLine();
bool playing_cp = playing;
ImGui::Checkbox("Playing", &playing);
if (!playing_cp && playing) {
last_frame_tick = app_state.current_time;
}
ImGui::SameLine();
ImGui::Text("%lu / %lu Frames", s.current_frame, s.frame_max);
ImGui::SameLine();
@ -347,49 +440,7 @@ namespace K::UI {
static String name{};
if (ImGui::Button("Add Layer") && !name.empty()) {
auto l = Layer{
VisualTrack{},
name,
Graphics::K_V_AlphaOver,
0UL,
s.frame_max
};
l.track.add_uniform("aspect_ratio", ShaderGraph::expand_type(ShaderGraph::T_XY));
if (s.width > s.height)
l.track.uniforms["aspect_ratio"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(static_cast<f32>(s.width)/static_cast<f32>(s.height), 1.0f);
else
l.track.uniforms["aspect_ratio"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(1.0f, static_cast<f32>(s.height)/static_cast<f32>(s.width));
l.track.add_uniform("opacity", ShaderGraph::expand_type(ShaderGraph::T_Float));
l.track.uniforms["opacity"].val = ShaderGraph::T_Map<ShaderGraph::T_Float>::type(1.0f);
l.track.add_uniform("rot", ShaderGraph::expand_type(ShaderGraph::T_Float));
l.track.uniforms["rot"].val = ShaderGraph::T_Map<ShaderGraph::T_Float>::type(.0f);
l.track.add_uniform("scale", ShaderGraph::expand_type(ShaderGraph::T_XY));
l.track.uniforms["scale"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(1.0f, 1.0f);
l.track.add_uniform("translate", ShaderGraph::expand_type(ShaderGraph::T_XY));
l.track.uniforms["translate"].val = ShaderGraph::T_Map<ShaderGraph::T_XY>::type(.0f, .0f);
l.track.shader = "void main() {\n"
"\tfloat angle = -rot * M_PI / 180.0f;\n"
"\tvec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y) - .5f;\n"
"\tuv = uv * aspect_ratio;\n"
"\tuv = uv - translate;\n"
"\tuv = vec2(cos(angle)*uv.x - sin(angle)*uv.y, sin(angle)*uv.x + cos(angle)*uv.y);\n"
"\tuv = uv / scale;\n"
"\tuv = uv + .5f;\n\n"
"\tvec4 tx = texture2D(s_texColor, uv);\n"
"\tgl_FragColor = vec4(tx.rgb, tx.a * opacity);\n"
"}\n";
l.track.compile();
l.track.expose_uniform(s, "aspect_ratio");
l.track.expose_uniform(s, "opacity");
l.track.expose_uniform(s, "rot");
l.track.expose_uniform(s, "scale");
l.track.expose_uniform(s, "translate");
s.layers.push_back(std::move(l));
AddTransformLayer(s, name);
}
ImGui::SameLine();
ImGui::SetNextItemWidth(-100.0f);
@ -869,7 +920,8 @@ namespace K::UI {
f32 x = i.begin + (i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
CompState ss = i.s;
ss.current_frame = static_cast<u64>(std::round(x));
return {x, std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(PlugboardGraph::Eval(ss, i.connected_v))};
bool good;
return {x, std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(PlugboardGraph::ConvertValue(PlugboardGraph::Eval(ss, i.connected_v), PlugboardGraph::T_Float, good))};
}, &info, info.samples);
ImPlot::EndPlot();
}

View file

@ -36,15 +36,13 @@ namespace K {
},val);
}
bgfx::TextureHandle
VisualTrack::get_frame(const CompState& s, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 *proj, f32 *view, f32 *transform) const {
bgfx::touch(K::Graphics::K_VIEW_COMP_COMPOSITE);
bgfx::setViewMode(K::Graphics::K_VIEW_COMP_COMPOSITE, bgfx::ViewMode::Sequential);
bgfx::setViewClear(K::Graphics::K_VIEW_COMP_COMPOSITE, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
bgfx::setViewFrameBuffer(K::Graphics::K_VIEW_COMP_COMPOSITE, fb);
void VisualTrack::get_frame(const CompState& s, u32 view_id, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 *proj, f32 *view, f32 *transform) const {
bgfx::setViewMode(view_id, bgfx::ViewMode::Sequential);
bgfx::setViewClear(view_id, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL);
bgfx::setViewFrameBuffer(view_id, fb);
bgfx::setViewTransform(K::Graphics::K_VIEW_COMP_COMPOSITE, view, proj);
bgfx::setViewRect(K::Graphics::K_VIEW_COMP_COMPOSITE, 0, 0, w, h);
bgfx::setViewTransform(view_id, view, proj);
bgfx::setViewRect(view_id, 0, 0, w, h);
for (auto& [_name, u] : uniforms) {
f32 pack[4]{};
@ -87,10 +85,8 @@ namespace K {
bgfx::setUniform(u.handle, pack);
}
Graphics::DrawTextureWithTransform(K::Graphics::K_VIEW_COMP_COMPOSITE, Graphics::mmaker->tx, transform,
(BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) &
~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS), pg);
return bgfx::getTexture(fb);
Graphics::DrawTextureWithTransform(view_id, Graphics::mmaker->tx, transform,
BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A, pg);
}
void VisualTrack::compile() {

View file

@ -7,11 +7,11 @@
namespace K::Graphics {
enum VIEW_ID {
K_VIEW_COMP_COMPOSITE,
K_VIEW_COMP_SAVE,
K_VIEW_DRAW,
K_VIEW_UI,
K_VIEW_LOGO,
K_VIEW_COMP_COMPOSITE, // Remember to call setViewOrder!
};
bool Init(u16 width, u16 height);
@ -120,7 +120,7 @@ namespace K::Graphics {
"Invalid"
};
void Composite(bgfx::FrameBufferHandle fb, bgfx::TextureHandle composite, bgfx::TextureHandle from, Blending mode, u16 w, u16 h, f32 proj[16], f32 transform[16]);
void Composite(u32 view_id, 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;
}

View file

@ -34,4 +34,14 @@ namespace K {
PlugboardGraph::PlugboardGraph plugboard;
};
extern struct AppState {
SDL_Window *window = nullptr;
u16 window_width = 1920;
u16 window_height = 1080;
u64 init_time{}, last_time{}, current_time{}, delta_t{};
u32 bgfx_frame{};
bool running = false;
} app_state; // global !
}

View file

@ -37,7 +37,7 @@ namespace K {
String shader;
Dict<String, Uniform> uniforms;
// Vector<String> samplers;
bgfx::TextureHandle get_frame(const CompState& s, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 proj[16], f32 view[16], f32 transform[16]) const;
void get_frame(const CompState& s, u32 view_id, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 proj[16], f32 view[16], f32 transform[16]) const;
void expose_uniform(CompState& s, const String& u);
void hide_uniform(CompState& s, const String& u);

View file

@ -12,7 +12,7 @@ P = lambda location, platform, frag, vert: { 'location': location, 'platform': p
plats = [
P('glsl', 'windows', '140', '140'),
# P('dx11', 'windows', 's_5_0', 's_5_0'),
P('spirv', 'windows', 'spirv', 'spirv'),
P('spirv', 'linux', 'spirv', 'spirv'),
P('metal', 'osx', 'metal', 'metal')
]

View file

@ -1,146 +1,113 @@
/* Reference: https://drafts.fxtf.org/compositing-1 */
$input v_texcoord0
#include <bgfx_shader.sh>
#include <shaderlib.sh>
uniform vec4 f_mode;
SAMPLER2D(v_A, 0);
SAMPLER2D(v_B, 1);
uniform vec4 u_mode;
SAMPLER2D(s_A, 0);
SAMPLER2D(s_B, 1);
void main()
{
void main() {
vec2 uv = vec2(v_texcoord0.x, 1.0f - v_texcoord0.y);
vec4 _A = texture2D(v_A, uv);
vec4 _B = texture2D(v_B, uv);
vec4 _A = texture2D(s_A, uv);
vec4 _B = texture2D(s_B, uv);
// Premult
_A.xyz = _A.xyz * _A.w;
_B.xyz = _B.xyz * _B.w;
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);
// Porter-Duff Source Over
gl_FragColor.w = _A.w + _B.w * (1 - _A.w);
vec3 blend = vec3(0.0f, 0.0f, 0.0f);
int mode = round(u_mode.x);
if (mode == 0) { // Normal
blend = _A.xyz;
}
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 (mode == 1) { // Dissolve
blend = _A.w > random(uv) ? _A.xyz : _B.xyz;
}
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 (mode == 2) { // Add
blend = _A.xyz + _B.xyz;
}
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 (mode == 3) { // Subtract
blend = _A.xyz - _B.xyz;
}
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 (mode == 4) { // Difference
blend = abs(_A.xyz - _B.xyz);
}
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 (mode == 5) { // Exclusion
blend = _B.xyz + _A.xyz - 2.0f * _B.xyz * _A.xyz;
}
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 (mode == 6) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 7) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 8) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 9) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 10) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 11) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 12) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 13) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 14) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 15) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 16) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 17) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 18) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 19) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 20) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 21) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 22) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 23) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 24) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
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 (mode == 25) {
gl_FragColor = vec4(50.0f, 0.0f, 0.0f, 1.0f);
}
else {
gl_FragColor = vec4(uv, 0.0f, 1.0f);
}
// Porter-Duff Source Over
gl_FragColor.xyz = blend + _B.xyz * (1.0f - _A.w);
// Unmult
gl_FragColor.xyz = gl_FragColor.xyz / gl_FragColor.w;
}

View file

@ -4,15 +4,14 @@
- Node groups
## Compositor
- Playback...
- Manage Samplers -- (Resources in general)
- Blender previews (important !)
- Data model for comps
- Dump and read back state, (de)serialization!!!
- Non-negotiables:
- Text (idea: index-based evaluation in plugboard)
- Shapes (idea: embed glisp :mmtroll:, need to inquire -- still a lot of friction for simple shapes if we don't also get the glisp gizmos)
- External data driving (csv, json or something else?) -- use a node to select source
- Data model for comps
- Pre-compose/Layer Groups (jokes -- can be completely UI side)
- Motion blur
@ -20,6 +19,8 @@
- Viewport gizmos (Layer-specific & nodes -- can separate into different tools?) -- Not sure how to go about this
- Node loop detection (separate DFS (extra work) or be smart in recursion)
- detect time-sensitive nodes in tree and display on timeline
- Key selection in comp panel
- Graph editor
# Later
## Compositor