you can fuck with the mandelbrot

This commit is contained in:
2026-01-13 19:53:43 +00:00
parent 89c0bb5f7f
commit abab81ce53
4 changed files with 134 additions and 29 deletions

121
main.cpp
View File

@@ -113,6 +113,30 @@ const int SIDEBAR_WIDTH = 200;
const int BUTTON_HEIGHT = 60;
const int BUTTON_MARGIN = 10;
// Slider UI
struct Slider {
std::string name;
float* value_ptr;
float min_val;
float max_val;
bool is_dragging;
};
// Mandelbrot Parameters
float m_exponent = 2.0f;
float m_z_real = 0.0f;
float m_z_imag = 0.0f;
float m_c_real = 0.0f;
float m_c_imag = 0.0f;
std::vector<Slider> mandel_sliders = {
{"Exp", &m_exponent, 1.0f, 10.0f, false},
{"Zr", &m_z_real, -1.0f, 1.0f, false},
{"Zi", &m_z_imag, -1.0f, 1.0f, false},
{"Cr", &m_c_real, -1.0f, 1.0f, false},
{"Ci", &m_c_imag, -1.0f, 1.0f, false}
};
// Forward declarations
void render_frame();
GLuint load_shader_src(const char *source, GLenum type);
@@ -332,10 +356,27 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uin
cursor_x = wl_fixed_to_double(sx);
cursor_y = wl_fixed_to_double(sy);
// Slider Logic
if (shaders[current_shader_index].name == "MANDEL") {
for (auto& s : mandel_sliders) {
if (s.is_dragging) {
// Calculate new value based on X position relative to sidebar
// Lets say slider width is SIDEBAR_WIDTH - 20
float track_x = 10;
float track_w = SIDEBAR_WIDTH - 20;
float normalized = (float)(cursor_x - track_x) / track_w;
if (normalized < 0.0f) normalized = 0.0f;
if (normalized > 1.0f) normalized = 1.0f;
*s.value_ptr = s.min_val + normalized * (s.max_val - s.min_val);
return; // Consume input
}
}
}
if (is_dragging) {
float dx = (cursor_x - old_x) / height;
float dy = (cursor_y - old_y) / height;
// Pan logic
view_x -= dx / zoom_level * 2.0;
view_y += dy / zoom_level * 2.0;
}
@@ -345,22 +386,41 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uin
if (button == 0x110) { // Left click
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
if (cursor_x < SIDEBAR_WIDTH) {
int clicked_index = -1;
for (size_t i = 0; i < shaders.size(); ++i) {
int y_start = BUTTON_MARGIN + i * (BUTTON_HEIGHT + BUTTON_MARGIN);
int y_end = y_start + BUTTON_HEIGHT;
if (cursor_y >= y_start && cursor_y <= y_end && cursor_x >= BUTTON_MARGIN && cursor_x <= SIDEBAR_WIDTH - BUTTON_MARGIN) {
clicked_index = i;
break;
// Check Sliders first if Mandelbrot
bool hit_slider = false;
if (shaders[current_shader_index].name == "MANDEL") {
// We need to know where they are drawn.
// Let's assume they are drawn starting at y = 500 (bottom of sidebar?)
// Or right after the buttons?
// We have 7 buttons. 7 * 70 = 490px.
float sy = 490 + 20;
for (auto& s : mandel_sliders) {
if (cursor_y >= sy && cursor_y < sy + 20) {
s.is_dragging = true;
hit_slider = true;
}
sy += 30; // 20 height + 10 margin
}
}
if (clicked_index != -1) {
current_shader_index = clicked_index;
std::cout << "Switched to shader: " << shaders[current_shader_index].name << std::endl;
if (shaders[current_shader_index].name == "MANDEL") {
zoom_level = 1.0f;
view_x = -0.5f;
view_y = 0.0f;
if (!hit_slider) {
int clicked_index = -1;
for (size_t i = 0; i < shaders.size(); ++i) {
int y_start = BUTTON_MARGIN + i * (BUTTON_HEIGHT + BUTTON_MARGIN);
int y_end = y_start + BUTTON_HEIGHT;
if (cursor_y >= y_start && cursor_y <= y_end && cursor_x >= BUTTON_MARGIN && cursor_x <= SIDEBAR_WIDTH - BUTTON_MARGIN) {
clicked_index = i;
break;
}
}
if (clicked_index != -1) {
current_shader_index = clicked_index;
// Reset slider drag states just in case
for (auto& s : mandel_sliders) s.is_dragging = false;
if (shaders[current_shader_index].name == "MANDEL") {
// Keep zoom? Yes.
}
}
}
} else {
@@ -368,6 +428,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uin
}
} else {
is_dragging = false;
for (auto& s : mandel_sliders) s.is_dragging = false; // Release sliders
}
}
}
@@ -491,6 +552,26 @@ void render_frame() {
draw_text(shaders[i].name, text_x, text_y, text_scale, 1.0f, 1.0f, 1.0f);
}
// Render Sliders if Mandelbrot
if (shaders[current_shader_index].name == "MANDEL") {
float sy = 490 + 20;
for (const auto& s : mandel_sliders) {
// Track
glUseProgram(sidebar_program);
draw_quad(10, sy + 8, SIDEBAR_WIDTH - 20, 4, width, height, 0.3f, 0.3f, 0.3f);
// Knob
float normalized = (*s.value_ptr - s.min_val) / (s.max_val - s.min_val);
float kx = 10 + normalized * (SIDEBAR_WIDTH - 20);
draw_quad(kx - 5, sy, 10, 20, width, height, 0.8f, 0.8f, 0.8f);
// Label
draw_text(s.name, 10, sy - 8, 1.0f, 1.0f, 1.0f, 0.0f); // Yellowish
sy += 30;
}
}
// 3. Render Active Shader
int view_w = width - SIDEBAR_WIDTH;
int view_h = height;
@@ -523,6 +604,16 @@ void render_frame() {
GLint centerLoc = glGetUniformLocation(active.program, "u_center");
if (centerLoc != -1) glUniform2f(centerLoc, view_x, view_y);
// Mandelbrot Params
GLint expLoc = glGetUniformLocation(active.program, "u_exponent");
if (expLoc != -1) glUniform1f(expLoc, m_exponent);
GLint zStartLoc = glGetUniformLocation(active.program, "u_z_start");
if (zStartLoc != -1) glUniform2f(zStartLoc, m_z_real, m_z_imag);
GLint cOffsetLoc = glGetUniformLocation(active.program, "u_c_offset");
if (cOffsetLoc != -1) glUniform2f(cOffsetLoc, m_c_real, m_c_imag);
if (active.is_stateful) {
// Ping-Pong rendering