Merge branch 'WIP' into main

This commit is contained in:
schmelczerandras 2020-10-12 16:12:08 +02:00
commit 1e4dd8555d
30 changed files with 571 additions and 275 deletions

View file

@ -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.
*

View file

@ -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) {

View file

@ -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(

View file

@ -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(

View file

@ -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(

View file

@ -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) {

View 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;
};

View file

@ -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)`
}
);

View file

@ -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);

View file

@ -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

View file

@ -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';