Working version

This commit is contained in:
schmelczerandras 2020-09-15 13:37:57 +02:00
parent 77bde04db3
commit b2c2cfcb41
63 changed files with 203 additions and 8301 deletions

View file

@ -0,0 +1,8 @@
import { Drawable } from './drawable';
export interface DrawableDescriptor {
uniformName: string;
countMacroName: string;
shaderCombinationSteps: Array<number>;
readonly empty: Drawable;
}

15
src/drawables/drawable.ts Normal file
View file

@ -0,0 +1,15 @@
import { mat2d, vec2 } from 'gl-matrix';
import { DrawableDescriptor } from './drawable-descriptor';
export abstract class Drawable {
static get descriptor(): DrawableDescriptor {
throw new Error('This getter should be overriden');
}
public abstract distance(target: vec2): number;
public abstract serializeToUniforms(
uniforms: any,
scale: number,
transform: mat2d
): void;
}

View file

@ -1,22 +1,26 @@
import { mat2d, vec2, vec3 } from 'gl-matrix';
import { settings } from '../../settings';
import { IDrawableDescriptor } from '../i-drawable-descriptor';
import { ILight } from './i-light';
import { settings } from '../../graphics/settings';
import { Drawable } from '../drawable';
import { DrawableDescriptor } from '../drawable-descriptor';
export class CircleLight implements ILight {
public static descriptor: IDrawableDescriptor = {
uniformName: 'circleLights',
countMacroName: 'circleLightCount',
shaderCombinationSteps: settings.shaderCombinations.circleLightSteps,
empty: new CircleLight(vec2.fromValues(0, 0), 0, vec3.fromValues(0, 0, 0), 0),
};
export class CircleLight extends Drawable {
public static get descriptor(): DrawableDescriptor {
return {
uniformName: 'circleLights',
countMacroName: 'circleLightCount',
shaderCombinationSteps: settings.shaderCombinations.circleLightSteps,
empty: new CircleLight(vec2.fromValues(0, 0), 0, vec3.fromValues(0, 0, 0), 0),
};
}
constructor(
public center: vec2,
public lightDrop: number,
public color: vec3,
public lightness: number
) {}
) {
super();
}
public distance(_: vec2): number {
return 0;

View file

@ -1,21 +1,23 @@
import { mat2d, vec2, vec3 } from 'gl-matrix';
import { settings } from '../../settings';
import { IDrawableDescriptor } from '../i-drawable-descriptor';
import { ILight } from './i-light';
import { settings } from '../../graphics/settings';
import { Drawable } from '../drawable';
import { DrawableDescriptor } from '../drawable-descriptor';
export class Flashlight implements ILight {
public static descriptor: IDrawableDescriptor = {
uniformName: 'flashlights',
countMacroName: 'flashlightCount',
shaderCombinationSteps: settings.shaderCombinations.flashlightSteps,
empty: new Flashlight(
vec2.fromValues(0, 0),
vec2.fromValues(0, 0),
0,
vec3.fromValues(0, 0, 0),
0
),
};
export class Flashlight extends Drawable {
public static get descriptor(): DrawableDescriptor {
return {
uniformName: 'flashlights',
countMacroName: 'flashlightCount',
shaderCombinationSteps: settings.shaderCombinations.flashlightSteps,
empty: new Flashlight(
vec2.fromValues(0, 0),
vec2.fromValues(0, 0),
0,
vec3.fromValues(0, 0, 0),
0
),
};
}
public constructor(
public center: vec2,
@ -23,7 +25,9 @@ export class Flashlight implements ILight {
public lightDrop: number,
public color: vec3,
public lightness: number
) {}
) {
super();
}
public distance(_: vec2): number {
return 0;

View file

@ -0,0 +1,36 @@
import { mat2d, vec2 } from 'gl-matrix';
import { settings } from '../../graphics/settings';
import { Drawable } from '../drawable';
import { DrawableDescriptor } from '../drawable-descriptor';
export class Circle extends Drawable {
public static get descriptor(): DrawableDescriptor {
return {
uniformName: 'circles',
countMacroName: 'circleCount',
shaderCombinationSteps: settings.shaderCombinations.circleSteps,
empty: new Circle(vec2.fromValues(0, 0), 0),
};
}
constructor(public center: vec2, public radius: number) {
super();
}
public distance(position: vec2): number {
return 0;
}
public serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void {
const { uniformName } = Circle.descriptor;
if (!Object.prototype.hasOwnProperty.call(uniforms, uniformName)) {
uniforms[uniformName] = [];
}
uniforms[uniformName].push({
center: vec2.transformMat2d(vec2.create(), this.center, transform),
radius: this.radius * scale,
});
}
}

View file

@ -1,8 +0,0 @@
import { IDrawable } from './i-drawable';
export interface IDrawableDescriptor {
uniformName: string;
countMacroName: string;
shaderCombinationSteps: Array<number>;
readonly empty: IDrawable;
}

View file

@ -1,6 +0,0 @@
import { vec2, mat2d } from 'gl-matrix';
export interface IDrawable {
distance(target: vec2): number;
serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void;
}

View file

@ -1,3 +0,0 @@
import { IDrawable } from '../i-drawable';
export type ILight = IDrawable;

View file

@ -1,7 +1,7 @@
import { mat2d, vec2 } from 'gl-matrix';
import { DrawableDescriptor } from '../../../drawables/drawable-descriptor';
import { getCombinations } from '../../../helper/get-combinations';
import { last } from '../../../helper/last';
import { IDrawableDescriptor } from '../../drawables/i-drawable-descriptor';
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
import { IProgram } from './i-program';
@ -18,7 +18,7 @@ export class UniformArrayAutoScalingProgram implements IProgram {
constructor(
private gl: WebGL2RenderingContext,
shaderSources: [string, string],
private descriptors: Array<IDrawableDescriptor>
private descriptors: Array<DrawableDescriptor>
) {
const names = descriptors.map((o) => o.countMacroName);
for (const combination of getCombinations(

View file

@ -1,6 +1,5 @@
import { vec2 } from 'gl-matrix';
import { IDrawable } from './drawables/i-drawable';
import { ILight } from './drawables/lights/i-light';
import { Drawable } from '../drawables/drawable';
export interface IRenderer {
initialize(): Promise<void>;
@ -8,9 +7,8 @@ export interface IRenderer {
startFrame(deltaTime: DOMHighResTimeStamp): void;
finishFrame(): void;
drawShape(drawable: IDrawable): void;
drawLight(light: ILight): void;
drawInfoText(text: string): void;
drawShape(drawable: Drawable): void;
drawLight(light: Drawable): void;
readonly canvasSize: vec2;
setViewArea(topLeft: vec2, size: vec2): void;

View file

@ -1,18 +1,18 @@
import { vec2 } from 'gl-matrix';
import { IDrawable } from '../drawables/i-drawable';
import { IDrawableDescriptor } from '../drawables/i-drawable-descriptor';
import { Drawable } from '../../drawables/drawable';
import { DrawableDescriptor } from '../../drawables/drawable-descriptor';
import { FrameBuffer } from '../graphics-library/frame-buffer/frame-buffer';
import { UniformArrayAutoScalingProgram } from '../graphics-library/program/uniform-array-autoscaling-program';
import { settings } from '../settings';
export class RenderingPass {
private drawables: Array<IDrawable> = [];
private drawables: Array<Drawable> = [];
private program: UniformArrayAutoScalingProgram;
constructor(
gl: WebGL2RenderingContext,
shaderSources: [string, string],
drawableDescriptors: Array<IDrawableDescriptor>,
drawableDescriptors: Array<DrawableDescriptor>,
private frame: FrameBuffer
) {
this.program = new UniformArrayAutoScalingProgram(
@ -26,7 +26,7 @@ export class RenderingPass {
await this.program.initialize();
}
public addDrawable(drawable: IDrawable) {
public addDrawable(drawable: Drawable) {
this.drawables.push(drawable);
}

View file

@ -1,8 +1,8 @@
import { vec2 } from 'gl-matrix';
import { IDrawable } from '../drawables/i-drawable';
import { CircleLight } from '../drawables/lights/circle-light';
import { Flashlight } from '../drawables/lights/flashlight';
import { ILight } from '../drawables/lights/i-light';
import { Drawable } from '../../drawables/drawable';
import { CircleLight } from '../../drawables/lights/circle-light';
import { Flashlight } from '../../drawables/lights/flashlight';
import { Circle } from '../../drawables/shapes/circle';
import { DefaultFrameBuffer } from '../graphics-library/frame-buffer/default-frame-buffer';
import { IntermediateFrameBuffer } from '../graphics-library/frame-buffer/intermediate-frame-buffer';
import { getWebGl2Context } from '../graphics-library/helper/get-webgl2-context';
@ -28,7 +28,7 @@ export class WebGl2Renderer implements IRenderer {
private initializePromise: Promise<[void, void]>;
constructor(private canvas: HTMLCanvasElement, private overlay: HTMLElement) {
constructor(private canvas: HTMLCanvasElement) {
this.gl = getWebGl2Context(canvas);
this.distanceFieldFrameBuffer = new IntermediateFrameBuffer(this.gl);
@ -37,7 +37,7 @@ export class WebGl2Renderer implements IRenderer {
this.distancePass = new RenderingPass(
this.gl,
[distanceVertexShader, distanceFragmentShader],
[],
[Circle.descriptor],
this.distanceFieldFrameBuffer
);
@ -74,11 +74,11 @@ export class WebGl2Renderer implements IRenderer {
await this.initializePromise;
}
public drawShape(shape: IDrawable) {
public drawShape(shape: Drawable) {
this.distancePass.addDrawable(shape);
}
public drawLight(light: ILight) {
public drawLight(light: Drawable) {
this.lightingPass.addDrawable(light);
}
@ -117,10 +117,4 @@ export class WebGl2Renderer implements IRenderer {
public get canvasSize(): vec2 {
return vec2.fromValues(this.canvas.clientWidth, this.canvas.clientHeight);
}
public drawInfoText(text: string) {
if (this.overlay.innerText != text) {
this.overlay.innerText = text;
}
}
}

View file

@ -51,9 +51,8 @@ export const settings = {
tileMultiplier: 8,
shaderMacros: {},
shaderCombinations: {
lineSteps: [0, 1, 2, 4, 8, 16, 128],
blobSteps: [0, 1, 2, 8],
circleLightSteps: [0, 1],
circleSteps: [0, 1, 16],
flashlightSteps: [0, 1],
},
};

View file

@ -2,8 +2,9 @@
precision lowp float;
#define LINE_COUNT {lineCount}
#define BLOB_COUNT {blobCount}
// #define LINE_COUNT {lineCount}
// #define BLOB_COUNT {blobCount}
#define CIRCLE_COUNT {circleCount}
#define SURFACE_OFFSET 0.001
@ -20,7 +21,7 @@ float smoothMin(float a, float b)
b = pow(b, k);
return pow((a * b) / (a + b), 1.0 / k);
}
/*
#if LINE_COUNT > 0
uniform struct {
vec2 from;
@ -53,7 +54,22 @@ float smoothMin(float a, float b)
minDistance = -myMinDistance;
}
#endif
*/
#if CIRCLE_COUNT > 0
uniform struct {
vec2 center;
float radius;
}[CIRCLE_COUNT] circles;
void circleMinDistance(inout float minDistance, inout float color) {
for (int i = 0; i < CIRCLE_COUNT; i++) {
float dist = distance(circles[i].center, position) - circles[i].radius;
minDistance = min(minDistance, dist);
}
}
#endif
/*
#if BLOB_COUNT > 0
uniform struct {
vec2 headCenter;
@ -88,22 +104,26 @@ float smoothMin(float a, float b)
}
}
#endif
*/
out vec2 fragmentColor;
void main() {
float minDistance = -maxMinDistance;
float color = 0.0;
float minDistance = 10.0; //-maxMinDistance;
float color = 1.0;
#if LINE_COUNT > 0
/*#if LINE_COUNT > 0
lineMinDistance(minDistance, color);
#endif
#if BLOB_COUNT > 0
blobMinDistance(minDistance, color);
#endif*/
#if CIRCLE_COUNT > 0
circleMinDistance(minDistance, color);
#endif
// minDistance / 2.0: NDC to UV scale
fragmentColor = vec2((minDistance - SURFACE_OFFSET) / 2.0, color);
fragmentColor = vec2(minDistance / 2.0, color);
}

View file

@ -1,18 +1,14 @@
import { glMatrix } from 'gl-matrix';
import { IRenderer } from './graphics/i-renderer';
import { WebGl2Renderer } from './graphics/rendering/webgl2-renderer';
import { applyArrayPlugins } from './helper/array';
import { Random } from './helper/random';
glMatrix.setMatrixArrayType(Array);
applyArrayPlugins();
export { Drawable } from './drawables/drawable';
export { CircleLight } from './drawables/lights/circle-light';
export { Circle } from './drawables/shapes/circle';
const main = async () => {
try {
Random.seed = 42;
//await new Game().start();
} catch (e) {
console.error(e);
alert(e);
}
export const compile = (canvas: HTMLCanvasElement): IRenderer => {
glMatrix.setMatrixArrayType(Array);
applyArrayPlugins();
return new WebGl2Renderer(canvas);
};
main();