2016-07-20 06:17:23 +10:00
#version 450
2016-08-03 03:55:54 +10:00
layout(push_constant) uniform Push
{
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
float blending_mode;
float adjacent_texel_alpha_blending;
} registers;
2016-07-20 06:17:23 +10:00
layout(std140, set = 0, binding = 0) uniform UBO
{
2016-07-21 07:50:07 +10:00
mat4 MVP;
2016-07-20 06:17:23 +10:00
} global;
2016-07-21 07:50:07 +10:00
////////////////////////////////////////////////////////////////////////////////
// Config //
////////////////////////////////////////////////////////////////////////////////
// 0 - only the space between dots is blending
// 1 - all texels are blended
2016-07-24 12:59:55 +10:00
/* TODO/FIXME - When set to zero, frame will be a solid green color */
2016-08-03 03:55:54 +10:00
#pragma parameter blending_mode "Blending Mode" 1.0 0.0 1.0 1.0
2016-07-21 07:50:07 +10:00
// The amount of alpha swapped between neighboring texels
2016-08-03 03:55:54 +10:00
#pragma parameter adjacent_texel_alpha_blending "Neighbor Blending" 0.1755 0.0 1.0 0.05
2016-07-20 06:17:23 +10:00
///////////////////////////////////////////////////////////////////////////
// //
// Gameboy Classic Shader v0.2.2 //
// //
// Copyright (C) 2013 Harlequin : unknown92835@gmail.com //
// //
// This program is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
// //
///////////////////////////////////////////////////////////////////////////
2016-07-21 07:50:07 +10:00
////////////////////////////////////////////////////////////////////////////////
// Vertex shader //
////////////////////////////////////////////////////////////////////////////////
2016-07-20 06:17:23 +10:00
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec2 texel;
layout(location = 2) out vec2 blur_coords_up;
layout(location = 3) out vec2 blur_coords_down;
layout(location = 4) out vec2 blur_coords_right;
layout(location = 5) out vec2 blur_coords_left;
layout(location = 6) out vec2 blur_coords_lower_bound;
layout(location = 7) out vec2 blur_coords_upper_bound;
void main()
{
2016-07-21 07:50:07 +10:00
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
2016-08-03 03:55:54 +10:00
texel = registers.SourceSize.zw;
2016-07-21 07:50:07 +10:00
blur_coords_down = vTexCoord + vec2(0.0, texel.y);
blur_coords_up = vTexCoord + vec2(0.0, -texel.y);
blur_coords_right = vTexCoord + vec2(texel.x, 0.0);
blur_coords_left = vTexCoord + vec2(-texel.x, 0.0);
blur_coords_lower_bound = vec2(0.0);
2016-08-03 03:55:54 +10:00
blur_coords_upper_bound = texel * (registers.OutputSize.xy - vec2(2.0));
2016-07-20 06:17:23 +10:00
}
2016-07-21 07:50:07 +10:00
////////////////////////////////////////////////////////////////////////////////
// Fragment shader //
////////////////////////////////////////////////////////////////////////////////
2016-07-20 06:17:23 +10:00
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 texel;
layout(location = 2) in vec2 blur_coords_up;
layout(location = 3) in vec2 blur_coords_down;
layout(location = 4) in vec2 blur_coords_right;
layout(location = 5) in vec2 blur_coords_left;
layout(location = 6) in vec2 blur_coords_lower_bound;
layout(location = 7) in vec2 blur_coords_upper_bound;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
2016-07-21 07:50:07 +10:00
////////////////////////////////////////////////////////////////////////////////
// Fragment definitions //
////////////////////////////////////////////////////////////////////////////////
2016-07-20 06:17:23 +10:00
2017-05-02 01:22:12 +10:00
float blending_modifier(float color){
float blend_bool = (color == 0.0) ? 1 : 0;
return clamp(blend_bool + registers.blending_mode, 0.0, 1.0);
}
2016-07-20 06:17:23 +10:00
void main()
{
2016-07-21 07:50:07 +10:00
// A simple blur technique that softens harsh color transitions
// Specialized to only blur alpha values and limited to only blurring texels
// lying in the spaces between two or more texels
2016-07-20 06:17:23 +10:00
2016-07-21 07:50:07 +10:00
// Sample the input textures
vec4 out_color = texture(Source, vTexCoord).rgba;
// Clamp the blur coords to the input texture size so it doesn't attempt to sample off the texture (it'll retrieve float4(0.0) and darken the edges otherwise)
vec2 blur_coords_up_clamped = clamp(blur_coords_up, blur_coords_lower_bound, blur_coords_upper_bound);
vec2 blur_coords_down_clamped = clamp(blur_coords_down, blur_coords_lower_bound, blur_coords_upper_bound);
2016-07-20 06:17:23 +10:00
vec2 blur_coords_right_clamped = clamp(blur_coords_right, blur_coords_lower_bound, blur_coords_upper_bound);
2016-07-21 07:50:07 +10:00
vec2 blur_coords_left_clamped = clamp(blur_coords_left, blur_coords_lower_bound, blur_coords_upper_bound);
2016-07-20 06:17:23 +10:00
2016-07-21 07:50:07 +10:00
//Sample adjacent texels based on the coordinates above
2016-07-20 06:17:23 +10:00
vec4 adjacent_texel_1 = texture(Source, blur_coords_up_clamped).rgba;
vec4 adjacent_texel_2 = texture(Source, blur_coords_down_clamped).rgba;
vec4 adjacent_texel_3 = texture(Source, blur_coords_right_clamped).rgba;
vec4 adjacent_texel_4 = texture(Source, blur_coords_left_clamped).rgba;
2016-07-21 07:50:07 +10:00
// Sum the alpha differences between neighboring texels, apply modifiers, then subtract the result from the current fragment alpha value
out_color.a -=
(
(out_color.a - adjacent_texel_1.a) +
(out_color.a - adjacent_texel_2.a) +
(out_color.a - adjacent_texel_3.a) +
(out_color.a - adjacent_texel_4.a)
2017-05-02 01:22:12 +10:00
) * registers.adjacent_texel_alpha_blending * blending_modifier(out_color.a);
2016-07-21 07:50:07 +10:00
FragColor = out_color;
}