Skip to content

Instantly share code, notes, and snippets.

@m4rt1n0
Created July 1, 2022 22:04
Show Gist options
  • Save m4rt1n0/a987ae8c82e5e658a2a945e3ed79263c to your computer and use it in GitHub Desktop.
Save m4rt1n0/a987ae8c82e5e658a2a945e3ed79263c to your computer and use it in GitHub Desktop.
Game Boy Camera shader for OBS ShaderFilter Plus
// Game Boy Camera shader for OBS ShaderFilter Plus plugin [https://github.com/Limeth/obs-shaderfilter-plus]
// A modified version of [https://www.shadertoy.com/view/ttsSzr] by yx
// Palettes from [https://www.deviantart.com/thewolfbunny64/art/Game-Boy-Palette-Set-Super-Game-Boy-Bash-879821261]
// Use .hlsl on Windows and .glsl on Linux
#pragma shaderfilter set mirror__description Mirror image
#pragma shaderfilter set mirror__default false
#pragma shaderfilter set preset_palette__description Preset palette
#pragma shaderfilter set preset_palette__default 0
#pragma shaderfilter set preset_palette__min 0
#pragma shaderfilter set preset_palette__max 35
#pragma shaderfilter set use_custom_palette__description Use custom palette:
#pragma shaderfilter set use_custom_palette__default false
#pragma shaderfilter set color1__description Color 1
#pragma shaderfilter set color1__default 081820FF
#pragma shaderfilter set color2__description Color 2
#pragma shaderfilter set color2__default 346856FF
#pragma shaderfilter set color3__description Color 3
#pragma shaderfilter set color3__default 88C070FF
#pragma shaderfilter set color4__description Color 4
#pragma shaderfilter set color4__default E0F8D0FF
uniform bool mirror;
uniform int preset_palette;
uniform bool use_custom_palette;
// ShaderFilter Plus requires HLSL syntax
uniform float4 color1;
uniform float4 color2;
uniform float4 color3;
uniform float4 color4;
vec4 render(vec2 uv)
{
// hardcoded Bayer filter
float bayer[64] = float[64](
0., 32., 8., 40., 2., 34., 10., 42.,
48., 16., 56., 24., 50., 18., 58., 26.,
12., 44., 4., 36., 14., 46., 6., 38.,
60., 28., 52., 20., 62., 30., 54., 22.,
3., 35., 11., 43., 1., 33., 9., 41.,
51., 19., 59., 27., 49., 17., 57., 25.,
15., 47., 7., 39., 13., 45., 5., 37.,
63., 31., 55., 23., 61., 29., 53., 21.
);
// custom palette
vec4 palette[4];
palette[0] = color1;
palette[1] = color2;
palette[2] = color3;
palette[3] = color4;
// preset palettes
vec3 p[144];
p[ 0] = vec3( 8, 24, 32)/255.; p[ 1] = vec3( 52,104, 86)/255.; p[ 2] = vec3(136,192,112)/255.; p[ 3] = vec3(224,248,208)/255.; // Shadertoy original
p[ 4] = vec3( 41, 65, 57)/255.; p[ 5] = vec3( 56, 89, 74)/255.; p[ 6] = vec3( 90,120, 65)/255.; p[ 7] = vec3(123,130, 16)/255.; // DMG pea soup
p[ 8] = vec3( 8, 24, 32)/255.; p[ 9] = vec3( 74, 81, 57)/255.; p[10] = vec3(140,146,106)/255.; p[11] = vec3(197,202,164)/255.; // GB Pocket
p[12] = vec3( 0, 80, 57)/255.; p[13] = vec3( 0,105, 74)/255.; p[14] = vec3( 0,153,115)/255.; p[15] = vec3( 0,178,132)/255.; // GB Light
p[16] = vec3( 48, 24, 80)/255.; p[17] = vec3(168, 40, 32)/255.; p[18] = vec3(216,144, 72)/255.; p[19] = vec3(248,232,200)/255.; // SGB 1-A
p[20] = vec3( 0, 0, 0)/255.; p[21] = vec3(176, 80, 16)/255.; p[22] = vec3(200,176,112)/255.; p[23] = vec3(216,216,192)/255.; // SGB 1-B
p[24] = vec3( 56, 56,152)/255.; p[25] = vec3(152, 56, 96)/255.; p[26] = vec3(232,152, 80)/255.; p[27] = vec3(248,192,248)/255.; // SGB 1-C
p[28] = vec3( 80, 24, 0)/255.; p[29] = vec3(248, 0, 0)/255.; p[30] = vec3(192,128, 72)/255.; p[31] = vec3(248,248,168)/255.; // SGB 1-D
p[32] = vec3( 88, 56, 32)/255.; p[33] = vec3(104,136, 64)/255.; p[34] = vec3(120,192,120)/255.; p[35] = vec3(248,216,176)/255.; // SGB 1-E
p[36] = vec3( 0, 64, 16)/255.; p[37] = vec3(168, 0, 0)/255.; p[38] = vec3(224,136, 80)/255.; p[39] = vec3(216,232,248)/255.; // SGB 1-F
p[40] = vec3(248,248, 88)/255.; p[41] = vec3(120,120, 0)/255.; p[42] = vec3( 0,160,232)/255.; p[43] = vec3( 0, 0, 80)/255.; // SGB 1-G
p[44] = vec3( 48, 24, 0)/255.; p[45] = vec3(128, 64, 0)/255.; p[46] = vec3(248,184,136)/255.; p[47] = vec3(248,232,224)/255.; // SGB 1-H
p[48] = vec3( 0, 0, 0)/255.; p[49] = vec3( 40,120, 0)/255.; p[50] = vec3(192,136, 72)/255.; p[51] = vec3(240,200,160)/255.; // SGB 2-A
p[52] = vec3( 80, 0, 88)/255.; p[53] = vec3(248, 48, 0)/255.; p[54] = vec3(248,232, 80)/255.; p[55] = vec3(248,248,248)/255.; // SGB 2-B
p[56] = vec3( 40, 40,152)/255.; p[57] = vec3(120, 48,232)/255.; p[58] = vec3(232,136, 36)/255.; p[59] = vec3(248,192,248)/255.; // SGB 2-C
p[60] = vec3( 0, 0, 80)/255.; p[61] = vec3(248, 48, 0)/255.; p[62] = vec3( 0,248, 0)/255.; p[63] = vec3(248,248,160)/255.; // SGB 2-D
p[64] = vec3( 16, 8, 16)/255.; p[65] = vec3( 40, 16, 96)/255.; p[66] = vec3(144,176,224)/255.; p[67] = vec3(248,200,128)/255.; // SGB 2-E
p[68] = vec3( 24, 0, 0)/255.; p[69] = vec3(160, 0, 0)/255.; p[70] = vec3(248,144, 80)/255.; p[71] = vec3(208,248,248)/255.; // SGB 2-F
p[72] = vec3( 0, 24, 0)/255.; p[73] = vec3(224,184,128)/255.; p[74] = vec3(224, 80, 64)/255.; p[75] = vec3(104, 84, 56)/255.; // SGB 2-G
p[76] = vec3( 0, 0, 0)/255.; p[77] = vec3(112,112,112)/255.; p[78] = vec3(184,184,184)/255.; p[79] = vec3(248,248,248)/255.; // SGB 2-H
p[ 80] = vec3( 48, 72, 96)/255.; p[ 81] = vec3(248, 96, 40)/255.; p[ 82] = vec3(112,192,192)/255.; p[ 83] = vec3(248,208,152)/255.; // SGB 3-A
p[ 84] = vec3( 0, 16, 16)/255.; p[ 85] = vec3( 0, 80, 0)/255.; p[ 86] = vec3(224,128, 32)/255.; p[ 87] = vec3(216,216,192)/255.; // SGB 3-B
p[ 88] = vec3( 32, 32, 88)/255.; p[ 89] = vec3( 0,184,248)/255.; p[ 90] = vec3(248,248,120)/255.; p[ 91] = vec3(224,168,200)/255.; // SGB 3-C
p[ 92] = vec3( 0, 0, 0)/255.; p[ 93] = vec3( 8,200, 0)/255.; p[ 94] = vec3(224,168,120)/255.; p[ 95] = vec3(240,248,184)/255.; // SGB 3-D
p[ 96] = vec3( 80, 72,112)/255.; p[ 97] = vec3(176,120, 32)/255.; p[ 98] = vec3(224,176,104)/255.; p[ 99] = vec3(248,248,192)/255.; // SGB 3-E
p[100] = vec3( 64, 64, 64)/255.; p[101] = vec3(248,208, 0)/255.; p[102] = vec3(248,104,248)/255.; p[103] = vec3(120,120,200)/255.; // SGB 3-F
p[104] = vec3( 56, 0, 0)/255.; p[105] = vec3(200, 48, 56)/255.; p[106] = vec3(248,248,248)/255.; p[107] = vec3( 96,216, 80)/255.; // SGB 3-G
p[108] = vec3( 8, 24, 0)/255.; p[109] = vec3( 72,136, 24)/255.; p[110] = vec3(120,200, 56)/255.; p[111] = vec3(224,248,160)/255.; // SGB 3-H
p[112] = vec3( 0, 0,120)/255.; p[113] = vec3(208, 0,208)/255.; p[114] = vec3(120,168,248)/255.; p[115] = vec3(240,168,104)/255.; // SGB 4-A
p[116] = vec3( 24, 8, 8)/255.; p[117] = vec3( 64,120, 56)/255.; p[118] = vec3(232,160, 96)/255.; p[119] = vec3(240,232,240)/255.; // SGB 4-B
p[120] = vec3( 8, 0, 0)/255.; p[121] = vec3(152,156,224)/255.; p[122] = vec3(216,160,208)/255.; p[123] = vec3(248,224,224)/255.; // SGB 4-C
p[124] = vec3( 8, 32, 72)/255.; p[125] = vec3( 72,104,120)/255.; p[126] = vec3(144,200,200)/255.; p[127] = vec3(248,248,184)/255.; // SGB 4-D
p[128] = vec3( 0, 32, 48)/255.; p[129] = vec3(120, 88,136)/255.; p[130] = vec3(224,168,120)/255.; p[131] = vec3(248,216,168)/255.; // SGB 4-E
p[132] = vec3( 56, 0, 0)/255.; p[133] = vec3(128, 0,160)/255.; p[134] = vec3(216,128,216)/255.; p[135] = vec3(184,208,208)/255.; // SGB 4-F
p[136] = vec3( 0,128, 96)/255.; p[137] = vec3( 40, 16, 0)/255.; p[138] = vec3(184, 32, 88)/255.; p[139] = vec3(176,224, 24)/255.; // SGB 4-G
p[140] = vec3( 64, 80, 40)/255.; p[141] = vec3(128,136, 64)/255.; p[142] = vec3(184,192, 88)/255.; p[143] = vec3(248,248,200)/255.; // SGB 4-H
vec4 res;
res.xy = vec2(128,112); // "square" resolution
res.zw = vec2(res.y*builtin_uv_size.x/builtin_uv_size.y,res.y); // widescreen resolution
vec2 new_uv = uv;
if (mirror) uv.x = 1.-uv.x; // optional mirror selfie mode
new_uv = floor(uv*res.zw) + 0.5;
int value = 0;
if (abs(new_uv.x*2.-res.z) < res.x)
{
vec3 image_color = image.Sample(builtin_texture_sampler, new_uv/res.zw).xyz;
float gray = dot(image_color, vec3(0.2126,0.7152,0.0722));
int x = int(new_uv.x)%8;
int y = int(new_uv.y)%8;
float dither = bayer[y*8+x]/64.;
value = int(floor(gray*3.+dither));
}
if (use_custom_palette) {
return palette[value];
} else {
return vec4(p[preset_palette * 4 + value], 1);
}
}
// Game Boy Camera shader for OBS ShaderFilter Plus plugin [https://github.com/Limeth/obs-shaderfilter-plus]
// A modified version of [https://www.shadertoy.com/view/ttsSzr] by yx
// Palettes from [https://www.deviantart.com/thewolfbunny64/art/Game-Boy-Palette-Set-Super-Game-Boy-Bash-879821261]
// Use .hlsl on Windows and .glsl on Linux
#pragma shaderfilter set mirror__description Mirror image
#pragma shaderfilter set mirror__default false
#pragma shaderfilter set preset_palette__description Preset palette
#pragma shaderfilter set preset_palette__default 0
#pragma shaderfilter set preset_palette__min 0
#pragma shaderfilter set preset_palette__max 35
#pragma shaderfilter set use_custom_palette__description Use custom palette:
#pragma shaderfilter set use_custom_palette__default false
#pragma shaderfilter set color1__description Color 1
#pragma shaderfilter set color1__default 081820FF
#pragma shaderfilter set color2__description Color 2
#pragma shaderfilter set color2__default 346856FF
#pragma shaderfilter set color3__description Color 3
#pragma shaderfilter set color3__default 88C070FF
#pragma shaderfilter set color4__description Color 4
#pragma shaderfilter set color4__default E0F8D0FF
uniform bool mirror;
uniform int preset_palette;
uniform bool use_custom_palette;
uniform float4 color1;
uniform float4 color2;
uniform float4 color3;
uniform float4 color4;
float4 render(float2 uv)
{
// hardcoded Bayer filter
float bayer[64] = {
0., 32., 8., 40., 2., 34., 10., 42.,
48., 16., 56., 24., 50., 18., 58., 26.,
12., 44., 4., 36., 14., 46., 6., 38.,
60., 28., 52., 20., 62., 30., 54., 22.,
3., 35., 11., 43., 1., 33., 9., 41.,
51., 19., 59., 27., 49., 17., 57., 25.,
15., 47., 7., 39., 13., 45., 5., 37.,
63., 31., 55., 23., 61., 29., 53., 21.
};
// custom palette
float4 palette[4];
palette[0] = color1;
palette[1] = color2;
palette[2] = color3;
palette[3] = color4;
// preset palettes
float3 p[144];
p[ 0] = float3( 8, 24, 32)/255.; p[ 1] = float3( 52,104, 86)/255.; p[ 2] = float3(136,192,112)/255.; p[ 3] = float3(224,248,208)/255.; // Shadertoy original
p[ 4] = float3( 41, 65, 57)/255.; p[ 5] = float3( 56, 89, 74)/255.; p[ 6] = float3( 90,120, 65)/255.; p[ 7] = float3(123,130, 16)/255.; // DMG pea soup
p[ 8] = float3( 8, 24, 32)/255.; p[ 9] = float3( 74, 81, 57)/255.; p[10] = float3(140,146,106)/255.; p[11] = float3(197,202,164)/255.; // GB Pocket
p[12] = float3( 0, 80, 57)/255.; p[13] = float3( 0,105, 74)/255.; p[14] = float3( 0,153,115)/255.; p[15] = float3( 0,178,132)/255.; // GB Light
p[16] = float3( 48, 24, 80)/255.; p[17] = float3(168, 40, 32)/255.; p[18] = float3(216,144, 72)/255.; p[19] = float3(248,232,200)/255.; // SGB 1-A
p[20] = float3( 0, 0, 0)/255.; p[21] = float3(176, 80, 16)/255.; p[22] = float3(200,176,112)/255.; p[23] = float3(216,216,192)/255.; // SGB 1-B
p[24] = float3( 56, 56,152)/255.; p[25] = float3(152, 56, 96)/255.; p[26] = float3(232,152, 80)/255.; p[27] = float3(248,192,248)/255.; // SGB 1-C
p[28] = float3( 80, 24, 0)/255.; p[29] = float3(248, 0, 0)/255.; p[30] = float3(192,128, 72)/255.; p[31] = float3(248,248,168)/255.; // SGB 1-D
p[32] = float3( 88, 56, 32)/255.; p[33] = float3(104,136, 64)/255.; p[34] = float3(120,192,120)/255.; p[35] = float3(248,216,176)/255.; // SGB 1-E
p[36] = float3( 0, 64, 16)/255.; p[37] = float3(168, 0, 0)/255.; p[38] = float3(224,136, 80)/255.; p[39] = float3(216,232,248)/255.; // SGB 1-F
p[40] = float3(248,248, 88)/255.; p[41] = float3(120,120, 0)/255.; p[42] = float3( 0,160,232)/255.; p[43] = float3( 0, 0, 80)/255.; // SGB 1-G
p[44] = float3( 48, 24, 0)/255.; p[45] = float3(128, 64, 0)/255.; p[46] = float3(248,184,136)/255.; p[47] = float3(248,232,224)/255.; // SGB 1-H
p[48] = float3( 0, 0, 0)/255.; p[49] = float3( 40,120, 0)/255.; p[50] = float3(192,136, 72)/255.; p[51] = float3(240,200,160)/255.; // SGB 2-A
p[52] = float3( 80, 0, 88)/255.; p[53] = float3(248, 48, 0)/255.; p[54] = float3(248,232, 80)/255.; p[55] = float3(248,248,248)/255.; // SGB 2-B
p[56] = float3( 40, 40,152)/255.; p[57] = float3(120, 48,232)/255.; p[58] = float3(232,136, 36)/255.; p[59] = float3(248,192,248)/255.; // SGB 2-C
p[60] = float3( 0, 0, 80)/255.; p[61] = float3(248, 48, 0)/255.; p[62] = float3( 0,248, 0)/255.; p[63] = float3(248,248,160)/255.; // SGB 2-D
p[64] = float3( 16, 8, 16)/255.; p[65] = float3( 40, 16, 96)/255.; p[66] = float3(144,176,224)/255.; p[67] = float3(248,200,128)/255.; // SGB 2-E
p[68] = float3( 24, 0, 0)/255.; p[69] = float3(160, 0, 0)/255.; p[70] = float3(248,144, 80)/255.; p[71] = float3(208,248,248)/255.; // SGB 2-F
p[72] = float3( 0, 24, 0)/255.; p[73] = float3(224,184,128)/255.; p[74] = float3(224, 80, 64)/255.; p[75] = float3(104, 84, 56)/255.; // SGB 2-G
p[76] = float3( 0, 0, 0)/255.; p[77] = float3(112,112,112)/255.; p[78] = float3(184,184,184)/255.; p[79] = float3(248,248,248)/255.; // SGB 2-H
p[ 80] = float3( 48, 72, 96)/255.; p[ 81] = float3(248, 96, 40)/255.; p[ 82] = float3(112,192,192)/255.; p[ 83] = float3(248,208,152)/255.; // SGB 3-A
p[ 84] = float3( 0, 16, 16)/255.; p[ 85] = float3( 0, 80, 0)/255.; p[ 86] = float3(224,128, 32)/255.; p[ 87] = float3(216,216,192)/255.; // SGB 3-B
p[ 88] = float3( 32, 32, 88)/255.; p[ 89] = float3( 0,184,248)/255.; p[ 90] = float3(248,248,120)/255.; p[ 91] = float3(224,168,200)/255.; // SGB 3-C
p[ 92] = float3( 0, 0, 0)/255.; p[ 93] = float3( 8,200, 0)/255.; p[ 94] = float3(224,168,120)/255.; p[ 95] = float3(240,248,184)/255.; // SGB 3-D
p[ 96] = float3( 80, 72,112)/255.; p[ 97] = float3(176,120, 32)/255.; p[ 98] = float3(224,176,104)/255.; p[ 99] = float3(248,248,192)/255.; // SGB 3-E
p[100] = float3( 64, 64, 64)/255.; p[101] = float3(248,208, 0)/255.; p[102] = float3(248,104,248)/255.; p[103] = float3(120,120,200)/255.; // SGB 3-F
p[104] = float3( 56, 0, 0)/255.; p[105] = float3(200, 48, 56)/255.; p[106] = float3(248,248,248)/255.; p[107] = float3( 96,216, 80)/255.; // SGB 3-G
p[108] = float3( 8, 24, 0)/255.; p[109] = float3( 72,136, 24)/255.; p[110] = float3(120,200, 56)/255.; p[111] = float3(224,248,160)/255.; // SGB 3-H
p[112] = float3( 0, 0,120)/255.; p[113] = float3(208, 0,208)/255.; p[114] = float3(120,168,248)/255.; p[115] = float3(240,168,104)/255.; // SGB 4-A
p[116] = float3( 24, 8, 8)/255.; p[117] = float3( 64,120, 56)/255.; p[118] = float3(232,160, 96)/255.; p[119] = float3(240,232,240)/255.; // SGB 4-B
p[120] = float3( 8, 0, 0)/255.; p[121] = float3(152,156,224)/255.; p[122] = float3(216,160,208)/255.; p[123] = float3(248,224,224)/255.; // SGB 4-C
p[124] = float3( 8, 32, 72)/255.; p[125] = float3( 72,104,120)/255.; p[126] = float3(144,200,200)/255.; p[127] = float3(248,248,184)/255.; // SGB 4-D
p[128] = float3( 0, 32, 48)/255.; p[129] = float3(120, 88,136)/255.; p[130] = float3(224,168,120)/255.; p[131] = float3(248,216,168)/255.; // SGB 4-E
p[132] = float3( 56, 0, 0)/255.; p[133] = float3(128, 0,160)/255.; p[134] = float3(216,128,216)/255.; p[135] = float3(184,208,208)/255.; // SGB 4-F
p[136] = float3( 0,128, 96)/255.; p[137] = float3( 40, 16, 0)/255.; p[138] = float3(184, 32, 88)/255.; p[139] = float3(176,224, 24)/255.; // SGB 4-G
p[140] = float3( 64, 80, 40)/255.; p[141] = float3(128,136, 64)/255.; p[142] = float3(184,192, 88)/255.; p[143] = float3(248,248,200)/255.; // SGB 4-H
float4 res;
res.xy = float2(128,112); // "square" resolution
res.zw = float2(res.y*builtin_uv_size.x/builtin_uv_size.y,res.y); // widescreen resolution
float2 new_uv = uv;
if (mirror) uv.x = 1.-uv.x; // optional mirror selfie mode
new_uv = floor(uv*res.zw) + 0.5;
int value = 0;
if (abs(new_uv.x*2.-res.z) < res.x)
{
float3 image_color = image.Sample(builtin_texture_sampler, new_uv/res.zw).xyz;
float gray = dot(image_color, float3(0.2126,0.7152,0.0722));
int x = int(new_uv.x)%8;
int y = int(new_uv.y)%8;
float dither = bayer[y*8+x]/64.;
value = int(floor(gray*3.+dither));
}
if (use_custom_palette) {
return palette[value];
} else {
return float4(p[preset_palette * 4 + value], 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment