Add lighting shader
This commit is contained in:
parent
e88b4589d2
commit
0cd383794c
11 changed files with 144 additions and 295 deletions
|
|
@ -0,0 +1,8 @@
|
|||
import { Command } from '../command';
|
||||
import { vec2 } from 'gl-matrix';
|
||||
|
||||
export class CursorMoveCommand extends Command {
|
||||
public constructor(public readonly position?: vec2) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,15 +6,17 @@ import { Rectangle } from '../math/rectangle';
|
|||
import { IntermediateFrameBuffer } from './graphics-library/intermediate-frame-buffer';
|
||||
import { FrameBuffer } from './graphics-library/frame-buffer';
|
||||
import { DefaultFrameBuffer } from './graphics-library/default-frame-buffer';
|
||||
import { translate } from 'gl-matrix/src/gl-matrix/mat2d';
|
||||
|
||||
export class WebGl2Renderer implements Drawer {
|
||||
private gl: WebGL2RenderingContext;
|
||||
private stopwatch: WebGlStopwatch;
|
||||
|
||||
private viewBox: Rectangle = new Rectangle();
|
||||
private nextFrameUniforms: any;
|
||||
private uniforms: any;
|
||||
private cursorPosition = vec2.create();
|
||||
private frameBuffers: Array<FrameBuffer> = [];
|
||||
private distanceFieldFrameBuffer: IntermediateFrameBuffer;
|
||||
private lightingFrameBuffer: DefaultFrameBuffer;
|
||||
|
||||
constructor(
|
||||
private canvas: HTMLCanvasElement,
|
||||
|
|
@ -26,20 +28,16 @@ export class WebGl2Renderer implements Drawer {
|
|||
throw new Error('WebGl2 is not supported');
|
||||
}
|
||||
|
||||
this.frameBuffers.push(
|
||||
new IntermediateFrameBuffer(this.gl, [
|
||||
new FragmentShaderOnlyProgram(this.gl, shaderSources[0]),
|
||||
])
|
||||
);
|
||||
this.distanceFieldFrameBuffer = new IntermediateFrameBuffer(this.gl, [
|
||||
new FragmentShaderOnlyProgram(this.gl, shaderSources[0]),
|
||||
]);
|
||||
|
||||
this.frameBuffers.push(
|
||||
new DefaultFrameBuffer(this.gl, [
|
||||
new FragmentShaderOnlyProgram(this.gl, shaderSources[1]),
|
||||
])
|
||||
);
|
||||
this.lightingFrameBuffer = new DefaultFrameBuffer(this.gl, [
|
||||
new FragmentShaderOnlyProgram(this.gl, shaderSources[1]),
|
||||
]);
|
||||
|
||||
this.frameBuffers[0].renderScale = 1;
|
||||
this.frameBuffers[1].renderScale = 1;
|
||||
this.distanceFieldFrameBuffer.renderScale = 0.2;
|
||||
this.lightingFrameBuffer.renderScale = 1;
|
||||
|
||||
try {
|
||||
this.stopwatch = new WebGlStopwatch(this.gl);
|
||||
|
|
@ -48,13 +46,54 @@ export class WebGl2Renderer implements Drawer {
|
|||
|
||||
startFrame(): void {
|
||||
this.stopwatch?.start();
|
||||
this.nextFrameUniforms = {};
|
||||
this.frameBuffers.forEach((f) => f.setSize());
|
||||
this.uniforms = {};
|
||||
this.distanceFieldFrameBuffer.setSize();
|
||||
this.lightingFrameBuffer.setSize();
|
||||
}
|
||||
|
||||
public finishFrame() {
|
||||
const resolution = vec2.fromValues(this.canvas.width, this.canvas.height);
|
||||
|
||||
const distanceScreenToWorld = this.getScreenToWorldTransform(
|
||||
this.distanceFieldFrameBuffer.getSize()
|
||||
);
|
||||
|
||||
const lightingScreenToWorld = this.getScreenToWorldTransform(
|
||||
this.lightingFrameBuffer.getSize()
|
||||
);
|
||||
|
||||
const screenToWorld = this.getScreenToWorldTransform(resolution);
|
||||
|
||||
const worldToDistanceUV = mat2d.scale(
|
||||
mat2d.create(),
|
||||
distanceScreenToWorld,
|
||||
this.distanceFieldFrameBuffer.getSize()
|
||||
);
|
||||
mat2d.invert(worldToDistanceUV, worldToDistanceUV);
|
||||
|
||||
const cursorPosition = vec2.transformMat2d(
|
||||
vec2.create(),
|
||||
vec2.multiply(vec2.create(), this.cursorPosition, resolution),
|
||||
screenToWorld
|
||||
);
|
||||
|
||||
this.giveUniforms({
|
||||
distanceScreenToWorld,
|
||||
lightingScreenToWorld,
|
||||
worldToDistanceUV,
|
||||
cursorPosition,
|
||||
});
|
||||
|
||||
this.distanceFieldFrameBuffer.render(this.uniforms);
|
||||
this.lightingFrameBuffer.render(
|
||||
this.uniforms,
|
||||
this.distanceFieldFrameBuffer.texture
|
||||
);
|
||||
|
||||
this.stopwatch?.stop();
|
||||
}
|
||||
|
||||
private getScreenToWorldTransform(screenSize: vec2) {
|
||||
const transform = mat2d.fromTranslation(
|
||||
mat2d.create(),
|
||||
this.viewBox.topLeft
|
||||
|
|
@ -62,29 +101,11 @@ export class WebGl2Renderer implements Drawer {
|
|||
mat2d.scale(
|
||||
transform,
|
||||
transform,
|
||||
vec2.divide(
|
||||
vec2.create(),
|
||||
this.viewBox.size,
|
||||
this.frameBuffers[0].getSize()
|
||||
)
|
||||
vec2.divide(vec2.create(), this.viewBox.size, screenSize)
|
||||
);
|
||||
mat2d.translate(transform, transform, vec2.fromValues(0.5, 0.5));
|
||||
this.nextFrameUniforms.transform = transform;
|
||||
|
||||
const transformUV = mat2d.fromScaling(
|
||||
mat2d.create(),
|
||||
vec2.divide(vec2.create(), vec2.fromValues(1, 1), resolution)
|
||||
);
|
||||
mat2d.translate(transformUV, transformUV, vec2.fromValues(0.5, 0.5));
|
||||
this.nextFrameUniforms.transformUV = transformUV;
|
||||
|
||||
this.frameBuffers[0].render(this.nextFrameUniforms);
|
||||
this.frameBuffers[1].render(
|
||||
this.nextFrameUniforms,
|
||||
(this.frameBuffers[0] as IntermediateFrameBuffer).texture
|
||||
);
|
||||
|
||||
this.stopwatch?.stop();
|
||||
return transform;
|
||||
}
|
||||
|
||||
public setCameraPosition(position: vec2) {
|
||||
|
|
@ -96,7 +117,7 @@ export class WebGl2Renderer implements Drawer {
|
|||
}
|
||||
|
||||
public giveUniforms(uniforms: any): void {
|
||||
this.nextFrameUniforms = { ...this.nextFrameUniforms, ...uniforms };
|
||||
this.uniforms = { ...this.uniforms, ...uniforms };
|
||||
}
|
||||
|
||||
public setInViewArea(size: number): vec2 {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import { InfoText } from './objects/types/info-text';
|
|||
import { timeIt } from './helper/timing';
|
||||
|
||||
import caveFragmentShader from '../shaders/cave-distance-fs.glsl';
|
||||
import lightsShader from '../shaders/rainbow-shading-fs.glsl';
|
||||
//import lightsShader from '../shaders/lights-shading-fs.glsl';
|
||||
// import lightsShader from '../shaders/rainbow-shading-fs.glsl';
|
||||
import lightsShader from '../shaders/lights-shading-fs.glsl';
|
||||
import { Dungeon } from './objects/types/dungeon';
|
||||
import { BeforeDrawCommand } from './commands/types/before-draw';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { SwipeCommand } from '../commands/types/swipe';
|
|||
import { ZoomCommand } from '../commands/types/zoom';
|
||||
import { vec2 } from 'gl-matrix';
|
||||
import { clamp01 } from '../helper/clamp';
|
||||
import { CursorMoveCommand } from '../commands/types/cursor-move-command';
|
||||
|
||||
export class MouseListener extends CommandGenerator {
|
||||
private previousPosition = vec2.create();
|
||||
|
|
@ -25,8 +26,9 @@ export class MouseListener extends CommandGenerator {
|
|||
});
|
||||
|
||||
target.addEventListener('mousemove', (event: MouseEvent) => {
|
||||
const position = this.positionFromEvent(event);
|
||||
|
||||
if (this.isMouseDown) {
|
||||
const position = this.positionFromEvent(event);
|
||||
this.sendCommand(
|
||||
new SwipeCommand(
|
||||
vec2.subtract(vec2.create(), this.previousPosition, position)
|
||||
|
|
@ -34,6 +36,8 @@ export class MouseListener extends CommandGenerator {
|
|||
);
|
||||
this.previousPosition = position;
|
||||
}
|
||||
|
||||
this.sendCommand(new CursorMoveCommand(position));
|
||||
});
|
||||
|
||||
target.addEventListener('mouseup', (event: MouseEvent) => {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { ZoomCommand } from '../../commands/types/zoom';
|
|||
import { BeforeDrawCommand } from '../../commands/types/before-draw';
|
||||
import { PrimaryActionCommand } from '../../commands/types/primary-action';
|
||||
import { vec2 } from 'gl-matrix';
|
||||
import { CursorMoveCommand } from '../../commands/types/cursor-move-command';
|
||||
|
||||
export class Camera extends GameObject {
|
||||
private inViewArea = 1920 * 1080;
|
||||
|
|
@ -14,11 +15,11 @@ export class Camera extends GameObject {
|
|||
|
||||
this.addCommandExecutor(BeforeDrawCommand, this.draw.bind(this));
|
||||
this.addCommandExecutor(MoveToCommand, this.moveTo.bind(this));
|
||||
this.addCommandExecutor(ZoomCommand, this.zoom.bind(this));
|
||||
this.addCommandExecutor(
|
||||
PrimaryActionCommand,
|
||||
CursorMoveCommand,
|
||||
this.setCursorPosition.bind(this)
|
||||
);
|
||||
this.addCommandExecutor(ZoomCommand, this.zoom.bind(this));
|
||||
}
|
||||
|
||||
private draw(c: BeforeDrawCommand) {
|
||||
|
|
@ -35,7 +36,7 @@ export class Camera extends GameObject {
|
|||
this.inViewArea *= c.factor;
|
||||
}
|
||||
|
||||
private setCursorPosition(c: PrimaryActionCommand) {
|
||||
private setCursorPosition(c: CursorMoveCommand) {
|
||||
this.cursorPosition = c.position;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ export class Dungeon extends GameObject {
|
|||
let previousRadius = 0;
|
||||
let previousEnd = vec2.create();
|
||||
|
||||
for (let i = 0; i < 5000; i += 50) {
|
||||
const height = previousEnd.y + (Math.random() - 0.5) * 200;
|
||||
for (let i = 0; i < 500000; i += 500) {
|
||||
const height = previousEnd.y + (Math.random() - 0.5) * 2000;
|
||||
const currentEnd = vec2.fromValues(i, height);
|
||||
const currentToRadius = Math.random() * 10 + 30;
|
||||
const currentToRadius = Math.random() * 10 + 300;
|
||||
|
||||
this.lines.push({
|
||||
start: previousEnd,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue