Add frame buffers

This commit is contained in:
schmelczerandras 2020-07-22 15:09:59 +02:00
commit 582979d3ed
5 changed files with 308 additions and 101 deletions

View file

@ -0,0 +1,26 @@
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
import { FrameBuffer } from './frame-buffer';
export class DefaultFrameBuffer extends FrameBuffer {
constructor(
gl: WebGL2RenderingContext,
programs: Array<FragmentShaderOnlyProgram>
) {
super(gl, programs);
this.frameBuffer = null;
this.setSize();
}
public setSize() {
super.setSize();
if (
this.gl.canvas.width !== this.size.x ||
this.gl.canvas.height !== this.size.y
) {
this.gl.canvas.width = this.size.x;
this.gl.canvas.height = this.size.y;
}
}
}

View file

@ -59,6 +59,19 @@ export class FragmentShaderOnlyProgram {
type: glUniform.type,
});
}
console.log(this.uniforms);
this.uniforms.map((u1) => {
const isSingle =
this.uniforms.filter((u2) => u2.name.includes(u1.name[0])).length == 1;
if (u1.name.includes('0') && isSingle) {
u1.name = u1.name.slice(0, -1);
}
return u1;
});
console.log(this.uniforms);
}
private createProgram(fragmentShaderSource: string) {

View file

@ -0,0 +1,48 @@
import { Vec2 } from '../../math/vec2';
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
export abstract class FrameBuffer {
public renderScale = 1;
public enableHighDpiRendering = false;
protected size: Vec2;
protected frameBuffer: WebGLFramebuffer;
constructor(
protected gl: WebGL2RenderingContext,
protected programs: Array<FragmentShaderOnlyProgram>
) {}
public render(uniforms: any, input?: WebGLTexture) {
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer);
if (input !== null) {
this.gl.bindTexture(this.gl.TEXTURE_2D, input);
}
this.gl.viewport(0, 0, this.size.x, this.size.y);
this.gl.clearColor(0, 0, 0, 0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
this.programs.forEach((p) => {
p.bind();
p.setUniforms(uniforms);
p.draw();
});
}
public setSize() {
const realToCssPixels = window.devicePixelRatio * this.renderScale;
const canvasWidth = (this.gl.canvas as HTMLCanvasElement).clientWidth;
const canvasHeight = (this.gl.canvas as HTMLCanvasElement).clientHeight;
const displayWidth = Math.floor(canvasWidth * realToCssPixels);
const displayHeight = Math.floor(canvasHeight * realToCssPixels);
this.size = new Vec2(displayWidth, displayHeight);
}
public getSize(): Vec2 {
return this.size;
}
}

View file

@ -0,0 +1,75 @@
import { FragmentShaderOnlyProgram } from './fragment-shader-only-program';
import { FrameBuffer } from './frame-buffer';
export class IntermediateFrameBuffer extends FrameBuffer {
private frameTexture: WebGLTexture;
constructor(
gl: WebGL2RenderingContext,
programs: Array<FragmentShaderOnlyProgram>
) {
super(gl, programs);
this.frameTexture = this.gl.createTexture();
this.configureTexture();
this.frameBuffer = this.gl.createFramebuffer();
this.configureFrameBuffer();
this.setSize();
}
public get texture(): WebGLTexture {
return this.frameTexture;
}
public setSize() {
super.setSize();
this.gl.bindTexture(this.gl.TEXTURE_2D, this.frameTexture);
this.gl.texImage2D(
this.gl.TEXTURE_2D,
0,
this.gl.RGBA,
this.size.x,
this.size.y,
0,
this.gl.RGBA,
this.gl.UNSIGNED_BYTE,
null
);
}
private configureTexture() {
this.gl.bindTexture(this.gl.TEXTURE_2D, this.frameTexture);
this.gl.texParameteri(
this.gl.TEXTURE_2D,
this.gl.TEXTURE_MIN_FILTER,
this.gl.LINEAR
);
this.gl.texParameteri(
this.gl.TEXTURE_2D,
this.gl.TEXTURE_WRAP_S,
this.gl.CLAMP_TO_EDGE
);
this.gl.texParameteri(
this.gl.TEXTURE_2D,
this.gl.TEXTURE_WRAP_T,
this.gl.CLAMP_TO_EDGE
);
}
private configureFrameBuffer() {
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer);
const attachmentPoint = this.gl.COLOR_ATTACHMENT0;
this.gl.framebufferTexture2D(
this.gl.FRAMEBUFFER,
attachmentPoint,
this.gl.TEXTURE_2D,
this.frameTexture,
0
);
}
}

View file

@ -16,12 +16,24 @@ export const loadUniform = (
) => void
> = new Map();
{
converters.set(WebGL2RenderingContext.FLOAT, (gl, v, l) =>
gl.uniform1f(l, v)
);
converters.set(WebGL2RenderingContext.FLOAT, (gl, v, l) => {
gl.uniform1fv(l, new Float32Array(v));
});
converters.set(WebGL2RenderingContext.FLOAT_VEC2, (gl, v: Vec2, l) =>
gl.uniform2fv(l, new Float32Array(v.list))
converters.set(
WebGL2RenderingContext.FLOAT_VEC2,
(gl, v: Vec2 | Array<Vec2>, l) => {
if (v instanceof Array) {
const result = new Float32Array(v.length * 2);
for (let i = 0; i < v.length; i++) {
result[2 * i] = v[i].x;
result[2 * i + 1] = v[i].y;
}
gl.uniform2fv(l, new Float32Array(result));
} else {
gl.uniform2fv(l, new Float32Array(v.list));
}
}
);
converters.set(WebGL2RenderingContext.FLOAT_MAT3, (gl, v: Mat3, l) =>