git add clock basic renderer
This commit is contained in:
parent
a7aae62233
commit
2550e2e14f
143
source/GLRender/BasicRenderer.ts
Normal file
143
source/GLRender/BasicRenderer.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import { AbstractRenderer, IRendererParam, IAnyObject } from "@Model/Renderer";
|
||||||
|
import { EventType } from "@Model/Emitter";
|
||||||
|
import { GLCanvas, GLCanvasOption } from "./GLCanvas";
|
||||||
|
import { GLContext } from "./GLContext";
|
||||||
|
import { Clock } from "@Model/Clock";
|
||||||
|
|
||||||
|
interface IRendererOwnParams {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染器参数
|
||||||
|
*/
|
||||||
|
type IRendererParams = IRendererOwnParams & GLCanvasOption;
|
||||||
|
|
||||||
|
abstract class BasicRenderer<
|
||||||
|
P extends IRendererParam = {},
|
||||||
|
M extends IAnyObject = {},
|
||||||
|
E extends Record<EventType, any> = {}
|
||||||
|
> extends AbstractRenderer<P, M & IRendererParams, E> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染器参数
|
||||||
|
*/
|
||||||
|
public param: Partial<M & IRendererParams> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用的画布
|
||||||
|
*/
|
||||||
|
public canvas: GLCanvas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染时钟
|
||||||
|
*/
|
||||||
|
protected clock: Clock;
|
||||||
|
|
||||||
|
public constructor(canvas: HTMLCanvasElement, param: Partial<M & IRendererParams> = {}) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// 初始化参数
|
||||||
|
this.param = {
|
||||||
|
autoResize: param.autoResize ?? true,
|
||||||
|
mouseEvent: param.autoResize ?? true,
|
||||||
|
eventLog: param.eventLog ?? false,
|
||||||
|
className: param.className ?? ""
|
||||||
|
} as M & IRendererParams;
|
||||||
|
|
||||||
|
// 实例化画布对象
|
||||||
|
this.canvas = new GLCanvas(canvas, this.param);
|
||||||
|
|
||||||
|
// 尝试 webgl2
|
||||||
|
this.gl = this.canvas.can.getContext("webgl2") as any;
|
||||||
|
if (this.gl) {
|
||||||
|
this.glVersion = 2;
|
||||||
|
console.log("Render: Using WebGL2 :)");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// 尝试 WebGL1
|
||||||
|
this.gl = this.canvas.can.getContext("webgl") as any;
|
||||||
|
if (this.gl){
|
||||||
|
this.glVersion = 1;
|
||||||
|
console.log("Render: Using WebGL1 :(");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取失败发出警告
|
||||||
|
else {
|
||||||
|
console.error("Render: Not supported WebGL!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例化时钟
|
||||||
|
*/
|
||||||
|
this.clock = new Clock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
this.onLoad(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行渲染
|
||||||
|
*/
|
||||||
|
protected run() {
|
||||||
|
this.clock.setFn(this.loop.bind(this));
|
||||||
|
this.clock.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大小变化
|
||||||
|
*/
|
||||||
|
protected resize() {
|
||||||
|
this.loop(0);
|
||||||
|
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开启自动大小调整
|
||||||
|
*/
|
||||||
|
protected autoResize() {
|
||||||
|
this.canvas.on("resize", this.resize.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清屏颜色
|
||||||
|
*/
|
||||||
|
public cleanColor: [number, number, number, number] = [.1, .1, .1, 1.];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清屏
|
||||||
|
*/
|
||||||
|
public cleanCanvas(){
|
||||||
|
this.gl.clearColor(
|
||||||
|
this.cleanColor[0], this.cleanColor[1],
|
||||||
|
this.cleanColor[2], this.cleanColor[3]
|
||||||
|
);
|
||||||
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GL 上下文
|
||||||
|
*/
|
||||||
|
public gl: GLContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebGL 版本
|
||||||
|
*/
|
||||||
|
public glVersion: (0 | 1 | 2) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
* @param param 渲染器参数
|
||||||
|
*/
|
||||||
|
abstract onLoad(param: Partial<M & IRendererParams>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染器执行
|
||||||
|
*/
|
||||||
|
abstract loop(dur: number): void;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicRenderer;
|
||||||
|
export { BasicRenderer, IRendererParams };
|
@ -1,49 +1,30 @@
|
|||||||
import { AbstractRenderer, ObjectID, ObjectData, ICommonParam } from "@Model/Renderer";
|
import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer";
|
||||||
import { GLCanvas, GLCanvasOption } from "./GLCanvas";
|
import { BasicRenderer, IRendererParams } from "./BasicRenderer";
|
||||||
|
|
||||||
interface IRendererOwnParams {}
|
interface IClassicRendererParams {}
|
||||||
|
|
||||||
/**
|
class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> {
|
||||||
* 渲染器参数
|
|
||||||
*/
|
|
||||||
type IRendererParams = IRendererOwnParams & GLCanvasOption;
|
|
||||||
|
|
||||||
class ClassicRenderer extends AbstractRenderer<{}, IRendererParams> {
|
onLoad(param: Partial<IClassicRendererParams & IRendererParams>): void {
|
||||||
|
this.run();
|
||||||
/**
|
this.autoResize();
|
||||||
* 渲染器参数
|
|
||||||
*/
|
|
||||||
public param: IRendererParams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用的画布
|
|
||||||
*/
|
|
||||||
public canvas: GLCanvas;
|
|
||||||
|
|
||||||
public constructor(canvas: HTMLCanvasElement, param: IRendererParams = {}) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// 初始化参数
|
|
||||||
this.param = {
|
|
||||||
autoResize: param.autoResize ?? true,
|
|
||||||
mouseEvent: param.autoResize ?? true,
|
|
||||||
eventLog: param.eventLog ?? false,
|
|
||||||
clasName: param.clasName ?? ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 实例化画布对象
|
|
||||||
this.canvas = new GLCanvas(canvas, this.param);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clean(id?: ObjectID | ObjectID[]): this {
|
clean(id?: ObjectID | ObjectID[]): this {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
points(id: ObjectID, position: ObjectData, param?: ICommonParam): this {
|
points(id: ObjectID, position: ObjectData, param?: ICommonParam): this {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
cube(id: ObjectID, position: ObjectData, param?: ICommonParam): this {
|
cube(id: ObjectID, position: ObjectData, param?: ICommonParam): this {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loop(): void {
|
||||||
|
this.cleanCanvas();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ClassicRenderer;
|
export default ClassicRenderer;
|
||||||
|
@ -27,7 +27,7 @@ interface GLCanvasOption {
|
|||||||
/**
|
/**
|
||||||
* 节点类名
|
* 节点类名
|
||||||
*/
|
*/
|
||||||
clasName?: string
|
className?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type GLCanvasEvent = {
|
type GLCanvasEvent = {
|
||||||
@ -270,7 +270,7 @@ class GLCanvas extends Emitter<GLCanvasEvent> {
|
|||||||
this.canvas = ele ?? document.createElement("canvas");
|
this.canvas = ele ?? document.createElement("canvas");
|
||||||
|
|
||||||
this.div = document.createElement("div");
|
this.div = document.createElement("div");
|
||||||
this.div.className = opt.clasName ?? "";
|
this.div.className = opt.className ?? "";
|
||||||
this.div.appendChild(this.canvas);
|
this.div.appendChild(this.canvas);
|
||||||
|
|
||||||
this.canvas.style.width = "100%";
|
this.canvas.style.width = "100%";
|
||||||
|
75
source/Model/Clock.ts
Normal file
75
source/Model/Clock.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
export {Clock, LoopFunction};
|
||||||
|
|
||||||
|
type LoopFunction = (t: number)=>void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时钟
|
||||||
|
*/
|
||||||
|
class Clock {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总用时
|
||||||
|
*/
|
||||||
|
private allTime: number = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 速率
|
||||||
|
*/
|
||||||
|
public speed: number = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主函数
|
||||||
|
*/
|
||||||
|
private fn: LoopFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动画循环
|
||||||
|
* @param fn 循环函数
|
||||||
|
*/
|
||||||
|
public constructor(fn?: LoopFunction){
|
||||||
|
this.fn = fn ?? ((t) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置函数
|
||||||
|
* @param fn 循环函数
|
||||||
|
*/
|
||||||
|
public setFn(fn:LoopFunction){
|
||||||
|
this.fn = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始
|
||||||
|
*/
|
||||||
|
public run(){
|
||||||
|
|
||||||
|
// 主循环
|
||||||
|
let loop = (t:number)=>{
|
||||||
|
|
||||||
|
// 时差
|
||||||
|
let dur = (t - this.allTime) * this.speed / 1000;
|
||||||
|
|
||||||
|
// 检测由于失焦导致的丢帧
|
||||||
|
if (t - this.allTime < 100) {
|
||||||
|
this.fn(dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新时间
|
||||||
|
this.allTime = t;
|
||||||
|
|
||||||
|
// 继续循环
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取时间
|
||||||
|
requestAnimationFrame((t)=>{
|
||||||
|
|
||||||
|
// 记录初始时间
|
||||||
|
this.allTime = t;
|
||||||
|
|
||||||
|
// 开启循环
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -57,6 +57,9 @@ interface IRendererConstructor<
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染器 API
|
* 渲染器 API
|
||||||
|
* @template P 渲染器绘制参数
|
||||||
|
* @template M 渲染器参数
|
||||||
|
* @template E 渲染器事件
|
||||||
*/
|
*/
|
||||||
abstract class AbstractRenderer<
|
abstract class AbstractRenderer<
|
||||||
P extends IRendererParam = {},
|
P extends IRendererParam = {},
|
||||||
@ -67,7 +70,7 @@ abstract class AbstractRenderer<
|
|||||||
/**
|
/**
|
||||||
* 渲染器参数
|
* 渲染器参数
|
||||||
*/
|
*/
|
||||||
abstract param: M;
|
abstract param: Partial<M>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型断言
|
* 类型断言
|
||||||
@ -119,4 +122,8 @@ abstract class AbstractRenderer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default AbstractRenderer;
|
export default AbstractRenderer;
|
||||||
export { AbstractRenderer, ObjectID, ICommonParam, ObjectData, IRendererConstructor };
|
export {
|
||||||
|
AbstractRenderer, ObjectID, IAnyObject,
|
||||||
|
ICommonParam, IRendererParam,
|
||||||
|
ObjectData, IRendererConstructor
|
||||||
|
};
|
@ -2,6 +2,7 @@ div.main-canvas {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
background-color: rgba($color: #000000, $alpha: .9);
|
||||||
|
|
||||||
div.canvas {
|
div.canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -23,7 +23,7 @@ class Laboratory extends Component {
|
|||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
|
|
||||||
const renderer = new ClassicRenderer(canvas, {
|
const renderer = new ClassicRenderer(canvas, {
|
||||||
clasName: "canvas"
|
className: "canvas"
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(renderer);
|
console.log(renderer);
|
||||||
|
Loading…
Reference in New Issue
Block a user