From 58928301049ef0b3249f7844c11d5afee7ad3470 Mon Sep 17 00:00:00 2001
From: Andras Schmelczer When using this, the size of the canvas must be fixed with CSS. The Usage:addDeltaTime method should be called once every frame. const renderer = await compile(...);
const autoscaler = new FpsQualityAutoscaler(renderer);
+ const renderer = await compile(...);
const autoscaler = new FpsQualityAutoscaler(renderer);
Example usage:
- <canvas id="main" style="width: 300px; height: 150px"></canvas>
+ <canvas id="main" style="width: 300px; height: 150px"></canvas>
The canvas needs to have a fixed size specified by CSS.
-import { CircleFactory, CircleLight, hsl, runAnimation } from 'sdf-2d';
const canvas = document.querySelector('canvas');
const Circle = CircleFactory(hsl(180, 100, 40));
runAnimation(canvas, [Circle.descriptor, CircleLight.descriptor], (renderer, time) => {
renderer.addDrawable(
new Circle([150 + 50 * Math.cos(time / 1000), 75 + 50 * Math.sin(time / 1000)], 25)
);
renderer.addDrawable(new CircleLight([150, 75], hsl(270, 100, 40), 0.1));
return true;
});
+import { CircleFactory, CircleLight, hsl, runAnimation } from 'sdf-2d';
const canvas = document.querySelector('canvas');
const Circle = CircleFactory(hsl(180, 100, 40));
runAnimation(canvas, [Circle.descriptor, CircleLight.descriptor], (renderer, time) => {
renderer.addDrawable(
new Circle([150 + 50 * Math.cos(time / 1000), 75 + 50 * Math.sin(time / 1000)], 25)
);
renderer.addDrawable(new CircleLight([150, 75], hsl(270, 100, 40), 0.1));
return true;
});
diff --git a/docs/index.html b/docs/index.html
index 503f9c5..55fbd1f 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -41,6 +41,20 @@ See its documentation fo
Add a static descriptor property of type DrawableDescriptor to your class
Follow the instructions given in Usage
+Custom drawable example
+The function named by sdf.distanceFunctionName must have the signature
+float distanceFunction(in vec2 target, out vec4 color) in both GLSL 100 and GLSL 300 ES.
+It returns the signed distance (negative inside, zero on the boundary, positive outside)
+and writes the closest drawable's RGBA color to color on every code path.
+This complete example defines a custom orange circle, maps its serialized properties
+to shader uniforms, and compiles and renders it. Use it in a JavaScript module with
+sdf-2d and gl-matrix installed. Documentation CI runs this exact code with both
+WebGL 1 and WebGL 2.
+
+import { compile, Drawable } from 'sdf-2d';
import { vec2 } from 'gl-matrix';
class CustomCircle extends Drawable {
constructor(center, radius) {
super();
this.center = center;
this.radius = radius;
}
static descriptor = {
propertyUniformMapping: {
center: 'customCircleCenters',
radius: 'customCircleRadii',
},
uniformCountMacroName: 'CUSTOM_CIRCLE_COUNT',
shaderCombinationSteps: [0, 1, 4],
// Unused array entries are filled with this zero-radius circle and moved away.
empty: new CustomCircle([0, 0], 0),
sdf: {
distanceFunctionName: 'customCircleDistance',
shader: `
uniform vec2 customCircleCenters[CUSTOM_CIRCLE_COUNT];
uniform float customCircleRadii[CUSTOM_CIRCLE_COUNT];
float customCircleDistance(in vec2 target, out vec4 color) {
color = vec4(1.0, 0.25, 0.0, 1.0);
float minDistance = 1000.0;
for (int i = 0; i < CUSTOM_CIRCLE_COUNT; i++) {
float d = distance(target, customCircleCenters[i]) - customCircleRadii[i];
minDistance = min(minDistance, d);
}
return minDistance;
}
`,
},
};
minDistance(target) {
return vec2.distance(this.center, target) - this.radius;
}
getObjectToSerialize(transform2d, transform1d) {
return {
center: vec2.transformMat2d(vec2.create(), this.center, transform2d),
radius: this.radius * transform1d,
};
}
}
const canvas = document.createElement('canvas');
canvas.width = 320;
canvas.height = 240;
document.body.appendChild(canvas);
const renderer = await compile(canvas, [CustomCircle.descriptor]);
renderer.setRuntimeSettings({ ambientLight: [1, 1, 1], motionBlur: 0 });
renderer.addDrawable(new CustomCircle([160, 120], 50));
renderer.renderDrawables();
// Call renderer.destroy() when the renderer is no longer needed.
+
+
+
Useful to know
Math
The vec2, vec3, and vec4 types seen in the documentation come from the glMatrix library and are equivalent to regular JS Arrays or Float32Arrays, so feel free to pass [x, y] to functions that expect a vec2.
@@ -49,11 +63,11 @@ See its documentation fo
Tile-based rendering
To optimise the evaluation of the distance field, the display is divided into a grid of tiles. The shaders for each tile are compiled to support a fixed maximum number of objects. When using the built-in drawables, this means that beyond a certain number of on-screen objects, new ones may stop appearing.
Mitigating this is easy. Instead of the following code:
-this.renderer = await compile(canvas, [Circle.descriptor, CircleLight.descriptor]);
+this.renderer = await compile(canvas, [Circle.descriptor, CircleLight.descriptor]);
modify it to something like this:
-this.renderer = await compile(canvas, [
{
...Circle.descriptor,
shaderCombinationSteps: [0, 1, 2, 24, 64],
},
{
...CircleLight.descriptor,
shaderCombinationSteps: [0, 1, 2, 4],
},
]);
+this.renderer = await compile(canvas, [
{
...Circle.descriptor,
shaderCombinationSteps: [0, 1, 2, 24, 64],
},
{
...CircleLight.descriptor,
shaderCombinationSteps: [0, 1, 2, 4],
},
]);
Using very large numbers is not advised, for both compatibility and performance reasons.
@@ -80,6 +94,9 @@ See its documentation fo
Usage (1st option)
Usage (2nd option)
Extending drawables
+
+
Useful to know
diff --git a/docs/interfaces/drawables_drawable-descriptor.DrawableDescriptor.html b/docs/interfaces/drawables_drawable-descriptor.DrawableDescriptor.html
index 66753ec..b24da15 100644
--- a/docs/interfaces/drawables_drawable-descriptor.DrawableDescriptor.html
+++ b/docs/interfaces/drawables_drawable-descriptor.DrawableDescriptor.html
@@ -16,11 +16,12 @@
shader code.
Each [[Drawable]] must have a static property of this type, called descriptor.
For more information on how to create your own DrawableDescriptors, look at the
-code of [[CircleFactory]] or [[InvertedTunnelFactory]].
+complete custom drawable example,
+or the code of [[CircleFactory]] or [[InvertedTunnelFactory]].
interface DrawableDescriptor {
empty: Drawable;
objectCountScaler?: number;
propertyUniformMapping: { [property: string]: string };
sdf?: {
distanceFunctionName: string;
isInverted?: boolean;
shader: string;
};
shaderCombinationSteps: number[];
uniformCountMacroName: string;
}
+- Defined in drawables/drawable-descriptor.ts:13
@@ -45,7 +46,7 @@ code of [[CircleFactory]] or [[InvertedTunnelFactory]].
the value of empty is used to pad out arrays.
+Defined in drawables/drawable-descriptor.ts:78
Optionalobject Count Scaler
objectCountScaler?: number
@@ -54,7 +55,7 @@ the value of empty is used to pad out arrays.
By default, its value is 1
+ Defined in drawables/drawable-descriptor.ts:62
property Uniform Mapping
propertyUniformMapping: { [property: string]: string }
@@ -62,7 +63,7 @@ the value of empty is used to pad out arrays.
getObjectToSerialize and the name of the arrays used in the GLSL code.
+Defined in drawables/drawable-descriptor.ts:18
Optionalsdf
sdf?: { distanceFunctionName: string; isInverted?: boolean; shader: string }
@@ -74,10 +75,14 @@ getObjectToSerialize and the name of the arrays used in the GLSL code.
distanceFunctionName: string
OptionalisInverted?: boolean
@@ -89,7 +94,7 @@ Its signature should look like this:
Your code should work with both GLSL version 100 and version 300 es.
+Defined in drawables/drawable-descriptor.ts:29
shader Combination Steps
shaderCombinationSteps: number[]
@@ -99,7 +104,7 @@ shader is used to render a given part of the scene.
Must contain 0 as a value.
+Defined in drawables/drawable-descriptor.ts:72
uniform Count Macro Name
uniformCountMacroName: string
@@ -107,7 +112,7 @@ shader is used to render a given part of the scene.
number of drawables of this type.
+Defined in drawables/drawable-descriptor.ts:24
The name of the function defined in the value of
-shader. -Its signature should look like this: