mirror of
				https://github.com/unanmed/HumanBreak.git
				synced 2025-11-04 07:02:58 +08:00 
			
		
		
		
	feat: fog weather & refactor: rain weather
This commit is contained in:
		
							parent
							
								
									1b8624041b
								
							
						
					
					
						commit
						df8328c33b
					
				@ -1,6 +1,8 @@
 | 
			
		||||
import { logger } from '@motajs/common';
 | 
			
		||||
import { MotaOffscreenCanvas2D } from '@motajs/render-core';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-elements';
 | 
			
		||||
import {
 | 
			
		||||
    MotaOffscreenCanvas2D,
 | 
			
		||||
    SizedCanvasImageSource
 | 
			
		||||
} from '@motajs/render-core';
 | 
			
		||||
 | 
			
		||||
// 经过测试(https://www.measurethat.net/Benchmarks/Show/30741/1/drawimage-img-vs-canvas-vs-bitmap-cropping-fix-loading)
 | 
			
		||||
// 得出结论,ImageBitmap和Canvas的绘制性能不如Image,于是直接画Image就行,所以缓存基本上就是存Image
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
import { RenderAdapter } from '@motajs/render-core';
 | 
			
		||||
import { RenderAdapter, SizedCanvasImageSource } from '@motajs/render-core';
 | 
			
		||||
import { logger } from '@motajs/common';
 | 
			
		||||
import { ILayerRenderExtends, Layer, LayerMovingRenderable } from './layer';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-elements';
 | 
			
		||||
import EventEmitter from 'eventemitter3';
 | 
			
		||||
import { texture } from './cache';
 | 
			
		||||
import { TimingFn } from 'mutate-animate';
 | 
			
		||||
 | 
			
		||||
@ -4,9 +4,9 @@ import {
 | 
			
		||||
    RenderItem,
 | 
			
		||||
    RenderItemPosition,
 | 
			
		||||
    MotaOffscreenCanvas2D,
 | 
			
		||||
    Transform
 | 
			
		||||
    Transform,
 | 
			
		||||
    SizedCanvasImageSource
 | 
			
		||||
} from '@motajs/render-core';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-elements';
 | 
			
		||||
import { isNil } from 'lodash-es';
 | 
			
		||||
import { RenderableData, AutotileRenderable, texture } from './cache';
 | 
			
		||||
import { IAnimateFrame, renderEmits } from './frame';
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { BaseProps, TagDefine } from '@motajs/render-vue';
 | 
			
		||||
import { Transform } from '@motajs/render-core';
 | 
			
		||||
import { CanvasStyle, Transform } from '@motajs/render-core';
 | 
			
		||||
import {
 | 
			
		||||
    ILayerGroupRenderExtends,
 | 
			
		||||
    FloorLayer,
 | 
			
		||||
@ -10,7 +10,6 @@ import {
 | 
			
		||||
import { EAnimateEvent } from './animate';
 | 
			
		||||
import { EIconEvent, EWinskinEvent } from './misc';
 | 
			
		||||
import { IEnemyCollection } from '@motajs/types';
 | 
			
		||||
import { CanvasStyle } from '@motajs/render-elements';
 | 
			
		||||
 | 
			
		||||
export interface AnimateProps extends BaseProps {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ export abstract class EffectBase<T> {
 | 
			
		||||
        this.program = program;
 | 
			
		||||
        this.shader = shader;
 | 
			
		||||
 | 
			
		||||
        shader.useProgram(program);
 | 
			
		||||
        this.initProgram(program, options);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,14 @@ import {
 | 
			
		||||
    onTick
 | 
			
		||||
} from '@motajs/render';
 | 
			
		||||
import { WeatherController } from '../weather';
 | 
			
		||||
import { defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue';
 | 
			
		||||
import {
 | 
			
		||||
    defineComponent,
 | 
			
		||||
    onMounted,
 | 
			
		||||
    onUnmounted,
 | 
			
		||||
    reactive,
 | 
			
		||||
    ref,
 | 
			
		||||
    shallowRef
 | 
			
		||||
} from 'vue';
 | 
			
		||||
import { Textbox, Tip } from '../components';
 | 
			
		||||
import { GameUI } from '@motajs/system-ui';
 | 
			
		||||
import {
 | 
			
		||||
@ -76,7 +83,7 @@ const MainScene = defineComponent(() => {
 | 
			
		||||
        width: 480
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const map = ref<LayerGroup>();
 | 
			
		||||
    const map = shallowRef<LayerGroup>();
 | 
			
		||||
    const hideStatus = ref(false);
 | 
			
		||||
    const locked = ref(false);
 | 
			
		||||
    const weather = new WeatherController();
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,11 @@
 | 
			
		||||
import { WeatherController } from './controller';
 | 
			
		||||
import { CloudWeather, RainWeather, SunWeather } from './presets';
 | 
			
		||||
import { CloudWeather, FogWeather, RainWeather, SunWeather } from './presets';
 | 
			
		||||
 | 
			
		||||
export function createWeather() {
 | 
			
		||||
    WeatherController.register('cloud', CloudWeather);
 | 
			
		||||
    WeatherController.register('rain', RainWeather);
 | 
			
		||||
    WeatherController.register('sun', SunWeather);
 | 
			
		||||
    WeatherController.register('fog', FogWeather);
 | 
			
		||||
    // WeatherController.register('snow', SnowWeather);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,83 +1,9 @@
 | 
			
		||||
import { MotaOffscreenCanvas2D, Sprite } from '@motajs/render-core';
 | 
			
		||||
import { Weather } from '../weather';
 | 
			
		||||
import { CloudLike } from './cloudLike';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-core';
 | 
			
		||||
 | 
			
		||||
export class CloudWeather extends Weather<Sprite> {
 | 
			
		||||
    /** 云层的不透明度 */
 | 
			
		||||
    private alpha: number = 0;
 | 
			
		||||
    /** 水平速度 */
 | 
			
		||||
    private vx: number = 0;
 | 
			
		||||
    /** 竖直速度 */
 | 
			
		||||
    private vy: number = 0;
 | 
			
		||||
    /** 水平位置 */
 | 
			
		||||
    private cx: number = 0;
 | 
			
		||||
    /** 竖直位置 */
 | 
			
		||||
    private cy: number = 0;
 | 
			
		||||
    /** 云层移动的最大速度 */
 | 
			
		||||
    private maxSpeed: number = 1;
 | 
			
		||||
    /** 云层图像 */
 | 
			
		||||
    private image: HTMLImageElement | null = null;
 | 
			
		||||
    /** 上一次执行速度变换的时刻 */
 | 
			
		||||
    private lastTick = 0;
 | 
			
		||||
 | 
			
		||||
    private drawCloud(canvas: MotaOffscreenCanvas2D) {
 | 
			
		||||
        const ctx = canvas.ctx;
 | 
			
		||||
        if (!this.image) return;
 | 
			
		||||
        ctx.globalAlpha = this.alpha;
 | 
			
		||||
        const { width, height } = this.image;
 | 
			
		||||
        for (let x = -1; x < 2; x++) {
 | 
			
		||||
            for (let y = -1; y < 2; y++) {
 | 
			
		||||
                const dx = x * width + this.cx;
 | 
			
		||||
                const dy = y * height + this.cy;
 | 
			
		||||
                if (dx > canvas.width || dy > canvas.height) continue;
 | 
			
		||||
                if (dx + width < 0 || dy + height < 0) continue;
 | 
			
		||||
                ctx.drawImage(this.image, dx, dy, width, height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tick(time: number): void {
 | 
			
		||||
        if (!this.element || !this.image) return;
 | 
			
		||||
        this.element.update();
 | 
			
		||||
        const dt = time - this.lastTick;
 | 
			
		||||
        this.lastTick = time;
 | 
			
		||||
        if (dt > 100) return;
 | 
			
		||||
        const dvx = (Math.random() - 0.5) * this.level * 10;
 | 
			
		||||
        const dvy = (Math.random() - 0.5) * this.level * 10;
 | 
			
		||||
        const addx = (dvx * dt) / 1000;
 | 
			
		||||
        const addy = (dvy * dt) / 1000;
 | 
			
		||||
        if (Math.sign(addx) === Math.sign(this.vx)) {
 | 
			
		||||
            const ratio = Math.sqrt(
 | 
			
		||||
                (this.maxSpeed - Math.abs(this.vx)) / this.maxSpeed
 | 
			
		||||
            );
 | 
			
		||||
            const value = Math.abs(addx) * ratio;
 | 
			
		||||
            this.vx += value * Math.sign(addx);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.vx += addx;
 | 
			
		||||
        }
 | 
			
		||||
        if (Math.sign(addy) === Math.sign(this.vy)) {
 | 
			
		||||
            const ratio = Math.sqrt(
 | 
			
		||||
                (this.maxSpeed - Math.abs(this.vy)) / this.maxSpeed
 | 
			
		||||
            );
 | 
			
		||||
            const value = Math.abs(addy) * ratio;
 | 
			
		||||
            this.vy += value * Math.sign(addy);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.vy += addy;
 | 
			
		||||
        }
 | 
			
		||||
        this.cx += (this.vx * dt) / 1000;
 | 
			
		||||
        this.cy += (this.vy * dt) / 1000;
 | 
			
		||||
        this.cx %= this.image.width;
 | 
			
		||||
        this.cy %= this.image.height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createElement(level: number): Sprite {
 | 
			
		||||
        const element = new Sprite('static', true);
 | 
			
		||||
        element.setRenderFn(canvas => this.drawCloud(canvas));
 | 
			
		||||
        this.maxSpeed = Math.sqrt(level) * 100;
 | 
			
		||||
        this.vx = ((Math.random() - 0.5) * this.maxSpeed) / 2;
 | 
			
		||||
        this.vy = ((Math.random() - 0.5) * this.maxSpeed) / 2;
 | 
			
		||||
        this.alpha = Math.sqrt(level) / 10;
 | 
			
		||||
        this.image = core.material.images.images['cloud.png'];
 | 
			
		||||
        return element;
 | 
			
		||||
export class CloudWeather extends CloudLike {
 | 
			
		||||
    getImage(): SizedCanvasImageSource | null {
 | 
			
		||||
        return core.material.images.images['cloud.png'] ?? null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onDestroy(): void {}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,88 @@
 | 
			
		||||
import { MotaOffscreenCanvas2D, Sprite } from '@motajs/render-core';
 | 
			
		||||
import { Weather } from '../weather';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-core';
 | 
			
		||||
 | 
			
		||||
export abstract class CloudLike extends Weather<Sprite> {
 | 
			
		||||
    /** 不透明度 */
 | 
			
		||||
    private alpha: number = 0;
 | 
			
		||||
    /** 水平速度 */
 | 
			
		||||
    private vx: number = 0;
 | 
			
		||||
    /** 竖直速度 */
 | 
			
		||||
    private vy: number = 0;
 | 
			
		||||
    /** 水平位置 */
 | 
			
		||||
    private cx: number = 0;
 | 
			
		||||
    /** 竖直位置 */
 | 
			
		||||
    private cy: number = 0;
 | 
			
		||||
    /** 移动的最大速度 */
 | 
			
		||||
    private maxSpeed: number = 1;
 | 
			
		||||
    /** 上一次执行速度变换的时刻 */
 | 
			
		||||
    private lastTick = 0;
 | 
			
		||||
    /** 绘制天气使用的图片 */
 | 
			
		||||
    private image: SizedCanvasImageSource | null = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取类多云天气所使用的图片
 | 
			
		||||
     */
 | 
			
		||||
    abstract getImage(): SizedCanvasImageSource | null;
 | 
			
		||||
 | 
			
		||||
    private drawImage(canvas: MotaOffscreenCanvas2D) {
 | 
			
		||||
        const ctx = canvas.ctx;
 | 
			
		||||
        if (!this.image) return;
 | 
			
		||||
        ctx.globalAlpha = this.alpha;
 | 
			
		||||
        const { width, height } = this.image;
 | 
			
		||||
        for (let x = -1; x < 2; x++) {
 | 
			
		||||
            for (let y = -1; y < 2; y++) {
 | 
			
		||||
                const dx = x * width + this.cx;
 | 
			
		||||
                const dy = y * height + this.cy;
 | 
			
		||||
                if (dx > canvas.width || dy > canvas.height) continue;
 | 
			
		||||
                if (dx + width < 0 || dy + height < 0) continue;
 | 
			
		||||
                ctx.drawImage(this.image, dx, dy, width, height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tick(time: number): void {
 | 
			
		||||
        if (!this.element || !this.image) return;
 | 
			
		||||
        this.element.update();
 | 
			
		||||
        const dt = time - this.lastTick;
 | 
			
		||||
        this.lastTick = time;
 | 
			
		||||
        if (dt > 100) return;
 | 
			
		||||
        const dvx = (Math.random() - 0.5) * this.level * 10;
 | 
			
		||||
        const dvy = (Math.random() - 0.5) * this.level * 10;
 | 
			
		||||
        const addx = (dvx * dt) / 1000;
 | 
			
		||||
        const addy = (dvy * dt) / 1000;
 | 
			
		||||
        if (Math.sign(addx) === Math.sign(this.vx)) {
 | 
			
		||||
            const ratio = Math.sqrt(
 | 
			
		||||
                (this.maxSpeed - Math.abs(this.vx)) / this.maxSpeed
 | 
			
		||||
            );
 | 
			
		||||
            const value = Math.abs(addx) * ratio;
 | 
			
		||||
            this.vx += value * Math.sign(addx);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.vx += addx;
 | 
			
		||||
        }
 | 
			
		||||
        if (Math.sign(addy) === Math.sign(this.vy)) {
 | 
			
		||||
            const ratio = Math.sqrt(
 | 
			
		||||
                (this.maxSpeed - Math.abs(this.vy)) / this.maxSpeed
 | 
			
		||||
            );
 | 
			
		||||
            const value = Math.abs(addy) * ratio;
 | 
			
		||||
            this.vy += value * Math.sign(addy);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.vy += addy;
 | 
			
		||||
        }
 | 
			
		||||
        this.cx += (this.vx * dt) / 1000;
 | 
			
		||||
        this.cy += (this.vy * dt) / 1000;
 | 
			
		||||
        this.cx %= this.image.width;
 | 
			
		||||
        this.cy %= this.image.height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createElement(level: number): Sprite {
 | 
			
		||||
        const element = new Sprite('static', true);
 | 
			
		||||
        element.setRenderFn(canvas => this.drawImage(canvas));
 | 
			
		||||
        this.maxSpeed = Math.sqrt(level) * 100;
 | 
			
		||||
        this.vx = ((Math.random() - 0.5) * this.maxSpeed) / 2;
 | 
			
		||||
        this.vy = ((Math.random() - 0.5) * this.maxSpeed) / 2;
 | 
			
		||||
        this.alpha = Math.sqrt(level) / 10;
 | 
			
		||||
        this.image = this.getImage();
 | 
			
		||||
        return element;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
import { MotaOffscreenCanvas2D } from '@motajs/render-core';
 | 
			
		||||
import { CloudLike } from './cloudLike';
 | 
			
		||||
import { SizedCanvasImageSource } from '@motajs/render-core';
 | 
			
		||||
 | 
			
		||||
export class FogWeather extends CloudLike {
 | 
			
		||||
    /** 雾天气的图像比较小,因此将四个进行合并 */
 | 
			
		||||
    private static mergedFog: MotaOffscreenCanvas2D | null = null;
 | 
			
		||||
 | 
			
		||||
    getImage(): SizedCanvasImageSource | null {
 | 
			
		||||
        if (FogWeather.mergedFog) {
 | 
			
		||||
            return FogWeather.mergedFog.canvas;
 | 
			
		||||
        } else {
 | 
			
		||||
            return FogWeather.mergeFog();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onDestroy(): void {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 将雾天气的图片 2x2 合并
 | 
			
		||||
     */
 | 
			
		||||
    static mergeFog() {
 | 
			
		||||
        const image = core.material.images.images['fog.png'];
 | 
			
		||||
        if (!image) return null;
 | 
			
		||||
        const { width, height } = image;
 | 
			
		||||
        this.mergedFog = new MotaOffscreenCanvas2D();
 | 
			
		||||
        this.mergedFog.size(width * 2, height * 2);
 | 
			
		||||
        const ctx = this.mergedFog.ctx;
 | 
			
		||||
        ctx.drawImage(image, 0, 0, width, width);
 | 
			
		||||
        ctx.drawImage(image, width, 0, width, width);
 | 
			
		||||
        ctx.drawImage(image, 0, height, width, width);
 | 
			
		||||
        ctx.drawImage(image, width, height, width, width);
 | 
			
		||||
        return this.mergedFog.canvas;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,4 +1,6 @@
 | 
			
		||||
export * from './cloud';
 | 
			
		||||
export * from './cloudLike';
 | 
			
		||||
export * from './fog';
 | 
			
		||||
export * from './rain';
 | 
			
		||||
export * from './snow';
 | 
			
		||||
export * from './sun';
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
import {
 | 
			
		||||
    Shader,
 | 
			
		||||
    ShaderProgram,
 | 
			
		||||
    IShaderUniform,
 | 
			
		||||
    UniformType
 | 
			
		||||
    UniformType,
 | 
			
		||||
    MotaOffscreenCanvas2D,
 | 
			
		||||
    GL2
 | 
			
		||||
} from '@motajs/render';
 | 
			
		||||
import { Weather } from '../weather';
 | 
			
		||||
 | 
			
		||||
@ -73,24 +74,61 @@ void main() {
 | 
			
		||||
    vec2 texPos = (pos + 1.0) / 2.0;
 | 
			
		||||
    texPos.y = 1.0 - texPos.y;
 | 
			
		||||
    vec4 tex = texture(u_sampler, texPos);
 | 
			
		||||
    outColor = mix(u_color, tex, 0.9);
 | 
			
		||||
    outColor = mix(u_color, tex, 0.8);
 | 
			
		||||
}
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
/** 雨滴顶点坐标 */
 | 
			
		||||
const vertex = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
 | 
			
		||||
 | 
			
		||||
export class RainWeather extends Weather<Shader> {
 | 
			
		||||
    /** 下雨流程的 uniform 变量 */
 | 
			
		||||
    private progress: IShaderUniform<UniformType.Uniform1f> | null = null;
 | 
			
		||||
    /** 使用的着色器程序 */
 | 
			
		||||
    private program: ShaderProgram | null = null;
 | 
			
		||||
interface RainCreateData {
 | 
			
		||||
    /** 进度变量 */
 | 
			
		||||
    readonly uProgress: IShaderUniform<UniformType.Uniform1f> | null;
 | 
			
		||||
    /** 下雨着色器程序 */
 | 
			
		||||
    readonly program: ShaderProgram;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class RainShader extends GL2 {
 | 
			
		||||
    /** 下雨程序 */
 | 
			
		||||
    private rainProgram: ShaderProgram | null = null;
 | 
			
		||||
    /** 背景程序 */
 | 
			
		||||
    private backProgram: ShaderProgram | null = null;
 | 
			
		||||
 | 
			
		||||
    create(level: number): RainCreateData {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        const program = this.createProgram(ShaderProgram);
 | 
			
		||||
        program.fs(rainFs);
 | 
			
		||||
        program.vs(rainVs);
 | 
			
		||||
        program.requestCompile();
 | 
			
		||||
        this.useProgram(program);
 | 
			
		||||
        const pos = program.defineAttribArray('a_rainVertex');
 | 
			
		||||
        program.defineAttribArray('a_offset');
 | 
			
		||||
        program.defineAttribArray('a_data');
 | 
			
		||||
        program.defineUniform('u_color', this.UNIFORM_4f);
 | 
			
		||||
        const uProgress = program.defineUniform('u_progress', this.UNIFORM_1f);
 | 
			
		||||
        program.mode(this.DRAW_ARRAYS_INSTANCED);
 | 
			
		||||
 | 
			
		||||
        if (pos) {
 | 
			
		||||
            pos.buffer(vertex, gl.STATIC_DRAW);
 | 
			
		||||
            pos.pointer(2, gl.FLOAT, false, 0, 0);
 | 
			
		||||
            pos.enable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        program.paramArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, 100 * level);
 | 
			
		||||
 | 
			
		||||
        this.generateRainPath(level, program);
 | 
			
		||||
        this.rainProgram = program;
 | 
			
		||||
        this.backProgram = this.createProgram(ShaderProgram);
 | 
			
		||||
        this.backProgram.requestCompile();
 | 
			
		||||
 | 
			
		||||
        return { uProgress, program };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 生成雨滴
 | 
			
		||||
     * @param num 雨滴数量
 | 
			
		||||
     */
 | 
			
		||||
    generateRainPath(level: number, program: ShaderProgram, shader: Shader) {
 | 
			
		||||
    generateRainPath(level: number, program: ShaderProgram) {
 | 
			
		||||
        const num = level * 100;
 | 
			
		||||
        const angle = (((Math.random() - 0.5) * Math.PI) / 30) * level;
 | 
			
		||||
        const deviation = (Math.PI / 180) * (12 - level);
 | 
			
		||||
@ -98,8 +136,8 @@ export class RainWeather extends Weather<Shader> {
 | 
			
		||||
        const aOffset = program.getAttribArray('a_offset');
 | 
			
		||||
        const aData = program.getAttribArray('a_data');
 | 
			
		||||
        const color = program.getUniform<UniformType.Uniform4f>('u_color');
 | 
			
		||||
        const gl = shader.gl;
 | 
			
		||||
        if (!aOffset || !aData) return;
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        if (!aOffset || !aData || !color) return;
 | 
			
		||||
 | 
			
		||||
        const tan = Math.tan(angle);
 | 
			
		||||
 | 
			
		||||
@ -135,52 +173,47 @@ export class RainWeather extends Weather<Shader> {
 | 
			
		||||
        aData.enable();
 | 
			
		||||
 | 
			
		||||
        program.paramArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, num);
 | 
			
		||||
        color?.set(1, 1, 1, 0.1);
 | 
			
		||||
        color.set(1, 1, 1, 0.1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createElement(level: number): Shader {
 | 
			
		||||
        const shader = new Shader();
 | 
			
		||||
        const gl = shader.gl;
 | 
			
		||||
        shader.size(480, 480);
 | 
			
		||||
    protected drawScene(
 | 
			
		||||
        canvas: MotaOffscreenCanvas2D,
 | 
			
		||||
        gl: WebGL2RenderingContext
 | 
			
		||||
    ): void {
 | 
			
		||||
        const program1 = this.backProgram;
 | 
			
		||||
        const program2 = this.rainProgram;
 | 
			
		||||
        if (!program1 || !program2) return;
 | 
			
		||||
        this.useProgram(program1);
 | 
			
		||||
        program1.texTexture('u_sampler', canvas.canvas);
 | 
			
		||||
        this.draw(gl, program1);
 | 
			
		||||
        this.useProgram(program2);
 | 
			
		||||
        program2.texTexture('u_sampler', canvas.canvas);
 | 
			
		||||
        this.draw(gl, program2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class RainWeather extends Weather<GL2> {
 | 
			
		||||
    /** 下雨流程的 uniform 变量 */
 | 
			
		||||
    private progress: IShaderUniform<UniformType.Uniform1f> | null = null;
 | 
			
		||||
    /** 下雨着色器程序 */
 | 
			
		||||
    private program: ShaderProgram | null = null;
 | 
			
		||||
 | 
			
		||||
    createElement(level: number): GL2 {
 | 
			
		||||
        const shader = new RainShader();
 | 
			
		||||
        shader.setHD(true);
 | 
			
		||||
        shader.setZIndex(100);
 | 
			
		||||
        const program = shader.createProgram(ShaderProgram);
 | 
			
		||||
        program.fs(rainFs);
 | 
			
		||||
        program.vs(rainVs);
 | 
			
		||||
        program.requestCompile();
 | 
			
		||||
        const pos = program.defineAttribArray('a_rainVertex');
 | 
			
		||||
        program.defineAttribArray('a_offset');
 | 
			
		||||
        program.defineAttribArray('a_data');
 | 
			
		||||
        program.defineUniform('u_progress', shader.UNIFORM_1f);
 | 
			
		||||
        program.defineUniform('u_color', shader.UNIFORM_4f);
 | 
			
		||||
        program.mode(shader.DRAW_ARRAYS_INSTANCED);
 | 
			
		||||
        shader.useProgram(program);
 | 
			
		||||
 | 
			
		||||
        if (pos) {
 | 
			
		||||
            pos.buffer(vertex, gl.STATIC_DRAW);
 | 
			
		||||
            pos.pointer(2, gl.FLOAT, false, 0, 0);
 | 
			
		||||
            pos.enable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        program.paramArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, 100 * this.level);
 | 
			
		||||
 | 
			
		||||
        this.progress = program.getUniform<UniformType.Uniform1f>('u_progress');
 | 
			
		||||
        this.generateRainPath(level, program, shader);
 | 
			
		||||
 | 
			
		||||
        const { uProgress, program } = shader.create(level);
 | 
			
		||||
        this.progress = uProgress;
 | 
			
		||||
        this.program = program;
 | 
			
		||||
        return shader;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tick(timestamp: number): void {
 | 
			
		||||
        if (!this.element) return;
 | 
			
		||||
        if (!this.element || !this.program) return;
 | 
			
		||||
        this.element.update();
 | 
			
		||||
        const time = 5000 - 400 * this.level;
 | 
			
		||||
        const progress = (timestamp % time) / time;
 | 
			
		||||
        this.progress?.set(progress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onDestroy(): void {
 | 
			
		||||
        if (!this.element || !this.program) return;
 | 
			
		||||
        this.element.deleteProgram(this.program);
 | 
			
		||||
    }
 | 
			
		||||
    onDestroy(): void {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -576,14 +576,6 @@ export function loadDefaultResource() {
 | 
			
		||||
                ] = res.resource;
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    const weathers: (keyof Weather)[] = ['fog'];
 | 
			
		||||
    weathers.forEach(v => {
 | 
			
		||||
        const res = LoadTask.add('material', `material/${v}.png`);
 | 
			
		||||
        res.once('load', res => {
 | 
			
		||||
            // @ts-expect-error 需要赋值
 | 
			
		||||
            core.animateFrame.weather[v] = res.resource;
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    // animates
 | 
			
		||||
    {
 | 
			
		||||
        const res = LoadTask.add(
 | 
			
		||||
@ -619,7 +611,6 @@ export async function loadCompressedResource() {
 | 
			
		||||
        HTMLImageElement
 | 
			
		||||
    >[];
 | 
			
		||||
    materialImages.push('keyboard');
 | 
			
		||||
    const weathers: (keyof Weather)[] = ['fog'];
 | 
			
		||||
 | 
			
		||||
    Object.entries(list).forEach(v => {
 | 
			
		||||
        const [uri, list] = v;
 | 
			
		||||
@ -696,9 +687,6 @@ export async function loadCompressedResource() {
 | 
			
		||||
                                    HTMLImageElement
 | 
			
		||||
                                >
 | 
			
		||||
                            ] = image;
 | 
			
		||||
                        } else if (weathers.some(v => name === v + '.png')) {
 | 
			
		||||
                            // @ts-expect-error 需要赋值
 | 
			
		||||
                            core.animateFrame.weather[v] = image;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import { MotaOffscreenCanvas2D } from './canvas2d';
 | 
			
		||||
import { ERenderItemEvent, RenderItem, RenderItemPosition } from './item';
 | 
			
		||||
import { Transform } from './transform';
 | 
			
		||||
import { isWebGL2Supported } from './utils';
 | 
			
		||||
import { SizedCanvasImageSource } from './types';
 | 
			
		||||
 | 
			
		||||
export interface IGL2ProgramPrefix {
 | 
			
		||||
    readonly VERTEX: string;
 | 
			
		||||
@ -170,23 +171,34 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
        super(type, false);
 | 
			
		||||
 | 
			
		||||
        this.canvas = document.createElement('canvas');
 | 
			
		||||
        this.gl = this.canvas.getContext('webgl2')!;
 | 
			
		||||
        const gl = this.canvas.getContext('webgl2')!;
 | 
			
		||||
        this.gl = gl;
 | 
			
		||||
        if (!GL2.support) {
 | 
			
		||||
            this.canvas.width = 0;
 | 
			
		||||
            this.canvas.height = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            const num = this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS);
 | 
			
		||||
            const num = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
 | 
			
		||||
            if (typeof num === 'number') {
 | 
			
		||||
                this.MAX_TEXTURE_COUNT = num;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        gl.viewport(0, 0, this.canvas.width, this.canvas.height);
 | 
			
		||||
 | 
			
		||||
        this.init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private init() {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        if (!gl) return;
 | 
			
		||||
        gl.enable(gl.DEPTH_TEST);
 | 
			
		||||
        gl.enable(gl.BLEND);
 | 
			
		||||
        gl.depthFunc(gl.LEQUAL);
 | 
			
		||||
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onResize(scale: number): void {
 | 
			
		||||
        this.sizeGL(this.width, this.height);
 | 
			
		||||
        super.onResize(scale);
 | 
			
		||||
        this.sizeGL(this.width, this.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setHD(hd: boolean): void {
 | 
			
		||||
@ -201,9 +213,10 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
 | 
			
		||||
    private sizeGL(width: number, height: number) {
 | 
			
		||||
        const ratio = this.highResolution ? devicePixelRatio : 1;
 | 
			
		||||
        const scale = ratio * this.cache.scale;
 | 
			
		||||
        const scale = ratio * this.scale;
 | 
			
		||||
        this.canvas.width = width * scale;
 | 
			
		||||
        this.canvas.height = height * scale;
 | 
			
		||||
        this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected render(
 | 
			
		||||
@ -218,12 +231,10 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
 | 
			
		||||
        // 清空画布
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.viewport(0, 0, this.canvas.width, this.canvas.height);
 | 
			
		||||
        gl.clearColor(0, 0, 0, 0);
 | 
			
		||||
        gl.clearDepth(1);
 | 
			
		||||
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
			
		||||
        this.program.ready();
 | 
			
		||||
        this.drawScene(canvas, gl, this.program, transform);
 | 
			
		||||
        this.drawScene(canvas, gl, transform);
 | 
			
		||||
 | 
			
		||||
        canvas.clear();
 | 
			
		||||
        canvas.ctx.drawImage(this.canvas, 0, 0, this.width, this.height);
 | 
			
		||||
@ -239,7 +250,6 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
    protected abstract drawScene(
 | 
			
		||||
        canvas: MotaOffscreenCanvas2D,
 | 
			
		||||
        gl: WebGL2RenderingContext,
 | 
			
		||||
        program: GL2Program,
 | 
			
		||||
        transform: Transform
 | 
			
		||||
    ): void;
 | 
			
		||||
 | 
			
		||||
@ -252,6 +262,7 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
        const indices = program.usingIndices;
 | 
			
		||||
        const param = program.getDrawParams(program.renderMode);
 | 
			
		||||
        if (!param) return;
 | 
			
		||||
        program.ready();
 | 
			
		||||
        switch (program.renderMode) {
 | 
			
		||||
            case RenderMode.Arrays: {
 | 
			
		||||
                const { mode, first, count } = param as DrawArraysParam;
 | 
			
		||||
@ -308,7 +319,6 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
        gl.bindTexture(gl.TEXTURE_2D, tex);
 | 
			
		||||
        gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
 | 
			
		||||
        if (clear) {
 | 
			
		||||
            gl.viewport(0, 0, this.canvas.width, this.canvas.height);
 | 
			
		||||
            gl.clearColor(0, 0, 0, 0);
 | 
			
		||||
            gl.clearDepth(1);
 | 
			
		||||
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
			
		||||
@ -404,15 +414,6 @@ export abstract class GL2<E extends EGL2Event = EGL2Event> extends RenderItem<
 | 
			
		||||
        this.canvas.remove();
 | 
			
		||||
        super.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private init() {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        if (!gl) return;
 | 
			
		||||
        gl.enable(gl.DEPTH_TEST);
 | 
			
		||||
        gl.enable(gl.BLEND);
 | 
			
		||||
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
        gl.depthFunc(gl.LEQUAL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type _U1 = [x0: number];
 | 
			
		||||
@ -727,6 +728,7 @@ class ShaderUniform<T extends UniformType> implements IShaderUniform<T> {
 | 
			
		||||
 | 
			
		||||
    set(...params: UniformSetFn[T]): void {
 | 
			
		||||
        // 因为ts类型推导的限制,类型肯定正确,但是推导不出,所以这里直接 as any 屏蔽掉类型推导
 | 
			
		||||
        this.gl.useProgram(this.program.program);
 | 
			
		||||
        const [x0, x1, x2, x3] = params as any[];
 | 
			
		||||
        switch (this.type) {
 | 
			
		||||
            case UniformType.Uniform1f:
 | 
			
		||||
@ -815,6 +817,7 @@ class ShaderAttrib<T extends AttribType> implements IShaderAttrib<T> {
 | 
			
		||||
 | 
			
		||||
    set(...params: AttribSetFn[T]) {
 | 
			
		||||
        // 因为ts类型推导的限制,类型肯定正确,但是推导不出,所以这里直接 as any 屏蔽掉类型推导
 | 
			
		||||
        this.gl.useProgram(this.program.program);
 | 
			
		||||
        const [x0, x1, x2, x3] = params as any[];
 | 
			
		||||
        switch (this.type) {
 | 
			
		||||
            case AttribType.Attrib1f:
 | 
			
		||||
@ -878,6 +881,7 @@ class ShaderAttribArray implements IShaderAttribArray {
 | 
			
		||||
    ): void;
 | 
			
		||||
    buffer(data: any, usage: any, srcOffset?: any, length?: any): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ARRAY_BUFFER, this.data);
 | 
			
		||||
        if (typeof srcOffset === 'number') {
 | 
			
		||||
            gl.bufferData(gl.ARRAY_BUFFER, data, usage, srcOffset, length);
 | 
			
		||||
@ -895,6 +899,7 @@ class ShaderAttribArray implements IShaderAttribArray {
 | 
			
		||||
    ): void;
 | 
			
		||||
    sub(dstOffset: any, data: any, offset?: any, length?: any): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ARRAY_BUFFER, this.data);
 | 
			
		||||
        if (typeof offset === 'number') {
 | 
			
		||||
            gl.bufferSubData(gl.ARRAY_BUFFER, dstOffset, data, offset, length);
 | 
			
		||||
@ -911,6 +916,7 @@ class ShaderAttribArray implements IShaderAttribArray {
 | 
			
		||||
        p4: GLintptr
 | 
			
		||||
    ): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ARRAY_BUFFER, this.data);
 | 
			
		||||
        gl.vertexAttribPointer(this.location, p0, p1, p2, p3, p4);
 | 
			
		||||
    }
 | 
			
		||||
@ -922,20 +928,24 @@ class ShaderAttribArray implements IShaderAttribArray {
 | 
			
		||||
        offset: GLintptr
 | 
			
		||||
    ): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ARRAY_BUFFER, this.data);
 | 
			
		||||
        gl.vertexAttribIPointer(this.location, size, type, stride, offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    divisor(divisor: number): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.vertexAttribDivisor(this.location, divisor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enable(): void {
 | 
			
		||||
        this.gl.useProgram(this.program.program);
 | 
			
		||||
        this.gl.enableVertexAttribArray(this.location);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    disable(): void {
 | 
			
		||||
        this.gl.useProgram(this.program.program);
 | 
			
		||||
        this.gl.disableVertexAttribArray(this.location);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -956,6 +966,7 @@ class ShaderIndices implements IShaderIndices {
 | 
			
		||||
    ): void;
 | 
			
		||||
    buffer(p0: any, p1: any, p2?: any, p3?: any): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.data);
 | 
			
		||||
        if (typeof p2 === 'number') {
 | 
			
		||||
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, p0, p1, p2, p3);
 | 
			
		||||
@ -973,6 +984,7 @@ class ShaderIndices implements IShaderIndices {
 | 
			
		||||
    ): void;
 | 
			
		||||
    sub(p0: any, p1: any, p2?: any, p3?: any): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.data);
 | 
			
		||||
        if (typeof p2 === 'number') {
 | 
			
		||||
            gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, p0, p1, p2, p3);
 | 
			
		||||
@ -991,6 +1003,7 @@ class ShaderUniformMatrix implements IShaderUniformMatrix {
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    set(x2: GLboolean, x3: Float32List, x4?: number, x5?: number): void {
 | 
			
		||||
        this.gl.useProgram(this.program.program);
 | 
			
		||||
        switch (this.type) {
 | 
			
		||||
            case UniformMatrix.UMatrix2x2:
 | 
			
		||||
                this.gl.uniformMatrix2fv(this.location, x2, x3, x4, x5);
 | 
			
		||||
@ -1037,6 +1050,7 @@ class ShaderUniformBlock implements IShaderUniformBlock {
 | 
			
		||||
    set(srcData: ArrayBufferView, srcOffset: number, length?: number): void;
 | 
			
		||||
    set(srcData: unknown, srcOffset?: unknown, length?: unknown): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        const buffer = this.buffer;
 | 
			
		||||
        gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
 | 
			
		||||
        if (srcOffset !== void 0) {
 | 
			
		||||
@ -1065,6 +1079,7 @@ class ShaderTexture2D implements IShaderTexture2D {
 | 
			
		||||
 | 
			
		||||
    set(source: TexImageSource): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.activeTexture(gl.TEXTURE0 + this.index);
 | 
			
		||||
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
 | 
			
		||||
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 | 
			
		||||
@ -1096,6 +1111,7 @@ class ShaderTexture2D implements IShaderTexture2D {
 | 
			
		||||
        height: number
 | 
			
		||||
    ): void {
 | 
			
		||||
        const gl = this.gl;
 | 
			
		||||
        gl.useProgram(this.program.program);
 | 
			
		||||
        gl.activeTexture(gl.TEXTURE0 + this.index);
 | 
			
		||||
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
 | 
			
		||||
 | 
			
		||||
@ -1191,8 +1207,6 @@ export class GL2Program extends EventEmitter<ShaderProgramEvent> {
 | 
			
		||||
    /** 当前正在使用的顶点索引数组 */
 | 
			
		||||
    usingIndices: IShaderIndices | null = null;
 | 
			
		||||
 | 
			
		||||
    /** 着色器内容是否是默认内容,可以用于优化空着色器 */
 | 
			
		||||
    modified: boolean = false;
 | 
			
		||||
    /** 渲染模式 */
 | 
			
		||||
    renderMode: RenderMode = RenderMode.Elements;
 | 
			
		||||
 | 
			
		||||
@ -1376,7 +1390,6 @@ export class GL2Program extends EventEmitter<ShaderProgramEvent> {
 | 
			
		||||
    vs(vs: string) {
 | 
			
		||||
        this.vertex = this.prefix.VERTEX + vs;
 | 
			
		||||
        this.shaderDirty = true;
 | 
			
		||||
        this.modified = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -1386,7 +1399,6 @@ export class GL2Program extends EventEmitter<ShaderProgramEvent> {
 | 
			
		||||
    fs(fs: string) {
 | 
			
		||||
        this.fragment = this.prefix.FRAGMENT + fs;
 | 
			
		||||
        this.shaderDirty = true;
 | 
			
		||||
        this.modified = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -1671,6 +1683,24 @@ export class GL2Program extends EventEmitter<ShaderProgramEvent> {
 | 
			
		||||
        return obj;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 绑定纹理,自动判断应该使用 sub 还是 set
 | 
			
		||||
     * @param program 使用的着色器程序
 | 
			
		||||
     * @param texture 要绑定至的纹理
 | 
			
		||||
     * @param source 纹理内容
 | 
			
		||||
     * @returns 是否绑定成功
 | 
			
		||||
     */
 | 
			
		||||
    texTexture(texture: string, source: SizedCanvasImageSource) {
 | 
			
		||||
        const tex = this.getTexture(texture);
 | 
			
		||||
        if (!tex) return false;
 | 
			
		||||
        if (tex.width === source.width && tex.height === source.height) {
 | 
			
		||||
            tex.sub(source, 0, 0, source.width, source.height);
 | 
			
		||||
        } else {
 | 
			
		||||
            tex.set(source);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 摧毁这个着色器程序,不要直接调用,请使用 {@link GL2.deleteProgram} 来删除一个着色器程序
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -8,4 +8,5 @@ export * from './render';
 | 
			
		||||
export * from './shader';
 | 
			
		||||
export * from './sprite';
 | 
			
		||||
export * from './transform';
 | 
			
		||||
export * from './types';
 | 
			
		||||
export * from './utils';
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { MotaOffscreenCanvas2D } from './canvas2d';
 | 
			
		||||
import { EGL2Event, GL2, GL2Program, IGL2ProgramPrefix } from './gl2';
 | 
			
		||||
import { RenderItemPosition } from './item';
 | 
			
		||||
 | 
			
		||||
const SHADER_PREFIX: IGL2ProgramPrefix = {
 | 
			
		||||
    VERTEX: /* glsl */ `#version 300 es
 | 
			
		||||
@ -38,20 +39,17 @@ export interface EShaderEvent extends EGL2Event {}
 | 
			
		||||
export class Shader<E extends EShaderEvent = EShaderEvent> extends GL2<
 | 
			
		||||
    EShaderEvent | E
 | 
			
		||||
> {
 | 
			
		||||
    constructor(type: RenderItemPosition = 'static') {
 | 
			
		||||
        super(type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected drawScene(
 | 
			
		||||
        canvas: MotaOffscreenCanvas2D,
 | 
			
		||||
        gl: WebGL2RenderingContext,
 | 
			
		||||
        program: GL2Program
 | 
			
		||||
        gl: WebGL2RenderingContext
 | 
			
		||||
    ): 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);
 | 
			
		||||
        }
 | 
			
		||||
        const program = this.program;
 | 
			
		||||
        if (!program) return;
 | 
			
		||||
        program.texTexture('u_sampler', canvas.canvas);
 | 
			
		||||
        this.draw(gl, program);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -63,9 +61,6 @@ export class ShaderProgram extends GL2Program {
 | 
			
		||||
        super(gl2, vs, fs);
 | 
			
		||||
        if (!vs) this.vs(DEFAULT_VS);
 | 
			
		||||
        if (!fs) this.fs(DEFAULT_FS);
 | 
			
		||||
        if (!vs && !fs) {
 | 
			
		||||
            this.modified = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ready(): boolean {
 | 
			
		||||
 | 
			
		||||
@ -2,11 +2,11 @@ import {
 | 
			
		||||
    Transform,
 | 
			
		||||
    ERenderItemEvent,
 | 
			
		||||
    RenderItem,
 | 
			
		||||
    MotaOffscreenCanvas2D
 | 
			
		||||
    MotaOffscreenCanvas2D,
 | 
			
		||||
    CanvasStyle
 | 
			
		||||
} from '@motajs/render-core';
 | 
			
		||||
import { logger } from '@motajs/common';
 | 
			
		||||
import { clamp, isEqual, isNil } from 'lodash-es';
 | 
			
		||||
import { CanvasStyle } from './types';
 | 
			
		||||
 | 
			
		||||
export type CircleParams = [
 | 
			
		||||
    cx?: number,
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,2 @@
 | 
			
		||||
export * from './graphics';
 | 
			
		||||
export * from './misc';
 | 
			
		||||
export * from './types';
 | 
			
		||||
 | 
			
		||||
@ -7,11 +7,11 @@ import {
 | 
			
		||||
    ElementLocator,
 | 
			
		||||
    ElementScale,
 | 
			
		||||
    CustomContainerRenderFn,
 | 
			
		||||
    CustomContainerPropagateFn
 | 
			
		||||
    CustomContainerPropagateFn,
 | 
			
		||||
    CanvasStyle
 | 
			
		||||
} from '@motajs/render-core';
 | 
			
		||||
import {
 | 
			
		||||
    BezierParams,
 | 
			
		||||
    CanvasStyle,
 | 
			
		||||
    CircleParams,
 | 
			
		||||
    EllipseParams,
 | 
			
		||||
    ILineProperty,
 | 
			
		||||
 | 
			
		||||
@ -130,6 +130,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
 | 
			
		||||
			"cloud.png",
 | 
			
		||||
			"def.png",
 | 
			
		||||
			"exp.png",
 | 
			
		||||
			"fog.png",
 | 
			
		||||
			"hero1.png",
 | 
			
		||||
			"hero2.png",
 | 
			
		||||
			"hp.png",
 | 
			
		||||
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB  | 
							
								
								
									
										1
									
								
								src/types/source/data.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/types/source/data.d.ts
									
									
									
									
										vendored
									
									
								
							@ -118,6 +118,7 @@ type ImageIds =
 | 
			
		||||
    | 'cloud.png'
 | 
			
		||||
    | 'def.png'
 | 
			
		||||
    | 'exp.png'
 | 
			
		||||
    | 'fog.png'
 | 
			
		||||
    | 'hero1.png'
 | 
			
		||||
    | 'hero2.png'
 | 
			
		||||
    | 'hp.png'
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user