mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-02 09:41:13 -06:00
Merge branch 'feature/FXAA' into integration/FXAA_Vol_Milkway
This commit is contained in:
@@ -53,25 +53,21 @@ void main() {
|
||||
// Detecting where to apply AA:
|
||||
// ============================
|
||||
|
||||
// Luma at the current fragment
|
||||
float lumaCenter = getLum(colorCenter.rgb);
|
||||
|
||||
// Luma at the four direct neighbours of the current fragment.
|
||||
float lumaDown = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb);
|
||||
float lumaUp = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb);
|
||||
float lumaLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb);
|
||||
float lumaRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb);
|
||||
float pixelLumCenter = getLum(colorCenter.rgb);
|
||||
float pixelLumDown = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,-1)).rgb);
|
||||
float pixelLumUp = getLum(textureOffset(renderedTexture, texCoord, ivec2(0,1)).rgb);
|
||||
float pixelLumLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,0)).rgb);
|
||||
float pixelLumRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,0)).rgb);
|
||||
|
||||
// Find the maximum and minimum luma around the current fragment.
|
||||
float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight)));
|
||||
float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight)));
|
||||
float pixelLumMin = min(pixelLumCenter, min(min(pixelLumDown, pixelLumUp), min(pixelLumLeft, pixelLumRight)));
|
||||
float pixelLumMax = max(pixelLumCenter, max(max(pixelLumDown, pixelLumUp), max(pixelLumLeft, pixelLumRight)));
|
||||
|
||||
// Compute the delta.
|
||||
float lumaRange = lumaMax - lumaMin;
|
||||
// Delta.
|
||||
float pixelLumRange = pixelLumMax - pixelLumMin;
|
||||
|
||||
// If the luma variation is lower that a threshold (or if we are in a really dark area),
|
||||
// If the pixelLum variation is lower that a threshold (or if we are in a really dark area),
|
||||
// we are not on an edge, don't perform any AA.
|
||||
if (lumaRange < max(EDGE_THRESHOLD_MIN, lumaMax * EDGE_THRESHOLD_MAX)) {
|
||||
if (pixelLumRange < max(EDGE_THRESHOLD_MIN, pixelLumMax * EDGE_THRESHOLD_MAX)) {
|
||||
aaFinalColor = colorCenter;
|
||||
return;
|
||||
}
|
||||
@@ -79,64 +75,50 @@ void main() {
|
||||
// ============================
|
||||
// Estimating the gradient:
|
||||
// ============================
|
||||
// Query the 4 remaining corners lumas.
|
||||
float lumaDownLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb);
|
||||
float lumaUpRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb);
|
||||
float lumaUpLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb);
|
||||
float lumaDownRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb);
|
||||
float pixelLumDownLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,-1)).rgb);
|
||||
float pixelLumUpRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,1)).rgb);
|
||||
float pixelLumUpLeft = getLum(textureOffset(renderedTexture, texCoord, ivec2(-1,1)).rgb);
|
||||
float pixelLumDownRight = getLum(textureOffset(renderedTexture, texCoord, ivec2(1,-1)).rgb);
|
||||
|
||||
// Combine the four edges lumas (using intermediary variables for future computations
|
||||
// with the same values).
|
||||
float lumaDownUp = lumaDown + lumaUp;
|
||||
float lumaLeftRight = lumaLeft + lumaRight;
|
||||
float pixelLumDownUp = pixelLumDown + pixelLumUp;
|
||||
float pixelLumLeftRight = pixelLumLeft + pixelLumRight;
|
||||
float pixelLumLeftCorners = pixelLumDownLeft + pixelLumUpLeft;
|
||||
float pixelLumDownCorners = pixelLumDownLeft + pixelLumDownRight;
|
||||
float pixelLumRightCorners = pixelLumDownRight + pixelLumUpRight;
|
||||
float pixelLumUpCorners = pixelLumUpRight + pixelLumUpLeft;
|
||||
|
||||
// Same for corners
|
||||
float lumaLeftCorners = lumaDownLeft + lumaUpLeft;
|
||||
float lumaDownCorners = lumaDownLeft + lumaDownRight;
|
||||
float lumaRightCorners = lumaDownRight + lumaUpRight;
|
||||
float lumaUpCorners = lumaUpRight + lumaUpLeft;
|
||||
|
||||
// Compute an estimation of the gradient along the horizontal and vertical axis.
|
||||
float edgeHorizontal = abs(-2.0 * lumaLeft + lumaLeftCorners) +
|
||||
abs(-2.0 * lumaCenter + lumaDownUp ) * 2.0 + abs(-2.0 * lumaRight + lumaRightCorners);
|
||||
float edgeVertical = abs(-2.0 * lumaUp + lumaUpCorners) +
|
||||
abs(-2.0 * lumaCenter + lumaLeftRight) * 2.0 + abs(-2.0 * lumaDown + lumaDownCorners);
|
||||
|
||||
// Is the local edge horizontal or vertical ?
|
||||
bool isHorizontal = (edgeHorizontal >= edgeVertical);
|
||||
// Compute an estimation of the gradient
|
||||
float edgeHorizontal = abs(-2.0 * pixelLumLeft + pixelLumLeftCorners) +
|
||||
abs(-2.0 * pixelLumCenter + pixelLumDownUp ) * 2.0 + abs(-2.0 * pixelLumRight + pixelLumRightCorners);
|
||||
float edgeVertical = abs(-2.0 * pixelLumUp + pixelLumUpCorners) +
|
||||
abs(-2.0 * pixelLumCenter + pixelLumLeftRight) * 2.0 + abs(-2.0 * pixelLumDown + pixelLumDownCorners);
|
||||
|
||||
// ============================
|
||||
// Choosing Edge Orientation:
|
||||
// ============================
|
||||
// Select the two neighboring texels lumas in the opposite direction to the local edge.
|
||||
float luma1 = isHorizontal ? lumaDown : lumaLeft;
|
||||
float luma2 = isHorizontal ? lumaUp : lumaRight;
|
||||
bool isHorizontal = (edgeHorizontal >= edgeVertical);
|
||||
float pixelLum1 = isHorizontal ? pixelLumDown : pixelLumLeft;
|
||||
float pixelLum2 = isHorizontal ? pixelLumUp : pixelLumRight;
|
||||
|
||||
// Compute gradients in this direction.
|
||||
float gradient1 = luma1 - lumaCenter;
|
||||
float gradient2 = luma2 - lumaCenter;
|
||||
// Gradients
|
||||
float gradient1 = pixelLum1 - pixelLumCenter;
|
||||
float gradient2 = pixelLum2 - pixelLumCenter;
|
||||
|
||||
// Which direction is the steepest ?
|
||||
bool is1Steepest = abs(gradient1) >= abs(gradient2);
|
||||
|
||||
// Gradient in the corresponding direction, normalized.
|
||||
float gradientScaled = 0.25 * max(abs(gradient1), abs(gradient2));
|
||||
|
||||
// Choose the step size (one pixel) according to the edge direction.
|
||||
// Step size (one pixel) according to the edge direction.
|
||||
float stepLength = isHorizontal ? inverseScreenSize.y : inverseScreenSize.x;
|
||||
|
||||
// Average luma in the correct direction.
|
||||
float lumaLocalAverage = 0.0;
|
||||
float pixelLumLocalAverage = 0.0;
|
||||
|
||||
if (is1Steepest) {
|
||||
// Switch the direction
|
||||
stepLength = - stepLength;
|
||||
lumaLocalAverage = 0.5 * (luma1 + lumaCenter);
|
||||
pixelLumLocalAverage = 0.5 * (pixelLum1 + pixelLumCenter);
|
||||
} else {
|
||||
lumaLocalAverage = 0.5 * (luma2 + lumaCenter);
|
||||
pixelLumLocalAverage = 0.5 * (pixelLum2 + pixelLumCenter);
|
||||
}
|
||||
|
||||
// Shift UV in the correct direction by half a pixel.
|
||||
vec2 currentUv = texCoord;
|
||||
if (isHorizontal) {
|
||||
currentUv.y += stepLength * 0.5;
|
||||
@@ -147,28 +129,22 @@ void main() {
|
||||
// ============================
|
||||
// Iterations:
|
||||
// ============================
|
||||
// Compute offset (for each iteration step) in the right direction.
|
||||
vec2 offset = isHorizontal ? vec2(inverseScreenSize.x, 0.0) : vec2(0.0, inverseScreenSize.y);
|
||||
|
||||
// Compute UVs to explore on each side of the edge, orthogonally.
|
||||
// The QUALITY allows us to step faster.
|
||||
vec2 uv1 = currentUv - offset;
|
||||
vec2 uv2 = currentUv + offset;
|
||||
|
||||
// Read the lumas at both current extremities of the exploration segment,
|
||||
// and compute the delta wrt to the local average luma.
|
||||
float lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb);
|
||||
float lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb);
|
||||
lumaEnd1 -= lumaLocalAverage;
|
||||
lumaEnd2 -= lumaLocalAverage;
|
||||
// Read the pixelLums at both current extremities of the exploration segment,
|
||||
// and compute the delta wrt to the local average pixelLum.
|
||||
float pixelLumEnd1 = getLum(texture(renderedTexture, uv1).rgb);
|
||||
float pixelLumEnd2 = getLum(texture(renderedTexture, uv2).rgb);
|
||||
pixelLumEnd1 -= pixelLumLocalAverage;
|
||||
pixelLumEnd2 -= pixelLumLocalAverage;
|
||||
|
||||
// If the luma deltas at the current extremities are larger than the local gradient,
|
||||
// we have reached the side of the edge.
|
||||
bool reached1 = abs(lumaEnd1) >= gradientScaled;
|
||||
bool reached2 = abs(lumaEnd2) >= gradientScaled;
|
||||
bool reached1 = abs(pixelLumEnd1) >= gradientScaled;
|
||||
bool reached2 = abs(pixelLumEnd2) >= gradientScaled;
|
||||
bool reachedBoth = reached1 && reached2;
|
||||
|
||||
// If the side is not reached, we continue to explore in this direction.
|
||||
if (!reached1) {
|
||||
uv1 -= offset;
|
||||
}
|
||||
@@ -177,27 +153,24 @@ void main() {
|
||||
uv2 += offset;
|
||||
}
|
||||
|
||||
// If both sides have not been reached, continue to explore.
|
||||
// Still exploring
|
||||
if (!reachedBoth) {
|
||||
for (int i = 2; i < ITERATIONS; i++) {
|
||||
// If needed, read luma in 1st direction, compute delta.
|
||||
// If needed, read pixelLum in 1st direction, compute delta.
|
||||
if (!reached1) {
|
||||
lumaEnd1 = getLum(texture(renderedTexture, uv1).rgb);
|
||||
lumaEnd1 = lumaEnd1 - lumaLocalAverage;
|
||||
pixelLumEnd1 = getLum(texture(renderedTexture, uv1).rgb);
|
||||
pixelLumEnd1 = pixelLumEnd1 - pixelLumLocalAverage;
|
||||
}
|
||||
// If needed, read luma in opposite direction, compute delta.
|
||||
// If needed, read pixelLum in opposite direction, compute delta.
|
||||
if (!reached2) {
|
||||
lumaEnd2 = getLum(texture(renderedTexture, uv2).rgb);
|
||||
lumaEnd2 = lumaEnd2 - lumaLocalAverage;
|
||||
pixelLumEnd2 = getLum(texture(renderedTexture, uv2).rgb);
|
||||
pixelLumEnd2 = pixelLumEnd2 - pixelLumLocalAverage;
|
||||
}
|
||||
// If the luma deltas at the current extremities is larger than
|
||||
// the local gradient, we have reached the side of the edge.
|
||||
reached1 = abs(lumaEnd1) >= gradientScaled;
|
||||
reached2 = abs(lumaEnd2) >= gradientScaled;
|
||||
reached1 = abs(pixelLumEnd1) >= gradientScaled;
|
||||
reached2 = abs(pixelLumEnd2) >= gradientScaled;
|
||||
reachedBoth = reached1 && reached2;
|
||||
|
||||
// If the side is not reached, we continue to explore in this direction,
|
||||
// with a variable quality.
|
||||
// If the side is not reached
|
||||
if (!reached1) {
|
||||
uv1 -= offset * QUALITY[i];
|
||||
}
|
||||
@@ -206,7 +179,7 @@ void main() {
|
||||
uv2 += offset * QUALITY[i];
|
||||
}
|
||||
|
||||
// If both sides have been reached, stop the exploration.
|
||||
// If both sides have been reached
|
||||
if (reachedBoth) {
|
||||
break;
|
||||
}
|
||||
@@ -216,55 +189,45 @@ void main() {
|
||||
// ============================
|
||||
// Estimating the offset:
|
||||
// ============================
|
||||
// Compute the distances to each extremity of the edge.
|
||||
float distance1 = isHorizontal ? (texCoord.x - uv1.x) : (texCoord.y - uv1.y);
|
||||
float distance2 = isHorizontal ? (uv2.x - texCoord.x) : (uv2.y - texCoord.y);
|
||||
|
||||
// In which direction is the extremity of the edge closer ?
|
||||
bool isDirection1 = distance1 < distance2;
|
||||
float distanceFinal = min(distance1, distance2);
|
||||
|
||||
// Length of the edge.
|
||||
float edgeThickness = (distance1 + distance2);
|
||||
|
||||
// UV offset: read in the direction of the closest side of the edge.
|
||||
// Read in the direction of the closest side of the edge.
|
||||
float pixelOffset = - distanceFinal / edgeThickness + 0.5;
|
||||
|
||||
// Is the luma at center smaller than the local average ?
|
||||
bool isLumaCenterSmaller = lumaCenter < lumaLocalAverage;
|
||||
bool ispixelLumCenterSmaller = pixelLumCenter < pixelLumLocalAverage;
|
||||
|
||||
// If the luma at center is smaller than at its neighbour, the delta luma at
|
||||
// If the pixelLum at center is smaller than at its neighbour, the delta pixelLum at
|
||||
// each end should be positive (same variation).
|
||||
// (in the direction of the closer side of the edge.)
|
||||
bool correctVariation = ((isDirection1 ? lumaEnd1 : lumaEnd2) < 0.0) != isLumaCenterSmaller;
|
||||
bool correctVariation = ((isDirection1 ? pixelLumEnd1 : pixelLumEnd2) < 0.0) != ispixelLumCenterSmaller;
|
||||
|
||||
// If the luma variation is incorrect, do not offset.
|
||||
// If the pixelLum variation is incorrect, do not offset.
|
||||
float finalOffset = correctVariation ? pixelOffset : 0.0;
|
||||
|
||||
// ============================
|
||||
// Subpixel antialiasing:
|
||||
// ============================
|
||||
// Sub-pixel shifting
|
||||
// Full weighted average of the luma over the 3x3 neighborhood.
|
||||
float lumaAverage = (1.0/12.0) * (2.0 * (lumaDownUp + lumaLeftRight) +
|
||||
lumaLeftCorners + lumaRightCorners);
|
||||
// Ratio of the delta between the global average and the center luma, over the luma range in the 3x3 neighborhood.
|
||||
float subPixelOffset1 = clamp(abs(lumaAverage - lumaCenter) / lumaRange, 0.0, 1.0);
|
||||
float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1;
|
||||
// Compute a sub-pixel offset based on this delta.
|
||||
float pixelLumAverage = (1.0/12.0) * (2.0 * (pixelLumDownUp + pixelLumLeftRight) +
|
||||
pixelLumLeftCorners + pixelLumRightCorners);
|
||||
|
||||
float subPixelOffset1 = clamp(abs(pixelLumAverage - pixelLumCenter) / pixelLumRange, 0.0, 1.0);
|
||||
float subPixelOffset2 = (-2.0 * subPixelOffset1 + 3.0) * subPixelOffset1 * subPixelOffset1;
|
||||
float subPixelOffsetFinal = subPixelOffset2 * subPixelOffset2 * SUBPIXEL_QUALITY;
|
||||
|
||||
// Pick the biggest of the two offsets.
|
||||
// Biggest of the two offsets.
|
||||
finalOffset = max(finalOffset, subPixelOffsetFinal);
|
||||
|
||||
// Compute the final UV coordinates.
|
||||
vec2 finalUv = texCoord;
|
||||
vec2 finalUV = texCoord;
|
||||
if (isHorizontal) {
|
||||
finalUv.y += finalOffset * stepLength;
|
||||
finalUV.y += finalOffset * stepLength;
|
||||
} else {
|
||||
finalUv.x += finalOffset * stepLength;
|
||||
finalUV.x += finalOffset * stepLength;
|
||||
}
|
||||
|
||||
// Read the color at the new UV coordinates, and use it.
|
||||
aaFinalColor = texture(renderedTexture, finalUv);
|
||||
aaFinalColor = texture(renderedTexture, finalUV);
|
||||
}
|
||||
Reference in New Issue
Block a user