042bb43b37
- cpp/functions/gfx: gl_shader, gl_framebuffer, fullscreen_quad, shader_canvas - cpp/apps/shaders_lab: main + 3 seed shaders (plasma, circle, checker) - ImGui docking layout: Code | Canvas | Controls Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
2.4 KiB
C++
86 lines
2.4 KiB
C++
#define GL_GLEXT_PROTOTYPES
|
|
#include <GL/gl.h>
|
|
#include <GL/glext.h>
|
|
|
|
#include "gfx/shader_canvas.h"
|
|
#include "imgui.h"
|
|
|
|
namespace fn::gfx {
|
|
|
|
void canvas_init(ShaderCanvas& c) {
|
|
if (c.initialized) return;
|
|
fb_init(c.fb);
|
|
quad_init(c.quad);
|
|
c.initialized = true;
|
|
}
|
|
|
|
void canvas_set_program(ShaderCanvas& c, unsigned int program) {
|
|
if (c.program) delete_program(c.program);
|
|
c.program = program;
|
|
}
|
|
|
|
void canvas_render(ShaderCanvas& c, float time_seconds) {
|
|
ImVec2 avail = ImGui::GetContentRegionAvail();
|
|
int w = static_cast<int>(avail.x);
|
|
int h = static_cast<int>(avail.y);
|
|
if (w < 1) w = 1;
|
|
if (h < 1) h = 1;
|
|
|
|
fb_resize(c.fb, w, h);
|
|
|
|
// Save GL state
|
|
GLint prev_fbo = 0;
|
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
|
|
GLint prev_vp[4];
|
|
glGetIntegerv(GL_VIEWPORT, prev_vp);
|
|
|
|
// Render to FBO
|
|
glBindFramebuffer(GL_FRAMEBUFFER, c.fb.fbo);
|
|
glViewport(0, 0, w, h);
|
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
if (c.program) {
|
|
glUseProgram(c.program);
|
|
|
|
GLint loc_res = glGetUniformLocation(c.program, "u_resolution");
|
|
GLint loc_time = glGetUniformLocation(c.program, "u_time");
|
|
GLint loc_mouse = glGetUniformLocation(c.program, "u_mouse");
|
|
|
|
if (loc_res >= 0) glUniform2f(loc_res, static_cast<float>(w), static_cast<float>(h));
|
|
if (loc_time >= 0) glUniform1f(loc_time, time_seconds);
|
|
if (loc_mouse >= 0) {
|
|
ImVec2 mouse = ImGui::GetMousePos();
|
|
ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
|
|
// cursor pos is AFTER content region starts
|
|
float mx = mouse.x - canvas_pos.x;
|
|
float my = static_cast<float>(h) - (mouse.y - canvas_pos.y);
|
|
glUniform2f(loc_mouse, mx, my);
|
|
}
|
|
|
|
quad_draw(c.quad);
|
|
glUseProgram(0);
|
|
}
|
|
|
|
// Restore GL state
|
|
glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prev_fbo));
|
|
glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]);
|
|
|
|
// Draw texture in ImGui panel (flip V: OpenGL origin is bottom-left)
|
|
ImGui::Image(
|
|
(ImTextureID)(intptr_t)c.fb.tex,
|
|
avail,
|
|
ImVec2(0, 1), ImVec2(1, 0)
|
|
);
|
|
}
|
|
|
|
void canvas_destroy(ShaderCanvas& c) {
|
|
if (!c.initialized) return;
|
|
if (c.program) { delete_program(c.program); c.program = 0; }
|
|
quad_destroy(c.quad);
|
|
fb_destroy(c.fb);
|
|
c.initialized = false;
|
|
}
|
|
|
|
} // namespace fn::gfx
|