Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,12 @@ target_sources(SuperMetroidSNESRecomp PRIVATE
target_include_directories(SuperMetroidSNESRecomp PRIVATE
${SNESRECOMP_ROOT}/host
${RECOMP_UI_ROOT}/src)

# GLSL shader presets (CRT/scanlines) for the OpenGL desktop backend. The
# launcher's shader dropdown scans assets/shaders beside the executable for
# *.glsl/*.glslp; src/main.c opts this game into that row.
if(NOT ANDROID)
snesrecomp_target_stage_dir(SuperMetroidSNESRecomp
${CMAKE_CURRENT_SOURCE_DIR}/assets/shaders
assets/shaders)
endif()
57 changes: 57 additions & 0 deletions assets/shaders/.src/crt.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Lightweight CRT look: scanlines + a coarse RGB aperture-grille mask +
// a soft vignette. Deliberately no curvature/distortion -- keeps every
// output pixel address identical to the input, so it stays cheap and safe
// (no sampling outside [0,1], no divide-by-zero). Single pass; see
// scanlines.glsl for the preset-format notes.

#if defined(VERTEX)

in vec2 VertexCoord;
in vec2 TexCoord;
out vec2 vTexCoord;
uniform mat4 MVPMatrix;

void main() {
gl_Position = MVPMatrix * vec4(VertexCoord, 0.0, 1.0);
vTexCoord = TexCoord;
}

#elif defined(FRAGMENT)

#pragma parameter CRT_SCANLINE_STRENGTH "CRT Scanline Strength" 0.78 0.0 1.0 0.02
#pragma parameter CRT_MASK_STRENGTH "CRT Mask Strength" 0.25 0.0 1.0 0.05
#pragma parameter CRT_VIGNETTE_STRENGTH "CRT Vignette Strength" 0.35 0.0 1.0 0.05

in vec2 vTexCoord;
out vec4 FragColor;

uniform sampler2D Texture;
uniform float CRT_SCANLINE_STRENGTH;
uniform float CRT_MASK_STRENGTH;
uniform float CRT_VIGNETTE_STRENGTH;

void main() {
vec4 color = texture(Texture, vTexCoord);

// One dark output row in every two.
float row = floor(gl_FragCoord.y);
float scan = mix(1.0, CRT_SCANLINE_STRENGTH, mod(row, 2.0));

// Coarse RGB aperture-grille mask across output columns.
float col = mod(floor(gl_FragCoord.x), 3.0);
vec3 mask;
if (col < 1.0)
mask = vec3(1.0, 1.0 - CRT_MASK_STRENGTH, 1.0 - CRT_MASK_STRENGTH);
else if (col < 2.0)
mask = vec3(1.0 - CRT_MASK_STRENGTH, 1.0, 1.0 - CRT_MASK_STRENGTH);
else
mask = vec3(1.0 - CRT_MASK_STRENGTH, 1.0 - CRT_MASK_STRENGTH, 1.0);

// Soft vignette toward the edges.
vec2 uv = vTexCoord * 2.0 - 1.0;
float vig = 1.0 - CRT_VIGNETTE_STRENGTH * dot(uv, uv) * 0.5;

FragColor = vec4(color.rgb * scan * mask * vig, color.a);
}

#endif
38 changes: 38 additions & 0 deletions assets/shaders/.src/scanlines.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Simple horizontal-scanline preset. Single pass; see glsl_shader.c for the
// preset/parameter parser this file is compiled against (GLSL 330 core --
// the profile src/opengl.c already requires via
// SDL_GL_CONTEXT_PROFILE_CORE). No #version line: the loader prepends
// "#version 330\n" (core, since no profile qualifier defaults to core).

#if defined(VERTEX)

in vec2 VertexCoord;
in vec2 TexCoord;
out vec2 vTexCoord;
uniform mat4 MVPMatrix;

void main() {
gl_Position = MVPMatrix * vec4(VertexCoord, 0.0, 1.0);
vTexCoord = TexCoord;
}

#elif defined(FRAGMENT)

#pragma parameter SCANLINE_STRENGTH "Scanline Strength" 0.72 0.0 1.0 0.02
#pragma parameter SCANLINE_WIDTH "Scanline Width (px)" 2.0 1.0 4.0 1.0

in vec2 vTexCoord;
out vec4 FragColor;

uniform sampler2D Texture;
uniform float SCANLINE_STRENGTH;
uniform float SCANLINE_WIDTH;

void main() {
vec4 color = texture(Texture, vTexCoord);
float row = floor(gl_FragCoord.y / SCANLINE_WIDTH);
float dark = mix(1.0, SCANLINE_STRENGTH, mod(row, 2.0));
FragColor = vec4(color.rgb * dark, color.a);
}

#endif
7 changes: 7 additions & 0 deletions assets/shaders/crt-light.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
shaders = "1"
shader0 = ".src/crt.glsl"
filter_linear0 = "false"
parameters = "CRT_SCANLINE_STRENGTH;CRT_MASK_STRENGTH;CRT_VIGNETTE_STRENGTH"
CRT_SCANLINE_STRENGTH = "0.88"
CRT_MASK_STRENGTH = "0.12"
CRT_VIGNETTE_STRENGTH = "0.18"
7 changes: 7 additions & 0 deletions assets/shaders/crt-strong.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
shaders = "1"
shader0 = ".src/crt.glsl"
filter_linear0 = "false"
parameters = "CRT_SCANLINE_STRENGTH;CRT_MASK_STRENGTH;CRT_VIGNETTE_STRENGTH"
CRT_SCANLINE_STRENGTH = "0.60"
CRT_MASK_STRENGTH = "0.40"
CRT_VIGNETTE_STRENGTH = "0.55"
3 changes: 3 additions & 0 deletions assets/shaders/crt.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
shaders = "1"
shader0 = ".src/crt.glsl"
filter_linear0 = "false"
6 changes: 6 additions & 0 deletions assets/shaders/scanlines-light.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
shaders = "1"
shader0 = ".src/scanlines.glsl"
filter_linear0 = "false"
parameters = "SCANLINE_STRENGTH;SCANLINE_WIDTH"
SCANLINE_STRENGTH = "0.85"
SCANLINE_WIDTH = "2.0"
6 changes: 6 additions & 0 deletions assets/shaders/scanlines-strong.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
shaders = "1"
shader0 = ".src/scanlines.glsl"
filter_linear0 = "false"
parameters = "SCANLINE_STRENGTH;SCANLINE_WIDTH"
SCANLINE_STRENGTH = "0.55"
SCANLINE_WIDTH = "2.0"
3 changes: 3 additions & 0 deletions assets/shaders/scanlines.glslp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
shaders = "1"
shader0 = ".src/scanlines.glsl"
filter_linear0 = "false"
6 changes: 5 additions & 1 deletion config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ VSync = 1
# presets), software, or an SDL render driver such as vulkan. Empty follows
# OutputMethod.
Renderer = auto
# OpenGL GLSL preset path, edited by the launcher's shader dropdown.
Shader =
WindowSize = Auto
Fullscreen = 0
WindowScale = 3
Expand Down Expand Up @@ -62,7 +64,9 @@ Save = Shift+F1,Shift+F2,Shift+F3,Shift+F4,Shift+F5,Shift+F6,Shift+F7,Shift+F8,S
# In-game overlays (framework modules). The save-state browser also opens
# with Select+R on the pad; rewind with [Controller] RewindGesture below.
SaveStateMenu = F11
Rewind = F12
Rewind = Shift+F12
# OpenGL framebuffer capture, saved under screenshots/.
Screenshot = F12

[GamepadMap]
EnableGamepad1 = true
Expand Down
2 changes: 1 addition & 1 deletion snesrecomp
1 change: 1 addition & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ static const SnesDesktopHostGame kSuperMetroidHost = {
.debug_port = 4380,
.widescreen_supported = 0, /* widescreen is this title's Mods page */
.msu1_supported = 0,
.shader_supported = 1,
.simulation_hz = SM_SIMULATION_HZ,
.frame_width = 256,
.frame_height = SM_HEIGHT,
Expand Down