Skip to content

Instantly share code, notes, and snippets.

@SableRaf
Created November 26, 2020 22:32
Show Gist options
  • Save SableRaf/bd9ba0f1687930404b006d713fed13e8 to your computer and use it in GitHub Desktop.
Save SableRaf/bd9ba0f1687930404b006d713fed13e8 to your computer and use it in GitHub Desktop.
Sohail Mehra – Spark AR Scripting - Ep 4 - Box Blur (updated for Spark AR Studio v102)
// Changes from the original tutorial by Sohail Mehra:
// - updated to work with the async API: loading assets using Promises
// - renamed some variables and broke down the blur calculation in smaller steps:
// - "blend_color" becomes "colorAccumulator"
// - "blurUV" becomes "sampleUV"
// - "pixelWH" becomes "clusterSize"
// - added "clusterWidth" and "clusterHeight"
// - added "sampleOffset" and "averageColor"
const S = require('Shaders');
const M = require('Materials');
const T = require('Textures');
const R = require('Reactive');
const D = require('Diagnostics');
const Scene = require('Scene');
const Time = require('Time');
async function boxBlur(tex, uv, steps, strength)
{
// Calculate the size of our pixel cluster
const clusterWidth = R.mul(R.div(1.0,canvas.width),strength);
const clusterHeight = R.mul(R.div(1.0, canvas.height),strength);
const clusterSize = R.pack2(clusterWidth, clusterHeight);
// Go through the pixel cluster to sample
// the color values and add them together
const iterStep = Math.floor(steps / 2.0);
let colorAccumulator = R.pack4(0,0,0,0);
for (let i = -iterStep; i <= iterStep; i++)
{
for (let j = -iterStep; j <= iterStep; j++)
{
const sampleOffset = R.mul(R.pack2(i,j), clusterSize);
const sampleUV = R.add(uv,sampleOffset);
const sampleColor = S.textureSampler(tex, sampleUV);
colorAccumulator = R.add(sampleColor, colorAccumulator);
}
}
// Average the color to get the blur value for the center pixel
const numSamples = steps*steps;
const averageColor = R.div(colorAccumulator, numSamples);
return averageColor;
}
// Load assets into an array
let defaultMat, cameraTex, canvas;
Promise.all([
M.findFirst('material0'),
T.findFirst('cameraTexture0'),
Scene.root.findFirst('canvas0')
]).then(main).catch(); // pass the assets to the main() function
async function main(assets)
{
// unpack assets from our array
defaultMat = assets[0];
cameraTex = assets[1];
canvas = assets[2];
// Vertex shader
const uv = S.vertexAttribute({"variableName" : S.VertexAttribute.TEX_COORDS});
// Fragment shader
const fuv = S.fragmentStage(uv);
const camTex = cameraTex.signal;
const curve = R.abs(R.sin(R.mul(Time.ms,0.001)));
const finalColor = await boxBlur(camTex, fuv, 9, R.add(1.0,curve));
// Output
const textureSlot = S.DefaultMaterialTextures.DIFFUSE;
defaultMat.setTextureSlot(textureSlot, finalColor);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment