Render in NDC
This commit is contained in:
parent
40a660b7cb
commit
05682dd2d5
16 changed files with 106 additions and 82 deletions
|
|
@ -9,6 +9,7 @@ export class DrawableBlob extends Blob implements IDrawable {
|
||||||
uniformName: 'blobs',
|
uniformName: 'blobs',
|
||||||
countMacroName: 'blobCount',
|
countMacroName: 'blobCount',
|
||||||
shaderCombinationSteps: settings.shaderCombinations.blobSteps,
|
shaderCombinationSteps: settings.shaderCombinations.blobSteps,
|
||||||
|
empty: new DrawableBlob(vec2.fromValues(0, 0)),
|
||||||
};
|
};
|
||||||
|
|
||||||
public serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void {
|
public serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export class DrawableTunnel extends TunnelShape implements IDrawable {
|
||||||
uniformName: 'lines',
|
uniformName: 'lines',
|
||||||
countMacroName: 'lineCount',
|
countMacroName: 'lineCount',
|
||||||
shaderCombinationSteps: settings.shaderCombinations.lineSteps,
|
shaderCombinationSteps: settings.shaderCombinations.lineSteps,
|
||||||
|
empty: new DrawableTunnel(vec2.fromValues(0, 0), vec2.fromValues(0, 0), 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
public serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void {
|
public serializeToUniforms(uniforms: any, scale: number, transform: mat2d): void {
|
||||||
|
|
@ -19,7 +20,7 @@ export class DrawableTunnel extends TunnelShape implements IDrawable {
|
||||||
|
|
||||||
uniforms[uniformName].push({
|
uniforms[uniformName].push({
|
||||||
from: vec2.transformMat2d(vec2.create(), this.from, transform),
|
from: vec2.transformMat2d(vec2.create(), this.from, transform),
|
||||||
toFromDelta: vec2.transformMat2d(vec2.create(), this.toFromDelta, transform),
|
toFromDelta: vec2.scale(vec2.create(), this.toFromDelta, scale),
|
||||||
fromRadius: this.fromRadius * scale,
|
fromRadius: this.fromRadius * scale,
|
||||||
toRadius: this.toRadius * scale,
|
toRadius: this.toRadius * scale,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
import { IDrawable } from './i-drawable';
|
||||||
|
|
||||||
export interface IDrawableDescriptor {
|
export interface IDrawableDescriptor {
|
||||||
uniformName: string;
|
uniformName: string;
|
||||||
countMacroName: string;
|
countMacroName: string;
|
||||||
shaderCombinationSteps: Array<number>;
|
shaderCombinationSteps: Array<number>;
|
||||||
|
readonly empty: IDrawable;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export class CircleLight implements ILight {
|
||||||
uniformName: 'circleLights',
|
uniformName: 'circleLights',
|
||||||
countMacroName: 'circleLightCount',
|
countMacroName: 'circleLightCount',
|
||||||
shaderCombinationSteps: settings.shaderCombinations.circleLightSteps,
|
shaderCombinationSteps: settings.shaderCombinations.circleLightSteps,
|
||||||
|
empty: new CircleLight(vec2.fromValues(0, 0), 0, vec3.fromValues(0, 0, 0), 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -17,7 +18,7 @@ export class CircleLight implements ILight {
|
||||||
public lightness: number
|
public lightness: number
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public distance(target: vec2): number {
|
public distance(_: vec2): number {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ export class PointLight implements ILight {
|
||||||
uniformName: 'pointLights',
|
uniformName: 'pointLights',
|
||||||
countMacroName: 'pointLightCount',
|
countMacroName: 'pointLightCount',
|
||||||
shaderCombinationSteps: settings.shaderCombinations.pointLightSteps,
|
shaderCombinationSteps: settings.shaderCombinations.pointLightSteps,
|
||||||
|
empty: new PointLight(vec2.fromValues(0, 0), 0, vec3.fromValues(0, 0, 0), 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { mat2d, vec2 } from 'gl-matrix';
|
||||||
import { getCombinations } from '../../../helper/get-combinations';
|
import { getCombinations } from '../../../helper/get-combinations';
|
||||||
import { last } from '../../../helper/last';
|
import { last } from '../../../helper/last';
|
||||||
import { IDrawableDescriptor } from '../../drawables/i-drawable-descriptor';
|
import { IDrawableDescriptor } from '../../drawables/i-drawable-descriptor';
|
||||||
|
|
@ -12,33 +12,40 @@ export class UniformArrayAutoScalingProgram implements IProgram {
|
||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
private current: FragmentShaderOnlyProgram;
|
private current: FragmentShaderOnlyProgram;
|
||||||
|
|
||||||
private drawingRectangleTopLeft = vec2.fromValues(0, 0);
|
private drawingRectangleTopLeft = vec2.fromValues(0, 0);
|
||||||
|
|
||||||
private drawingRectangleSize = vec2.fromValues(1, 1);
|
private drawingRectangleSize = vec2.fromValues(1, 1);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private gl: WebGL2RenderingContext,
|
private gl: WebGL2RenderingContext,
|
||||||
shaderSources: [string, string],
|
shaderSources: [string, string],
|
||||||
private options: Array<IDrawableDescriptor>
|
private descriptors: Array<IDrawableDescriptor>
|
||||||
) {
|
) {
|
||||||
const names = options.map((o) => o.countMacroName);
|
const names = descriptors.map((o) => o.countMacroName);
|
||||||
for (const combination of getCombinations(
|
for (const combination of getCombinations(
|
||||||
options.map((o) => o.shaderCombinationSteps)
|
descriptors.map((o) => o.shaderCombinationSteps)
|
||||||
)) {
|
)) {
|
||||||
this.createProgram(names, combination, shaderSources);
|
this.createProgram(names, combination, shaderSources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bindAndSetUniforms(uniforms: { [name: string]: any }): void {
|
public bindAndSetUniforms(uniforms: { [name: string]: any }): void {
|
||||||
const values = this.options.map((o) =>
|
const values = this.descriptors.map((d) =>
|
||||||
uniforms[o.uniformName] ? uniforms[o.uniformName].length : 0
|
uniforms[d.uniformName] ? uniforms[d.uniformName].length : 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const closest = this.programs.find((p) => p.values.every((v, i) => v >= values[i]));
|
const closest = this.programs.find((p) => p.values.every((v, i) => v >= values[i]));
|
||||||
|
|
||||||
this.current = closest ? closest.program : last(this.programs).program;
|
this.current = closest ? closest.program : last(this.programs).program;
|
||||||
|
|
||||||
|
if (closest) {
|
||||||
|
this.descriptors.map((d, i) => {
|
||||||
|
const difference = closest.values[i] - values[i];
|
||||||
|
for (let i = 0; i < difference; i++) {
|
||||||
|
d.empty.serializeToUniforms(uniforms, 0, mat2d.create());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.current.setDrawingRectangle(
|
this.current.setDrawingRectangle(
|
||||||
this.drawingRectangleTopLeft,
|
this.drawingRectangleTopLeft,
|
||||||
this.drawingRectangleSize
|
this.drawingRectangleSize
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,12 @@ export class RenderingPass {
|
||||||
this.drawables.push(drawable);
|
this.drawables.push(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(commonUniforms: any, inputTexture?: WebGLTexture) {
|
public render(
|
||||||
|
commonUniforms: any,
|
||||||
|
scale: number,
|
||||||
|
transform: mat2d,
|
||||||
|
inputTexture?: WebGLTexture
|
||||||
|
) {
|
||||||
this.frame.bindAndClear(inputTexture);
|
this.frame.bindAndClear(inputTexture);
|
||||||
const q = 1 / settings.tileMultiplier;
|
const q = 1 / settings.tileMultiplier;
|
||||||
const tileUvSize = vec2.fromValues(q, q);
|
const tileUvSize = vec2.fromValues(q, q);
|
||||||
|
|
@ -51,13 +56,10 @@ export class RenderingPass {
|
||||||
|
|
||||||
let sumLineCount = 0;
|
let sumLineCount = 0;
|
||||||
|
|
||||||
const scale = 1;
|
|
||||||
const transform = mat2d.create();
|
|
||||||
|
|
||||||
for (let x = 0; x < 1; x += q) {
|
for (let x = 0; x < 1; x += q) {
|
||||||
for (let y = 0; y < 1; y += q) {
|
for (let y = 0; y < 1; y += q) {
|
||||||
const uniforms = { ...commonUniforms };
|
const uniforms = { ...commonUniforms };
|
||||||
uniforms.maxMinDistance = 2 * worldR;
|
uniforms.maxMinDistance = 2 * worldR * scale;
|
||||||
|
|
||||||
const uvBottomLeft = vec2.fromValues(x, y);
|
const uvBottomLeft = vec2.fromValues(x, y);
|
||||||
this.program.setDrawingRectangle(uvBottomLeft, tileUvSize);
|
this.program.setDrawingRectangle(uvBottomLeft, tileUvSize);
|
||||||
|
|
@ -69,7 +71,7 @@ export class RenderingPass {
|
||||||
);
|
);
|
||||||
|
|
||||||
const primitivesNearTile = this.drawables.filter(
|
const primitivesNearTile = this.drawables.filter(
|
||||||
(p) => p.distance(tileCenterWorldCoordinates) < 2 * worldR
|
(d) => d.distance(tileCenterWorldCoordinates) < 2 * worldR
|
||||||
);
|
);
|
||||||
|
|
||||||
sumLineCount += primitivesNearTile.length;
|
sumLineCount += primitivesNearTile.length;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import { IDrawable } from '../drawables/i-drawable';
|
||||||
import { CircleLight } from '../drawables/lights/circle-light';
|
import { CircleLight } from '../drawables/lights/circle-light';
|
||||||
import { ILight } from '../drawables/lights/i-light';
|
import { ILight } from '../drawables/lights/i-light';
|
||||||
import { PointLight } from '../drawables/lights/point-light';
|
import { PointLight } from '../drawables/lights/point-light';
|
||||||
// import lightsShader from '../shaders/rainbow-shading-fs.glsl';
|
|
||||||
import { DefaultFrameBuffer } from '../graphics-library/frame-buffer/default-frame-buffer';
|
import { DefaultFrameBuffer } from '../graphics-library/frame-buffer/default-frame-buffer';
|
||||||
import { IntermediateFrameBuffer } from '../graphics-library/frame-buffer/intermediate-frame-buffer';
|
import { IntermediateFrameBuffer } from '../graphics-library/frame-buffer/intermediate-frame-buffer';
|
||||||
import { getWebGl2Context } from '../graphics-library/helper/get-webgl2-context';
|
import { getWebGl2Context } from '../graphics-library/helper/get-webgl2-context';
|
||||||
|
|
@ -21,32 +20,28 @@ import { RenderingPass } from './rendering-pass';
|
||||||
|
|
||||||
export class WebGl2Renderer implements IRenderer {
|
export class WebGl2Renderer implements IRenderer {
|
||||||
private gl: WebGL2RenderingContext;
|
private gl: WebGL2RenderingContext;
|
||||||
|
|
||||||
private stopwatch?: WebGlStopwatch;
|
private stopwatch?: WebGlStopwatch;
|
||||||
|
|
||||||
|
private upscaleTransform = mat2d.create();
|
||||||
|
private linearDownscale = 1;
|
||||||
|
|
||||||
private viewBoxBottomLeft = vec2.create();
|
private viewBoxBottomLeft = vec2.create();
|
||||||
|
|
||||||
private viewBoxSize = vec2.create();
|
private viewBoxSize = vec2.create();
|
||||||
|
private viewAreaScale: vec2;
|
||||||
private cursorPosition = vec2.create();
|
private cursorPosition = vec2.create();
|
||||||
|
|
||||||
private distanceFieldFrameBuffer: IntermediateFrameBuffer;
|
private distanceFieldFrameBuffer: IntermediateFrameBuffer;
|
||||||
|
|
||||||
private lightingFrameBuffer: DefaultFrameBuffer;
|
private lightingFrameBuffer: DefaultFrameBuffer;
|
||||||
|
|
||||||
private distancePass: RenderingPass;
|
private distancePass: RenderingPass;
|
||||||
|
|
||||||
private lightingPass: RenderingPass;
|
private lightingPass: RenderingPass;
|
||||||
|
|
||||||
private autoscaler: FpsAutoscaler;
|
private autoscaler: FpsAutoscaler;
|
||||||
|
|
||||||
private matrices: {
|
private matrices: {
|
||||||
distanceScreenToWorld?: mat2d;
|
distanceScreenToWorld?: mat2d;
|
||||||
worldToDistanceUV?: mat2d;
|
worldToDistanceUV?: mat2d;
|
||||||
cursorPosition?: mat2d;
|
cursorPosition?: mat2d;
|
||||||
ndcToUv?: mat2d;
|
|
||||||
uvToWorld?: mat2d;
|
uvToWorld?: mat2d;
|
||||||
} = { ndcToUv: mat2d.fromValues(0.5, 0, 0, 0.5, 0.5, 0.5) };
|
} = {};
|
||||||
|
|
||||||
constructor(private canvas: HTMLCanvasElement, private overlay: HTMLElement) {
|
constructor(private canvas: HTMLCanvasElement, private overlay: HTMLElement) {
|
||||||
this.gl = getWebGl2Context(canvas);
|
this.gl = getWebGl2Context(canvas);
|
||||||
|
|
@ -92,6 +87,7 @@ export class WebGl2Renderer implements IRenderer {
|
||||||
this.autoscaler.autoscale(deltaTime);
|
this.autoscaler.autoscale(deltaTime);
|
||||||
|
|
||||||
this.stopwatch?.start();
|
this.stopwatch?.start();
|
||||||
|
|
||||||
this.distanceFieldFrameBuffer.setSize();
|
this.distanceFieldFrameBuffer.setSize();
|
||||||
this.lightingFrameBuffer.setSize();
|
this.lightingFrameBuffer.setSize();
|
||||||
}
|
}
|
||||||
|
|
@ -99,16 +95,24 @@ export class WebGl2Renderer implements IRenderer {
|
||||||
public finishFrame() {
|
public finishFrame() {
|
||||||
this.calculateMatrices();
|
this.calculateMatrices();
|
||||||
|
|
||||||
this.distancePass.render(this.uniforms);
|
this.distancePass.render(this.uniforms, this.linearDownscale, this.upscaleTransform);
|
||||||
|
this.lightingPass.render(
|
||||||
this.lightingPass.render(this.uniforms, this.distanceFieldFrameBuffer.colorTexture);
|
this.uniforms,
|
||||||
|
this.linearDownscale,
|
||||||
|
this.upscaleTransform,
|
||||||
|
this.distanceFieldFrameBuffer.colorTexture
|
||||||
|
);
|
||||||
|
|
||||||
this.stopwatch?.stop();
|
this.stopwatch?.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private get uniforms(): any {
|
private get uniforms(): any {
|
||||||
const cursorPosition = this.screenUvToWorldCoordinate(this.cursorPosition);
|
const cursorPosition = this.screenUvToWorldCoordinate(this.cursorPosition);
|
||||||
return { ...this.matrices, cursorPosition, viewBoxSize: this.viewBoxSize };
|
return {
|
||||||
|
...this.matrices,
|
||||||
|
cursorPosition,
|
||||||
|
viewAreaScale: this.viewAreaScale,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateMatrices() {
|
private calculateMatrices() {
|
||||||
|
|
@ -157,12 +161,31 @@ export class WebGl2Renderer implements IRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public setViewArea(viewArea: BoundingBoxBase) {
|
public setViewArea(viewArea: BoundingBoxBase) {
|
||||||
|
const targetRange = 2 ** 7;
|
||||||
|
|
||||||
this.viewBoxSize = viewArea.size;
|
this.viewBoxSize = viewArea.size;
|
||||||
this.viewBoxBottomLeft = vec2.add(
|
this.viewBoxBottomLeft = vec2.add(
|
||||||
vec2.create(),
|
vec2.create(),
|
||||||
viewArea.topLeft,
|
viewArea.topLeft,
|
||||||
vec2.fromValues(0, -viewArea.size.y)
|
vec2.fromValues(0, -viewArea.size.y)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.linearDownscale = targetRange / Math.max(this.viewBoxSize.x, this.viewBoxSize.y);
|
||||||
|
|
||||||
|
this.viewAreaScale = vec2.fromValues(
|
||||||
|
(this.viewBoxSize.x * this.linearDownscale) / 2,
|
||||||
|
(this.viewBoxSize.y * this.linearDownscale) / 2
|
||||||
|
);
|
||||||
|
|
||||||
|
mat2d.fromScaling(
|
||||||
|
this.upscaleTransform,
|
||||||
|
vec2.fromValues(this.linearDownscale, this.linearDownscale)
|
||||||
|
);
|
||||||
|
|
||||||
|
const translate = vec2.scale(vec2.create(), this.viewBoxBottomLeft, -1);
|
||||||
|
vec2.subtract(translate, translate, vec2.scale(vec2.create(), this.viewBoxSize, 0.5));
|
||||||
|
|
||||||
|
mat2d.translate(this.upscaleTransform, this.upscaleTransform, translate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCursorPosition(position: vec2): void {
|
public setCursorPosition(position: vec2): void {
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,9 @@ export const settings = {
|
||||||
},
|
},
|
||||||
tileMultiplier: 8,
|
tileMultiplier: 8,
|
||||||
shaderMacros: {
|
shaderMacros: {
|
||||||
edgeSmoothing: 10,
|
headRadius: 0.05,
|
||||||
headRadius: 5,
|
torsoRadius: 0.08,
|
||||||
torsoRadius: 8,
|
footRadius: 0.02,
|
||||||
footRadius: 2,
|
|
||||||
},
|
},
|
||||||
shaderCombinations: {
|
shaderCombinations: {
|
||||||
lineSteps: [0, 1, 2, 4, 8, 16, 128],
|
lineSteps: [0, 1, 2, 4, 8, 16, 128],
|
||||||
|
|
|
||||||
|
|
@ -69,18 +69,18 @@ uniform float maxMinDistance;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
in vec2 worldCoordinates;
|
in vec2 position;
|
||||||
out vec2 fragmentColor;
|
out vec2 fragmentColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float minDistance = -maxMinDistance;
|
float minDistance = -maxMinDistance;
|
||||||
|
|
||||||
#if LINE_COUNT > 0
|
#if LINE_COUNT > 0
|
||||||
lineMinDistance(worldCoordinates, minDistance);
|
lineMinDistance(position, minDistance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BLOB_COUNT > 0
|
#if BLOB_COUNT > 0
|
||||||
blobMinDistance(worldCoordinates, minDistance);
|
//blobMinDistance(position, minDistance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fragmentColor = vec2(minDistance, 0.0);
|
fragmentColor = vec2(minDistance, 0.0);
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,13 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
#define INFINITY 1000.0
|
#define INFINITY 1000.0
|
||||||
#define LIGHT_DROP 500.0
|
#define LIGHT_DROP 50.0
|
||||||
#define AMBIENT_LIGHT vec3(0.15)
|
#define AMBIENT_LIGHT vec3(0.15)
|
||||||
|
|
||||||
#define CIRCLE_LIGHT_COUNT {circleLightCount}
|
#define CIRCLE_LIGHT_COUNT {circleLightCount}
|
||||||
#define POINT_LIGHT_COUNT {pointLightCount}
|
#define POINT_LIGHT_COUNT {pointLightCount}
|
||||||
#define EDGE_SMOOTHING {edgeSmoothing}
|
|
||||||
|
|
||||||
uniform sampler2D distanceTexture;
|
uniform sampler2D distanceTexture;
|
||||||
uniform vec2 viewBoxSize;
|
|
||||||
|
|
||||||
vec3[4] colors = vec3[4](
|
vec3[4] colors = vec3[4](
|
||||||
vec3(0.5),
|
vec3(0.5),
|
||||||
|
|
@ -50,8 +48,10 @@ float getDistance(in vec2 target) {
|
||||||
in vec2[POINT_LIGHT_COUNT] pointLightDirections;
|
in vec2[POINT_LIGHT_COUNT] pointLightDirections;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
in vec2 worldCoordinates;
|
in vec2 position;
|
||||||
in vec2 uvCoordinates;
|
in vec2 uvCoordinates;
|
||||||
|
uniform vec2 viewAreaScale;
|
||||||
|
|
||||||
out vec4 fragmentColor;
|
out vec4 fragmentColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
@ -63,13 +63,13 @@ void main() {
|
||||||
for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) {
|
for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) {
|
||||||
float lightCenterDistance = distance(
|
float lightCenterDistance = distance(
|
||||||
circleLights[i].center,
|
circleLights[i].center,
|
||||||
worldCoordinates
|
position
|
||||||
);
|
);
|
||||||
float lightDistance = lightCenterDistance - circleLights[i].radius;
|
float lightDistance = lightCenterDistance - circleLights[i].radius;
|
||||||
|
|
||||||
/*if (lightDistance < 0.0) {
|
if (lightDistance < 0.0) {
|
||||||
lighting = vec3(1.0, 1.0, 0.0);
|
lighting = vec3(1.0, 1.0, 0.0);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
vec3 lightColorAtPosition = circleLights[i].value / pow(
|
vec3 lightColorAtPosition = circleLights[i].value / pow(
|
||||||
lightDistance / LIGHT_DROP + 1.0, 2.0
|
lightDistance / LIGHT_DROP + 1.0, 2.0
|
||||||
|
|
@ -77,8 +77,7 @@ void main() {
|
||||||
|
|
||||||
float q = INFINITY;
|
float q = INFINITY;
|
||||||
float rayLength = startingDistance;
|
float rayLength = startingDistance;
|
||||||
vec2 direction = normalize(circleLightDirections[i]) / viewBoxSize;
|
vec2 direction = normalize(circleLightDirections[i]) / viewAreaScale / 2.0;
|
||||||
|
|
||||||
for (int j = 0; j < 48; j++) {
|
for (int j = 0; j < 48; j++) {
|
||||||
if (rayLength >= lightDistance) {
|
if (rayLength >= lightDistance) {
|
||||||
lighting += lightColorAtPosition * clamp(
|
lighting += lightColorAtPosition * clamp(
|
||||||
|
|
@ -124,6 +123,7 @@ void main() {
|
||||||
}*/
|
}*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fragmentColor = vec4(vec3(startingDistance / 100.0), 1.0);
|
||||||
fragmentColor = vec4(
|
fragmentColor = vec4(
|
||||||
colorAtPosition * lighting * step(0.0, startingDistance),
|
colorAtPosition * lighting * step(0.0, startingDistance),
|
||||||
1.0
|
1.0
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
uniform mat3 modelTransform;
|
uniform mat3 modelTransform;
|
||||||
uniform mat3 uvToWorld;
|
uniform vec2 viewAreaScale;
|
||||||
uniform mat3 ndcToUv;
|
|
||||||
|
|
||||||
in vec4 vertexPosition;
|
in vec4 vertexPosition;
|
||||||
out vec2 worldCoordinates;
|
out vec2 position;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 vertexPosition2D = vec3(vertexPosition.xy, 1.0) * modelTransform;
|
vec3 vertexPosition2D = vec3(vertexPosition.xy, 1.0) * modelTransform;
|
||||||
worldCoordinates = (vertexPosition2D * ndcToUv * uvToWorld).xy;
|
|
||||||
gl_Position = vec4(vertexPosition2D.xy, 0.0, 1.0);
|
gl_Position = vec4(vertexPosition2D.xy, 0.0, 1.0);
|
||||||
|
position = vertexPosition2D.xy * viewAreaScale;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,13 @@ precision mediump float;
|
||||||
#define POINT_LIGHT_COUNT {pointLightCount}
|
#define POINT_LIGHT_COUNT {pointLightCount}
|
||||||
|
|
||||||
uniform mat3 modelTransform;
|
uniform mat3 modelTransform;
|
||||||
uniform mat3 cameraTransform;
|
|
||||||
uniform mat3 ndcToUv;
|
|
||||||
uniform mat3 uvToWorld;
|
|
||||||
|
|
||||||
in vec4 vertexPosition;
|
in vec4 vertexPosition;
|
||||||
|
|
||||||
out vec2 worldCoordinates;
|
out vec2 position;
|
||||||
out vec2 uvCoordinates;
|
out vec2 uvCoordinates;
|
||||||
|
|
||||||
|
uniform vec2 viewAreaScale;
|
||||||
|
|
||||||
#if CIRCLE_LIGHT_COUNT > 0
|
#if CIRCLE_LIGHT_COUNT > 0
|
||||||
uniform struct CircleLight {
|
uniform struct CircleLight {
|
||||||
vec2 center;
|
vec2 center;
|
||||||
|
|
@ -37,21 +35,24 @@ out vec2 uvCoordinates;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 vertexPosition2D = vec3(vertexPosition.xy, 1.0) * modelTransform;
|
vec3 vertexPosition2D = vec3(vertexPosition.xy, 1.0) * modelTransform;
|
||||||
vec3 uvCoordinates1 = vertexPosition2D * ndcToUv;
|
gl_Position = vec4(vertexPosition2D.xy, 0.0, 1.0);
|
||||||
worldCoordinates = (uvCoordinates1 * uvToWorld).xy;
|
position = vertexPosition2D.xy * viewAreaScale;
|
||||||
uvCoordinates = (uvCoordinates1).xy;
|
|
||||||
|
uvCoordinates = (vertexPosition2D * mat3(
|
||||||
|
0.5, 0.0, 0.5,
|
||||||
|
0.0, 0.5, 0.5,
|
||||||
|
0.0, 0.0, 1.0
|
||||||
|
)).xy;
|
||||||
|
|
||||||
#if CIRCLE_LIGHT_COUNT > 0
|
#if CIRCLE_LIGHT_COUNT > 0
|
||||||
for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) {
|
for (int i = 0; i < CIRCLE_LIGHT_COUNT; i++) {
|
||||||
circleLightDirections[i] = circleLights[i].center - worldCoordinates;
|
circleLightDirections[i] = circleLights[i].center - position;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if POINT_LIGHT_COUNT > 0
|
#if POINT_LIGHT_COUNT > 0
|
||||||
for (int i = 0; i < POINT_LIGHT_COUNT; i++) {
|
for (int i = 0; i < POINT_LIGHT_COUNT; i++) {
|
||||||
pointLightDirections[i] = pointLights[i].center - worldCoordinates;
|
pointLightDirections[i] = pointLights[i].center - position;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_Position = vec4(vertexPosition2D.xy, 0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { CommandGenerator } from '../commands/command-generator';
|
||||||
import { clamp01 } from '../helper/clamp';
|
import { clamp01 } from '../helper/clamp';
|
||||||
import { CursorMoveCommand } from './commands/cursor-move-command';
|
import { CursorMoveCommand } from './commands/cursor-move-command';
|
||||||
import { PrimaryActionCommand } from './commands/primary-action';
|
import { PrimaryActionCommand } from './commands/primary-action';
|
||||||
import { SwipeCommand } from './commands/swipe';
|
|
||||||
import { SecondaryActionCommand } from './commands/secondary-action';
|
import { SecondaryActionCommand } from './commands/secondary-action';
|
||||||
|
import { SwipeCommand } from './commands/swipe';
|
||||||
import { ZoomCommand } from './commands/zoom';
|
import { ZoomCommand } from './commands/zoom';
|
||||||
|
|
||||||
export class MouseListener extends CommandGenerator {
|
export class MouseListener extends CommandGenerator {
|
||||||
|
|
@ -39,11 +39,11 @@ export class MouseListener extends CommandGenerator {
|
||||||
this.sendCommand(new CursorMoveCommand(position));
|
this.sendCommand(new CursorMoveCommand(position));
|
||||||
});
|
});
|
||||||
|
|
||||||
target.addEventListener('mouseup', (event: MouseEvent) => {
|
target.addEventListener('mouseup', (_: MouseEvent) => {
|
||||||
this.isMouseDown = false;
|
this.isMouseDown = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
target.addEventListener('mouseleave', (event: MouseEvent) => {
|
target.addEventListener('mouseleave', (_: MouseEvent) => {
|
||||||
this.isMouseDown = false;
|
this.isMouseDown = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,8 @@ import { Lamp } from './lamp';
|
||||||
|
|
||||||
export class Character extends GameObject {
|
export class Character extends GameObject {
|
||||||
private keysDown: Set<string> = new Set();
|
private keysDown: Set<string> = new Set();
|
||||||
|
|
||||||
private light = new Lamp(vec2.create(), 40, vec3.fromValues(0.67, 0.0, 0.33), 2);
|
private light = new Lamp(vec2.create(), 40, vec3.fromValues(0.67, 0.0, 0.33), 2);
|
||||||
|
|
||||||
private shape = new DrawableBlob(vec2.create());
|
private shape = new DrawableBlob(vec2.create());
|
||||||
|
|
||||||
private static speed = 1.5;
|
private static speed = 1.5;
|
||||||
|
|
||||||
constructor(private game: IGame) {
|
constructor(private game: IGame) {
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,22 @@
|
||||||
import { vec2 } from 'gl-matrix';
|
import { vec2 } from 'gl-matrix';
|
||||||
import { IShape } from '../i-shape';
|
|
||||||
import { BoundingBox } from '../bounding-box';
|
|
||||||
import { Circle } from './circle';
|
|
||||||
import { settings } from '../../drawing/settings';
|
import { settings } from '../../drawing/settings';
|
||||||
import { GameObject } from '../../objects/game-object';
|
import { GameObject } from '../../objects/game-object';
|
||||||
|
import { BoundingBox } from '../bounding-box';
|
||||||
|
import { IShape } from '../i-shape';
|
||||||
|
import { Circle } from './circle';
|
||||||
|
|
||||||
export class Blob implements IShape {
|
export class Blob implements IShape {
|
||||||
private static readonly boundingCircleRadius = 19;
|
private static readonly boundingCircleRadius = 19;
|
||||||
|
|
||||||
private static readonly headOffset = vec2.fromValues(0, 15);
|
private static readonly headOffset = vec2.fromValues(0, 15);
|
||||||
|
|
||||||
private static readonly torsoOffset = vec2.fromValues(0, 0);
|
private static readonly torsoOffset = vec2.fromValues(0, 0);
|
||||||
|
|
||||||
private static readonly leftFootOffset = vec2.fromValues(-5, -10);
|
private static readonly leftFootOffset = vec2.fromValues(-5, -10);
|
||||||
|
|
||||||
private static readonly rightFootOffset = vec2.fromValues(5, -10);
|
private static readonly rightFootOffset = vec2.fromValues(5, -10);
|
||||||
|
|
||||||
public readonly isInverted = false;
|
public readonly isInverted = false;
|
||||||
|
|
||||||
protected boundingCircle = new Circle(vec2.create(), Blob.boundingCircleRadius);
|
protected boundingCircle = new Circle(vec2.create(), Blob.boundingCircleRadius);
|
||||||
|
|
||||||
protected head = new Circle(vec2.create(), settings.shaderMacros.headRadius);
|
protected head = new Circle(vec2.create(), settings.shaderMacros.headRadius);
|
||||||
|
|
||||||
protected torso = new Circle(vec2.create(), settings.shaderMacros.torsoRadius);
|
protected torso = new Circle(vec2.create(), settings.shaderMacros.torsoRadius);
|
||||||
|
|
||||||
protected leftFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius);
|
protected leftFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius);
|
||||||
|
|
||||||
protected rightFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius);
|
protected rightFoot = new Circle(vec2.create(), settings.shaderMacros.footRadius);
|
||||||
|
|
||||||
public constructor(center: vec2, public readonly gameObject: GameObject = null) {
|
public constructor(center: vec2, public readonly gameObject: GameObject = null) {
|
||||||
this.position = center;
|
this.position = center;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue