mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-07-29 19:41:47 +08:00
107 lines
2.8 KiB
TypeScript
107 lines
2.8 KiB
TypeScript
import { MotaOffscreenCanvas2D } from './canvas2d';
|
|
import { EGL2Event, GL2, GL2Program, IGL2ProgramPrefix } from './gl2';
|
|
|
|
const SHADER_PREFIX: IGL2ProgramPrefix = {
|
|
VERTEX: /* glsl */ `#version 300 es
|
|
precision highp float;
|
|
|
|
in vec4 a_position;
|
|
in vec2 a_texCoord;
|
|
|
|
out vec2 v_texCoord;
|
|
`,
|
|
FRAGMENT: /* glsl */ `#version 300 es
|
|
precision highp float;
|
|
|
|
in vec2 v_texCoord;
|
|
|
|
uniform sampler2D u_sampler;
|
|
`
|
|
};
|
|
|
|
const DEFAULT_VS = /* glsl */ `
|
|
void main() {
|
|
v_texCoord = a_texCoord;
|
|
gl_Position = a_position;
|
|
}
|
|
`;
|
|
const DEFAULT_FS = /* glsl */ `
|
|
out vec4 color;
|
|
|
|
void main() {
|
|
color = texture(u_sampler, v_texCoord);
|
|
}
|
|
`;
|
|
|
|
export interface EShaderEvent extends EGL2Event {}
|
|
|
|
export class Shader<E extends EShaderEvent = EShaderEvent> extends GL2<
|
|
EShaderEvent | E
|
|
> {
|
|
protected drawScene(
|
|
canvas: MotaOffscreenCanvas2D,
|
|
gl: WebGL2RenderingContext,
|
|
program: GL2Program
|
|
): void {
|
|
if (!program.modified) return;
|
|
const tex = program.getTexture('u_sampler');
|
|
if (!tex) return;
|
|
const c = canvas.canvas;
|
|
if (tex.width === c.width && tex.height === c.height) {
|
|
tex.sub(c, 0, 0, c.width, c.height);
|
|
} else {
|
|
tex.set(c);
|
|
}
|
|
this.draw(gl, program);
|
|
}
|
|
}
|
|
|
|
export class ShaderProgram extends GL2Program {
|
|
protected readonly prefix: IGL2ProgramPrefix = SHADER_PREFIX;
|
|
|
|
constructor(gl2: GL2, vs?: string, fs?: string) {
|
|
super(gl2, vs, fs);
|
|
if (!vs) this.vs(DEFAULT_VS);
|
|
if (!fs) this.fs(DEFAULT_FS);
|
|
if (!vs && !fs) {
|
|
this.modified = false;
|
|
}
|
|
}
|
|
|
|
ready(): boolean {
|
|
this.useIndices('defaultIndices');
|
|
return true;
|
|
}
|
|
|
|
protected override compile() {
|
|
const success = super.compile();
|
|
if (!success) return false;
|
|
const shader = this.element;
|
|
const gl = shader.gl;
|
|
if (!gl) return false;
|
|
|
|
const tex = this.defineAttribArray('a_texCoord');
|
|
const position = this.defineAttribArray('a_position');
|
|
const sampler = this.defineTexture('u_sampler', 0);
|
|
const indices = this.defineIndices('defaultIndices');
|
|
if (!tex || !position || !sampler || !indices) {
|
|
return true;
|
|
}
|
|
position.buffer(
|
|
new Float32Array([1, -1, -1, -1, 1, 1, -1, 1]),
|
|
gl.STATIC_DRAW
|
|
);
|
|
position.pointer(2, gl.FLOAT, false, 0, 0);
|
|
position.enable();
|
|
tex.buffer(new Float32Array([1, 1, 0, 1, 1, 0, 0, 0]), gl.STATIC_DRAW);
|
|
tex.pointer(2, gl.FLOAT, false, 0, 0);
|
|
tex.enable();
|
|
indices.buffer(new Uint16Array([0, 1, 2, 2, 3, 1]), gl.STATIC_DRAW);
|
|
this.useIndices(indices);
|
|
this.mode(this.element.DRAW_ELEMENTS);
|
|
this.paramElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
|
|
|
return true;
|
|
}
|
|
}
|