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