From 57760d501e02773d4c7383477a6eeb42c66d7ce3 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sat, 24 Aug 2024 21:32:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=9D=80=E8=89=B2?= =?UTF-8?q?=E5=99=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/render.ts | 33 ++++++++++++++++++++++----- src/core/render/shader.ts | 47 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/core/render/render.ts b/src/core/render/render.ts index 9dca107..16d9bd7 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -75,6 +75,8 @@ Mota.require('var', 'hook').once('reset', () => { const transform = render.transform; render.mount(); + const ani = new Animation(); + const shader = new Shader(); const layer = new LayerGroup(); @@ -93,14 +95,35 @@ Mota.require('var', 'hook').once('reset', () => { shader.appendChild(layer); shader.size(480, 480); shader.fs(` + uniform float u_offset; + void main() { - vec2 coord = v_texCoord; - if (coord.y > 0.25 && coord.y < 0.35) { - coord.y = sin((coord.y - 0.25) * 3.1415926535 / 0.2) * 0.1 + 0.25; - } - gl_FragColor = texture2D(u_sampler, coord); + // 计算当前像素到爆炸中心的距离 + vec2 coordToCenter = v_texCoord - vec2(0.5, 0.5); + float distance = length(coordToCenter); + + // 根据时间计算当前距离上的波动相位 + 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(() => { hero.setImage(core.material.images.images['hero2.png']); diff --git a/src/core/render/shader.ts b/src/core/render/shader.ts index 0a0c5a8..21f598f 100644 --- a/src/core/render/shader.ts +++ b/src/core/render/shader.ts @@ -1,8 +1,9 @@ +import { isNil } from 'lodash-es'; import { logger } from '../common/logger'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { isWebGL2Supported } from '../fx/webgl'; import { Container } from './container'; -import { ERenderItemEvent, RenderItemPosition } from './item'; +import { ERenderItemEvent, RenderItem, RenderItemPosition } from './item'; import { Transform } from './transform'; const SHADER_VERTEX_PREFIX_300 = /* glsl */ `#version 300 es @@ -94,6 +95,8 @@ export class Shader extends Container { private shaderModified: boolean = false; /** 需要重新编译的着色器 */ private shaderDirty: boolean = true; + /** 是否需要重新渲染着色器 */ + private shaderRanderDirty: boolean = true; /** 当前程序是否被外部调用过 */ private programExterned: boolean = false; @@ -141,7 +144,6 @@ export class Shader extends Container { if (this.shaderDirty) { this.cacheDirty = true; this.compileShader(); - this.shaderDirty = false; } if (this.cacheDirty) { @@ -150,10 +152,14 @@ export class Shader extends Container { ctx.save(); super.render(this.cache, transform); ctx.restore(); - this.drawScene(); this.cacheDirty = false; } + if (this.shaderRanderDirty) { + this.drawScene(); + this.shaderRanderDirty = false; + } + canvas.ctx.drawImage(this.canvas, 0, 0, this.width, this.height); } } @@ -175,9 +181,17 @@ export class Shader extends Container { this.canvas.height = height * scale; } + update(item?: RenderItem): void { + const isSelf = item === this && !this.cacheDirty; + super.update(item); + if (isSelf) this.cacheDirty = false; + this.shaderRanderDirty = true; + } + drawScene() { const gl = this.gl; if (!this.uniform || !gl) return; + // 清空画布 gl.viewport(0, 0, this.canvas.width, this.canvas.height); @@ -305,6 +319,7 @@ export class Shader extends Container { Shader.deleteProgram(this, this.getProgram()); } this.programExterned = false; + this.shaderDirty = false; this.program = program.program; this.shader = program.shader; @@ -313,6 +328,32 @@ export class Shader extends Container { 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() {