diff --git a/src/shader_manager.py b/src/shader_manager.py index 2f72c5b..c403aa5 100644 --- a/src/shader_manager.py +++ b/src/shader_manager.py @@ -1,9 +1,9 @@ -# src/shader_manager.py import OpenGL.GL as gl class ShaderManager: def __init__(self): self.program = None + self.bg_program = None def compile_shader(self, vertex_src: str, fragment_src: str) -> int: program = gl.glCreateProgram() @@ -33,7 +33,6 @@ class ShaderManager: info_log = info_log.decode() raise RuntimeError(f"Program linking failed: {info_log}") - # Optional: delete shaders as they are linked into the program gl.glDeleteShader(vert_shader) gl.glDeleteShader(frag_shader) @@ -60,3 +59,42 @@ class ShaderManager: gl.glUniform3f(loc, value[0], value[1], value[2]) elif len(value) == 4: 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) diff --git a/tests/test_dynamic_background.py b/tests/test_dynamic_background.py new file mode 100644 index 0000000..7814dba --- /dev/null +++ b/tests/test_dynamic_background.py @@ -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()