@remotion/effects 4.0.468 → 4.0.470

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ export declare const dotGridSchema: {
2
+ readonly dotSize: {
3
+ readonly type: "number";
4
+ readonly min: 0;
5
+ readonly max: 400;
6
+ readonly step: 1;
7
+ readonly default: 16;
8
+ readonly description: "Dot size";
9
+ };
10
+ readonly gridSize: {
11
+ readonly type: "number";
12
+ readonly min: 1;
13
+ readonly max: 400;
14
+ readonly step: 1;
15
+ readonly default: 20;
16
+ readonly description: "Grid size";
17
+ };
18
+ readonly invert: {
19
+ readonly type: "boolean";
20
+ readonly default: false;
21
+ readonly description: "Invert";
22
+ };
23
+ };
24
+ export type DotGridParams = {
25
+ readonly dotSize?: number;
26
+ readonly gridSize?: number;
27
+ readonly invert?: boolean;
28
+ };
29
+ export declare const dotGrid: (params?: (DotGridParams & {
30
+ readonly disabled?: boolean | undefined;
31
+ }) | undefined) => import("remotion").EffectDescriptor<unknown>;
@@ -0,0 +1,54 @@
1
+ import type { ParsedColorRgba } from '../color-utils.js';
2
+ export type DropShadowState = {
3
+ readonly gl: WebGL2RenderingContext;
4
+ readonly programExtract: WebGLProgram;
5
+ readonly programHorizontal: WebGLProgram;
6
+ readonly programVertical: WebGLProgram;
7
+ readonly programComposite: WebGLProgram;
8
+ readonly vao: WebGLVertexArrayObject;
9
+ readonly vbo: WebGLBuffer;
10
+ readonly textureSource: WebGLTexture;
11
+ readonly textureShadowA: WebGLTexture;
12
+ readonly textureShadowB: WebGLTexture;
13
+ readonly framebuffer: WebGLFramebuffer;
14
+ readonly extract: {
15
+ readonly uSource: WebGLUniformLocation | null;
16
+ readonly uColor: WebGLUniformLocation | null;
17
+ readonly uOpacity: WebGLUniformLocation | null;
18
+ };
19
+ readonly horizontal: {
20
+ readonly uRadius: WebGLUniformLocation | null;
21
+ readonly uTexelSize: WebGLUniformLocation | null;
22
+ readonly uSource: WebGLUniformLocation | null;
23
+ };
24
+ readonly vertical: {
25
+ readonly uRadius: WebGLUniformLocation | null;
26
+ readonly uTexelSize: WebGLUniformLocation | null;
27
+ readonly uSource: WebGLUniformLocation | null;
28
+ };
29
+ readonly composite: {
30
+ readonly uSource: WebGLUniformLocation | null;
31
+ readonly uShadow: WebGLUniformLocation | null;
32
+ readonly uOffset: WebGLUniformLocation | null;
33
+ readonly uTexelSize: WebGLUniformLocation | null;
34
+ };
35
+ readonly colorCtx: CanvasRenderingContext2D;
36
+ cachedColorStr: string;
37
+ cachedColorRgba: ParsedColorRgba;
38
+ };
39
+ export declare const setupDropShadow: (target: HTMLCanvasElement) => DropShadowState;
40
+ export declare const cleanupDropShadow: ({ gl, programExtract, programHorizontal, programVertical, programComposite, vao, vbo, textureSource, textureShadowA, textureShadowB, framebuffer, }: DropShadowState) => void;
41
+ type ApplyDropShadowParams = {
42
+ readonly state: DropShadowState;
43
+ readonly source: CanvasImageSource;
44
+ readonly width: number;
45
+ readonly height: number;
46
+ readonly radius: number;
47
+ readonly offsetX: number;
48
+ readonly offsetY: number;
49
+ readonly opacity: number;
50
+ readonly color: ParsedColorRgba;
51
+ readonly flipSourceY: boolean;
52
+ };
53
+ export declare const applyDropShadow: ({ state, source, width, height, radius, offsetX, offsetY, opacity, color, flipSourceY, }: ApplyDropShadowParams) => void;
54
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare const DROP_SHADOW_VS = "#version 300 es\nlayout(location = 0) in vec2 aPos;\nlayout(location = 1) in vec2 aUv;\nout vec2 vUv;\n\nvoid main() {\n\tvUv = aUv;\n\tgl_Position = vec4(aPos, 0.0, 1.0);\n}\n";
2
+ export declare const DROP_SHADOW_EXTRACT_FS = "#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform sampler2D uSource;\nuniform vec4 uColor;\nuniform float uOpacity;\n\nvoid main() {\n\tvec4 source = texture(uSource, vUv);\n\tfloat shadowAlpha = source.a * uColor.a * clamp(uOpacity, 0.0, 1.0);\n\n\tfragColor = vec4(uColor.rgb * shadowAlpha, shadowAlpha);\n}\n";
3
+ export declare const DROP_SHADOW_BLUR_FS_HORIZONTAL: string;
4
+ export declare const DROP_SHADOW_BLUR_FS_VERTICAL: string;
5
+ export declare const DROP_SHADOW_COMPOSITE_FS = "#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform sampler2D uSource;\nuniform sampler2D uShadow;\nuniform vec2 uOffset;\nuniform vec2 uTexelSize;\n\nvoid main() {\n\tvec4 source = texture(uSource, vUv);\n\tvec2 shadowUv = vUv - vec2(uOffset.x, -uOffset.y) * uTexelSize;\n\tvec4 shadow = vec4(0.0);\n\n\tif (\n\t\tshadowUv.x >= 0.0 &&\n\t\tshadowUv.x <= 1.0 &&\n\t\tshadowUv.y >= 0.0 &&\n\t\tshadowUv.y <= 1.0\n\t) {\n\t\tshadow = texture(uShadow, shadowUv);\n\t}\n\n\tfragColor = source + shadow * (1.0 - source.a);\n}\n";
@@ -0,0 +1,15 @@
1
+ export type DropShadowParams = {
2
+ /** Blur radius of the shadow in pixels. Defaults to `12`. */
3
+ readonly radius?: number;
4
+ /** Horizontal shadow offset in pixels. Defaults to `8`. */
5
+ readonly offsetX?: number;
6
+ /** Vertical shadow offset in pixels. Defaults to `8`. */
7
+ readonly offsetY?: number;
8
+ /** Shadow opacity from `0` to `1`. Defaults to `0.5`. */
9
+ readonly opacity?: number;
10
+ /** Color of the shadow. Defaults to black. */
11
+ readonly color?: string;
12
+ };
13
+ export declare const dropShadow: (params?: (DropShadowParams & {
14
+ readonly disabled?: boolean | undefined;
15
+ }) | undefined) => import("remotion").EffectDescriptor<unknown>;
@@ -0,0 +1 @@
1
+ export { dropShadow, type DropShadowParams } from './drop-shadow/index.js';
package/dist/esm/blur.mjs CHANGED
@@ -27,20 +27,12 @@ var assertOptionalColor = (value, name) => {
27
27
  // src/blur/blur-runtime.ts
28
28
  import { Internals } from "remotion";
29
29
 
30
- // src/blur/blur-shaders.ts
31
- var BLUR_VS = `#version 300 es
32
- layout(location = 0) in vec2 aPos;
33
- layout(location = 1) in vec2 aUv;
34
- out vec2 vUv;
35
- void main() {
36
- vUv = aUv;
37
- gl_Position = vec4(aPos, 0.0, 1.0);
38
- }
39
- `;
40
- var buildFs = (direction) => {
30
+ // src/gaussian-blur-shader.ts
31
+ var buildGaussianBlurFs = (direction) => {
41
32
  const dirVec = direction === "horizontal" ? "vec2(1.0, 0.0)" : "vec2(0.0, 1.0)";
42
33
  return `#version 300 es
43
34
  precision highp float;
35
+
44
36
  in vec2 vUv;
45
37
  out vec4 fragColor;
46
38
 
@@ -48,7 +40,9 @@ uniform sampler2D uSource;
48
40
  uniform float uRadius;
49
41
  uniform vec2 uTexelSize;
50
42
 
51
- const int KERNEL_HALF = 4;
43
+ const int MIN_KERNEL_HALF = 4;
44
+ const int MAX_KERNEL_HALF = 32;
45
+ const float TARGET_SAMPLE_DISTANCE_PX = 2.0;
52
46
  const vec2 DIRECTION = ${dirVec};
53
47
 
54
48
  void main() {
@@ -57,14 +51,24 @@ void main() {
57
51
  return;
58
52
  }
59
53
 
60
- float pixelStride = uRadius / float(KERNEL_HALF);
54
+ int kernelHalf = int(
55
+ min(
56
+ float(MAX_KERNEL_HALF),
57
+ max(float(MIN_KERNEL_HALF), ceil(uRadius / TARGET_SAMPLE_DISTANCE_PX))
58
+ )
59
+ );
60
+ float pixelStride = uRadius / float(kernelHalf);
61
61
  float sigma = uRadius / 3.0;
62
62
  float twoSigmaSq = 2.0 * sigma * sigma;
63
63
 
64
64
  vec4 sum = vec4(0.0);
65
65
  float weightSum = 0.0;
66
66
 
67
- for (int i = -KERNEL_HALF; i <= KERNEL_HALF; ++i) {
67
+ for (int i = -MAX_KERNEL_HALF; i <= MAX_KERNEL_HALF; ++i) {
68
+ if (abs(i) > kernelHalf) {
69
+ continue;
70
+ }
71
+
68
72
  float offsetPx = float(i) * pixelStride;
69
73
  float w = exp(-(offsetPx * offsetPx) / twoSigmaSq);
70
74
  vec2 uv = vUv + DIRECTION * uTexelSize * offsetPx;
@@ -76,8 +80,19 @@ void main() {
76
80
  }
77
81
  `;
78
82
  };
79
- var BLUR_FS_HORIZONTAL = buildFs("horizontal");
80
- var BLUR_FS_VERTICAL = buildFs("vertical");
83
+
84
+ // src/blur/blur-shaders.ts
85
+ var BLUR_VS = `#version 300 es
86
+ layout(location = 0) in vec2 aPos;
87
+ layout(location = 1) in vec2 aUv;
88
+ out vec2 vUv;
89
+ void main() {
90
+ vUv = aUv;
91
+ gl_Position = vec4(aPos, 0.0, 1.0);
92
+ }
93
+ `;
94
+ var BLUR_FS_HORIZONTAL = buildGaussianBlurFs("horizontal");
95
+ var BLUR_FS_VERTICAL = buildGaussianBlurFs("vertical");
81
96
 
82
97
  // src/blur/blur-runtime.ts
83
98
  var { createWebGL2ContextError } = Internals;
@@ -0,0 +1,349 @@
1
+ // src/dot-grid.ts
2
+ import { Internals } from "remotion";
3
+
4
+ // src/validate-effect-param.ts
5
+ var assertEffectParamsObject = (params, effectLabel) => {
6
+ if (params === null || typeof params !== "object") {
7
+ throw new TypeError(`${effectLabel} effect requires a parameters object, but got ${JSON.stringify(params)}`);
8
+ }
9
+ };
10
+ var assertRequiredFiniteNumber = (value, name) => {
11
+ if (typeof value !== "number" || !Number.isFinite(value)) {
12
+ throw new TypeError(`"${name}" must be a finite number, but got ${JSON.stringify(value)}`);
13
+ }
14
+ };
15
+ var assertRequiredColor = (value, name) => {
16
+ if (typeof value !== "string" || value.length === 0) {
17
+ throw new TypeError(`"${name}" must be a non-empty string, but got ${JSON.stringify(value)}`);
18
+ }
19
+ };
20
+ var assertOptionalColor = (value, name) => {
21
+ if (value === undefined) {
22
+ return;
23
+ }
24
+ assertRequiredColor(value, name);
25
+ };
26
+
27
+ // src/color-utils.ts
28
+ var DEFAULT_AMOUNT = 1;
29
+ var DEFAULT_BRIGHTNESS_AMOUNT = 0;
30
+ var DEFAULT_HUE_DEGREES = 0;
31
+ var colorAmountSchema = {
32
+ type: "number",
33
+ min: 0,
34
+ max: 1,
35
+ step: 0.01,
36
+ default: DEFAULT_AMOUNT,
37
+ description: "Amount"
38
+ };
39
+ var colorMultiplierSchema = {
40
+ type: "number",
41
+ min: 0,
42
+ step: 0.01,
43
+ default: DEFAULT_AMOUNT,
44
+ description: "Amount"
45
+ };
46
+ var brightnessAmountSchema = {
47
+ type: "number",
48
+ min: -1,
49
+ max: 1,
50
+ step: 0.01,
51
+ default: DEFAULT_BRIGHTNESS_AMOUNT,
52
+ description: "Amount"
53
+ };
54
+ var hueDegreesSchema = {
55
+ type: "number",
56
+ step: 1,
57
+ default: DEFAULT_HUE_DEGREES,
58
+ description: "Degrees"
59
+ };
60
+ var assertOptionalFiniteNumber = (value, name) => {
61
+ if (value === undefined) {
62
+ return;
63
+ }
64
+ assertRequiredFiniteNumber(value, name);
65
+ };
66
+ var validateUnitInterval = (value, name) => {
67
+ if (value < 0) {
68
+ throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
69
+ }
70
+ if (value > 1) {
71
+ throw new TypeError(`"${name}" must be <= 1, but got ${JSON.stringify(value)}`);
72
+ }
73
+ };
74
+ var validateNonNegative = (value, name) => {
75
+ if (value < 0) {
76
+ throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
77
+ }
78
+ };
79
+ var validateSignedUnitInterval = (value, name) => {
80
+ if (value < -1) {
81
+ throw new TypeError(`"${name}" must be >= -1, but got ${JSON.stringify(value)}`);
82
+ }
83
+ if (value > 1) {
84
+ throw new TypeError(`"${name}" must be <= 1, but got ${JSON.stringify(value)}`);
85
+ }
86
+ };
87
+ var clampColorChannel = (value) => {
88
+ return Math.max(0, Math.min(255, value));
89
+ };
90
+ var parseColorRgba = (ctx, color) => {
91
+ ctx.clearRect(0, 0, 1, 1);
92
+ ctx.fillStyle = color;
93
+ ctx.fillRect(0, 0, 1, 1);
94
+ const { data } = ctx.getImageData(0, 0, 1, 1);
95
+ return [data[0], data[1], data[2], data[3]];
96
+ };
97
+
98
+ // src/dot-grid.ts
99
+ var { createEffect, createWebGL2ContextError } = Internals;
100
+ var DEFAULT_DOT_SIZE = 16;
101
+ var DEFAULT_GRID_SIZE = 20;
102
+ var DEFAULT_INVERT = false;
103
+ var dotGridSchema = {
104
+ dotSize: {
105
+ type: "number",
106
+ min: 0,
107
+ max: 400,
108
+ step: 1,
109
+ default: DEFAULT_DOT_SIZE,
110
+ description: "Dot size"
111
+ },
112
+ gridSize: {
113
+ type: "number",
114
+ min: 1,
115
+ max: 400,
116
+ step: 1,
117
+ default: DEFAULT_GRID_SIZE,
118
+ description: "Grid size"
119
+ },
120
+ invert: {
121
+ type: "boolean",
122
+ default: DEFAULT_INVERT,
123
+ description: "Invert"
124
+ }
125
+ };
126
+ var resolve = (p) => ({
127
+ dotSize: p.dotSize ?? DEFAULT_DOT_SIZE,
128
+ gridSize: p.gridSize ?? DEFAULT_GRID_SIZE,
129
+ invert: p.invert ?? DEFAULT_INVERT
130
+ });
131
+ var assertOptionalBoolean = (value, name) => {
132
+ if (value === undefined) {
133
+ return;
134
+ }
135
+ if (typeof value !== "boolean") {
136
+ throw new TypeError(`"${name}" must be a boolean, but got ${JSON.stringify(value)}`);
137
+ }
138
+ };
139
+ var validatePositive = (value, name) => {
140
+ if (value <= 0) {
141
+ throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
142
+ }
143
+ };
144
+ var validateDotGridParams = (params) => {
145
+ assertEffectParamsObject(params, "Dot grid");
146
+ assertOptionalFiniteNumber(params.dotSize, "dotSize");
147
+ assertOptionalFiniteNumber(params.gridSize, "gridSize");
148
+ assertOptionalBoolean(params.invert, "invert");
149
+ if (params.dotSize !== undefined) {
150
+ validateNonNegative(params.dotSize, "dotSize");
151
+ }
152
+ if (params.gridSize !== undefined) {
153
+ validatePositive(params.gridSize, "gridSize");
154
+ }
155
+ };
156
+ var DOT_GRID_VS = `#version 300 es
157
+ in vec2 aPos;
158
+ in vec2 aUv;
159
+ out vec2 vUv;
160
+
161
+ void main() {
162
+ vUv = aUv;
163
+ gl_Position = vec4(aPos, 0.0, 1.0);
164
+ }
165
+ `;
166
+ var DOT_GRID_FS = `#version 300 es
167
+ precision highp float;
168
+
169
+ in vec2 vUv;
170
+ out vec4 fragColor;
171
+
172
+ uniform sampler2D uSource;
173
+ uniform vec2 uResolution;
174
+ uniform float uDotSize;
175
+ uniform float uGridSize;
176
+ uniform bool uInvert;
177
+
178
+ void main() {
179
+ vec2 fragPos = vUv * uResolution;
180
+ vec2 center = uResolution * 0.5;
181
+ vec2 gridPos = fragPos - center;
182
+
183
+ float gridSize = max(uGridSize, 0.001);
184
+ vec2 cellIndex = floor(gridPos / gridSize + 0.5);
185
+ vec2 gridCenter = cellIndex * gridSize;
186
+ vec2 diff = gridPos - gridCenter;
187
+
188
+ float radius = uDotSize * 0.5;
189
+ float dotCoverage = radius <= 0.005
190
+ ? 0.0
191
+ : 1.0 - smoothstep(radius - 0.75, radius + 0.75, length(diff));
192
+ float coverage = uInvert ? 1.0 - dotCoverage : dotCoverage;
193
+
194
+ vec4 texColor = texture(uSource, vUv);
195
+ fragColor = texColor * coverage;
196
+ }
197
+ `;
198
+ var compileShader = (gl, type, source) => {
199
+ const shader = gl.createShader(type);
200
+ if (!shader) {
201
+ throw new Error("Failed to create WebGL shader");
202
+ }
203
+ gl.shaderSource(shader, source);
204
+ gl.compileShader(shader);
205
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
206
+ const log = gl.getShaderInfoLog(shader);
207
+ gl.deleteShader(shader);
208
+ throw new Error(`Dot grid shader compile failed: ${log ?? "(no log)"}`);
209
+ }
210
+ return shader;
211
+ };
212
+ var linkProgram = (gl, vs, fs) => {
213
+ const program = gl.createProgram();
214
+ if (!program) {
215
+ throw new Error("Failed to create WebGL program");
216
+ }
217
+ gl.attachShader(program, vs);
218
+ gl.attachShader(program, fs);
219
+ gl.linkProgram(program);
220
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
221
+ const log = gl.getProgramInfoLog(program);
222
+ gl.deleteProgram(program);
223
+ throw new Error(`Dot grid program link failed: ${log ?? "(no log)"}`);
224
+ }
225
+ return program;
226
+ };
227
+ var dotGrid = createEffect({
228
+ type: "remotion/dot-grid",
229
+ label: "dotGrid()",
230
+ documentationLink: "https://www.remotion.dev/docs/effects/dot-grid",
231
+ backend: "webgl2",
232
+ calculateKey: (params) => {
233
+ const r = resolve(params);
234
+ return `dot-grid-${r.dotSize}-${r.gridSize}-${r.invert ? 1 : 0}`;
235
+ },
236
+ setup: (target) => {
237
+ const gl = target.getContext("webgl2", {
238
+ premultipliedAlpha: true,
239
+ alpha: true,
240
+ preserveDrawingBuffer: true
241
+ });
242
+ if (!gl) {
243
+ throw createWebGL2ContextError("dot grid effect");
244
+ }
245
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
246
+ const vs = compileShader(gl, gl.VERTEX_SHADER, DOT_GRID_VS);
247
+ const fs = compileShader(gl, gl.FRAGMENT_SHADER, DOT_GRID_FS);
248
+ const program = linkProgram(gl, vs, fs);
249
+ gl.deleteShader(vs);
250
+ gl.deleteShader(fs);
251
+ const vao = gl.createVertexArray();
252
+ if (!vao) {
253
+ throw new Error("Failed to create WebGL vertex array");
254
+ }
255
+ gl.bindVertexArray(vao);
256
+ const data = new Float32Array([
257
+ -1,
258
+ -1,
259
+ 0,
260
+ 0,
261
+ 1,
262
+ -1,
263
+ 1,
264
+ 0,
265
+ -1,
266
+ 1,
267
+ 0,
268
+ 1,
269
+ 1,
270
+ 1,
271
+ 1,
272
+ 1
273
+ ]);
274
+ const vbo = gl.createBuffer();
275
+ if (!vbo) {
276
+ throw new Error("Failed to create WebGL buffer");
277
+ }
278
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
279
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
280
+ const aPos = gl.getAttribLocation(program, "aPos");
281
+ const aUv = gl.getAttribLocation(program, "aUv");
282
+ gl.enableVertexAttribArray(aPos);
283
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
284
+ gl.enableVertexAttribArray(aUv);
285
+ gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
286
+ gl.bindVertexArray(null);
287
+ const texture = gl.createTexture();
288
+ if (!texture) {
289
+ throw new Error("Failed to create WebGL texture");
290
+ }
291
+ gl.bindTexture(gl.TEXTURE_2D, texture);
292
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
293
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
294
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
295
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
296
+ gl.bindTexture(gl.TEXTURE_2D, null);
297
+ return {
298
+ gl,
299
+ program,
300
+ vao,
301
+ vbo,
302
+ texture,
303
+ uSource: gl.getUniformLocation(program, "uSource"),
304
+ uResolution: gl.getUniformLocation(program, "uResolution"),
305
+ uDotSize: gl.getUniformLocation(program, "uDotSize"),
306
+ uGridSize: gl.getUniformLocation(program, "uGridSize"),
307
+ uInvert: gl.getUniformLocation(program, "uInvert")
308
+ };
309
+ },
310
+ apply: ({ source, width, height, params, state, flipSourceY }) => {
311
+ const r = resolve(params);
312
+ const { gl, program, vao, texture } = state;
313
+ gl.viewport(0, 0, width, height);
314
+ gl.clearColor(0, 0, 0, 0);
315
+ gl.clear(gl.COLOR_BUFFER_BIT);
316
+ gl.useProgram(program);
317
+ gl.bindVertexArray(vao);
318
+ gl.activeTexture(gl.TEXTURE0);
319
+ gl.bindTexture(gl.TEXTURE_2D, texture);
320
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
321
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
322
+ if (state.uSource)
323
+ gl.uniform1i(state.uSource, 0);
324
+ if (state.uResolution)
325
+ gl.uniform2f(state.uResolution, width, height);
326
+ if (state.uDotSize)
327
+ gl.uniform1f(state.uDotSize, r.dotSize);
328
+ if (state.uGridSize)
329
+ gl.uniform1f(state.uGridSize, r.gridSize);
330
+ if (state.uInvert)
331
+ gl.uniform1i(state.uInvert, r.invert ? 1 : 0);
332
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
333
+ gl.bindVertexArray(null);
334
+ gl.bindTexture(gl.TEXTURE_2D, null);
335
+ gl.useProgram(null);
336
+ },
337
+ cleanup: ({ gl, program, vao, vbo, texture }) => {
338
+ gl.deleteBuffer(vbo);
339
+ gl.deleteProgram(program);
340
+ gl.deleteVertexArray(vao);
341
+ gl.deleteTexture(texture);
342
+ },
343
+ schema: dotGridSchema,
344
+ validateParams: validateDotGridParams
345
+ });
346
+ export {
347
+ dotGridSchema,
348
+ dotGrid
349
+ };