Add lighting shader

This commit is contained in:
schmelczerandras 2020-07-22 22:47:26 +02:00
parent e88b4589d2
commit 0cd383794c
11 changed files with 144 additions and 295 deletions

View file

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