diff --git a/src/shader_manager.py b/src/shader_manager.py index da535d9..512d474 100644 --- a/src/shader_manager.py +++ b/src/shader_manager.py @@ -5,6 +5,7 @@ class ShaderManager: self.program = None self.bg_program = None self.pp_program = None + self.blur_program = None def compile_shader(self, vertex_src: str, fragment_src: str) -> int: program = gl.glCreateProgram() @@ -151,3 +152,51 @@ void main() { gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4) gl.glBindTexture(gl.GL_TEXTURE_2D, 0) gl.glUseProgram(0) + + def setup_frosted_glass_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) +); +const vec2 uvs[4] = vec2[]( + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(1.0, 1.0) +); +out vec2 v_uv; +void main() { + gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0); + v_uv = uvs[gl_VertexID]; +} +""" + fragment_src = """ +#version 330 core +in vec2 v_uv; +uniform sampler2D u_texture; +uniform float u_blur_radius; +uniform float u_tint_intensity; +uniform float u_opacity; +out vec4 FragColor; +void main() { + vec2 res = vec2(textureSize(u_texture, 0)); + vec2 offset = u_blur_radius / res; + vec4 sum = vec4(0.0); + sum += texture(u_texture, v_uv + vec2(-offset.x, -offset.y)) * 0.0625; + sum += texture(u_texture, v_uv + vec2(0.0, -offset.y)) * 0.125; + sum += texture(u_texture, v_uv + vec2(offset.x, -offset.y)) * 0.0625; + sum += texture(u_texture, v_uv + vec2(-offset.x, 0.0)) * 0.125; + sum += texture(u_texture, v_uv + vec2(0.0, 0.0)) * 0.25; + sum += texture(u_texture, v_uv + vec2(offset.x, 0.0)) * 0.125; + sum += texture(u_texture, v_uv + vec2(-offset.x, offset.y)) * 0.0625; + sum += texture(u_texture, v_uv + vec2(0.0, offset.y)) * 0.125; + sum += texture(u_texture, v_uv + vec2(offset.x, offset.y)) * 0.0625; + vec3 tinted = mix(sum.rgb, vec3(1.0), u_tint_intensity); + FragColor = vec4(tinted, sum.a * u_opacity); +} +""" + self.blur_program = self.compile_shader(vertex_src, fragment_src) diff --git a/tests/test_frosted_glass_shader.py b/tests/test_frosted_glass_shader.py new file mode 100644 index 0000000..4cab44a --- /dev/null +++ b/tests/test_frosted_glass_shader.py @@ -0,0 +1,19 @@ +import pytest +from unittest.mock import patch, MagicMock + +def test_shader_manager_frosted_glass_compilation(): + # Mock OpenGL before importing 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() + + # This should fail initially because the method doesn't exist + manager.setup_frosted_glass_shader() + + assert manager.blur_program is not None + assert mock_gl.glCreateProgram.called