feat(shaders): Implement dynamic background shader
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
# src/shader_manager.py
|
|
||||||
import OpenGL.GL as gl
|
import OpenGL.GL as gl
|
||||||
|
|
||||||
class ShaderManager:
|
class ShaderManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.program = None
|
self.program = None
|
||||||
|
self.bg_program = None
|
||||||
|
|
||||||
def compile_shader(self, vertex_src: str, fragment_src: str) -> int:
|
def compile_shader(self, vertex_src: str, fragment_src: str) -> int:
|
||||||
program = gl.glCreateProgram()
|
program = gl.glCreateProgram()
|
||||||
@@ -33,7 +33,6 @@ class ShaderManager:
|
|||||||
info_log = info_log.decode()
|
info_log = info_log.decode()
|
||||||
raise RuntimeError(f"Program linking failed: {info_log}")
|
raise RuntimeError(f"Program linking failed: {info_log}")
|
||||||
|
|
||||||
# Optional: delete shaders as they are linked into the program
|
|
||||||
gl.glDeleteShader(vert_shader)
|
gl.glDeleteShader(vert_shader)
|
||||||
gl.glDeleteShader(frag_shader)
|
gl.glDeleteShader(frag_shader)
|
||||||
|
|
||||||
@@ -60,3 +59,42 @@ class ShaderManager:
|
|||||||
gl.glUniform3f(loc, value[0], value[1], value[2])
|
gl.glUniform3f(loc, value[0], value[1], value[2])
|
||||||
elif len(value) == 4:
|
elif len(value) == 4:
|
||||||
gl.glUniform4f(loc, value[0], value[1], value[2], value[3])
|
gl.glUniform4f(loc, value[0], value[1], value[2], value[3])
|
||||||
|
|
||||||
|
def setup_background_shader(self):
|
||||||
|
vertex_src = """
|
||||||
|
#version 330 core
|
||||||
|
const vec2 positions[4] = vec2[](
|
||||||
|
vec2(-1.0, -1.0),
|
||||||
|
vec2( 1.0, -1.0),
|
||||||
|
vec2(-1.0, 1.0),
|
||||||
|
vec2( 1.0, 1.0)
|
||||||
|
);
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
fragment_src = """
|
||||||
|
#version 330 core
|
||||||
|
uniform float u_time;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
out vec4 FragColor;
|
||||||
|
void main() {
|
||||||
|
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
||||||
|
vec3 col = 0.5 + 0.5 * cos(u_time + uv.xyx + vec3(0, 2, 4));
|
||||||
|
FragColor = vec4(col, 1.0);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.bg_program = self.compile_shader(vertex_src, fragment_src)
|
||||||
|
|
||||||
|
def render_background(self, width, height, time):
|
||||||
|
if not self.bg_program:
|
||||||
|
return
|
||||||
|
gl.glUseProgram(self.bg_program)
|
||||||
|
u_time_loc = gl.glGetUniformLocation(self.bg_program, "u_time")
|
||||||
|
if u_time_loc != -1:
|
||||||
|
gl.glUniform1f(u_time_loc, float(time))
|
||||||
|
u_res_loc = gl.glGetUniformLocation(self.bg_program, "u_resolution")
|
||||||
|
if u_res_loc != -1:
|
||||||
|
gl.glUniform2f(u_res_loc, float(width), float(height))
|
||||||
|
gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)
|
||||||
|
gl.glUseProgram(0)
|
||||||
|
|||||||
33
tests/test_dynamic_background.py
Normal file
33
tests/test_dynamic_background.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import pytest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
def test_dynamic_background_rendering():
|
||||||
|
# Mock OpenGL before importing
|
||||||
|
with patch("src.shader_manager.gl") as mock_gl:
|
||||||
|
from src.shader_manager import ShaderManager
|
||||||
|
|
||||||
|
# Setup mock return values
|
||||||
|
mock_gl.glCreateProgram.return_value = 1
|
||||||
|
mock_gl.glCreateShader.return_value = 2
|
||||||
|
mock_gl.glGetShaderiv.return_value = 1 # GL_TRUE
|
||||||
|
mock_gl.glGetProgramiv.return_value = 1 # GL_TRUE
|
||||||
|
mock_gl.glGetUniformLocation.return_value = 10
|
||||||
|
|
||||||
|
manager = ShaderManager()
|
||||||
|
manager.setup_background_shader()
|
||||||
|
|
||||||
|
# Verify background program was created
|
||||||
|
assert manager.bg_program == 1
|
||||||
|
assert mock_gl.glCreateProgram.called
|
||||||
|
|
||||||
|
# Render background
|
||||||
|
manager.render_background(800, 600, 1.0)
|
||||||
|
|
||||||
|
# Verify OpenGL calls
|
||||||
|
mock_gl.glUseProgram.assert_any_call(1)
|
||||||
|
mock_gl.glDrawArrays.assert_called_with(mock_gl.GL_TRIANGLE_STRIP, 0, 4)
|
||||||
|
mock_gl.glUseProgram.assert_any_call(0)
|
||||||
|
|
||||||
|
# Verify uniforms were updated
|
||||||
|
mock_gl.glUniform1f.assert_called()
|
||||||
|
mock_gl.glUniform2f.assert_called()
|
||||||
Reference in New Issue
Block a user