Merge branch 'WIP' into main
This commit is contained in:
commit
1e4dd8555d
30 changed files with 571 additions and 275 deletions
|
|
@ -47,6 +47,15 @@ export interface DrawableDescriptor {
|
|||
isInverted?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculating the number of objects to be drawn is done using the following pseudo-formula:
|
||||
*
|
||||
* objectCountScaler * propertyUniformMapping[0].length
|
||||
*
|
||||
* By default, its value is 1
|
||||
*/
|
||||
objectCountScaler?: number;
|
||||
|
||||
/**
|
||||
* Number of possible drawables around each tile.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export class CircleLight extends LightDrawable {
|
|||
},
|
||||
uniformCountMacroName: 'CIRCLE_LIGHT_COUNT',
|
||||
shaderCombinationSteps: [0, 1, 2, 4, 8, 16],
|
||||
empty: new CircleLight(vec2.fromValues(0, 0), vec3.fromValues(0, 0, 0), 0),
|
||||
empty: new CircleLight(vec2.create(), vec3.create(), 0),
|
||||
};
|
||||
|
||||
constructor(center: vec2, color: vec3, intensity: number) {
|
||||
|
|
|
|||
|
|
@ -16,12 +16,7 @@ export class Flashlight extends LightDrawable {
|
|||
},
|
||||
uniformCountMacroName: 'FLASHLIGHT_COUNT',
|
||||
shaderCombinationSteps: [0, 1, 2, 4],
|
||||
empty: new Flashlight(
|
||||
vec2.fromValues(0, 0),
|
||||
vec3.fromValues(0, 0, 0),
|
||||
0,
|
||||
vec2.fromValues(1, 0)
|
||||
),
|
||||
empty: new Flashlight(vec2.create(), vec3.create(), 0, vec2.create()),
|
||||
};
|
||||
|
||||
public constructor(
|
||||
|
|
|
|||
|
|
@ -51,12 +51,7 @@ export class Droplet extends Drawable {
|
|||
},
|
||||
uniformCountMacroName: 'DROPLET_COUNT',
|
||||
shaderCombinationSteps: [0, 1, 4, 16, 32],
|
||||
empty: new Droplet(
|
||||
vec2.fromValues(-100000, -100000),
|
||||
vec2.fromValues(-100000, -100000),
|
||||
0,
|
||||
0
|
||||
),
|
||||
empty: new Droplet(vec2.create(), vec2.create(), 0, 0),
|
||||
};
|
||||
|
||||
constructor(
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ export class InvertedTunnel extends Drawable {
|
|||
uniform sampler2D noiseTexture;
|
||||
|
||||
#ifdef WEBGL2_IS_AVAILABLE
|
||||
float myTerrain(float h) {
|
||||
float invertedTunnelTerrain(float h) {
|
||||
return texture(
|
||||
noiseTexture,
|
||||
vec2(h, 0.5)
|
||||
)[0] - 0.5;
|
||||
}
|
||||
#else
|
||||
float myTerrain(float h) {
|
||||
float invertedTunnelTerrain(float h) {
|
||||
return texture2D(
|
||||
noiseTexture,
|
||||
vec2(h, 0.5)
|
||||
|
|
@ -39,7 +39,7 @@ export class InvertedTunnel extends Drawable {
|
|||
float invertedTunnelMinDistance(vec2 target, out float colorIndex) {
|
||||
colorIndex = 3.0;
|
||||
|
||||
float minDistance = 1000.0;
|
||||
float minDistance = -1000.0;
|
||||
for (int i = 0; i < INVERTED_TUNNEL_COUNT; i++) {
|
||||
|
||||
vec2 targetFromDelta = target - froms[i];
|
||||
|
|
@ -53,12 +53,12 @@ export class InvertedTunnel extends Drawable {
|
|||
fromRadii[i], toRadii[i], clampedH
|
||||
) + distance(
|
||||
targetFromDelta, toFromDeltas[i] * clampedH
|
||||
) - myTerrain(h) / 12.0;
|
||||
) - invertedTunnelTerrain(h) / 12.0;
|
||||
|
||||
minDistance = min(minDistance, currentDistance);
|
||||
minDistance = max(minDistance, -currentDistance);
|
||||
}
|
||||
|
||||
return -minDistance;
|
||||
return minDistance;
|
||||
}
|
||||
`,
|
||||
isInverted: true,
|
||||
|
|
@ -72,12 +72,7 @@ export class InvertedTunnel extends Drawable {
|
|||
},
|
||||
uniformCountMacroName: 'INVERTED_TUNNEL_COUNT',
|
||||
shaderCombinationSteps: [0, 1, 4, 16, 32],
|
||||
empty: new InvertedTunnel(
|
||||
vec2.fromValues(10000, 10000),
|
||||
vec2.fromValues(10000, 10000),
|
||||
0,
|
||||
0
|
||||
),
|
||||
empty: new InvertedTunnel(vec2.create(), vec2.create(), 0, 0),
|
||||
};
|
||||
|
||||
constructor(
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export class MetaCircle extends Drawable {
|
|||
},
|
||||
uniformCountMacroName: 'META_CIRCLE_COUNT',
|
||||
shaderCombinationSteps: [0, 1, 2, 3, 8, 16],
|
||||
empty: new MetaCircle(vec2.fromValues(10000, 10000), -1000),
|
||||
empty: new MetaCircle(vec2.create(), 0),
|
||||
};
|
||||
|
||||
constructor(public center: vec2, public radius: number) {
|
||||
|
|
|
|||
165
src/drawables/shapes/polygon-factory.ts
Normal file
165
src/drawables/shapes/polygon-factory.ts
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
import { mat2d, vec2 } from 'gl-matrix';
|
||||
import { clamp01 } from '../../helper/clamp';
|
||||
import { Drawable } from '../drawable';
|
||||
import { DrawableDescriptor } from '../drawable-descriptor';
|
||||
|
||||
/**
|
||||
* @category Drawable
|
||||
*/
|
||||
export const PolygonFactory = (
|
||||
vertexCount: number
|
||||
): { new (vertices: Array<vec2>): Drawable; descriptor: DrawableDescriptor } => {
|
||||
class Polygon extends Drawable {
|
||||
public static descriptor: DrawableDescriptor = {
|
||||
sdf: {
|
||||
shader: `
|
||||
uniform vec2 polygon${vertexCount}Vertices[POLGYON${vertexCount}_COUNT * ${vertexCount}];
|
||||
|
||||
vec2 polygon${vertexCount}LineDistance(vec2 target, vec2 from, vec2 to) {
|
||||
vec2 targetFromDelta = target - from;
|
||||
vec2 toFromDelta = to - from;
|
||||
float h = clamp(
|
||||
dot(targetFromDelta, toFromDelta) / dot(toFromDelta, toFromDelta),
|
||||
0.0, 1.0
|
||||
);
|
||||
|
||||
vec2 diff = targetFromDelta - toFromDelta * h;
|
||||
return vec2(
|
||||
dot(diff, diff),
|
||||
toFromDelta.x * targetFromDelta.y - toFromDelta.y * targetFromDelta.x
|
||||
);
|
||||
}
|
||||
|
||||
float polygon${vertexCount}MinDistance(vec2 target, out float colorIndex) {
|
||||
colorIndex = 1.0;
|
||||
float minDistance = 100.0;
|
||||
|
||||
for (int j = 0; j < POLGYON${vertexCount}_COUNT; j++) {
|
||||
vec2 startEnd = polygon${vertexCount}Vertices[j * ${vertexCount}];
|
||||
vec2 vb = startEnd;
|
||||
|
||||
float d = 10000.0;
|
||||
float s = 1.0;
|
||||
for (int k = 1; k < ${vertexCount}; k++) {
|
||||
vec2 va = vb;
|
||||
vb = polygon${vertexCount}Vertices[j * ${vertexCount} + k];
|
||||
vec2 ds = polygon${vertexCount}LineDistance(target, va, vb);
|
||||
|
||||
bvec3 cond = bvec3(target.y >= va.y, target.y < vb.y, ds.y > 0.0);
|
||||
if (all(cond) || all(not(cond))) {
|
||||
s *= -1.0;
|
||||
}
|
||||
|
||||
d = min(d, ds.x);
|
||||
}
|
||||
|
||||
vec2 ds = polygon${vertexCount}LineDistance(target, vb, startEnd);
|
||||
|
||||
bvec3 cond = bvec3(target.y >= vb.y, target.y < startEnd.y, ds.y > 0.0);
|
||||
if (all(cond) || all(not(cond))) {
|
||||
s *= -1.0;
|
||||
}
|
||||
|
||||
d = min(d, ds.x);
|
||||
minDistance = min(minDistance, s * sqrt(d));
|
||||
}
|
||||
|
||||
return minDistance;
|
||||
}
|
||||
`,
|
||||
distanceFunctionName: `polygon${vertexCount}MinDistance`,
|
||||
},
|
||||
propertyUniformMapping: {
|
||||
vertices: `polygon${vertexCount}Vertices`,
|
||||
},
|
||||
objectCountScaler: 1 / vertexCount,
|
||||
uniformCountMacroName: `POLGYON${vertexCount}_COUNT`,
|
||||
shaderCombinationSteps: [0, 1, 2, 3, 8, 16],
|
||||
empty: new Polygon(new Array(vertexCount).fill(vec2.create())),
|
||||
};
|
||||
|
||||
constructor(public vertices: Array<vec2>) {
|
||||
super();
|
||||
|
||||
if (vertices.length > vertexCount) {
|
||||
throw new Error(
|
||||
`Too many vertices, expected ${vertexCount}, got ${vertices.length}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public minDistance(target: vec2): number {
|
||||
const startEnd = this.vertices[0];
|
||||
let vb = startEnd;
|
||||
|
||||
let d = vec2.squaredDistance(target, vb);
|
||||
let sign = 1;
|
||||
|
||||
for (let i = 1; i <= this.vertices.length; i++) {
|
||||
const va = vb;
|
||||
vb = i === this.vertices.length ? startEnd : this.vertices[i];
|
||||
const targetFromDelta = vec2.subtract(vec2.create(), target, va);
|
||||
const toFromDelta = vec2.subtract(vec2.create(), vb, va);
|
||||
const h = clamp01(
|
||||
vec2.dot(targetFromDelta, toFromDelta) / vec2.squaredLength(toFromDelta)
|
||||
);
|
||||
|
||||
const ds = vec2.fromValues(
|
||||
vec2.dist(targetFromDelta, vec2.scale(vec2.create(), toFromDelta, h)),
|
||||
toFromDelta.x * targetFromDelta.y - toFromDelta.y * targetFromDelta.x
|
||||
);
|
||||
|
||||
if (
|
||||
(target.y >= va.y && target.y < vb.y && ds.y > 0) ||
|
||||
(target.y < va.y && target.y >= vb.y && ds.y <= 0)
|
||||
) {
|
||||
sign *= -1;
|
||||
}
|
||||
|
||||
d = Math.min(d, ds.x);
|
||||
}
|
||||
|
||||
return sign * d;
|
||||
}
|
||||
|
||||
public getVertices(): Array<vec2> {
|
||||
return this.vertices;
|
||||
}
|
||||
|
||||
private get actualVertices(): Array<vec2> {
|
||||
return this.vertices.length < vertexCount
|
||||
? ([
|
||||
...this.vertices,
|
||||
...new Array(vertexCount - this.vertices.length).fill(this.vertices[0]),
|
||||
] as Array<vec2>)
|
||||
: this.vertices;
|
||||
}
|
||||
|
||||
protected getObjectToSerialize(transform2d: mat2d, transform1d: number): any {
|
||||
return {
|
||||
vertices: this.actualVertices.map((v) =>
|
||||
vec2.transformMat2d(vec2.create(), v, transform2d)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
public serializeToUniforms(
|
||||
uniforms: any,
|
||||
transform2d: mat2d,
|
||||
transform1d: number
|
||||
): void {
|
||||
const { propertyUniformMapping } = (this.constructor as typeof Drawable).descriptor;
|
||||
|
||||
const serialized = this.getObjectToSerialize(transform2d, transform1d);
|
||||
Object.entries(propertyUniformMapping).forEach(([k, v]) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(uniforms, v)) {
|
||||
uniforms[v] = [];
|
||||
}
|
||||
|
||||
uniforms[v].push(...serialized[k]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Polygon;
|
||||
};
|
||||
|
|
@ -75,7 +75,8 @@ export class UniformArrayAutoScalingProgram implements IProgram {
|
|||
return 0;
|
||||
}
|
||||
const uniformName = uniformNames[1];
|
||||
return uniforms[uniformName] ? uniforms[uniformName].length : 0;
|
||||
const scaler = d.objectCountScaler === undefined ? 1 : d.objectCountScaler;
|
||||
return uniforms[uniformName] ? scaler * uniforms[uniformName].length : 0;
|
||||
});
|
||||
|
||||
const closest = this.programs.find((p) => p.values.every((v, i) => v >= values[i]));
|
||||
|
|
@ -91,7 +92,11 @@ export class UniformArrayAutoScalingProgram implements IProgram {
|
|||
this.descriptors!.map((d, i) => {
|
||||
const difference = closest.values[i] - values[i];
|
||||
for (let i = 0; i < difference; i++) {
|
||||
d.empty.serializeToUniforms(uniforms, mat2d.create(), 0);
|
||||
d.empty.serializeToUniforms(
|
||||
uniforms,
|
||||
mat2d.fromTranslation(mat2d.create(), vec2.fromValues(-10000, -10000)),
|
||||
0
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -171,12 +176,12 @@ export class UniformArrayAutoScalingProgram implements IProgram {
|
|||
}(position, objectColor);
|
||||
|
||||
color = mix(
|
||||
objectColor / {paletteSize},
|
||||
color,
|
||||
objectColor / {paletteSize},
|
||||
color,
|
||||
${
|
||||
descriptors[i].sdf?.isInverted
|
||||
? `step(-distanceNdcPixelSize, -objectMinDistance)`
|
||||
: `step(1.0 * distanceNdcPixelSize, objectMinDistance)`
|
||||
: `step(distanceNdcPixelSize, objectMinDistance)`
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ export class RendererImplementation implements Renderer {
|
|||
palette: 1,
|
||||
|
||||
distanceNdcPixelSize: 2 / Math.max(...this.distanceFieldFrameBuffer.getSize()),
|
||||
shadingNdcPixelSize: 2 / Math.max(...this.distanceFieldFrameBuffer.getSize()),
|
||||
shadingNdcPixelSize: 2 / Math.max(...this.lightingFrameBuffer.getSize()),
|
||||
};
|
||||
|
||||
this.distancePass.render(this.uniformsProvider.getUniforms(common), ...this.textures);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ float getDistance(in vec2 target) {
|
|||
|
||||
float shadowTransparency(float startingDistance, float lightCenterDistance, vec2 direction) {
|
||||
float rayLength = startingDistance;
|
||||
for (int j = 0; j < SHADOW_TRACE_COUNT; j++) {
|
||||
for (int i = 0; i < SHADOW_TRACE_COUNT; i++) {
|
||||
rayLength += max(0.0, getDistance(uvCoordinates + direction * rayLength));
|
||||
}
|
||||
return min(1.0, pow(rayLength / lightCenterDistance, 0.3));
|
||||
|
|
@ -103,7 +103,7 @@ void main() {
|
|||
lightCenterDistance,
|
||||
direction
|
||||
);
|
||||
|
||||
|
||||
lightingInside += lightColorAtPosition;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ export * from './drawables/lights/circle-light';
|
|||
export * from './drawables/lights/flashlight';
|
||||
export * from './drawables/shapes/circle';
|
||||
export * from './drawables/shapes/droplet';
|
||||
export * from './drawables/shapes/polygon-factory';
|
||||
export * from './drawables/shapes/inverted-tunnel';
|
||||
export * from './drawables/shapes/meta-circle';
|
||||
export * from './drawables/shapes/rotated-rectangle';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue