Add textures

This commit is contained in:
schmelczerandras 2020-10-04 10:48:26 +02:00
parent 5723b91b32
commit 7bfad8711b
25 changed files with 407 additions and 104 deletions

View file

@ -1,4 +1,5 @@
import { vec2 } from 'gl-matrix';
import { Texture } from '../texture/texture';
import { UniversalRenderingContext } from '../universal-rendering-context';
/** @internal */
@ -13,13 +14,10 @@ export abstract class FrameBuffer {
constructor(protected readonly gl: UniversalRenderingContext) {}
public bindAndClear(inputTextures: Array<WebGLTexture>) {
public bindAndClear(inputTextures: Array<Texture>) {
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.frameBuffer);
inputTextures.forEach((t, i) => {
this.gl.activeTexture(this.gl.TEXTURE0 + i);
this.gl.bindTexture(this.gl.TEXTURE_2D, t);
});
inputTextures.forEach((t) => t.bind());
this.gl.viewport(0, 0, this.size.x, this.size.y);
}

View file

@ -1,65 +0,0 @@
import { vec3, vec4 } from 'gl-matrix';
import { UniversalRenderingContext } from './universal-rendering-context';
/** @internal */
export class PaletteTexture {
private texture: WebGLTexture;
constructor(
private readonly gl: UniversalRenderingContext,
private readonly paletteSize: number
) {
this.texture = gl.createTexture()!;
this.bind();
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
}
public get colorTexture(): WebGLTexture {
return this.texture;
}
private bind() {
this.gl.activeTexture(this.gl.TEXTURE1);
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
}
public setPalette(colors: Array<vec3 | vec4>) {
const canvas = document.createElement('canvas');
canvas.width = this.paletteSize;
canvas.height = 1;
const ctx = canvas.getContext('2d')!;
const imageData = ctx.createImageData(this.paletteSize, 1);
colors.forEach((c, i) => {
imageData.data[4 * i + 0] = c[0] * 255;
imageData.data[4 * i + 1] = c[1] * 255;
imageData.data[4 * i + 2] = c[2] * 255;
imageData.data[4 * i + 3] = c.length == 4 ? c[3] * 255 : 255;
});
ctx.putImageData(imageData, 0, 0);
this.setImage(canvas);
}
public setImage(image: TexImageSource) {
this.bind();
this.gl.texImage2D(
this.gl.TEXTURE_2D,
0,
this.gl.RGBA,
this.gl.RGBA,
this.gl.UNSIGNED_BYTE,
image
);
}
public destroy() {
this.gl.deleteTexture(this.texture);
}
}

View file

@ -16,10 +16,10 @@ export class FragmentShaderOnlyProgram extends Program {
public async initialize(
sources: [string, string],
substitutions: { [name: string]: string },
compiler: ParallelCompiler
compiler: ParallelCompiler,
substitutions: { [name: string]: string } = {}
): Promise<void> {
await super.initialize(sources, substitutions, compiler);
await super.initialize(sources, compiler, substitutions);
this.prepareScreenQuad('vertexPosition');
}
@ -32,7 +32,7 @@ export class FragmentShaderOnlyProgram extends Program {
}
}
public draw(uniforms: { [name: string]: any }) {
public draw(uniforms: { [name: string]: any } = {}) {
super.draw(uniforms);
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
}

View file

@ -20,8 +20,8 @@ export default abstract class Program implements IProgram {
public async initialize(
[vertexShaderSource, fragmentShaderSource]: [string, string],
substitutions: { [name: string]: string },
compiler: ParallelCompiler
compiler: ParallelCompiler,
substitutions: { [name: string]: string } = {}
): Promise<void> {
substitutions = { ...substitutions };

View file

@ -0,0 +1,29 @@
import { vec3, vec4 } from 'gl-matrix';
import { UniversalRenderingContext } from '../universal-rendering-context';
import { Texture } from './texture';
/** @internal */
export class PaletteTexture extends Texture {
constructor(gl: UniversalRenderingContext, private readonly paletteSize: number) {
super(gl, 1);
}
public setPalette(colors: Array<vec3 | vec4>) {
const canvas = document.createElement('canvas');
canvas.width = this.paletteSize;
canvas.height = 1;
const ctx = canvas.getContext('2d')!;
const imageData = ctx.createImageData(this.paletteSize, 1);
colors.forEach((c, i) => {
imageData.data[4 * i + 0] = c[0] * 255;
imageData.data[4 * i + 1] = c[1] * 255;
imageData.data[4 * i + 2] = c[2] * 255;
imageData.data[4 * i + 3] = c.length == 4 ? c[3] * 255 : 255;
});
ctx.putImageData(imageData, 0, 0);
this.setImage(canvas);
}
}

View file

@ -0,0 +1,22 @@
export enum WrapOptions {
CLAMP_TO_EDGE = 'CLAMP_TO_EDGE',
REPEAT = 'REPEAT',
MIRRORED_REPEAT = 'MIRRORED_REPEAT',
}
export enum FilteringOptions {
LINEAR = 'LINEAR',
NEAREST = 'NEAREST',
}
export interface TextureOptions {
wrapS: WrapOptions;
wrapT: WrapOptions;
minFilter: FilteringOptions;
maxFilter: FilteringOptions;
}
export type TextureWithOptions = {
source: TexImageSource;
overrides: Partial<TextureOptions>;
};

View file

@ -0,0 +1,62 @@
import { UniversalRenderingContext } from '../universal-rendering-context';
import { FilteringOptions, TextureOptions, WrapOptions } from './texture-options';
/**
* @internal
*/
export class Texture {
protected texture: WebGLTexture;
constructor(
protected readonly gl: UniversalRenderingContext,
private textureUnitId: number,
textureOptionOverrides: Partial<TextureOptions> = {}
) {
const defaultTextureOptions: TextureOptions = {
wrapS: WrapOptions.CLAMP_TO_EDGE,
wrapT: WrapOptions.CLAMP_TO_EDGE,
minFilter: FilteringOptions.NEAREST,
maxFilter: FilteringOptions.NEAREST,
};
const textureOptions = {
...defaultTextureOptions,
...textureOptionOverrides,
};
this.texture = gl.createTexture()!;
this.bind();
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl[textureOptions.wrapS]);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl[textureOptions.wrapT]);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl[textureOptions.minFilter]);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl[textureOptions.maxFilter]);
}
public get colorTexture(): WebGLTexture {
return this.texture;
}
public bind() {
this.gl.activeTexture(this.gl.TEXTURE0 + this.textureUnitId);
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture);
}
public setImage(image: TexImageSource) {
this.bind();
this.gl.texImage2D(
this.gl.TEXTURE_2D,
0,
this.gl.RGBA,
this.gl.RGBA,
this.gl.UNSIGNED_BYTE,
image
);
}
public destroy() {
this.gl.deleteTexture(this.texture);
}
}