slang-shaders/anti-aliasing/shaders/smaa/smaa-edge-detection.slang
2016-10-31 11:01:11 -05:00

185 lines
5.6 KiB
Plaintext

#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#include "smaa-common.h"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 texcoord;
layout(location = 1) out vec4 offset[3];
void main()
{
gl_Position = global.MVP * Position;
texcoord = TexCoord;
offset[0] = fma(SMAA_RT_METRICS.xyxy, vec4(-1.0, 0.0, 0.0, -1.0), texcoord.xyxy);
offset[1] = fma(SMAA_RT_METRICS.xyxy, vec4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy);
offset[2] = fma(SMAA_RT_METRICS.xyxy, vec4(-2.0, 0.0, 0.0, -2.0), texcoord.xyxy);
}
#pragma stage fragment
layout(location = 0) in vec2 texcoord;
layout(location = 1) in vec4 offset[3];
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
/**
* Luma Edge Detection
*
* IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and
* thus 'colorTex' should be a non-sRGB texture.
*/
vec2 SMAALumaEdgeDetectionPS(vec2 texcoord, vec4 offset[3], sampler2D colorTex
#if SMAA_PREDICATION
, SMAATexture2D(predicationTex)
#endif
) {
// Calculate the threshold:
#if SMAA_PREDICATION
vec2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex);
#else
vec2 threshold = vec2(SMAA_THRESHOLD, SMAA_THRESHOLD);
#endif
// Calculate lumas:
vec3 weights = vec3(0.2126, 0.7152, 0.0722);
float L = dot(texture(colorTex, texcoord).rgb, weights);
float Lleft = dot(texture(colorTex, offset[0].xy).rgb, weights);
float Ltop = dot(texture(colorTex, offset[0].zw).rgb, weights);
// We do the usual threshold:
vec4 delta;
delta.xy = abs(L - vec2(Lleft, Ltop));
vec2 edges = step(threshold, delta.xy);
// Then discard if there is no edge:
if (dot(edges, vec2(1.0, 1.0)) == 0.0)
discard;
// Calculate right and bottom deltas:
float Lright = dot(texture(colorTex, offset[1].xy).rgb, weights);
float Lbottom = dot(texture(colorTex, offset[1].zw).rgb, weights);
delta.zw = abs(L - vec2(Lright, Lbottom));
// Calculate the maximum delta in the direct neighborhood:
vec2 maxDelta = max(delta.xy, delta.zw);
// Calculate left-left and top-top deltas:
float Lleftleft = dot(texture(colorTex, offset[2].xy).rgb, weights);
float Ltoptop = dot(texture(colorTex, offset[2].zw).rgb, weights);
delta.zw = abs(vec2(Lleft, Ltop) - vec2(Lleftleft, Ltoptop));
// Calculate the final maximum delta:
maxDelta = max(maxDelta.xy, delta.zw);
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
return edges;
}
/**
* Color Edge Detection
*
* IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and
* thus 'colorTex' should be a non-sRGB texture.
*/
vec2 SMAAColorEdgeDetectionPS(vec2 texcoord,
vec4 offset[3],
sampler2D colorTex
#if SMAA_PREDICATION
, sampler2D predicationTex
#endif
) {
// Calculate the threshold:
#if SMAA_PREDICATION
vec2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex);
#else
vec2 threshold = vec2(SMAA_THRESHOLD, SMAA_THRESHOLD);
#endif
// Calculate color deltas:
vec4 delta;
vec3 C = texture(colorTex, texcoord).rgb;
vec3 Cleft = texture(colorTex, offset[0].xy).rgb;
vec3 t = abs(C - Cleft);
delta.x = max(max(t.r, t.g), t.b);
vec3 Ctop = texture(colorTex, offset[0].zw).rgb;
t = abs(C - Ctop);
delta.y = max(max(t.r, t.g), t.b);
// We do the usual threshold:
vec2 edges = step(threshold, delta.xy);
// Then discard if there is no edge:
if (dot(edges, vec2(1.0, 1.0)) == 0.0)
discard;
// Calculate right and bottom deltas:
vec3 Cright = texture(colorTex, offset[1].xy).rgb;
t = abs(C - Cright);
delta.z = max(max(t.r, t.g), t.b);
vec3 Cbottom = texture(colorTex, offset[1].zw).rgb;
t = abs(C - Cbottom);
delta.w = max(max(t.r, t.g), t.b);
// Calculate the maximum delta in the direct neighborhood:
vec2 maxDelta = max(delta.xy, delta.zw);
// Calculate left-left and top-top deltas:
vec3 Cleftleft = texture(colorTex, offset[2].xy).rgb;
t = abs(C - Cleftleft);
delta.z = max(max(t.r, t.g), t.b);
vec3 Ctoptop = texture(colorTex, offset[2].zw).rgb;
t = abs(C - Ctoptop);
delta.w = max(max(t.r, t.g), t.b);
// Calculate the final maximum delta:
maxDelta = max(maxDelta.xy, delta.zw);
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
return edges;
}
/**
* Depth Edge Detection
*/
vec2 SMAADepthEdgeDetectionPS(vec2 texcoord,
vec4 offset[3],
sampler2D depthTex) {
vec3 neighbours = SMAAGatherNeighbours(texcoord, offset, depthTex);
vec2 delta = abs(neighbours.xx - vec2(neighbours.y, neighbours.z));
vec2 edges = step(SMAA_DEPTH_THRESHOLD, delta);
if (dot(edges, vec2(1.0, 1.0)) == 0.0)
discard;
return edges;
}
void main()
{
FragColor = vec4(SMAALumaEdgeDetectionPS(texcoord, offset, Source), 0.0, 0.0);
}