mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-02-28 17:37:07 +08:00
feat: 优化着色器组件
This commit is contained in:
parent
2561d7f23d
commit
57760d501e
@ -75,6 +75,8 @@ Mota.require('var', 'hook').once('reset', () => {
|
|||||||
const transform = render.transform;
|
const transform = render.transform;
|
||||||
render.mount();
|
render.mount();
|
||||||
|
|
||||||
|
const ani = new Animation();
|
||||||
|
|
||||||
const shader = new Shader();
|
const shader = new Shader();
|
||||||
const layer = new LayerGroup();
|
const layer = new LayerGroup();
|
||||||
|
|
||||||
@ -93,14 +95,35 @@ Mota.require('var', 'hook').once('reset', () => {
|
|||||||
shader.appendChild(layer);
|
shader.appendChild(layer);
|
||||||
shader.size(480, 480);
|
shader.size(480, 480);
|
||||||
shader.fs(`
|
shader.fs(`
|
||||||
|
uniform float u_offset;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 coord = v_texCoord;
|
// 计算当前像素到爆炸中心的距离
|
||||||
if (coord.y > 0.25 && coord.y < 0.35) {
|
vec2 coordToCenter = v_texCoord - vec2(0.5, 0.5);
|
||||||
coord.y = sin((coord.y - 0.25) * 3.1415926535 / 0.2) * 0.1 + 0.25;
|
float distance = length(coordToCenter);
|
||||||
}
|
|
||||||
gl_FragColor = texture2D(u_sampler, coord);
|
// 根据时间计算当前距离上的波动相位
|
||||||
|
float wavePhase = 100.0 * (distance - u_offset);
|
||||||
|
|
||||||
|
// 计算波动的强度(正弦波)并结合衰减
|
||||||
|
float wave = sin(wavePhase) * 0.02 / (1.0 + 10.0 * distance);
|
||||||
|
|
||||||
|
// 将波动效果应用到纹理坐标上,造成扭曲
|
||||||
|
vec2 warpedCoords = v_texCoord + normalize(coordToCenter) * wave;
|
||||||
|
|
||||||
|
// 采样纹理并输出颜色
|
||||||
|
gl_FragColor = texture2D(u_sampler, warpedCoords);
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
shader.compileShader();
|
||||||
|
|
||||||
|
const offset = shader.getUniform('u_offset');
|
||||||
|
shader.delegateTicker(() => {
|
||||||
|
shader.gl.uniform1f(offset, ani.value.offset);
|
||||||
|
shader.update();
|
||||||
|
}, 20000);
|
||||||
|
ani.value.offset = 0;
|
||||||
|
ani.mode(linear()).time(10000).absolute().apply('offset', 1);
|
||||||
|
|
||||||
layer.requestAfterFrame(() => {
|
layer.requestAfterFrame(() => {
|
||||||
hero.setImage(core.material.images.images['hero2.png']);
|
hero.setImage(core.material.images.images['hero2.png']);
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
import { isNil } from 'lodash-es';
|
||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
||||||
import { isWebGL2Supported } from '../fx/webgl';
|
import { isWebGL2Supported } from '../fx/webgl';
|
||||||
import { Container } from './container';
|
import { Container } from './container';
|
||||||
import { ERenderItemEvent, RenderItemPosition } from './item';
|
import { ERenderItemEvent, RenderItem, RenderItemPosition } from './item';
|
||||||
import { Transform } from './transform';
|
import { Transform } from './transform';
|
||||||
|
|
||||||
const SHADER_VERTEX_PREFIX_300 = /* glsl */ `#version 300 es
|
const SHADER_VERTEX_PREFIX_300 = /* glsl */ `#version 300 es
|
||||||
@ -94,6 +95,8 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
private shaderModified: boolean = false;
|
private shaderModified: boolean = false;
|
||||||
/** 需要重新编译的着色器 */
|
/** 需要重新编译的着色器 */
|
||||||
private shaderDirty: boolean = true;
|
private shaderDirty: boolean = true;
|
||||||
|
/** 是否需要重新渲染着色器 */
|
||||||
|
private shaderRanderDirty: boolean = true;
|
||||||
/** 当前程序是否被外部调用过 */
|
/** 当前程序是否被外部调用过 */
|
||||||
private programExterned: boolean = false;
|
private programExterned: boolean = false;
|
||||||
|
|
||||||
@ -141,7 +144,6 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
if (this.shaderDirty) {
|
if (this.shaderDirty) {
|
||||||
this.cacheDirty = true;
|
this.cacheDirty = true;
|
||||||
this.compileShader();
|
this.compileShader();
|
||||||
this.shaderDirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.cacheDirty) {
|
if (this.cacheDirty) {
|
||||||
@ -150,10 +152,14 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
ctx.save();
|
ctx.save();
|
||||||
super.render(this.cache, transform);
|
super.render(this.cache, transform);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
this.drawScene();
|
|
||||||
this.cacheDirty = false;
|
this.cacheDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.shaderRanderDirty) {
|
||||||
|
this.drawScene();
|
||||||
|
this.shaderRanderDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
canvas.ctx.drawImage(this.canvas, 0, 0, this.width, this.height);
|
canvas.ctx.drawImage(this.canvas, 0, 0, this.width, this.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,9 +181,17 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
this.canvas.height = height * scale;
|
this.canvas.height = height * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(item?: RenderItem<any>): void {
|
||||||
|
const isSelf = item === this && !this.cacheDirty;
|
||||||
|
super.update(item);
|
||||||
|
if (isSelf) this.cacheDirty = false;
|
||||||
|
this.shaderRanderDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
drawScene() {
|
drawScene() {
|
||||||
const gl = this.gl;
|
const gl = this.gl;
|
||||||
if (!this.uniform || !gl) return;
|
if (!this.uniform || !gl) return;
|
||||||
|
|
||||||
// 清空画布
|
// 清空画布
|
||||||
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
|
||||||
@ -305,6 +319,7 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
Shader.deleteProgram(this, this.getProgram());
|
Shader.deleteProgram(this, this.getProgram());
|
||||||
}
|
}
|
||||||
this.programExterned = false;
|
this.programExterned = false;
|
||||||
|
this.shaderDirty = false;
|
||||||
|
|
||||||
this.program = program.program;
|
this.program = program.program;
|
||||||
this.shader = program.shader;
|
this.shader = program.shader;
|
||||||
@ -313,6 +328,32 @@ export class Shader extends Container<EShaderEvent> {
|
|||||||
this.gl?.useProgram(this.program);
|
this.gl?.useProgram(this.program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取属性位置
|
||||||
|
* @param name 属性名称
|
||||||
|
*/
|
||||||
|
getAttribute(name: string) {
|
||||||
|
if (!this.attribute || !this.gl || !this.program) return null;
|
||||||
|
if (!isNil(this.attribute[name])) return this.attribute[name];
|
||||||
|
return (this.attribute[name] = this.gl.getAttribLocation(
|
||||||
|
this.program,
|
||||||
|
name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取uniform位置
|
||||||
|
* @param name 属性名称
|
||||||
|
*/
|
||||||
|
getUniform(name: string) {
|
||||||
|
if (!this.uniform || !this.gl || !this.program) return null;
|
||||||
|
if (!isNil(this.uniform[name])) return this.uniform[name];
|
||||||
|
return (this.uniform[name] = this.gl.getUniformLocation(
|
||||||
|
this.program,
|
||||||
|
name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// ----- 初始化部分
|
// ----- 初始化部分
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
|
Loading…
Reference in New Issue
Block a user