UNPKG

gl-tiled

Version:

A Tiled editor renderer for WebGL.

125 lines (95 loc) 3.21 kB
// @if DEBUG import { ASSERT } from './debug'; // @endif import { IImagelayer } from './tiled/layers'; import { loadImage } from './utils/loadImage'; import { parseColorStr } from './utils/parseColorStr'; import { ELayerType } from './ELayerType'; import { GLProgram } from './utils/GLProgram'; import { IAssetCache } from './IAssetCache'; export class GLImagelayer { type: ELayerType.Imagelayer = ELayerType.Imagelayer; scrollScaleX = 1; scrollScaleY = 1; gl: WebGLRenderingContext | null = null; texture: WebGLTexture | null = null; image: TexImageSource | null = null; alpha: number; private _transparentColor: Float32Array; constructor(public readonly desc: IImagelayer, assetCache?: IAssetCache) { this.alpha = typeof desc.opacity === 'number' ? desc.opacity : 1.0; // parse the transparent color this._transparentColor = new Float32Array(4); if (desc.transparentcolor) parseColorStr(desc.transparentcolor, this._transparentColor); loadImage(desc.image, assetCache, (errEvent, img) => { this.image = img; this.upload(); }); } glInitialize(gl: WebGLRenderingContext): void { this.glTerminate(); this.gl = gl; this.texture = gl.createTexture(); this.upload(); } glTerminate(): void { if (!this.gl) return; if (this.texture) { this.gl.deleteTexture(this.texture); this.texture = null; } this.gl = null; } upload(): void { if (!this.gl || !this.image) return; this.setupTexture(); this.uploadData(false); } uploadUniforms(shader: GLProgram): void { if (!this.gl || !this.image) return; const gl = this.gl; // @if DEBUG ASSERT(!!(shader.uniforms.uAlpha && shader.uniforms.uTransparentColor && shader.uniforms.uSize), 'Invalid uniforms for image layer.'); // @endif gl.uniform1f(shader.uniforms.uAlpha!, this.alpha); gl.uniform4fv(shader.uniforms.uTransparentColor!, this._transparentColor); gl.uniform2f(shader.uniforms.uSize!, this.image.width, this.image.height); } uploadData(doBind: boolean = true): void { if (!this.gl || !this.image) return; const gl = this.gl; if (doBind) gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image); } setupTexture(doBind: boolean = true): void { if (!this.gl) return; const gl = this.gl; if (doBind) gl.bindTexture(gl.TEXTURE_2D, this.texture); // TODO: Allow user to set filtering gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 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); } }