forked from spleennooname/sparkar-procedural-pattern
-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
98 lines (89 loc) · 2.89 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* Procedural texture with SparkAR Reactive Script (v85+)
* an example by Andrea Bovo <https://github.com/spleennooname>
*/
// modules
const R = require('Reactive')
const Time = require('Time')
const M = require('Materials')
const T = require('Textures')
const Shaders = require('Shaders')
// const CameraInfo = require('CameraInfo')
// rotate: uv coords and angle(radians, of course)
const rotate2d = (uv, angle) => {
const cos = Math.cos(angle)
const sin = Math.sin(angle)
uv = R.pack2(
R.add(
uv.x.mul(cos),
uv.y.mul(sin)
),
R.sub(
uv.y.mul(cos),
uv.x.mul(sin)
)
)
return uv
}
// get a correct grey-scale value from texture sample
const luma = sample => {
const l = R.dot(R.pack4(0.299, 0.587, 0.114, 1), R.pack4(sample.x, sample.y, sample.z, sample.w))
return R.pack4(l, l, l, sample.w)
}
// main stuff
Promise.all([
M.findFirst('cameraMat'),
T.findFirst('cameraTexture0'),
T.findFirst('gold')
])
.then(assets => {
// material
const cameraMaterial = assets[0]
const cameraSignal = assets[1].signal
const matSignal = assets[2].signal
// uv
const uv = Shaders.fragmentStage(Shaders.vertexAttribute({
variableName: Shaders.VertexAttribute.TEX_COORDS
}))
const time = Time.ms.mul(0.01)
// play with params ;)
const levels = 5.7
const angle = Math.PI / levels
const spacing = 0.014
const alias = 0.0025
const height = 0.005
const bright = 0.1
const width = 0.005
const dist = 0.10
// create a procedural pattern.
const pattern = (color, uv, time) => {
let result = R.pack4(1, 1, 1, 1)
const sample = luma(Shaders.textureSampler(color, uv))
for (let i = 0, nuv, wave, x, y, line, waves; i < levels; i += 1.0) {
nuv = rotate2d(uv, angle + angle * i)
wave = R.sin(nuv.x.mul(frequency)).mul(height)
x = wave.sum((spacing * 0.85))
y = R.mod(nuv.y, spacing)
line = (R.val(0.9).sub(sample.mul(bright)).sub(i * dist)).mul(width)
waves = R.smoothStep(line, line.sum(alias), R.abs(x.sub(y)))
result = result.sum(waves)
}
result = result.div(levels)
result = R.mix(color, result.mul(color), 0.97)
return R.smoothStep(result, 0.0, 0.95)
}
// play with hardcoded values for change pattern
const displacementFactor = R.val(2.0).add(R.sin(time.mul(0.025)).mul(1.0))
const frequency = R.abs(R.sin(time.mul(0.01)).mul(20))
const render = (signal, uv, time) => {
const patternSignal = pattern(signal, uv, time)
const displacementSignal = luma(Shaders.composition(cameraSignal, uv))
const displacementOffset = R.mul(displacementSignal.y, displacementFactor)
cameraMaterial.setTextureSlot(
Shaders.DefaultMaterialTextures.DIFFUSE,
Shaders.composition(patternSignal, uv.add(displacementOffset))
)
}
// render things
render(matSignal, uv, time)
})