diff --git a/CHANGES b/CHANGES index 3aef9e246..ef075bd9c 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,7 @@ Misc: - Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632) - Qt: Pass logging context through to video proxy thread (fixes mgba.io/i/3095) - Qt: Show maker code and game version in ROM info + - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) - Scripting: Add `callbacks:oneshot` for single-call callbacks - Switch: Add bilinear filtering option (closes mgba.io/i/3111) - Vita: Add imc0 and xmc0 mount point support diff --git a/res/shaders/nso-gba-color.shader/manifest.ini b/res/shaders/nso-gba-color.shader/manifest.ini new file mode 100644 index 000000000..42faa25bd --- /dev/null +++ b/res/shaders/nso-gba-color.shader/manifest.ini @@ -0,0 +1,24 @@ +[shader] +name=NSO GBA Color +author=Pokefan531 and hunterk +description=Shader that replicates the Nintendo Switch Online's GBA color filter. +passes=1 + +[pass.0] +fragmentShader=nso-gba-color.fs +vertexShader=nso-gba-color.vs +blend=1 +width=-1 +height=-1 + +[pass.0.uniform.darken_screen] +type=float +default=0.8 +readableName=Darken Screen + +[pass.0.uniform.color_mode] +type=int +default=1 +min=1 +max=3 +readableName=Color Profile (1=sRGB, 2=DCI, 3=Rec2020) diff --git a/res/shaders/nso-gba-color.shader/nso-gba-color.fs b/res/shaders/nso-gba-color.shader/nso-gba-color.fs new file mode 100644 index 000000000..8d8a0ec92 --- /dev/null +++ b/res/shaders/nso-gba-color.shader/nso-gba-color.fs @@ -0,0 +1,21 @@ +// Shader that replicates the LCD Colorspace from Gameboy Advance -- +varying vec2 texCoord; +varying mat4 profile; +uniform sampler2D tex; +uniform vec2 texSize; + +uniform float darken_screen; +const float target_gamma = 2.2; +const float display_gamma = 2.2; + +void main() { + // bring out our stored luminance value + float lum = profile[3].w; + + // our adjustments need to happen in linear gamma + vec4 screen = pow(texture2D(tex, texCoord), vec4(target_gamma + darken_screen)).rgba; + + screen = clamp(screen * lum, 0.0, 1.0); + screen = profile * screen; + gl_FragColor = pow(screen, vec4(1.0 / display_gamma)); +} diff --git a/res/shaders/nso-gba-color.shader/nso-gba-color.vs b/res/shaders/nso-gba-color.shader/nso-gba-color.vs new file mode 100644 index 000000000..c9c89181b --- /dev/null +++ b/res/shaders/nso-gba-color.shader/nso-gba-color.vs @@ -0,0 +1,34 @@ +uniform int color_mode; +attribute vec4 position; +varying vec2 texCoord; +varying mat4 profile; + +const mat4 GBA_sRGB = mat4( + 0.865, 0.0575, 0.0575, 0.0, //red channel + 0.1225, 0.925, 0.1225, 0.0, //green channel + 0.0125, 0.0125, 0.82, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +const mat4 GBA_DCI = mat4( + 0.72, 0.0875, 0.0725, 0.0, //red channel + 0.2675, 0.9, 0.185, 0.0, //green channel + 0.0125, 0.0125, 0.7425, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +const mat4 GBA_Rec2020 = mat4( + 0.57, 0.115, 0.0725, 0.0, //red channel + 0.3825, 0.8625, 0.195, 0.0, //green channel + 0.0475, 0.0225, 0.7325, 0.0, //blue channel + 0.0, 0.0, 0.0, 1.0 //alpha channel +); + +void main() { + if (color_mode == 1) profile = GBA_sRGB; + else if (color_mode == 2) profile = GBA_DCI; + else if (color_mode == 3) profile = GBA_Rec2020; + + gl_Position = position; + texCoord = (position.st + vec2(1.0, 1.0)) * vec2(0.5, 0.5); +}