from OpenGL.GL import * ui_vertex_src = """ #version 330 core layout(location = 0) in vec2 aPos; layout(location = 1) in vec2 aUV; out vec2 vUV; void main() { gl_Position = vec4(aPos, 0.0, 1.0); vUV = aUV; } """ ui_fragment_src = """ #version 330 core in vec2 vUV; uniform sampler2D uTexture; uniform vec4 uColor; uniform int useTexture; out vec4 FragColor; void main() { if (useTexture == 1) FragColor = texture(uTexture, vUV) * uColor; else FragColor = uColor; } """ basic_vertex_src = """ #version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec3 aColor; layout(location = 2) in vec2 aUV; uniform mat4 uModel; uniform mat4 uView; uniform mat4 uProjection; uniform vec2 uUVTiling; uniform vec2 uUVOffset; out vec3 vColor; out vec2 vUV; void main() { gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0); vColor = aColor; vUV = aUV * uUVTiling + uUVOffset; } """ basic_fragment_src = """ #version 330 core in vec3 vColor; in vec2 vUV; uniform sampler2D uTexture; uniform int useTexture; out vec4 FragColor; void main() { if (useTexture == 1) FragColor = texture(uTexture, vUV); else FragColor = vec4(vColor, 1.0); } """ def compile_shader(src, shader_type): shader = glCreateShader(shader_type) glShaderSource(shader, src) glCompileShader(shader) if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE: error = glGetShaderInfoLog(shader).decode() raise RuntimeError(f"Shader compile error: {error}") return shader def create_shader(vertex_src, fragment_src): vert = compile_shader(vertex_src, GL_VERTEX_SHADER) frag = compile_shader(fragment_src, GL_FRAGMENT_SHADER) program = glCreateProgram() glAttachShader(program, vert) glAttachShader(program, frag) glLinkProgram(program) if glGetProgramiv(program, GL_LINK_STATUS) != GL_TRUE: error = glGetProgramInfoLog(program).decode() raise RuntimeError(f"Program link error: {error}") glDeleteShader(vert) glDeleteShader(frag) return program class ShaderProgram: def __init__(self, vertex_src, fragment_src): self.program = create_shader(vertex_src, fragment_src) self.uniform_locations = {} def use(self): glUseProgram(self.program) def get_uniform_location(self, name): if name not in self.uniform_locations: self.uniform_locations[name] = glGetUniformLocation(self.program, name) return self.uniform_locations[name] def set_uniform_1i(self, name, value): glUniform1i(self.get_uniform_location(name), value) def set_uniform_1f(self, name, value): glUniform1f(self.get_uniform_location(name), value) def set_uniform_vec2(self, name, vec): glUniform2fv(self.get_uniform_location(name), 1, vec) def set_uniform_vec3(self, name, vec): glUniform3fv(self.get_uniform_location(name), 1, vec) def set_uniform_mat4(self, name, mat, transpose=False): glUniformMatrix4fv(self.get_uniform_location(name), 1, transpose, mat) def create_ui_shader(): return ShaderProgram(ui_vertex_src, ui_fragment_src) def basic_shader(): return ShaderProgram(basic_vertex_src, basic_fragment_src)