着色器特效支持动画

This commit is contained in:
unanmed 2023-08-28 13:06:53 +08:00
parent f15007513a
commit a06021531d

View File

@ -1,6 +1,6 @@
import { Ticker } from 'mutate-animate'; import { Animation, Ticker, hyper } from 'mutate-animate';
import { EmitableEvent, EventEmitter } from '../common/eventEmitter'; import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
import { loading } from '../loader/load'; import { ensureArray } from '../../plugin/utils';
interface ShaderEvent extends EmitableEvent {} interface ShaderEvent extends EmitableEvent {}
@ -33,6 +33,32 @@ interface MixedImage {
update(): void; update(): void;
} }
type UniformBinderNum = 1 | 2 | 3 | 4;
type UniformBinderType = 'f' | 'i';
type UniformFunc<
N extends UniformBinderNum,
T extends UniformBinderType,
V extends 'v' | ''
> = `uniform${N}${T}${V}`;
type UniformBinderValue<N extends UniformBinderNum> = N extends 1
? number
: N extends 2
? [number, number]
: N extends 3
? [number, number, number]
: [number, number, number, number];
interface UniformBinder<
N extends UniformBinderNum,
T extends UniformBinderType,
V extends 'v' | ''
> {
value: UniformBinderValue<N>;
set(value: UniformBinderValue<N>): void;
get(): UniformBinderValue<N>;
}
const builtinVs = ` const builtinVs = `
#ifdef GL_ES #ifdef GL_ES
precision highp float; precision highp float;
@ -106,25 +132,31 @@ export class ShaderEffect extends EventEmitter<ShaderEvent> {
* @param compile * @param compile
*/ */
update(compile: boolean = false) { update(compile: boolean = false) {
const gl = this.gl; if (compile) this.compile();
if (compile) {
gl.deleteProgram(this.program);
gl.deleteTexture(this.texture);
gl.deleteBuffer(this.buffer?.position ?? null);
gl.deleteBuffer(this.buffer?.texture ?? null);
gl.deleteShader(this.shader?.vertex ?? null);
gl.deleteShader(this.shader?.fragment ?? null);
this.program = this.createProgram();
this.programInfo = this.getProgramInfo();
this.buffer = this.initBuffers();
this.texture = this.createTexture();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
}
this.textureCanvas?.update(); this.textureCanvas?.update();
this.drawScene(); this.drawScene();
} }
/**
*
*/
compile() {
const gl = this.gl;
gl.deleteProgram(this.program);
gl.deleteTexture(this.texture);
gl.deleteBuffer(this.buffer?.position ?? null);
gl.deleteBuffer(this.buffer?.texture ?? null);
gl.deleteShader(this.shader?.vertex ?? null);
gl.deleteShader(this.shader?.fragment ?? null);
this.program = this.createProgram();
this.programInfo = this.getProgramInfo();
this.buffer = this.initBuffers();
this.texture = this.createTexture();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.useProgram(this.program);
}
/** /**
* 使 glsl api * 使 glsl api
* main gl_Position * main gl_Position
@ -182,6 +214,64 @@ export class ShaderEffect extends EventEmitter<ShaderEvent> {
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
} }
/**
*
* @param uniform
* @param num float和int视为1vec2 vec3 vec4分别视为 2 3 4
* @param type 'f''i'
* @param vector 'v'''
* @returns uniform绑定器uniform
*/
createUniformBinder<
N extends UniformBinderNum,
T extends UniformBinderType,
V extends 'v' | ''
>(uniform: string, num: N, type: T, vector: V): UniformBinder<N, T, V> {
if (!this.program) {
throw new Error(
`Uniform binder should be use when the program initialized.`
);
}
const suffix = `${num}${type}${vector ? 'v' : ''}`;
const func = `uniform${suffix}` as UniformFunc<N, T, V>;
const value = (
num === 1 ? 0 : Array(num).fill(0)
) as UniformBinderValue<N>;
const loc = this.gl.getUniformLocation(this.program, uniform);
const gl = this.gl;
return {
value,
set(value) {
this.value = value;
let v;
if (vector === 'v') {
let _v = ensureArray(value);
if (type === 'f') {
v = new Float32Array(_v);
} else {
v = new Int32Array(_v);
}
} else {
v = ensureArray(value);
}
// 对uniform赋值
if (vector === 'v') {
// @ts-ignore
gl[func](loc, v);
} else {
// @ts-ignore
gl[func](loc, ...v);
}
},
get() {
return this.value;
}
};
}
private createProgram() { private createProgram() {
const gl = this.gl; const gl = this.gl;
const vs = this.loadShader(gl.VERTEX_SHADER, this.vsSource); const vs = this.loadShader(gl.VERTEX_SHADER, this.vsSource);
@ -398,7 +488,8 @@ export function replaceGameCanvas(effect: ShaderEffect, canvas: string[]) {
let zIndex = 0; let zIndex = 0;
canvas.forEach(v => { canvas.forEach(v => {
const canvas = core.canvas[v].canvas; const canvas = core.canvas[v].canvas;
const z = parseInt(canvas.style.zIndex); const style = getComputedStyle(canvas);
const z = parseInt(style.zIndex);
if (z > zIndex) zIndex = z; if (z > zIndex) zIndex = z;
canvas.style.display = 'none'; canvas.style.display = 'none';
}); });