feat(shaders): Implement CRT post-process shader logic
This commit is contained in:
@@ -4,6 +4,7 @@ class ShaderManager:
|
||||
def __init__(self):
|
||||
self.program = None
|
||||
self.bg_program = None
|
||||
self.pp_program = None
|
||||
|
||||
def compile_shader(self, vertex_src: str, fragment_src: str) -> int:
|
||||
program = gl.glCreateProgram()
|
||||
@@ -98,3 +99,55 @@ void main() {
|
||||
gl.glUniform2f(u_res_loc, float(width), float(height))
|
||||
gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)
|
||||
gl.glUseProgram(0)
|
||||
|
||||
def setup_post_process_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_time;
|
||||
out vec4 FragColor;
|
||||
void main() {
|
||||
vec4 color = texture(u_texture, v_uv);
|
||||
float scanline = sin(v_uv.y * 800.0 + u_time * 2.0) * 0.04;
|
||||
color.rgb -= scanline;
|
||||
FragColor = color;
|
||||
}
|
||||
"""
|
||||
self.pp_program = self.compile_shader(vertex_src, fragment_src)
|
||||
|
||||
def render_post_process(self, texture_id, width, height, time):
|
||||
if not self.pp_program:
|
||||
return
|
||||
gl.glUseProgram(self.pp_program)
|
||||
gl.glActiveTexture(gl.GL_TEXTURE0)
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D, texture_id)
|
||||
u_tex_loc = gl.glGetUniformLocation(self.pp_program, "u_texture")
|
||||
if u_tex_loc != -1:
|
||||
gl.glUniform1i(u_tex_loc, 0)
|
||||
u_time_loc = gl.glGetUniformLocation(self.pp_program, "u_time")
|
||||
if u_time_loc != -1:
|
||||
gl.glUniform1f(u_time_loc, float(time))
|
||||
gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D, 0)
|
||||
gl.glUseProgram(0)
|
||||
|
||||
53
tests/test_post_process.py
Normal file
53
tests/test_post_process.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
import sys
|
||||
|
||||
# Mock OpenGL.GL before importing ShaderManager
|
||||
gl_mock = MagicMock()
|
||||
# Setup some constants
|
||||
gl_mock.GL_VERTEX_SHADER = 0x8B31
|
||||
gl_mock.GL_FRAGMENT_SHADER = 0x8B30
|
||||
gl_mock.GL_COMPILE_STATUS = 0x8B81
|
||||
gl_mock.GL_LINK_STATUS = 0x8B82
|
||||
gl_mock.GL_TEXTURE0 = 0x84C0
|
||||
gl_mock.GL_TEXTURE_2D = 0x0DE1
|
||||
gl_mock.GL_TRIANGLE_STRIP = 0x0005
|
||||
|
||||
opengl_mock = MagicMock()
|
||||
sys.modules['OpenGL'] = opengl_mock
|
||||
sys.modules['OpenGL.GL'] = gl_mock
|
||||
opengl_mock.GL = gl_mock
|
||||
|
||||
from src.shader_manager import ShaderManager
|
||||
|
||||
class TestPostProcess(unittest.TestCase):
|
||||
def setUp(self):
|
||||
gl_mock.reset_mock()
|
||||
# Mock return values for shader compilation
|
||||
gl_mock.glCreateProgram.return_value = 1
|
||||
gl_mock.glCreateShader.return_value = 2
|
||||
gl_mock.glGetShaderiv.return_value = 1 # GL_TRUE
|
||||
gl_mock.glGetProgramiv.return_value = 1 # GL_TRUE
|
||||
gl_mock.glGetUniformLocation.return_value = 10
|
||||
|
||||
def test_setup_post_process_shader(self):
|
||||
sm = ShaderManager()
|
||||
sm.setup_post_process_shader()
|
||||
self.assertEqual(sm.pp_program, 1)
|
||||
gl_mock.glCreateProgram.assert_called()
|
||||
gl_mock.glLinkProgram.assert_called_with(1)
|
||||
|
||||
def test_render_post_process(self):
|
||||
sm = ShaderManager()
|
||||
sm.pp_program = 1
|
||||
sm.render_post_process(texture_id=5, width=800, height=600, time=1.0)
|
||||
|
||||
gl_mock.glUseProgram.assert_any_call(1)
|
||||
gl_mock.glActiveTexture.assert_called_with(gl_mock.GL_TEXTURE0)
|
||||
gl_mock.glBindTexture.assert_any_call(gl_mock.GL_TEXTURE_2D, 5)
|
||||
gl_mock.glUniform1f.assert_called()
|
||||
gl_mock.glDrawArrays.assert_called_with(gl_mock.GL_TRIANGLE_STRIP, 0, 4)
|
||||
gl_mock.glUseProgram.assert_any_call(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user