From aed461ef28433d844b84c417ba05781cb372aa42 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 13 Mar 2026 21:35:23 -0400 Subject: [PATCH] fix(shader): Add proper VAO setup for OpenGL 3.3 core profile - Create _create_quad_vao() method that creates VAO with vertex buffer - Use explicit vertex attributes (a_position, a_texcoord) in shaders - Bind VAO before glDrawArrays calls - Use ctypes for proper buffer sizing --- src/gui_2.py | 4 --- src/shader_manager.py | 66 +++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/gui_2.py b/src/gui_2.py index b9a5723..cc48fab 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -4055,10 +4055,6 @@ def hello(): return True def _pre_new_frame(self) -> None: - # DISABLED: OpenGL 3.3 core profile doesn't support fixed-function glBegin/glEnd - # and vertex attrib setup is failing in imgui-bundle context - # TODO: Fix with proper VAO setup or use different OpenGL context - return if not self.ui_frosted_glass_enabled: return ws = imgui.get_io().display_size diff --git a/src/shader_manager.py b/src/shader_manager.py index b8abe8f..0afa481 100644 --- a/src/shader_manager.py +++ b/src/shader_manager.py @@ -162,6 +162,7 @@ class BlurPipeline: self.h_blur_program: int | None = None self.v_blur_program: int | None = None self.deepsea_program: int | None = None + self._quad_vao: int | None = None self._fb_width: int = 0 self._fb_height: int = 0 self._fb_scale: int = 1 @@ -209,6 +210,26 @@ class BlurPipeline: gl.glBindTexture(gl.GL_TEXTURE_2D, 0) return fbo, tex + def _create_quad_vao(self) -> int: + import ctypes + vao = gl.glGenVertexArrays(1) + gl.glBindVertexArray(vao) + vertices = (ctypes.c_float * 16)( + -1.0, -1.0, 0.0, 0.0, + 1.0, -1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, 1.0, + 1.0, 1.0, 1.0, 1.0 + ) + vbo = gl.glGenBuffers(1) + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo) + gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(vertices), vertices, gl.GL_STATIC_DRAW) + gl.glEnableVertexAttribArray(0) + gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 16, None) + gl.glEnableVertexAttribArray(1) + gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, 16, ctypes.c_void_p(8)) + gl.glBindVertexArray(0) + return vao + def setup_fbos(self, width: int, height: int, fb_scale: float = 1.0): scale = max(1, int(fb_scale)) blur_w = max(1, (width * scale) // 4) @@ -225,8 +246,8 @@ class BlurPipeline: def compile_blur_shaders(self): vert_src = """ #version 330 core -in vec2 a_position; -in vec2 a_texcoord; +layout(location = 0) in vec2 a_position; +layout(location = 1) in vec2 a_texcoord; out vec2 v_uv; void main() { gl_Position = vec4(a_position, 0.0, 1.0); @@ -289,8 +310,8 @@ void main() { def compile_deepsea_shader(self): vert_src = """ #version 330 core -in vec2 a_position; -in vec2 a_texcoord; +layout(location = 0) in vec2 a_position; +layout(location = 1) in vec2 a_texcoord; out vec2 v_uv; void main() { gl_Position = vec4(a_position, 0.0, 1.0); @@ -356,9 +377,10 @@ void main() { } """ self.deepsea_program = self._compile_shader(vert_src, frag_src) + self._quad_vao = self._create_quad_vao() def render_deepsea_to_fbo(self, width: int, height: int, time: float): - if not self.deepsea_program or not self.scene_fbo: + if not self.deepsea_program or not self.scene_fbo or not self._quad_vao: return scene_w = width * self._fb_scale scene_h = height * self._fb_scale @@ -367,19 +389,15 @@ void main() { gl.glClearColor(0.01, 0.05, 0.12, 1.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT) gl.glUseProgram(self.deepsea_program) - u_time = gl.glGetUniformLocation(self.deepsea_program, "u_time") - if u_time != -1: - gl.glUniform1f(u_time, time) - u_res = gl.glGetUniformLocation(self.deepsea_program, "u_resolution") - if u_res != -1: - gl.glUniform2f(u_res, float(scene_w), float(scene_h)) - # Draw fullscreen quad using deprecated but working glBegin/glEnd - gl.glBegin(gl.GL_TRIANGLE_STRIP) - gl.glVertex2f(-1.0, -1.0); gl.glTexCoord2f(0.0, 0.0) - gl.glVertex2f( 1.0, -1.0); gl.glTexCoord2f(1.0, 0.0) - gl.glVertex2f(-1.0, 1.0); gl.glTexCoord2f(0.0, 1.0) - gl.glVertex2f( 1.0, 1.0); gl.glTexCoord2f(1.0, 1.0) - gl.glEnd() + u_time_loc = gl.glGetUniformLocation(self.deepsea_program, "u_time") + if u_time_loc != -1: + gl.glUniform1f(u_time_loc, time) + u_res_loc = gl.glGetUniformLocation(self.deepsea_program, "u_resolution") + if u_res_loc != -1: + gl.glUniform2f(u_res_loc, float(scene_w), float(scene_h)) + gl.glBindVertexArray(self._quad_vao) + gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4) + gl.glBindVertexArray(0) gl.glUseProgram(0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) @@ -393,12 +411,9 @@ void main() { u_ts = gl.glGetUniformLocation(program, "u_texel_size") if u_ts != -1: gl.glUniform2f(u_ts, texel_size[0], texel_size[1]) - gl.glBegin(gl.GL_TRIANGLE_STRIP) - gl.glVertex2f(-1.0, -1.0); gl.glTexCoord2f(0.0, 0.0) - gl.glVertex2f( 1.0, -1.0); gl.glTexCoord2f(1.0, 0.0) - gl.glVertex2f(-1.0, 1.0); gl.glTexCoord2f(0.0, 1.0) - gl.glVertex2f( 1.0, 1.0); gl.glTexCoord2f(1.0, 1.0) - gl.glEnd() + gl.glBindVertexArray(self._quad_vao) + gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4) + gl.glBindVertexArray(0) gl.glBindTexture(gl.GL_TEXTURE_2D, 0) gl.glUseProgram(0) @@ -445,6 +460,8 @@ void main() { if progs: for p in progs: gl.glDeleteProgram(p) + if self._quad_vao: + gl.glDeleteVertexArrays(1, [self._quad_vao]) self.scene_fbo = None self.scene_tex = None self.blur_fbo_a = None @@ -454,3 +471,4 @@ void main() { self.h_blur_program = None self.v_blur_program = None self.deepsea_program = None + self._quad_vao = None