- Add compile_deepsea_shader() with animated underwater-like GLSL shader - Add render_deepsea_to_fbo() to render background to scene FBO - Deep Sea shader features: FBM noise, animated blobs, caustic lines, vignette - Add deepsea_program to cleanup() for proper resource management - Add 2 new tests for Deep Sea shader compilation and FBO rendering Task: Phase 1, Task 2 of frosted_glass_20260313 track
160 lines
5.6 KiB
Python
160 lines
5.6 KiB
Python
import pytest
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
def test_blur_pipeline_import():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
assert pipeline is not None
|
|
assert pipeline.scene_fbo is None
|
|
assert pipeline.blur_fbo_a is None
|
|
assert pipeline.blur_fbo_b is None
|
|
assert pipeline.scene_tex is None
|
|
assert pipeline.blur_tex_a is None
|
|
assert pipeline.blur_tex_b is None
|
|
assert pipeline.h_blur_program is None
|
|
assert pipeline.v_blur_program is None
|
|
|
|
def test_blur_pipeline_setup_fbos():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
tex_counter = iter([10, 20, 30])
|
|
fbo_counter = iter([1, 2, 3])
|
|
mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter)
|
|
mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter)
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.setup_fbos(800, 600)
|
|
assert mock_gl.glGenFramebuffers.called
|
|
assert mock_gl.glGenTextures.called
|
|
assert pipeline.scene_fbo is not None
|
|
assert pipeline.blur_fbo_a is not None
|
|
assert pipeline.blur_fbo_b is not None
|
|
|
|
def test_blur_pipeline_compile_shaders():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
mock_gl.glCreateProgram.return_value = 100
|
|
mock_gl.glCreateShader.return_value = 200
|
|
mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE
|
|
mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.compile_blur_shaders()
|
|
assert mock_gl.glCreateProgram.called
|
|
assert pipeline.h_blur_program is not None
|
|
assert pipeline.v_blur_program is not None
|
|
|
|
def test_blur_pipeline_render_deepsea_to_fbo():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
tex_counter = iter([10, 20, 30])
|
|
fbo_counter = iter([1, 2, 3])
|
|
mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter)
|
|
mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter)
|
|
mock_gl.glCreateProgram.return_value = 300
|
|
mock_gl.glCreateShader.return_value = 400
|
|
mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE
|
|
mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.setup_fbos(800, 600)
|
|
pipeline.compile_deepsea_shader()
|
|
pipeline.render_deepsea_to_fbo(800, 600, 0.0)
|
|
assert mock_gl.glBindFramebuffer.called
|
|
assert mock_gl.glUseProgram.called
|
|
assert mock_gl.glDrawArrays.called
|
|
|
|
def test_blur_pipeline_deepsea_shader_compilation():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
mock_gl.glCreateProgram.return_value = 500
|
|
mock_gl.glCreateShader.return_value = 600
|
|
mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE
|
|
mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.compile_deepsea_shader()
|
|
assert mock_gl.glCreateProgram.called
|
|
assert pipeline.deepsea_program is not None
|
|
|
|
def test_blur_pipeline_prepare_blur():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
mock_gl.glGenFramebuffers.return_value = None
|
|
mock_gl.glGenTextures.return_value = None
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.scene_fbo = 1
|
|
pipeline.scene_tex = 10
|
|
pipeline.blur_fbo_a = 2
|
|
pipeline.blur_tex_a = 20
|
|
pipeline.blur_fbo_b = 3
|
|
pipeline.blur_tex_b = 30
|
|
pipeline.h_blur_program = 100
|
|
pipeline.v_blur_program = 101
|
|
pipeline.prepare_blur(800, 600, 0.0)
|
|
assert mock_gl.glBindFramebuffer.called
|
|
assert mock_gl.glUseProgram.called
|
|
|
|
def test_blur_pipeline_cleanup():
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
from src.shader_manager import BlurPipeline
|
|
pipeline = BlurPipeline()
|
|
pipeline.scene_fbo = 1
|
|
pipeline.blur_fbo_a = 2
|
|
pipeline.blur_fbo_b = 3
|
|
pipeline.scene_tex = 10
|
|
pipeline.blur_tex_a = 20
|
|
pipeline.blur_tex_b = 30
|
|
pipeline.h_blur_program = 100
|
|
pipeline.v_blur_program = 101
|
|
pipeline.cleanup()
|
|
assert mock_gl.glDeleteFramebuffers.called
|
|
assert mock_gl.glDeleteTextures.called
|
|
assert mock_gl.glDeleteProgram.called
|
|
|
|
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
|
|
|
|
def test_shader_manager_uniform_update():
|
|
# Mock OpenGL.GL functions
|
|
with patch("src.shader_manager.gl") as mock_gl:
|
|
from src.shader_manager import ShaderManager
|
|
manager = ShaderManager()
|
|
# Set a mock program ID
|
|
manager.program = 1
|
|
|
|
# Mock glGetUniformLocation to return some valid locations
|
|
# u_time -> 10, u_resolution -> 20
|
|
def mock_get_loc(prog, name):
|
|
if name == "u_time": return 10
|
|
if name == "u_resolution": return 20
|
|
return -1
|
|
|
|
mock_gl.glGetUniformLocation.side_effect = mock_get_loc
|
|
|
|
# Call the method
|
|
manager.update_uniforms({"u_time": 1.5, "u_resolution": (800, 600)})
|
|
|
|
# Assert calls
|
|
mock_gl.glGetUniformLocation.assert_any_call(1, "u_time")
|
|
mock_gl.glGetUniformLocation.assert_any_call(1, "u_resolution")
|
|
mock_gl.glUniform1f.assert_called_once_with(10, 1.5)
|
|
mock_gl.glUniform2f.assert_called_once_with(20, 800, 600)
|