@icanvas/renderer
Version:
这是icanvas的渲染模块
131 lines (126 loc) • 5.02 kB
JavaScript
import GAME from '@icanvas/core';
import Extends from './canvas3d.js';
import * as Shader from './shader';
let Context = GAME.Api.Canvas('main').getContext('webgl');
Object.assign(Context, Extends);
let Renderer = class {
Context = Context;
//初始化设置大小、视图和颜色,获取最大可用纹理数量
constructor(width, height) {
this.Context.SetSize(width, height);
this.Context.AddProgram('Texture', Shader.Texture.Vertex, Shader.Texture.Fragment);
this.Context.UseProgram('Texture');
this.Context.enableVertexAttribArray(this.Context.Program.a_Position.id);
this.Context.enableVertexAttribArray(this.Context.Program.a_TexCoord.id);
this.Context.enable(this.Context.BLEND); //色彩混合
this.Context.blendFunc(this.Context.SRC_ALPHA, this.Context.ONE_MINUS_SRC_ALPHA); //混合模式
// this.Context.MAX_TEXTURE = this.Context.GetMax();
console.log(this.Context.canvas);
}
/**
* 标记当前是否暂停渲染
* @type {boolean}
*/
Pause = false;
/**
*
* @type {Number} 当前时间戳
*/
Time = Date.now();
/**
*
* @param {CanvasRenderingContext2D} Context 主舞台
* @param {GAME.Component} Component 根舞台
* @param {Number} Interval 每帧间隔
*/
Run(Stage, Interval = 1000 / 60, Callback) {
var delta,
then = Date.now();
let HandleUpdate = time => {
if (this.Pause) return;
requestAnimationFrame(HandleUpdate);
this.Time = Date.now();
delta = this.Time - then;
if (delta > Interval) {
then = this.Time - (delta % Interval);
this.Update(Stage, this.Context);
if (Callback) Callback(time);
}
};
HandleUpdate();
return this;
}
MatrixUpdate(matrix, component, r) {
if (r) {
matrix
.scale(1 / component.scale.x, 1 / component.scale.y)
.rotate(component.radian, (component.position.x / GAME.Pos.width) * 2, -(component.position.y / GAME.Pos.height) * 2, -1)
.translate(-(component.position.x / GAME.Pos.width) * 2, (component.position.y / GAME.Pos.height) * 2);
} else {
matrix
.translate((component.position.x / GAME.Pos.width) * 2, -(component.position.y / GAME.Pos.height) * 2)
.rotate(-component.radian, (component.position.x / GAME.Pos.width) * 2, -(component.position.y / GAME.Pos.height) * 2, -1)
.scale(component.scale.x, component.scale.y);
}
return matrix;
}
Handle = {
// LookAtMatrix: new GAME.Math.Matrix3(), //视图矩阵
WorldMatrix: new GAME.Math.Matrix4(), //模型矩阵
Components: [],
};
Update(Stage, Context) {
this.Handle.WorldMatrix.identity();
this.PerUpdate(Stage);
this.Handle.Components.sort((a, b) => a.zIndex - b.zIndex || a.oldIndex - b.oldIndex);
this.Updating(Context);
this.Handle.Components.length = 0;
}
PerUpdate(Component, Components = this.Handle.Components, Matrix = this.Handle.WorldMatrix) {
if (!Component) return;
if (Component instanceof Array) {
for (let i = 0, l = Component.length; i < l; i++) this.PerUpdate(Component[i], Components, Matrix);
} else {
if (!Component._visible) return;
if (Component.perUpdate) Component.perUpdate();
this.MatrixUpdate(Matrix, Component);
if (!Component.matrix) Component.matrix = new GAME.Math.Matrix4();
Component.matrix.setToArray(Matrix);
if (Component.update) Component.oldIndex = Components.push(Component);
if (Component.children.length) this.PerUpdate(Component.children, Components, Matrix);
this.MatrixUpdate(Matrix, Component, true);
}
}
Updating(gl, Components = this.Handle.Components, Clear = true) {
if (Clear) Context.clear(gl.COLOR_BUFFER_BIT);
Components.forEach(Component => {
Component.matrix.translate(-(Component.anchor.x / GAME.Pos.width) * 2, (Component.anchor.y / GAME.Pos.height) * 2);
gl.uniformMatrix4fv(gl.Program.u_MvpMatrix.id, false, Component.matrix); //传递矩阵参数
Component.update(gl);
});
}
HitWorldMatrix = new GAME.Math.Matrix3();
HitCompare(Component, touch, hitParent = false) {
if (!Component) return false;
if (Component instanceof Array) {
for (let i = Component.length - 1; i >= 0; i--) if (this.HitCompare(Component[i], touch, hitParent)) return true;
} else {
if (!Component._visible) return;
// this.MatrixUpdate(this.HitWorldMatrix, Component, true);
var hitMe = true;
// let matrix = this.HitWorldMatrix;
// let mx = matrix.a * x + matrix.c * y + matrix.tx + Component.anchor.x;
// let my = matrix.b * x + matrix.d * y + matrix.ty + Component.anchor.y;
// if (Component.size) hitMe = mx > 0 && my > 0 && mx <= Component.size.x && my <= Component.size.y;
var hitChild = false;
if (Component.touchChildren && Component.children.length) hitChild = this.HitCompare(Component.children, touch, hitMe);
// this.MatrixUpdate(this.HitWorldMatrix, Component);
if (hitChild) return true;
if (!Component.touchTap) return Component.touchStop;
if (!hitMe) return false;
let Result = Component.touchTap(touch.x, touch.y, touch);
return Result === undefined ? true : Result;
}
}
};
export default Renderer;