-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayers.ts
108 lines (95 loc) · 2.81 KB
/
layers.ts
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
99
100
101
102
103
104
105
106
107
108
import * as GL from 'luma.gl/constants'
import { withParameters, Texture2D, Framebuffer } from 'luma.gl'
import { Cell, Seed, Pattern } from './loop'
import Shader from './shader'
import { GLContext, Stage } from './contexts'
export type Layer = {
output?: Texture2D
opacity?: number
destination?: Framebuffer
additive?: boolean
}
const STAGE_SHADER = Shader({
vs: `
attribute vec3 aPosition;
varying vec3 vPosition;
void main() {
vPosition = (aPosition + vec3(1.0, 1.0, 0.0)) / 2.0;
gl_Position = vec4(aPosition, 1.0);
}
`,
fs: `
precision highp float;
uniform sampler2D uColor;
varying vec3 vPosition;
uniform float uOpacity;
void main() {
gl_FragColor = vec4(texture2D(uColor, vec2(vPosition)).rgb, uOpacity);
}
`,
})
const getTexture = (cell: Cell, val: any) => {
if (!val) return val
if (val instanceof Pattern) return getTexture(cell, cell.read(val))
if (val instanceof Texture2D) return val
if (val instanceof Framebuffer) return val.color
return getTexture(cell, val.output)
}
export default function Layers(layers: Layer[], cell?: Cell) {
if (!cell) return Seed(Layers, layers)
const gl = cell.read(GLContext)
const aPosition = cell.read(Stage.aPosition)
const uCount = cell.read(Stage.uCount)
const stage = cell.read(STAGE_SHADER)
if (!gl || !aPosition || !stage) return
stage.vertexArray.setAttributes({ aPosition })
const last = layers[layers.length - 1]
let framebuffer = undefined
let blendFunc = [GL.SRC_ALPHA, GL.DST_ALPHA]
let viewport = [0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight]
if (last && last.destination) {
framebuffer = last.destination
viewport = [0, 0, framebuffer.width, framebuffer.height]
}
if (last && last.additive)
blendFunc = [GL.ONE, GL.ONE]
withParameters(gl, {
[GL.BLEND]: true,
blendFunc,
framebuffer
}, () => {
// TODO: Invalidate framebuffers when we draw to
// avoid having to do this.
cell.invalidate()
gl.clear(GL.COLOR_BUFFER_BIT)
let i = layers.length; while (i --> 0) {
const input = layers[i]
const layer = cell.read(input)
if (!layer) continue
const uColor = getTexture(cell, layer)
if (!uColor) continue
const uOpacity =
typeof input.opacity === 'number'
? input.opacity
:
input['props'] && typeof input['props']['opacity'] === 'number'
? input['props']['opacity']
:
typeof layer.opacity === 'number'
? layer.opacity
:
1.0
gl.viewport(...viewport)
stage.program.draw({
vertexArray: stage.vertexArray,
vertexCount: uCount,
drawMode: GL.TRIANGLE_STRIP,
uniforms: {
uColor,
uOpacity,
}
})
}
})
return framebuffer
}