# src/bg_shader.py import time import math from typing import Optional import numpy as np from imgui_bundle import imgui, nanovg as nvg, hello_imgui class BackgroundShader: def __init__(self): self.enabled = False self.start_time = time.time() self.ctx: Optional[nvg.Context] = None def render(self, width: float, height: float): if not self.enabled: return # In imgui-bundle, hello_imgui handles the background. # We can use the background_draw_list to draw primitives. # Since we don't have raw GLSL easily in Python without PyOpenGL, # we'll use a "faux-shader" approach with NanoVG or DrawList gradients. t = time.time() - self.start_time dl = imgui.get_background_draw_list() # Base deep sea color dl.add_rect_filled(imgui.ImVec2(0, 0), imgui.ImVec2(width, height), imgui.get_color_u32(imgui.ImVec4(0.01, 0.07, 0.20, 1.0))) # Layer 1: Slow moving large blobs (FBM approximation) for i in range(3): phase = t * (0.1 + i * 0.05) x = (math.sin(phase) * 0.5 + 0.5) * width y = (math.cos(phase * 0.8) * 0.5 + 0.5) * height radius = (0.4 + 0.2 * math.sin(t * 0.2)) * max(width, height) col = imgui.ImVec4(0.02, 0.26, 0.55, 0.3) dl.add_circle_filled(imgui.ImVec2(x, y), radius, imgui.get_color_u32(col), num_segments=32) # Layer 2: Shimmering caustics (Animated Lines) num_lines = 15 for i in range(num_lines): offset = (t * 20.0 + i * (width / num_lines)) % width alpha = 0.1 * (1.0 + math.sin(t + i)) col = imgui.get_color_u32(imgui.ImVec4(0.08, 0.60, 0.88, alpha)) p1 = imgui.ImVec2(offset, 0) p2 = imgui.ImVec2(offset - 100, height) dl.add_line(p1, p2, col, thickness=2.0) # Vignette center = imgui.ImVec2(width/2, height/2) radius = max(width, height) * 0.8 # Draw multiple concentric circles for a soft vignette for i in range(10): r = radius + (i * 50) alpha = (i / 10.0) * 0.5 dl.add_circle(center, r, imgui.get_color_u32(imgui.ImVec4(0, 0, 0, alpha)), num_segments=64, thickness=60.0) _bg: Optional[BackgroundShader] = None def get_bg(): global _bg if _bg is None: _bg = BackgroundShader() return _bg