@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
59 lines (42 loc) • 1.78 kB
JavaScript
import LineBuilder from "../../../../../core/codegen/LineBuilder.js";
import { gaussian } from "../../../../../core/math/gaussian.js";
/**
* Pre-build kernel internally, no branches in convolution code, everything is inlined
* @param {number} samples
* @param {number} distance
* @returns {string}
*/
export function makeGaussianBlurShader({ samples = 5, distance = samples }) {
const kernel_size = samples * samples;
const sigma = (kernel_size - 1) / 6;
const lb = new LineBuilder();
lb.add('uniform vec2 resolution;');
lb.add('uniform sampler2D tDiffuse;');
lb.add('uniform sampler2D tMask;');
lb.add('varying vec2 vUv;');
const half_samples = (samples / 2) | 0;
lb.add('void main(){');
lb.indent();
lb.add('if( texture2D(tMask, vUv).x < 1.0){ gl_FragColor = vec4(0.0); return; }');
lb.add('vec2 pixel_uv = 1.0 / resolution;')
lb.add('vec4 accumulator;')
const scale_x = (distance / samples);
const scale_y = (distance / samples);
// prepare samples
let total_value = 0;
for (let iy = 0; iy < samples; iy++) {
const fy = gaussian(sigma, iy - half_samples);
const offset_y = (iy - half_samples) * scale_y;
for (let ix = 0; ix < samples; ix++) {
const fx = gaussian(sigma, ix - half_samples);
const offset_x = (ix - half_samples) * scale_x;
const value = fx * fy;
total_value += value;
lb.add(`accumulator += texture2D(tDiffuse, vUv + vec2(float(${offset_x}), float(${offset_y})) * pixel_uv) * float(${value});`);
}
}
lb.add(`gl_FragColor = accumulator / ${total_value};`);
lb.dedent();
lb.add('}');
return lb.build();
}