molstar
Version:
A comprehensive macromolecular library.
219 lines (169 loc) • 8.29 kB
JavaScript
"use strict";
/**
* Slightly adapted from https://github.com/mrdoob/three.js
* MIT License Copyright (c) 2010-2020 three.js authors
*
* WebGL port of Subpixel Morphological Antialiasing (SMAA) v2.8
* Preset: SMAA 1x Medium (with color edge detection)
* https://github.com/iryoku/smaa/releases/tag/v2.8
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.weights_frag = void 0;
exports.weights_frag = `
precision highp float;
precision highp int;
precision highp sampler2D;
uniform sampler2D tEdges;
uniform sampler2D tArea;
uniform sampler2D tSearch;
uniform vec2 uTexSizeInv;
varying vec2 vUv;
varying vec4 vOffset[3];
varying vec2 vPixCoord;
vec2 round(vec2 x) {
return sign(x) * floor(abs(x) + 0.5);
}
float SMAASearchLength(sampler2D searchTex, vec2 e, float bias, float scale) {
// Not required if searchTex accesses are set to point:
// float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);
// e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +
// e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;
e.r = bias + e.r * scale;
return 255.0 * texture2D(searchTex, e, 0.0).r;
}
float SMAASearchXLeft(sampler2D edgesTex, sampler2D searchTex, vec2 texCoord, float end) {
/**
* @PSEUDO_GATHER4
* This texCoord has been offset by (-0.25, -0.125) in the vertex shader to
* sample between edge, thus fetching four edges in a row.
* Sampling with different offsets in each direction allows to disambiguate
* which edges are active from the four fetched ones.
*/
vec2 e = vec2(0.0, 1.0);
for (int i = 0; i < dMaxSearchSteps; i++) { // WebGL port note: Changed while to for
e = texture2D( edgesTex, texCoord, 0.0).rg;
texCoord -= vec2(2.0, 0.0) * uTexSizeInv;
if (!(texCoord.x > end && e.g > 0.8281 && e.r == 0.0)) break;
}
// We correct the previous (-0.25, -0.125) offset we applied:
texCoord.x += 0.25 * uTexSizeInv.x;
// The searches are bias by 1, so adjust the coords accordingly:
texCoord.x += uTexSizeInv.x;
// Disambiguate the length added by the last step:
texCoord.x += 2.0 * uTexSizeInv.x; // Undo last step
texCoord.x -= uTexSizeInv.x * SMAASearchLength(searchTex, e, 0.0, 0.5);
return texCoord.x;
}
float SMAASearchXRight(sampler2D edgesTex, sampler2D searchTex, vec2 texCoord, float end) {
vec2 e = vec2( 0.0, 1.0 );
for (int i = 0; i < dMaxSearchSteps; i++) { // WebGL port note: Changed while to for
e = texture2D(edgesTex, texCoord, 0.0).rg;
texCoord += vec2(2.0, 0.0) * uTexSizeInv;
if (!(texCoord.x < end && e.g > 0.8281 && e.r == 0.0)) break;
}
texCoord.x -= 0.25 * uTexSizeInv.x;
texCoord.x -= uTexSizeInv.x;
texCoord.x -= 2.0 * uTexSizeInv.x;
texCoord.x += uTexSizeInv.x * SMAASearchLength( searchTex, e, 0.5, 0.5 );
return texCoord.x;
}
float SMAASearchYUp(sampler2D edgesTex, sampler2D searchTex, vec2 texCoord, float end) {
vec2 e = vec2( 1.0, 0.0 );
for (int i = 0; i < dMaxSearchSteps; i++) { // WebGL port note: Changed while to for
e = texture2D(edgesTex, texCoord, 0.0).rg;
texCoord += vec2(0.0, 2.0) * uTexSizeInv; // WebGL port note: Changed sign
if (!(texCoord.y > end && e.r > 0.8281 && e.g == 0.0)) break;
}
texCoord.y -= 0.25 * uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y -= uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y -= 2.0 * uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y += uTexSizeInv.y * SMAASearchLength(searchTex, e.gr, 0.0, 0.5); // WebGL port note: Changed sign
return texCoord.y;
}
float SMAASearchYDown(sampler2D edgesTex, sampler2D searchTex, vec2 texCoord, float end) {
vec2 e = vec2( 1.0, 0.0 );
for (int i = 0; i < dMaxSearchSteps; i++) { // WebGL port note: Changed while to for
e = texture2D(edgesTex, texCoord, 0.0).rg;
texCoord -= vec2( 0.0, 2.0 ) * uTexSizeInv; // WebGL port note: Changed sign
if (!(texCoord.y < end && e.r > 0.8281 && e.g == 0.0)) break;
}
texCoord.y += 0.25 * uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y += uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y += 2.0 * uTexSizeInv.y; // WebGL port note: Changed sign
texCoord.y -= uTexSizeInv.y * SMAASearchLength(searchTex, e.gr, 0.5, 0.5); // WebGL port note: Changed sign
return texCoord.y;
}
vec2 SMAAArea(sampler2D areaTex, vec2 dist, float e1, float e2, float offset) {
// Rounding prevents precision errors of bilinear filtering:
vec2 texCoord = float(SMAA_AREATEX_MAX_DISTANCE) * round(4.0 * vec2(e1, e2)) + dist;
// We do a scale and bias for mapping to texel space:
texCoord = SMAA_AREATEX_PIXEL_SIZE * texCoord + (0.5 * SMAA_AREATEX_PIXEL_SIZE);
// Move to proper place, according to the subpixel offset:
texCoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
return texture2D(areaTex, texCoord, 0.0).rg;
}
vec4 SMAABlendingWeightCalculationPS(vec2 texCoord, vec2 pixCoord, vec4 offset[3], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices) {
vec4 weights = vec4(0.0, 0.0, 0.0, 0.0);
vec2 e = texture2D(edgesTex, texCoord).rg;
if (e.g > 0.0) { // Edge at north
vec2 d;
// Find the distance to the left:
vec2 coords;
coords.x = SMAASearchXLeft(edgesTex, searchTex, offset[0].xy, offset[2].x );
coords.y = offset[1].y; // offset[1].y = texCoord.y - 0.25 * uTexSizeInv.y (@CROSSING_OFFSET)
d.x = coords.x;
// Now fetch the left crossing edges, two at a time using bilinear
// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
// discern what value each edge has:
float e1 = texture2D(edgesTex, coords, 0.0).r;
// Find the distance to the right:
coords.x = SMAASearchXRight(edgesTex, searchTex, offset[0].zw, offset[2].y);
d.y = coords.x;
// We want the distances to be in pixel units (doing this here allow to
// better interleave arithmetic and memory accesses):
d = d / uTexSizeInv.x - pixCoord.x;
// SMAAArea below needs a sqrt, as the areas texture is compressed
// quadratically:
vec2 sqrt_d = sqrt(abs(d));
// Fetch the right crossing edges:
coords.y -= 1.0 * uTexSizeInv.y; // WebGL port note: Added
float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, ivec2(1, 0)).r;
// Ok, we know how this pattern looks like, now it is time for getting
// the actual area:
weights.rg = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.y));
}
if (e.r > 0.0) { // Edge at west
vec2 d;
// Find the distance to the top:
vec2 coords;
coords.y = SMAASearchYUp(edgesTex, searchTex, offset[1].xy, offset[2].z );
coords.x = offset[0].x; // offset[1].x = texCoord.x - 0.25 * uTexSizeInv.x;
d.x = coords.y;
// Fetch the top crossing edges:
float e1 = texture2D(edgesTex, coords, 0.0).g;
// Find the distance to the bottom:
coords.y = SMAASearchYDown(edgesTex, searchTex, offset[1].zw, offset[2].w);
d.y = coords.y;
// We want the distances to be in pixel units:
d = d / uTexSizeInv.y - pixCoord.y;
// SMAAArea below needs a sqrt, as the areas texture is compressed
// quadratically:
vec2 sqrt_d = sqrt(abs(d));
// Fetch the bottom crossing edges:
coords.y -= 1.0 * uTexSizeInv.y; // WebGL port note: Added
float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, ivec2(0, 1)).g;
// Get the area for this direction:
weights.ba = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.x));
}
return weights;
}
void main() {
gl_FragColor = SMAABlendingWeightCalculationPS(vUv, vPixCoord, vOffset, tEdges, tArea, tSearch, ivec4(0.0));
}
`;