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
This commit is contained in:
2026-03-13 21:35:23 -04:00
parent 1d36357c64
commit aed461ef28
2 changed files with 42 additions and 28 deletions

View File

@@ -4055,10 +4055,6 @@ def hello():
return True return True
def _pre_new_frame(self) -> None: 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: if not self.ui_frosted_glass_enabled:
return return
ws = imgui.get_io().display_size ws = imgui.get_io().display_size

View File

@@ -162,6 +162,7 @@ class BlurPipeline:
self.h_blur_program: int | None = None self.h_blur_program: int | None = None
self.v_blur_program: int | None = None self.v_blur_program: int | None = None
self.deepsea_program: int | None = None self.deepsea_program: int | None = None
self._quad_vao: int | None = None
self._fb_width: int = 0 self._fb_width: int = 0
self._fb_height: int = 0 self._fb_height: int = 0
self._fb_scale: int = 1 self._fb_scale: int = 1
@@ -209,6 +210,26 @@ class BlurPipeline:
gl.glBindTexture(gl.GL_TEXTURE_2D, 0) gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
return fbo, tex 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): def setup_fbos(self, width: int, height: int, fb_scale: float = 1.0):
scale = max(1, int(fb_scale)) scale = max(1, int(fb_scale))
blur_w = max(1, (width * scale) // 4) blur_w = max(1, (width * scale) // 4)
@@ -225,8 +246,8 @@ class BlurPipeline:
def compile_blur_shaders(self): def compile_blur_shaders(self):
vert_src = """ vert_src = """
#version 330 core #version 330 core
in vec2 a_position; layout(location = 0) in vec2 a_position;
in vec2 a_texcoord; layout(location = 1) in vec2 a_texcoord;
out vec2 v_uv; out vec2 v_uv;
void main() { void main() {
gl_Position = vec4(a_position, 0.0, 1.0); gl_Position = vec4(a_position, 0.0, 1.0);
@@ -289,8 +310,8 @@ void main() {
def compile_deepsea_shader(self): def compile_deepsea_shader(self):
vert_src = """ vert_src = """
#version 330 core #version 330 core
in vec2 a_position; layout(location = 0) in vec2 a_position;
in vec2 a_texcoord; layout(location = 1) in vec2 a_texcoord;
out vec2 v_uv; out vec2 v_uv;
void main() { void main() {
gl_Position = vec4(a_position, 0.0, 1.0); 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.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): 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 return
scene_w = width * self._fb_scale scene_w = width * self._fb_scale
scene_h = height * 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.glClearColor(0.01, 0.05, 0.12, 1.0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT) gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glUseProgram(self.deepsea_program) gl.glUseProgram(self.deepsea_program)
u_time = gl.glGetUniformLocation(self.deepsea_program, "u_time") u_time_loc = gl.glGetUniformLocation(self.deepsea_program, "u_time")
if u_time != -1: if u_time_loc != -1:
gl.glUniform1f(u_time, time) gl.glUniform1f(u_time_loc, time)
u_res = gl.glGetUniformLocation(self.deepsea_program, "u_resolution") u_res_loc = gl.glGetUniformLocation(self.deepsea_program, "u_resolution")
if u_res != -1: if u_res_loc != -1:
gl.glUniform2f(u_res, float(scene_w), float(scene_h)) gl.glUniform2f(u_res_loc, float(scene_w), float(scene_h))
# Draw fullscreen quad using deprecated but working glBegin/glEnd gl.glBindVertexArray(self._quad_vao)
gl.glBegin(gl.GL_TRIANGLE_STRIP) gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)
gl.glVertex2f(-1.0, -1.0); gl.glTexCoord2f(0.0, 0.0) gl.glBindVertexArray(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.glUseProgram(0) gl.glUseProgram(0)
gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
@@ -393,12 +411,9 @@ void main() {
u_ts = gl.glGetUniformLocation(program, "u_texel_size") u_ts = gl.glGetUniformLocation(program, "u_texel_size")
if u_ts != -1: if u_ts != -1:
gl.glUniform2f(u_ts, texel_size[0], texel_size[1]) gl.glUniform2f(u_ts, texel_size[0], texel_size[1])
gl.glBegin(gl.GL_TRIANGLE_STRIP) gl.glBindVertexArray(self._quad_vao)
gl.glVertex2f(-1.0, -1.0); gl.glTexCoord2f(0.0, 0.0) gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)
gl.glVertex2f( 1.0, -1.0); gl.glTexCoord2f(1.0, 0.0) gl.glBindVertexArray(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.glBindTexture(gl.GL_TEXTURE_2D, 0) gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
gl.glUseProgram(0) gl.glUseProgram(0)
@@ -445,6 +460,8 @@ void main() {
if progs: if progs:
for p in progs: for p in progs:
gl.glDeleteProgram(p) gl.glDeleteProgram(p)
if self._quad_vao:
gl.glDeleteVertexArrays(1, [self._quad_vao])
self.scene_fbo = None self.scene_fbo = None
self.scene_tex = None self.scene_tex = None
self.blur_fbo_a = None self.blur_fbo_a = None
@@ -454,3 +471,4 @@ void main() {
self.h_blur_program = None self.h_blur_program = None
self.v_blur_program = None self.v_blur_program = None
self.deepsea_program = None self.deepsea_program = None
self._quad_vao = None