diff --git a/data/shaders/crtpi_fragment.glsl b/data/shaders/crtpi_fragment.glsl index c17d77d9..a1919d37 100644 --- a/data/shaders/crtpi_fragment.glsl +++ b/data/shaders/crtpi_fragment.glsl @@ -31,9 +31,10 @@ out vec4 FragColor; // Uniforms uniform sampler2D Texture; uniform vec2 TextureSize; -uniform float uVignette; // 0 = sin viñeta, 1 = máxima -uniform float uScanlines; // 0 = desactivadas, 1 = plenas -uniform float uChroma; // 0 = sin aberración, 1 = máxima +uniform float uVignette; // 0 = sin viñeta, 1 = máxima +uniform float uScanlines; // 0 = desactivadas, 1 = plenas +uniform float uChroma; // 0 = sin aberración, 1 = máxima +uniform float uOutputHeight; // altura del viewport en pixels de pantalla #if defined(CURVATURE) vec2 Distort(vec2 coord) @@ -103,8 +104,20 @@ void main() #else float tempY = floor(texcoordInPixels.y) + 0.5; float yCoord = tempY / TextureSize.y; + + // Scanline en espacio de pantalla (subpíxel) + float scaleY = uOutputHeight / TextureSize.y; + float screenY = vTexCoord.y * uOutputHeight; + float posInRow = mod(screenY, scaleY); + float scanLineDY = posInRow / scaleY - 0.5; + float localFilterWidth = 1.0 / scaleY; + float scanLineWeight = CalcScanLineWeight(scanLineDY); + scanLineWeight += CalcScanLineWeight(scanLineDY - localFilterWidth); + scanLineWeight += CalcScanLineWeight(scanLineDY + localFilterWidth); + scanLineWeight *= 0.3333333; + + // Phosphor blur en espacio textura (sin cambios) float dy = texcoordInPixels.y - tempY; - float scanLineWeight = CalcScanLine(dy); float signY = sign(dy); dy = dy * dy; dy = dy * dy; diff --git a/data/shaders/crtpi_fragment_es.glsl b/data/shaders/crtpi_fragment_es.glsl index c10a2d06..1eb8f55e 100644 --- a/data/shaders/crtpi_fragment_es.glsl +++ b/data/shaders/crtpi_fragment_es.glsl @@ -34,9 +34,10 @@ out vec4 FragColor; // Uniforms uniform sampler2D Texture; uniform vec2 TextureSize; -uniform float uVignette; // 0 = sin viñeta, 1 = máxima -uniform float uScanlines; // 0 = desactivadas, 1 = plenas -uniform float uChroma; // 0 = sin aberración, 1 = máxima +uniform float uVignette; // 0 = sin viñeta, 1 = máxima +uniform float uScanlines; // 0 = desactivadas, 1 = plenas +uniform float uChroma; // 0 = sin aberración, 1 = máxima +uniform float uOutputHeight; // altura del viewport en pixels de pantalla #if defined(CURVATURE) vec2 Distort(vec2 coord) @@ -106,8 +107,20 @@ void main() #else float tempY = floor(texcoordInPixels.y) + 0.5; float yCoord = tempY / TextureSize.y; + + // Scanline en espacio de pantalla (subpíxel) + float scaleY = uOutputHeight / TextureSize.y; + float screenY = vTexCoord.y * uOutputHeight; + float posInRow = mod(screenY, scaleY); + float scanLineDY = posInRow / scaleY - 0.5; + float localFilterWidth = 1.0 / scaleY; + float scanLineWeight = CalcScanLineWeight(scanLineDY); + scanLineWeight += CalcScanLineWeight(scanLineDY - localFilterWidth); + scanLineWeight += CalcScanLineWeight(scanLineDY + localFilterWidth); + scanLineWeight *= 0.3333333; + + // Phosphor blur en espacio textura (sin cambios) float dy = texcoordInPixels.y - tempY; - float scanLineWeight = CalcScanLine(dy); float signY = sign(dy); dy = dy * dy; dy = dy * dy; diff --git a/source/core/rendering/opengl/opengl_shader.cpp b/source/core/rendering/opengl/opengl_shader.cpp index 090f79cc..a7ec9ec8 100644 --- a/source/core/rendering/opengl/opengl_shader.cpp +++ b/source/core/rendering/opengl/opengl_shader.cpp @@ -338,9 +338,10 @@ auto OpenGLShader::init(SDL_Window* window, } // Uniforms PostFX - vignette_location_ = glGetUniformLocation(program_id_, "uVignette"); - scanlines_location_ = glGetUniformLocation(program_id_, "uScanlines"); - chroma_location_ = glGetUniformLocation(program_id_, "uChroma"); + vignette_location_ = glGetUniformLocation(program_id_, "uVignette"); + scanlines_location_ = glGetUniformLocation(program_id_, "uScanlines"); + chroma_location_ = glGetUniformLocation(program_id_, "uChroma"); + output_height_location_ = glGetUniformLocation(program_id_, "uOutputHeight"); if (vignette_location_ != -1) { glUniform1f(vignette_location_, postfx_vignette_); } if (scanlines_location_ != -1) { glUniform1f(scanlines_location_, postfx_scanlines_); } if (chroma_location_ != -1) { glUniform1f(chroma_location_, postfx_chroma_); } @@ -446,6 +447,10 @@ void OpenGLShader::render() { glViewport(viewport_x, viewport_y, viewport_w, viewport_h); checkGLError("glViewport"); + if (output_height_location_ != -1) { + glUniform1f(output_height_location_, static_cast(viewport_h)); + } + // Dibujar quad usando VAO glBindVertexArray(vao_); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); diff --git a/source/core/rendering/opengl/opengl_shader.hpp b/source/core/rendering/opengl/opengl_shader.hpp index 2e20b4cb..1d14d325 100644 --- a/source/core/rendering/opengl/opengl_shader.hpp +++ b/source/core/rendering/opengl/opengl_shader.hpp @@ -59,6 +59,7 @@ class OpenGLShader : public ShaderBackend { GLint vignette_location_ = -1; GLint scanlines_location_ = -1; GLint chroma_location_ = -1; + GLint output_height_location_ = -1; // Valores cacheados de PostFX float postfx_vignette_ = 0.6F; diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index 0298f07e..0973683c 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -61,7 +61,12 @@ fragment float4 postfx_fs(PostVOut in [[stage_in]], color.b = scene.sample(samp, in.uv - float2( ca, 0.0)).b; color.a = scene.sample(samp, in.uv).a; - float scan = 0.85 + 0.15 * sin(in.uv.y * 3.14159265 * u.screen_height); + float texHeight = float(scene.get_height()); + float scaleY = u.screen_height / texHeight; + float screenY = in.uv.y * u.screen_height; + float posInRow = fmod(screenY, scaleY); + float scanLineDY = posInRow / scaleY - 0.5; + float scan = max(1.0 - scanLineDY * scanLineDY * 6.0, 0.12) * 3.5; color.rgb *= mix(1.0, scan, u.scanline_strength); float2 d = in.uv - float2(0.5, 0.5); @@ -312,6 +317,8 @@ void SDL3GPUShader::render() { return; } + uniforms_.screen_height = static_cast(sh); + // ---- Render pass: PostFX → swapchain ---- SDL_GPUColorTargetInfo color_target = {}; color_target.texture = swapchain;