Created
November 26, 2020 22:32
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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