UNPKG

@icanvas/renderer

Version:
131 lines (126 loc) 5.02 kB
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;