diff --git a/src/shader_manager.py b/src/shader_manager.py new file mode 100644 index 0000000..19ecf57 --- /dev/null +++ b/src/shader_manager.py @@ -0,0 +1,40 @@ +# src/shader_manager.py +import OpenGL.GL as gl + +class ShaderManager: + def __init__(self): + pass + + def compile_shader(self, vertex_src: str, fragment_src: str) -> int: + program = gl.glCreateProgram() + + def _compile(src, shader_type): + shader = gl.glCreateShader(shader_type) + gl.glShaderSource(shader, src) + gl.glCompileShader(shader) + + if not gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS): + info_log = gl.glGetShaderInfoLog(shader) + if hasattr(info_log, "decode"): + info_log = info_log.decode() + raise RuntimeError(f"Shader compilation failed: {info_log}") + return shader + + vert_shader = _compile(vertex_src, gl.GL_VERTEX_SHADER) + frag_shader = _compile(fragment_src, gl.GL_FRAGMENT_SHADER) + + gl.glAttachShader(program, vert_shader) + gl.glAttachShader(program, frag_shader) + gl.glLinkProgram(program) + + if not gl.glGetProgramiv(program, gl.GL_LINK_STATUS): + info_log = gl.glGetProgramInfoLog(program) + if hasattr(info_log, "decode"): + 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) + + return program diff --git a/tests/test_shader_manager.py b/tests/test_shader_manager.py new file mode 100644 index 0000000..f4e9cc6 --- /dev/null +++ b/tests/test_shader_manager.py @@ -0,0 +1,25 @@ +import pytest +from unittest.mock import patch, MagicMock + +def test_shader_manager_initialization_and_compilation(): + # Import inside test to allow patching OpenGL before import if needed + # In this case, we patch the OpenGL.GL functions used by ShaderManager + with patch("src.shader_manager.gl") as mock_gl: + mock_gl.glCreateProgram.return_value = 1 + mock_gl.glCreateShader.return_value = 2 + mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE + mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE + + from src.shader_manager import ShaderManager + + manager = ShaderManager() + + # Basic vertex and fragment shader source + vert_src = "void main() {}" + frag_src = "void main() {}" + + program_id = manager.compile_shader(vert_src, frag_src) + + assert program_id == 1 + assert mock_gl.glCreateProgram.called + assert mock_gl.glCreateShader.called