Skip to content

Commit

Permalink
feat: convert built-in types to webgl (#929)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarthificial committed Feb 3, 2024
1 parent 849216e commit a0f0b7d
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 11 deletions.
2 changes: 2 additions & 0 deletions packages/2d/src/lib/components/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,8 @@ export class Node implements Promisable<Node> {
const value = unwrap(uniform);
if (typeof value === 'number') {
gl.uniform1f(location, value);
} else if ('toUniform' in value) {
value.toUniform(gl, location);
} else if (value.length === 1) {
gl.uniform1f(location, value[0]);
} else if (value.length === 2) {
Expand Down
3 changes: 2 additions & 1 deletion packages/2d/src/lib/partials/ShaderConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
SignalValue,
useLogger,
useScene,
WebGLConvertible,
} from '@motion-canvas/core';
import {Node} from '../components';

Expand Down Expand Up @@ -60,7 +61,7 @@ export interface ShaderConfig {
* uniform vec3 my_vector;
* ```
*/
uniforms?: Record<string, SignalValue<number | number[]>>;
uniforms?: Record<string, SignalValue<number | number[] | WebGLConvertible>>;

/**
* A custom hook run before the shader is used.
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/types/BBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {CompoundSignal, CompoundSignalContext, SignalValue} from '../signals';
import {InterpolationFunction, arcLerp, map} from '../tweening';
import {PossibleMatrix2D} from './Matrix2D';
import {Spacing} from './Spacing';
import {Type} from './Type';
import {Type, WebGLConvertible} from './Type';
import {Vector2} from './Vector';

export type SerializedBBox = {
Expand All @@ -25,7 +25,7 @@ export type RectSignal<T> = CompoundSignal<
T
>;

export class BBox implements Type {
export class BBox implements Type, WebGLConvertible {
public static readonly symbol = Symbol.for('@motion-canvas/core/types/Rect');

public x = 0;
Expand Down Expand Up @@ -342,6 +342,13 @@ export class BBox implements Type {
return `BBox(${this.x}, ${this.y}, ${this.width}, ${this.height})`;
}

public toUniform(
gl: WebGL2RenderingContext,
location: WebGLUniformLocation,
): void {
gl.uniform4f(location, this.x, this.y, this.width, this.height);
}

public serialize(): SerializedBBox {
return {x: this.x, y: this.y, width: this.width, height: this.height};
}
Expand Down
12 changes: 10 additions & 2 deletions packages/core/src/types/Color.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Color, ColorSpace, InterpolationMode, mix} from 'chroma-js';
import {Signal, SignalContext, SignalValue} from '../signals';
import type {InterpolationFunction} from '../tweening';
import type {Type} from './Type';
import type {Type, WebGLConvertible} from './Type';

export type SerializedColor = string;

Expand All @@ -14,7 +14,7 @@ export type PossibleColor =
export type ColorSignal<T> = Signal<PossibleColor, Color, T>;

declare module 'chroma-js' {
interface Color extends Type {
interface Color extends Type, WebGLConvertible {
serialize(): string;
lerp(
to: ColorInterface | string,
Expand Down Expand Up @@ -108,6 +108,14 @@ const ExtendedColor: typeof Color = (() => {
return Color.symbol;
};

Color.prototype.toUniform = function (
this: Color,
gl: WebGL2RenderingContext,
location: WebGLUniformLocation,
): void {
gl.uniform4fv(location, this.gl());
};

Color.prototype.serialize = function (this: Color): SerializedColor {
return this.css();
};
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/types/Matrix2D.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {DEG2RAD} from '../utils';
import {EPSILON, Type} from './Type';
import {EPSILON, Type, WebGLConvertible} from './Type';
import {PossibleVector2, Vector2} from './Vector';

export type PossibleMatrix2D =
Expand Down Expand Up @@ -30,7 +30,7 @@ export type PossibleMatrix2D =
* - (rA)^-1 = r^-1 A^-1, r != 0 does not hold for a Matrix2D
* - r(AB) = (rA)B = A(rB) does not hold for a Matrix2D
*/
export class Matrix2D implements Type {
export class Matrix2D implements Type, WebGLConvertible {
public static readonly symbol = Symbol.for(
'@motion-canvas/core/types/Matrix2D',
);
Expand Down Expand Up @@ -691,6 +691,13 @@ export class Matrix2D implements Type {
return Matrix2D.symbol;
}

public toUniform(
gl: WebGL2RenderingContext,
location: WebGLUniformLocation,
): void {
gl.uniformMatrix3x2fv(location, false, this.values);
}

public equals(other: Matrix2D, threshold: number = EPSILON): boolean {
return (
Math.abs(this.values[0] - other.values[0]) <=
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/types/Spacing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {CompoundSignal, CompoundSignalContext, SignalValue} from '../signals';
import {InterpolationFunction, map} from '../tweening';
import {Type} from './Type';
import {Type, WebGLConvertible} from './Type';

export type SerializedSpacing = {
top: number;
Expand All @@ -24,7 +24,7 @@ export type SpacingSignal<T> = CompoundSignal<
T
>;

export class Spacing implements Type {
export class Spacing implements Type, WebGLConvertible {
public static readonly symbol = Symbol.for(
'@motion-canvas/core/types/Spacing',
);
Expand Down Expand Up @@ -130,6 +130,13 @@ export class Spacing implements Type {
return `Spacing(${this.top}, ${this.right}, ${this.bottom}, ${this.left})`;
}

public toUniform(
gl: WebGL2RenderingContext,
location: WebGLUniformLocation,
): void {
gl.uniform4f(location, this.top, this.right, this.bottom, this.left);
}

public serialize(): SerializedSpacing {
return {
top: this.top,
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/types/Type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export interface Type {
toSymbol(): symbol;
}

export interface WebGLConvertible {
toUniform(gl: WebGL2RenderingContext, location: WebGLUniformLocation): void;
}

export function isType(value: any): value is Type {
return value && typeof value === 'object' && 'toSymbol' in value;
}
11 changes: 9 additions & 2 deletions packages/core/src/types/Vector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {clamp, map} from '../tweening/interpolationFunctions';
import {DEG2RAD, RAD2DEG} from '../utils';
import {Matrix2D, PossibleMatrix2D} from './Matrix2D';
import {Direction, Origin} from './Origin';
import {EPSILON, Type} from './Type';
import {EPSILON, Type, WebGLConvertible} from './Type';

export type SerializedVector2<T = number> = {
x: T;
Expand All @@ -35,7 +35,7 @@ export type SimpleVector2Signal<T> = Signal<PossibleVector2, Vector2, T>;
/**
* Represents a two-dimensional vector.
*/
export class Vector2 implements Type {
export class Vector2 implements Type, WebGLConvertible {
public static readonly symbol = Symbol.for(
'@motion-canvas/core/types/Vector2',
);
Expand Down Expand Up @@ -481,6 +481,13 @@ export class Vector2 implements Type {
return `Vector2(${this.x}, ${this.y})`;
}

public toUniform(
gl: WebGL2RenderingContext,
location: WebGLUniformLocation,
): void {
gl.uniform2f(location, this.x, this.y);
}

public serialize(): SerializedVector2 {
return {x: this.x, y: this.y};
}
Expand Down

0 comments on commit a0f0b7d

Please sign in to comment.