lingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
182 lines (137 loc) • 6.04 kB
JavaScript
export default `// a basic shader to implement temporal resolving
uniform sampler2D inputTexture;
uniform sampler2D accumulatedTexture;
uniform sampler2D velocityTexture;
uniform sampler2D lastVelocityTexture;
uniform float blend;
uniform float correction;
uniform float exponent;
uniform vec2 invTexSize;
uniform mat4 curInverseProjectionMatrix;
uniform mat4 curCameraMatrixWorld;
uniform mat4 prevInverseProjectionMatrix;
uniform mat4 prevCameraMatrixWorld;
varying vec2 vUv;
vec3 transformexponent;
vec3 undoColorTransformExponent;
// idea from: https://www.elopezr.com/temporal-aa-and-the-quest-for-the-holy-trail/
vec3 transformColor(vec3 color) {
if (exponent == 1.0) return color;
return pow(abs(color), transformexponent);
}
vec3 undoColorTransform(vec3 color) {
if (exponent == 1.0) return color;
return max(pow(abs(color), undoColorTransformExponent), vec3(0.0));
}
void main() {
if (exponent != 1.0) {
transformexponent = vec3(1.0 / exponent);
undoColorTransformExponent = vec3(exponent);
}
vec4 inputTexel = textureLod(inputTexture, vUv, 0.0);
vec4 accumulatedTexel;
vec3 inputColor = transformColor(inputTexel.rgb);
vec3 accumulatedColor;
float alpha = inputTexel.a;
// REPROJECT_START
float velocityDisocclusion;
bool didReproject = false;
vec3 boxBlurredColor = inputTexel.rgb;
vec4 velocity = textureLod(velocityTexture, vUv, 0.0);
bool isMoving = alpha < 1.0 || dot(velocity.xy, velocity.xy) > 0.0;
if (isMoving) {
vec3 minNeighborColor = inputColor;
vec3 maxNeighborColor = inputColor;
vec3 col;
vec2 neighborUv;
vec2 reprojectedUv = vUv - velocity.xy;
vec4 lastVelocity = textureLod(lastVelocityTexture, reprojectedUv, 0.0);
float depth = velocity.b;
float closestDepth = depth;
float lastClosestDepth = lastVelocity.b;
float neighborDepth;
float lastNeighborDepth;
for (int x = -correctionRadius; x <= correctionRadius; x++) {
for (int y = -correctionRadius; y <= correctionRadius; y++) {
if (x != 0 || y != 0) {
neighborUv = vUv + vec2(x, y) * invTexSize;
vec4 neigborVelocity = textureLod(velocityTexture, neighborUv, 0.0);
neighborDepth = neigborVelocity.b;
col = textureLod(inputTexture, neighborUv, 0.0).xyz;
int absX = abs(x);
int absY = abs(y);
if (absX == 1 && absY == 1) {
if (neighborDepth > closestDepth) {
velocity = neigborVelocity;
closestDepth = neighborDepth;
}
vec4 lastNeighborVelocity = textureLod(velocityTexture, vUv + vec2(x, y) * invTexSize, 0.0);
lastNeighborDepth = lastNeighborVelocity.b;
if (neighborDepth > closestDepth) {
lastVelocity = lastNeighborVelocity;
lastClosestDepth = lastNeighborDepth;
}
}
// the neighbor pixel is invalid if it's too far away from this pixel
if (abs(depth - neighborDepth) < MAX_NEIGHBOR_DEPTH_DIFFERENCE) {
if (absX <= 2 && absY <= 2) boxBlurredColor += col;
col = transformColor(col);
minNeighborColor = min(col, minNeighborColor);
maxNeighborColor = max(col, maxNeighborColor);
}
}
}
}
// velocity
float velocityLength = length(lastVelocity.xy - velocity.xy);
// using the velocity to find disocclusions
velocityDisocclusion = (velocityLength - 0.000005) * 10.0;
velocityDisocclusion *= velocityDisocclusion;
reprojectedUv = vUv - velocity.xy;
// box blur
// box blur
float pxRadius = correctionRadius > 5 ? 121.0 : pow(float(correctionRadius * 2 + 1), 2.0);
boxBlurredColor /= pxRadius;
boxBlurredColor = transformColor(boxBlurredColor);
// the reprojected UV coordinates are inside the view
if (reprojectedUv.x >= 0.0 && reprojectedUv.x <= 1.0 && reprojectedUv.y >= 0.0 && reprojectedUv.y <= 1.0) {
accumulatedTexel = textureLod(accumulatedTexture, reprojectedUv, 0.0);
accumulatedColor = transformColor(accumulatedTexel.rgb);
vec3 clampedColor = clamp(accumulatedColor, minNeighborColor, maxNeighborColor);
accumulatedColor = mix(accumulatedColor, clampedColor, correction);
didReproject = true;
} else {
// reprojected UV coordinates are outside of screen
accumulatedColor = boxBlurredColor;
accumulatedColor = inputColor;
}
// this texel is marked as constantly moving (e.g. from a VideoTexture), so treat it accordingly
if (velocity.r > FLOAT_ONE_MINUS_EPSILON && velocity.g > FLOAT_ONE_MINUS_EPSILON) {
alpha = 0.0;
velocityDisocclusion = 1.0;
}
} else {
// there was no need to do neighborhood clamping, let's re-use the accumulated texel from the same UV coordinate
accumulatedColor = transformColor(textureLod(accumulatedTexture, vUv, 0.0).rgb);
}
// REPROJECT_END
vec3 outputColor = inputColor;
// the user's shader to compose a final outputColor from the inputTexel and accumulatedTexel
gl_FragColor = vec4(undoColorTransform(outputColor), alpha);
}`;
//# sourceMappingURL=temporalResolve.js.map