mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-31 23:29:27 +08:00
着色器特效支持动画
This commit is contained in:
parent
f15007513a
commit
a06021531d
@ -1,6 +1,6 @@
|
||||
import { Ticker } from 'mutate-animate';
|
||||
import { Animation, Ticker, hyper } from 'mutate-animate';
|
||||
import { EmitableEvent, EventEmitter } from '../common/eventEmitter';
|
||||
import { loading } from '../loader/load';
|
||||
import { ensureArray } from '../../plugin/utils';
|
||||
|
||||
interface ShaderEvent extends EmitableEvent {}
|
||||
|
||||
@ -33,6 +33,32 @@ interface MixedImage {
|
||||
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 = `
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
@ -106,25 +132,31 @@ export class ShaderEffect extends EventEmitter<ShaderEvent> {
|
||||
* @param compile 是否重新编译着色器脚本,并重新创建纹理
|
||||
*/
|
||||
update(compile: boolean = false) {
|
||||
const gl = this.gl;
|
||||
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);
|
||||
}
|
||||
if (compile) this.compile();
|
||||
this.textureCanvas?.update();
|
||||
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
|
||||
* 着色器中必须包含 main 函数,同时为 gl_Position 赋值
|
||||
@ -182,6 +214,64 @@ export class ShaderEffect extends EventEmitter<ShaderEvent> {
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个全局变量绑定器,用于操作全局变量
|
||||
* @param uniform 全局变量的变量名
|
||||
* @param num 变量的元素数量,float和int视为1,vec2 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() {
|
||||
const gl = this.gl;
|
||||
const vs = this.loadShader(gl.VERTEX_SHADER, this.vsSource);
|
||||
@ -398,7 +488,8 @@ export function replaceGameCanvas(effect: ShaderEffect, canvas: string[]) {
|
||||
let zIndex = 0;
|
||||
canvas.forEach(v => {
|
||||
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;
|
||||
canvas.style.display = 'none';
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user