90 lines
2.6 KiB
Text
90 lines
2.6 KiB
Text
|
|
// Fragment shader for tilt-shift effect
|
||
|
|
// Applies gradient blur based on distance from focus line
|
||
|
|
|
||
|
|
#extension GL_OES_EGL_image_external : require
|
||
|
|
|
||
|
|
precision mediump float;
|
||
|
|
|
||
|
|
// Camera texture (external texture for camera preview)
|
||
|
|
uniform samplerExternalOES uTexture;
|
||
|
|
|
||
|
|
// Effect parameters
|
||
|
|
uniform float uAngle; // Rotation angle in radians
|
||
|
|
uniform float uPosition; // Center position of focus (0-1)
|
||
|
|
uniform float uSize; // Size of in-focus region (0-1)
|
||
|
|
uniform float uBlurAmount; // Maximum blur intensity (0-1)
|
||
|
|
uniform vec2 uResolution; // Texture resolution for proper sampling
|
||
|
|
|
||
|
|
varying vec2 vTexCoord;
|
||
|
|
|
||
|
|
// Blur kernel size (must be odd)
|
||
|
|
const int KERNEL_SIZE = 9;
|
||
|
|
const float KERNEL_HALF = 4.0;
|
||
|
|
|
||
|
|
// Gaussian weights for 9-tap blur (sigma ~= 2.0)
|
||
|
|
const float weights[9] = float[](
|
||
|
|
0.0162, 0.0540, 0.1216, 0.1933, 0.2258,
|
||
|
|
0.1933, 0.1216, 0.0540, 0.0162
|
||
|
|
);
|
||
|
|
|
||
|
|
// Calculate signed distance from the focus line
|
||
|
|
float focusDistance(vec2 uv) {
|
||
|
|
// Rotate coordinate system around center
|
||
|
|
vec2 center = vec2(0.5, uPosition);
|
||
|
|
vec2 rotated = uv - center;
|
||
|
|
|
||
|
|
float cosA = cos(uAngle);
|
||
|
|
float sinA = sin(uAngle);
|
||
|
|
|
||
|
|
// After rotation, measure vertical distance from center line
|
||
|
|
float rotatedY = -rotated.x * sinA + rotated.y * cosA;
|
||
|
|
|
||
|
|
return abs(rotatedY);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate blur factor based on distance from focus
|
||
|
|
float blurFactor(float dist) {
|
||
|
|
// Smooth transition from in-focus to blurred
|
||
|
|
float halfSize = uSize * 0.5;
|
||
|
|
float transitionSize = halfSize * 0.5;
|
||
|
|
|
||
|
|
if (dist < halfSize) {
|
||
|
|
return 0.0; // In focus region
|
||
|
|
}
|
||
|
|
|
||
|
|
// Smooth falloff using smoothstep
|
||
|
|
float normalizedDist = (dist - halfSize) / transitionSize;
|
||
|
|
return smoothstep(0.0, 1.0, normalizedDist) * uBlurAmount;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Sample with Gaussian blur
|
||
|
|
vec4 sampleBlurred(vec2 uv, float blur) {
|
||
|
|
if (blur < 0.01) {
|
||
|
|
return texture2D(uTexture, uv);
|
||
|
|
}
|
||
|
|
|
||
|
|
vec4 color = vec4(0.0);
|
||
|
|
vec2 texelSize = 1.0 / uResolution;
|
||
|
|
|
||
|
|
// Blur direction perpendicular to focus line
|
||
|
|
float blurAngle = uAngle + 1.5707963; // +90 degrees
|
||
|
|
vec2 blurDir = vec2(cos(blurAngle), sin(blurAngle));
|
||
|
|
|
||
|
|
// Scale blur radius by blur amount
|
||
|
|
float radius = blur * 20.0;
|
||
|
|
|
||
|
|
for (int i = 0; i < KERNEL_SIZE; i++) {
|
||
|
|
float offset = (float(i) - KERNEL_HALF);
|
||
|
|
vec2 samplePos = uv + blurDir * texelSize * offset * radius;
|
||
|
|
color += texture2D(uTexture, samplePos) * weights[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
return color;
|
||
|
|
}
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
float dist = focusDistance(vTexCoord);
|
||
|
|
float blur = blurFactor(dist);
|
||
|
|
|
||
|
|
gl_FragColor = sampleBlurred(vTexCoord, blur);
|
||
|
|
}
|