Browse Source

主框架基本完成

master
blobt 4 years ago
parent
commit
8b61ec211a
  1. BIN
      data/pic0.png
  2. BIN
      data/pic1.jpg
  3. 1
      data/test.txt
  4. BIN
      data/textureUV.jpg
  5. 20102
      package-lock.json
  6. 1
      public/index.html
  7. BIN
      public/pic0.png
  8. BIN
      public/pic1.jpg
  9. 13
      src/App.tsx
  10. 299
      src/examples/Demo1.ts
  11. 7
      src/render/common.ts
  12. 347
      src/render/common/DrawHelper.ts
  13. 78
      src/render/common/HttpRequest.ts
  14. 9
      src/render/common/ImageInfo.ts
  15. 6
      src/render/core/Application.ts
  16. 53
      src/render/core/CameraApplication.ts
  17. 2
      src/render/core/Event.ts
  18. 6
      src/render/core/Primitives.ts
  19. 4
      src/render/ds/TypedArrayList.ts
  20. 2
      src/render/math/Mat4.ts
  21. 1545
      src/render/math/TSM.ts
  22. 5
      src/render/math/Util.ts
  23. 91
      src/render/webgl/WebGLApplication.ts
  24. 2
      src/render/webgl/WebGLMatrixStack.ts
  25. 3
      src/render/webgl/WebGLMesh.ts
  26. 6
      src/render/webgl/WebGLShaderSource.ts
  27. 10
      src/render/webgl/index.ts

BIN
data/pic0.png

After

Width: 886  |  Height: 584  |  Size: 100 KiB

BIN
data/pic1.jpg

After

Width: 256  |  Height: 192  |  Size: 25 KiB

1
data/test.txt

@ -0,0 +1 @@
test.txt测试文件

BIN
data/textureUV.jpg

After

Width: 1024  |  Height: 1024  |  Size: 636 KiB

20102
package-lock.json
File diff suppressed because it is too large
View File

1
public/index.html

@ -28,6 +28,7 @@
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<canvas id="render" width="800" height="600" style="background: lightgray"> </canvas>
<div id="root"></div> <div id="root"></div>
<!-- <!--
This HTML file is a template. This HTML file is a template.

BIN
public/pic0.png

After

Width: 886  |  Height: 584  |  Size: 100 KiB

BIN
public/pic1.jpg

After

Width: 256  |  Height: 192  |  Size: 25 KiB

13
src/App.tsx

@ -1,12 +1,21 @@
import React from 'react'; import React from 'react';
import './App.css'; import './App.css';
import { vec3, vec4 } from "./render/math";
import { Demo1 } from "./examples/Demo1";
import { Application } from "./render/core/Application";
function frameCallback(app: Application): void {
//console.log(app);
}
function App() { function App() {
let canvas: HTMLCanvasElement | null = document.getElementById('render') as HTMLCanvasElement;
let instance = new Demo1(canvas);
instance.frameCallback = frameCallback;
instance.run();
return ( return (
<div className="App"> <div className="App">
sasa
</div> </div>
); );
} }

299
src/examples/Demo1.ts

@ -0,0 +1,299 @@
import { vec3, vec4, Util } from "../render/math";
import { GLProgram, GLTexture, GLStaticMesh, GLtextureCache, GLProgramCache } from "../render/webgl";
import { CameraApplication } from "../render/core/CameraApplication";
import { HttpRequest } from "../render/common/HttpRequest";
import { DrawHelper } from "../render/common/DrawHelper";
import { CanvasKeyBoardEvent } from "../render/core/Event";
import { Cube, GeometryData } from "../render/core/Primitives";
import { EAxisType } from "../render/common";
import { mat4 } from "../render/math/Mat4";
export class Demo1 extends CameraApplication {
/**
* @var GPU Program对象
*/
colorProgram: GLProgram;
/**
* @var GPU Program对象
*/
textureProgram: GLProgram
/**
* @var hao
*/
currentTexIdx: number;
/**
* @var
*/
textures: GLTexture[];
/**
* @var
*/
cube: Cube;
/**
* @var
*/
cubeVAO: GLStaticMesh;
/**
* @var cube的角位移
*/
cubeAngle: number;
/**
* @var cube位移速度
*/
cubeSpeed: number;
/**
* @var
*/
cubeMatrix: mat4
/**
* @var
*/
triAngle: number;
/**
* @var
*/
triSpeed: number;
/**
* @var
*/
triTimerId: number;
/**
* @var
*/
triMatrix: mat4;
/**
* @var enum值
*/
private _hitAxis: EAxisType;
public constructor(canvas: HTMLCanvasElement) {
super(canvas, { premultipliedAlpha: false }, true);
this.cubeAngle = 0;
this.cubeSpeed = 100;
this.triAngle = 0;
this.triSpeed = 1;
this.triTimerId = -1;
this.currentTexIdx = 0;
this.textures = [];
this.textures.push(GLtextureCache.instance.getMust("default"));
this.textureProgram = GLProgramCache.instance.getMust("texture");
this.colorProgram = GLProgramCache.instance.getMust("color");
this.cube = new Cube(0.5, 0.5, 0.5);
let data: GeometryData = this.cube.makeGeometryData();
this.cubeVAO = data.makeStaticVAO(this.gl);
this._hitAxis = EAxisType.NONE;
this.cubeMatrix = new mat4();
this.triMatrix = new mat4();
this.camera.z = 8;
}
/**
*
*/
private _renderCube(): void {
//绑定textture 和 program
this.textures[this.currentTexIdx].bind();
this.textureProgram.bind();
this.textureProgram.loadSampler();
//绘制立方体
this.matStack.loadIdentity();
this.matStack.pushMatrix();//矩阵进栈
this.matStack.rotate(this.cubeAngle, vec3.up, false);
//合成mvp矩阵
mat4.product(this.camera.viewProjecttionMatrix, this.matStack.modelViewMatrix, this.cubeMatrix);
//将合成矩阵作用到GLProgram
this.textureProgram.setMatrix4(GLProgram.MVPMatrix, this.cubeMatrix);
//使用当前绑定的texture和program绘制cubeVao对象
this.cubeVAO.draw();
//绘制坐标系
DrawHelper.drawCoordSystem(this.builder, this.cubeMatrix, this._hitAxis, 1);
//释放资源
this.matStack.popMatrix();
this.textureProgram.unbind();
this.textures[this.currentTexIdx].unbind();
}
/**
*
*/
private _renderTriangle(): void {
//关闭背面剔除
this.gl.disable(this.gl.CULL_FACE);
//绑定gpu program和color program
this.colorProgram.bind();
//生成一个矩阵 并 旋转
this.matStack.pushMatrix();
this.matStack.translate(new vec3([-2, 0, 0]));
this.matStack.rotate(this.triAngle, vec3.forward, true);
//使用类似opengl1.1的立即绘制模式,默认使用gl.TRIANGLES方式绘制
this.builder.begin();
this.builder.color(1, 0, 0).vertex(-0.5, 0, 0);
this.builder.color(0, 1, 0).vertex(0.5, 0, 0);
this.builder.color(0, 0, 1).vertex(0, 0.5, 0);
//合成mvp矩阵
mat4.product(this.camera.viewProjecttionMatrix, this.matStack.modelViewMatrix, this.triMatrix);
//绘制
this.builder.end(this.triMatrix);
//释放资源
this.matStack.popMatrix();
this.colorProgram.unbind();
this.gl.enable(this.gl.CULL_FACE);
}
/**
*
* @param text
* @param x
* @param y
*/
private _renderText(text: string, x: number = this.canvas.width * 0.5, y: number = 150): void {
if (this.ctx2D !== null) {
this.ctx2D.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx2D.save();
this.ctx2D.fillStyle = "red";
this.ctx2D.textAlign = "center";
this.ctx2D.textBaseline = "top";
this.ctx2D.font = "30px Arial";
this.ctx2D.fillText(text, x, y);
this.ctx2D.restore();
}
}
/**
*
* @param pos
* @param axis
* @param mvp
* @param inverse
*/
public drawText(pos: vec3, axis: EAxisType, mvp: mat4, inverse: boolean = false): void {
if (this.ctx2D === null) {
return;
}
let out: vec3 = new vec3();
if (Util.obj2GLViewportSpace(pos, mvp, this.camera.getViewport(), out)) {
out.y = this.canvas.height - out.y;//变换到屏幕坐标系,左手系,原点再左上角,x向右,有向下
this.ctx2D.save();
this.ctx2D.font = "30px Arial";
if (axis === EAxisType.XAXIS) {
this.ctx2D.textBaseline = "top";
this.ctx2D.fillStyle = "red";
if (inverse === true) {
this.ctx2D.textAlign = "right";
this.ctx2D.fillText("-x", out.x, out.y);
} else {
this.ctx2D.textAlign = "left";
this.ctx2D.fillText("x", out.x, out.y);
}
} else if (axis === EAxisType.YAXIS) {
this.ctx2D.textAlign = "center";
this.ctx2D.fillStyle = "green";
if (inverse === true) {
this.ctx2D.textBaseline = "top";
this.ctx2D.fillText("-y", out.x, out.y);
} else {
this.ctx2D.textBaseline = "bottom";
this.ctx2D.fillText("y", out.x, out.y);
}
} else {
this.ctx2D.fillStyle = "blue";
this.ctx2D.textBaseline = "top";
if (inverse === true) {
this.ctx2D.textAlign = "right";
this.ctx2D.fillText("-z", out.x, out.y);
} else {
this.ctx2D.textAlign = "left";
this.ctx2D.fillText("z", out.x, out.y);
}
}
this.ctx2D.restore();
}
}
public render(): void {
//this._renderCube();
this._renderTriangle();
//this._renderText("Hello world!");
}
public update(elapsecMsec: number, intervalSec: number): void {
this.cubeAngle += this.cubeSpeed * intervalSec;
super.update(elapsecMsec, intervalSec);
}
public cubeTimeCallback(id: number, data: any): void {
this.currentTexIdx++;
this.currentTexIdx %= this.textures.length;
}
/**
*
*/
public async run(): Promise<void> {
// let img: HTMLImageElement = await HttpRequest.loadImageAsync("pic0.png");
// let tex: GLTexture = new GLTexture(this.gl);
// tex.upload(img, 0, true);
// tex.filter();
// this.textures.push(tex);
// img = await HttpRequest.loadImageAsync("pic1.jpg");
// tex = new GLTexture(this.gl);
// tex.upload(img, 0, true);
// tex.filter();
// this.textures.push(tex);
//this.addTimer(this.cubeTimeCallback.bind(this), 2, false);
super.run();
}
public triTimeCallback(id: number, data: any): void {
this.triAngle += this.triSpeed;
}
public onKeyDown(evt: CanvasKeyBoardEvent): void {
if (evt.key === "q") {
if (this.triTimerId === -1) {
this.triTimerId = this.addTimer(this.triTimeCallback.bind(this), 100.25, false);
}
} else if (evt.key === "e") {
if (this.triTimerId !== -1) {
if (this.removeTimer(this.triTimerId)) {
this.triTimerId = -1;
}
}
}
}
}

7
src/render/common.ts

@ -48,3 +48,10 @@ export enum EMatrixMode {
PROJECTION, PROJECTION,
TEXTURE TEXTURE
} }
export enum EAxisType {
NONE = -1,
XAXIS,
YAXIS,
ZAXIS
}

347
src/render/common/DrawHelper.ts

@ -0,0 +1,347 @@
import { TypedArrayList } from "../ds/TypedArrayList";
import { EAxisType } from "../common";
import { GLMeshBuilder } from "../webgl"
import { mat4, vec3, vec4 } from "../math";
export class CoordSystem {
/**
* @var
*/
public viewport: number[] = [];
/**
* @var
*/
public axis: vec3;
/**
* @var
*/
public angle: number;
/**
* @var [0,0,0]
*/
public pos: vec3;
/**
* @var
*/
public isDrawAxis: boolean;
/**
* @var
*/
public isD3D: boolean;
public constructor(viewport: number[], pos: vec3 = vec3.zero, axis: vec3 = vec3.up, angle: number = 0, isDrawAxis: boolean = false, isD3D: boolean = false) {
this.viewport = viewport;
this.axis = axis;
this.angle = angle;
this.pos = pos;
this.isDrawAxis = isDrawAxis;
this.isD3D = isD3D;
}
}
export class DrawHelper {
/**
* @var
*/
public static defaultHitCollor: vec4 = new vec4([1, 1, 0]);
/**
* xy平面上的圆的点
* @param pts
* @param radius
* @param segment
*/
public static getCirclePointsOnXYPlane(pts: TypedArrayList<Float32Array>, radius: number, segment: number = 32): void {
pts.clear();
let step: number = Math.PI / segment;
let ang: number = 0;
for (let i: number = 0; i < segment; i++) {
ang = i * step;
pts.push(Math.cos(ang));
pts.push(Math.sin(ang));
pts.push(0.0);
}
}
/**
* full
* @param builder
* @param mat
* @param len
* @param rotateAxis
*/
public static drawFullCoordSystem(builder: GLMeshBuilder, mat: mat4, len: number = 1, rotateAxis: vec3 | null = null): void {
builder.gl.lineWidth(5);//用5个像素大小的直径绘制线段,但是目前仅Safari支持
builder.gl.disable(builder.gl.DEPTH_TEST);//关闭深度测试
builder.begin(builder.gl.LINES);//开始绘制
//+x轴
builder.color(1.0, 0.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(1.0, 0.0, 0.0).vertex(len, 0.0, 0.0);
//-x轴
builder.color(1.0, 0.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(1.0, 0.0, 0.0).vertex(-len, 0.0, 0.0);
//+y轴
builder.color(0.0, 1.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 1.0, 0.0).vertex(0.0, len, 0.0);
//-y轴
builder.color(0.0, 1.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 1.0, 0.0).vertex(0.0, -len, 0.0);
//+z轴
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, len);
//-z轴
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, len);
//绘制旋转轴
if (rotateAxis !== null) {
let scale: vec3 = rotateAxis.scale(len);
builder.color(0.0, 0.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 0.0, 0.0).vertex(scale.x, scale.y, scale.z);
}
builder.end(mat);//结束绘制
builder.gl.enable(builder.gl.DEPTH_TEST);//开启深度测试
builder.gl.lineWidth(1);
}
/**
*
* @param builder
* @param mat
* @param hitAxis
* @param len
* @param rotateAxis
* @param isLeftHandness
*/
public static drawCoordSystem(builder: GLMeshBuilder, mat: mat4, hitAxis: EAxisType, len: number = 5, rotateAxis: vec3 | null = null, isLeftHandness: boolean = false): void {
builder.gl.lineWidth(5);//用5个像素大小的直径绘制线段,但是目前仅Safari支持
builder.gl.disable(builder.gl.DEPTH_TEST);//关闭深度测试
builder.begin(builder.gl.LINES);//开始绘制
//+x轴
if (hitAxis === EAxisType.XAXIS) {
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, 0.0, 0.0);
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(len, 0.0, 0.0);
} else {
builder.color(1.0, 0.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(1.0, 0.0, 0.0).vertex(len, 0.0, 0.0);
}
//+y轴
if (hitAxis === EAxisType.YAXIS) {
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, 0.0, 0.0);
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, len, 0.0);
} else {
builder.color(0.0, 1.0, 0.0).vertex(0.0, 0.0, 0.0);
builder.color(0.0, 1.0, 0.0).vertex(0.0, len, 0.0);
}
//+z轴
if (hitAxis === EAxisType.ZAXIS) {
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, 0.0, 0.0);
if (isLeftHandness === true) {
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, 0.0, -len);
} else {
builder.color(DrawHelper.defaultHitCollor.r, DrawHelper.defaultHitCollor.g, DrawHelper.defaultHitCollor.b).vertex(0.0, 0.0, len);
}
} else {
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, 0.0);
if (isLeftHandness === true) {
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, -len);
} else {
builder.color(0.0, 0.0, 1.0).vertex(0.0, 0.0, len);
}
}
//绘制旋转轴
if (rotateAxis !== null) {
let scale: vec3 = rotateAxis.scale(len);
builder.color(0.0, 0.0, 0.0).vertex(0.0, 0.0, 0.0);
if (isLeftHandness === true) {
builder.color(0.0, 0.0, 0.0).vertex(scale.x, scale.y, -scale.z);
} else {
builder.color(0.0, 0.0, 0.0).vertex(scale.x, scale.y, scale.z);
}
}
builder.end(mat);//结束绘制
builder.gl.enable(builder.gl.DEPTH_TEST);//开启深度测试
builder.gl.lineWidth(1);
}
/**
*
* mins点2maxs5使线
* /3--------/7 |
* / | / |
* / | / |
* 1---------5 |
* | /2- - -|- -6
* | / | /
* |/ | /
* 0---------4/
* @param builder
* @param mat
* @param mins
* @param maxs
* @param color
*/
public static drawBoundBox(builder: GLMeshBuilder, mat: mat4, mins: vec3, maxs: vec3, color: vec4 = vec4.red): void {
builder.gl.disable(builder.gl.DEPTH_TEST);//关闭深度测试
//使用LINE_LOOP绘制底面
builder.begin(builder.gl.LINE_LOOP);
builder.color(color.r, color.g, color.b).vertex(mins.x, mins.y, mins.z); // 2 - - -
builder.color(color.r, color.g, color.b).vertex(mins.x, mins.y, maxs.z); // 0 - - +
builder.color(color.r, color.g, color.b).vertex(maxs.x, mins.y, maxs.z); // 4 + - +
builder.color(color.r, color.g, color.b).vertex(maxs.x, mins.y, mins.z); // 6 + - -
builder.end(mat);
//使用LINE_LOOP绘制顶面
builder.begin(builder.gl.LINE_LOOP);
builder.color(color.r, color.g, color.b).vertex(mins.x, maxs.y, mins.z); // 3 - + -
builder.color(color.r, color.g, color.b).vertex(maxs.x, maxs.y, mins.z); // 7 + + -
builder.color(color.r, color.g, color.b).vertex(maxs.x, maxs.y, maxs.z); // 5 + + +
builder.color(color.r, color.g, color.b).vertex(mins.x, maxs.y, maxs.z); // 1 - + +
builder.end(mat);
//使用LINES绘制侧四个面
builder.begin(builder.gl.LINES);
builder.color(color.r, color.g, color.b).vertex(mins.x, mins.y, mins.z); // 2 - - -
builder.color(color.r, color.g, color.b).vertex(mins.x, maxs.y, mins.z); // 3 - + -
builder.color(color.r, color.g, color.b).vertex(mins.x, mins.y, maxs.z); // 0 - - +
builder.color(color.r, color.g, color.b).vertex(mins.x, maxs.y, maxs.z); // 1 - + +
builder.color(color.r, color.g, color.b).vertex(maxs.x, mins.y, maxs.z); // 4 + - +
builder.color(color.r, color.g, color.b).vertex(maxs.x, maxs.y, maxs.z); // 5 + + +
builder.color(color.r, color.g, color.b).vertex(maxs.x, mins.y, mins.z); // 6 + - -
builder.color(color.r, color.g, color.b).vertex(maxs.x, maxs.y, mins.z); // 7 + + -
builder.end(mat);
builder.gl.enable(builder.gl.DEPTH_TEST);
}
/**
*
* @param builder
* @param mat
* @param halfLen
* @param color
*/
public static drawWireFrameCubeBox(builder: GLMeshBuilder, mat: mat4, halfLen: number = 0.2, color: vec4 = vec4.red): void {
let mins: vec3 = new vec3([-halfLen, -halfLen, -halfLen]);
let maxs: vec3 = new vec3([halfLen, halfLen, halfLen]);
DrawHelper.drawBoundBox(builder, mat, mins, maxs, color);
}
/**
* /3--------/7 |
* / | / |
* / | / |
* 1---------5 |
* | /2- - -|- -6
* | / | /
* |/ | /
* 0---------4/
* @param builder
* @param mat
* @param halfLen
* @param tc
*/
public static drawTextureCubeBox(builder: GLMeshBuilder, mat: mat4, halfLen: number = 0.2, tc: number[] = [
0, 0, 1, 0, 1, 1, 0, 1, // 前面
0, 0, 1, 0, 1, 1, 0, 1, // 右面
0, 0, 1, 0, 1, 1, 0, 1, // 后面
0, 0, 1, 0, 1, 1, 0, 1, // 左面
0, 0, 1, 0, 1, 1, 0, 1, // 上面
0, 0, 1, 0, 1, 1, 0, 1, // 下面
]): void {
//绘制前面
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[0], tc[1]).vertex(-halfLen, -halfLen, halfLen); // 0 - - +
builder.texcoord(tc[2], tc[3]).vertex(halfLen, -halfLen, halfLen); // 4 + - +
builder.texcoord(tc[4], tc[5]).vertex(halfLen, halfLen, halfLen); // 5 + + +
builder.texcoord(tc[6], tc[7]).vertex(-halfLen, halfLen, halfLen); // 1 - + +
builder.end(mat);
//绘制右边
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[8], tc[9]).vertex(halfLen, -halfLen, halfLen); // 4 + - +
builder.texcoord(tc[10], tc[11]).vertex(halfLen, -halfLen, -halfLen); // 6 + - -
builder.texcoord(tc[12], tc[13]).vertex(halfLen, halfLen, -halfLen); // 7 + + -
builder.texcoord(tc[14], tc[15]).vertex(halfLen, halfLen, halfLen); // 5 + + +
builder.end(mat);
// 后面
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[16], tc[17]).vertex(halfLen, -halfLen, -halfLen); // 6 + - -
builder.texcoord(tc[18], tc[19]).vertex(-halfLen, -halfLen, -halfLen); // 2 - - -
builder.texcoord(tc[20], tc[21]).vertex(-halfLen, halfLen, -halfLen); // 3 - + -
builder.texcoord(tc[22], tc[23]).vertex(halfLen, halfLen, -halfLen); // 7 + + -
builder.end(mat);
// 左面
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[24], tc[25]).vertex(-halfLen, -halfLen, -halfLen); // 2 - - -
builder.texcoord(tc[26], tc[27]).vertex(-halfLen, -halfLen, halfLen); // 0 - - +
builder.texcoord(tc[28], tc[29]).vertex(-halfLen, halfLen, halfLen); // 1 - + +
builder.texcoord(tc[30], tc[31]).vertex(-halfLen, halfLen, -halfLen); // 3 - + -
builder.end(mat);
// 上面
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[32], tc[33]).vertex(-halfLen, halfLen, halfLen); // 1 - + +
builder.texcoord(tc[34], tc[35]).vertex(halfLen, halfLen, halfLen); // 5 + + +
builder.texcoord(tc[36], tc[37]).vertex(halfLen, halfLen, -halfLen); // 7 + + -
builder.texcoord(tc[38], tc[39]).vertex(-halfLen, halfLen, -halfLen); // 3 - + -
builder.end(mat);
// 下面
builder.begin(builder.gl.TRIANGLE_FAN);
builder.texcoord(tc[40], tc[41]).vertex(-halfLen, -halfLen, halfLen); // 0 - - +
builder.texcoord(tc[42], tc[43]).vertex(-halfLen, -halfLen, -halfLen); // 2 - - -
builder.texcoord(tc[44], tc[45]).vertex(halfLen, -halfLen, -halfLen); // 6 + - -
builder.texcoord(tc[46], tc[47]).vertex(halfLen, -halfLen, halfLen); // 4 + - +
builder.end(mat);
}
public static drawWireFrameFrustum(builder: GLMeshBuilder, mat: mat4, pts: vec3[], color: vec4 = vec4.red): void {
builder.gl.disable(builder.gl.DEPTH_TEST);
//使用LINE_LOOP绘制近平面四边形
builder.begin(builder.gl.LINE_LOOP);
builder.color(color.r, color.g, color.b).vertex(pts[0].x, pts[0].y, pts[0].z);
builder.color(color.r, color.g, color.b).vertex(pts[1].x, pts[1].y, pts[1].z);
builder.color(color.r, color.g, color.b).vertex(pts[2].x, pts[2].y, pts[2].z);
builder.color(color.r, color.g, color.b).vertex(pts[3].x, pts[3].y, pts[3].z);
builder.end(mat);
//使用LINE_LOOP绘制远平面四边形
builder.begin(builder.gl.LINE_LOOP);
builder.color(color.r, color.g, color.b).vertex(pts[4].x, pts[4].y, pts[4].z);
builder.color(color.r, color.g, color.b).vertex(pts[5].x, pts[5].y, pts[5].z);
builder.color(color.r, color.g, color.b).vertex(pts[6].x, pts[6].y, pts[6].z);
builder.color(color.r, color.g, color.b).vertex(pts[7].x, pts[7].y, pts[7].z);
builder.end(mat);
// 使用LINES绘制绘制近平面与远平面的四条边
builder.begin(builder.gl.LINES); // 使用的是LINES图元绘制模式
builder.color(color.r, color.g, color.b).vertex(pts[0].x, pts[0].y, pts[0].z); //
builder.color(color.r, color.g, color.b).vertex(pts[4].x, pts[4].y, pts[4].z); //
builder.color(color.r, color.g, color.b).vertex(pts[1].x, pts[1].y, pts[1].z); //
builder.color(color.r, color.g, color.b).vertex(pts[5].x, pts[5].y, pts[5].z); //
builder.color(color.r, color.g, color.b).vertex(pts[2].x, pts[2].y, pts[2].z); //
builder.color(color.r, color.g, color.b).vertex(pts[6].x, pts[6].y, pts[6].z); //
builder.color(color.r, color.g, color.b).vertex(pts[3].x, pts[3].y, pts[3].z); //
builder.color(color.r, color.g, color.b).vertex(pts[7].x, pts[7].y, pts[7].z); //
builder.end(mat);
builder.gl.enable(builder.gl.DEPTH_TEST);
}
}

78
src/render/common/HttpRequest.ts

@ -0,0 +1,78 @@
import { rejects } from "node:assert";
import { ImageInfo } from "./ImageInfo";
export class HttpRequest {
/**
*
* tsconfig.json中将default的es5改成ES2015
* @param url
*/
public static loadImageAsync(url: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject): void => {
const image: HTMLImageElement = new Image();
image.onload = function () {
resolve(image);
}
image.onerror = function () {
reject(new Error("Cloud not load image '" + url + "'."));
}
image.src = url;
});
}
/**
*
* @param url
* @param name
* @returns
*/
public static loadImageAsyncSafe(url: string, name: string = url): Promise<ImageInfo | null> {
return new Promise((resolve, rehect): void => {
let image: HTMLImageElement = new Image();
image.onload = function () {
let info: ImageInfo = new ImageInfo(name, image);
resolve(info);
}
image.onerror = function () {
resolve(null);
}
image.src = url;
});
}
/**
*
* @param url
*/
public static loadTextFileAsync(url: string): Promise<string> {
return new Promise((resolve, reject): void => {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.onreadystatechange = (ev: Event): any => {
if (xhr.readyState === 4 && xhr.status === 200) {
resolve(xhr.responseText);
}
}
xhr.open("get", url, true, null, null);
xhr.send();
});
}
/**
*
* @param url
*/
public static loadArrayBufferAsync(url: string): Promise<ArrayBuffer> {
return new Promise((resolve, reject): void => {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = (ev: Event): any => {
if (xhr.readyState === 4 && xhr.status === 2000) {
resolve(xhr.response as ArrayBuffer);
}
}
xhr.open("get", url, true, null, null);
xhr.send();
});
}
}

9
src/render/common/ImageInfo.ts

@ -0,0 +1,9 @@
export class ImageInfo {
public name: string;
public image: HTMLElement;
public constructor(path: string, image: HTMLElement) {
this.name = path;
this.image = image;
}
}

6
src/render/core/Application.ts

@ -1,4 +1,4 @@
import { vec2 } from "../math/TSM";
import { vec2 } from "../math";
import { CanvasKeyBoardEvent, CanvasMouseEvent, EInputEventType } from "./Event"; import { CanvasKeyBoardEvent, CanvasMouseEvent, EInputEventType } from "./Event";
import { Timer, TimerCallback } from "./Timer"; import { Timer, TimerCallback } from "./Timer";
@ -71,6 +71,7 @@ export class Application implements EventListenerObject {
public constructor(canvas: HTMLCanvasElement) { public constructor(canvas: HTMLCanvasElement) {
this.canvas = canvas; this.canvas = canvas;
//设置鼠标的监听事件 //设置鼠标的监听事件
@ -340,7 +341,7 @@ export class Application implements EventListenerObject {
return timer.id; return timer.id;
} }
} }
console.log(timeout);
timer = new Timer(callback); timer = new Timer(callback);
timer.callback = callback; timer.callback = callback;
timer.callbackData = data; timer.callbackData = data;
@ -350,7 +351,6 @@ export class Application implements EventListenerObject {
this.timers.push(timer); this.timers.push(timer);
timer.id = ++this._timerId; timer.id = ++this._timerId;
return timer.id; return timer.id;
} }

53
src/render/core/CameraApplication.ts

@ -0,0 +1,53 @@
import { WebGLApplication } from "../webgl/WebGLApplication";
import { CanvasKeyBoardEvent } from "./Event";
import { Camera } from "./Camera";
export class CameraApplication extends WebGLApplication {
/**
* @var
*/
public camera: Camera;
public constructor(canvas: HTMLCanvasElement, contextAttributes: WebGLContextAttributes = { premultipliedAlpha: false }, need2d: boolean = false) {
super(canvas, contextAttributes, need2d);
this.camera = new Camera(this.gl, canvas.width, canvas.height, 45, 1, 200);
this.camera.z = 4;
}
/**
* camera的updatecamera的投影和视图矩阵
* CameraApplication的子类复写本函数 super.update(elapsedMsec, intervalSec)
* @param elapsedMsec
* @param intervalSec
*/
public update(elapsedMsec: number, intervalSec: number) {
this.camera.update(intervalSec);
}
/**
* onKeyPress
* @param evt
*/
public onKeyPress(evt: CanvasKeyBoardEvent): void {
if (evt.key === "w") {
this.camera.moveForward(-1);//摄像机前行
} else if (evt.key === "s") {
this.camera.moveForward(1);//摄像机后退
} else if (evt.key === "a") {
this.camera.moveRightward(1);//摄像机向左运行
} else if (evt.key === "d") {
this.camera.moveRightward(-1);//摄像机向右运行
} else if (evt.key === "z") {
this.camera.moveUpward(1);//摄像机升高
} else if (evt.key === "x") {
this.camera.moveUpward(-1);//摄像机降低
} else if (evt.key === "y") {
this.camera.yaw(1); //摄像机绕本身y轴旋转
} else if (evt.key === "r") {
this.camera.roll(1); //摄像机绕本身z轴旋转
} else if (evt.key === "p") {
this.camera.pitch(1); //摄像机绕本身x轴旋转
}
}
}

2
src/render/core/Event.ts

@ -1,4 +1,4 @@
import { vec2 } from "../math/TSM";
import { vec2 } from "../math";
/** /**
* appliaction所有事件 * appliaction所有事件

6
src/render/core/Primitives.ts

@ -253,10 +253,8 @@ export class GridPlane {
ret.uvs.push(new vec2([u, 1.0 - v])); ret.uvs.push(new vec2([u, 1.0 - v]));
ret.normals.push(new vec3([0, 0, 1])); ret.normals.push(new vec3([0, 0, 1]));
if (iy < this.ny && ix < this.nx) { if (iy < this.ny && ix < this.nx) {
{
ret.indices.push(iy * (this.nx + 1) + ix, (iy + 1) * (this.nx + 1) + ix + 1, iy * (this.nx + 1) + ix + 1);
ret.indices.push((iy + 1) * (this.nx + 1) + ix + 1, iy * (this.nx + 1) + ix, (iy + 1) * (this.nx + 1) + ix);
}
ret.indices.push(iy * (this.nx + 1) + ix, (iy + 1) * (this.nx + 1) + ix + 1, iy * (this.nx + 1) + ix + 1);
ret.indices.push((iy + 1) * (this.nx + 1) + ix + 1, iy * (this.nx + 1) + ix, (iy + 1) * (this.nx + 1) + ix);
} }
} }
} }

4
src/render/ds/TypedArrayList.ts

@ -8,7 +8,7 @@ export class TypedArrayList<T extends Uint16Array | Float32Array | Uint8Array>{
public constructor(typedArrayConstructor: new (capacity: number) => T, capacity: number = 8) { public constructor(typedArrayConstructor: new (capacity: number) => T, capacity: number = 8) {
this._typedArrayConstructor = typedArrayConstructor; this._typedArrayConstructor = typedArrayConstructor;
this._capacity = capacity; this._capacity = capacity;
if (this._capacity == 0) {
if (this._capacity === 0) {
this._capacity = 8; this._capacity = 8;
} }
this._array = new this._typedArrayConstructor(this._capacity); this._array = new this._typedArrayConstructor(this._capacity);
@ -20,7 +20,7 @@ export class TypedArrayList<T extends Uint16Array | Float32Array | Uint8Array>{
if (this._length > this._capacity) { if (this._length > this._capacity) {
if (this._capacity > 0) { if (this._capacity > 0) {
this._capacity += this._capacity; this._capacity += this._capacity;
console.log("curr capaticy = " + this._capacity);
// console.log("curr capaticy = " + this._capacity);
} }
let oldArray: T = this._array; let oldArray: T = this._array;
this._array = new this._typedArrayConstructor(this._capacity); this._array = new this._typedArrayConstructor(this._capacity);

2
src/render/math/Mat4.ts

@ -631,7 +631,7 @@ export class mat4 {
} }
/** /**
* ??????
* mvp矩阵的
* @param m1 * @param m1
* @param m2 * @param m2
* @param result * @param result

1545
src/render/math/TSM.ts
File diff suppressed because it is too large
View File

5
src/render/math/Util.ts

@ -26,7 +26,8 @@ export class Util {
} }
--x; --x;
for (var i = 1; i < 32; i <<= 1) { for (var i = 1; i < 32; i <<= 1) {
x = x | x >> i;
let t:number = x >> i;
x = x | t;
} }
return x + 1; return x + 1;
} }
@ -66,7 +67,7 @@ export class Util {
} }
/** /**
*
*
* @param localPt * @param localPt
* @param mvp * @param mvp
* @param viewport * @param viewport

91
src/render/webgl/WebGLApplication.ts

@ -1,10 +1,99 @@
import { Application } from "../core/Application"; import { Application } from "../core/Application";
import { GLMatrixStack, GLWordMatrixStack } from "./WebGLMatrixStack";
import { GLTexture } from "./WebGLTexture";
import { GLtextureCache } from "./WebGLTextureCache";
import { GLProgram } from "./WebGLProgram";
import { GLProgramCache } from "./WebGLProgramCache";
import { GLMeshBuilder } from "./WebGLMesh";
import { GLAttribState } from "./WebGLAttribState";
import { GLHelper } from "./WebGLHepler";
export class WebGLApplication extends Application { export class WebGLApplication extends Application {
/** /**
* @var WebGL * @var WebGL
*/ */
//public gl: WebGLRenderingContext;
public gl: WebGLRenderingContext;
/**
* @var OpenGL1.1
*/
public matStack: GLWordMatrixStack;
/**
* @var OpenGL1.1
*/
public builder: GLMeshBuilder;
/**
* @var canvas
*/
protected canvas2D: HTMLCanvasElement | null = null;
protected ctx2D: CanvasRenderingContext2D | null = null;
public constructor(canvas: HTMLCanvasElement, contextAttributes: WebGLContextAttributes = { premultipliedAlpha: false }, need2D: boolean = false) {
super(canvas);
//创建渲染上下文
let ctx: WebGLRenderingContext | null = this.canvas.getContext("webgl", contextAttributes);
if (ctx === null) {
throw new Error("create WebGLRenderingContext falied.");
}
this.gl = ctx;
//2维渲染
if (need2D === true) {
let canvasElem: HTMLCanvasElement = document.createElement("canvas") as HTMLCanvasElement;
canvasElem.width = this.canvas.width;
canvasElem.height = this.canvas.height;
canvasElem.style.backgroundColor = "transparent";
canvasElem.style.position = "absolute";
canvasElem.style.left = "0px";
canvasElem.style.top = "0px";
let parent: HTMLElement | null = this.canvas.parentElement;
if (parent === null) {
throw new Error("The canvas element must have a father.");
}
parent.appendChild(canvasElem);
this.ctx2D = canvasElem.getContext("2d");
canvasElem.addEventListener("mousedown", this, false);
canvasElem.addEventListener("mouseup", this, false);
canvasElem.addEventListener("mousemove", this, false);
this.canvas.removeEventListener("mousedown", this);
this.canvas.removeEventListener("mouseup", this);
this.canvas.removeEventListener("mousemove", this);
this.canvas2D = canvasElem;
}
//初始化矩阵栈
this.matStack = new GLWordMatrixStack();
//初始化渲染状态
GLHelper.setDefaultState(this.gl);
//由于canva是左手系,而webgl是右手系
this.isFlipYCoord = true;
//初始化默认纹理
GLtextureCache.instance.set("default", GLTexture.createDefaultTexture(this.gl));
//初始化颜色和纹理program
GLProgramCache.instance.set("color", GLProgram.createDefaultColorProgram(this.gl));
GLProgramCache.instance.set("texture", GLProgram.createDefaultTextureProgram(this.gl));
this.builder = new GLMeshBuilder(this.gl, GLAttribState.POSITION_BIT | GLAttribState.COLOR_BIT, GLProgramCache.instance.getMust("color"));
}
protected getMouseCanvas(): HTMLCanvasElement {
if (this.canvas2D !== null && this.ctx2D !== null) {
return this.canvas2D;
} else {
return this.canvas;
}
}
} }

2
src/render/webgl/WebGLMatrixStack.ts

@ -183,7 +183,7 @@ export class GLMatrixStack {
*/ */
public perspective(fov: number, aspect: number, near: number, far: number, isRadians: boolean = false): GLMatrixStack { public perspective(fov: number, aspect: number, near: number, far: number, isRadians: boolean = false): GLMatrixStack {
this.matrixMode = EMatrixMode.PROJECTION; this.matrixMode = EMatrixMode.PROJECTION;
if (isRadians == false) {
if (isRadians === false) {
fov = Util.toRadian(fov); fov = Util.toRadian(fov);
} }
let mat: mat4 = mat4.perspective(fov, aspect, near, far); let mat: mat4 = mat4.perspective(fov, aspect, near, far);

3
src/render/webgl/WebGLMesh.ts

@ -125,7 +125,8 @@ export class GLStaticMesh extends GLMeshBase {
if (vb === null) { if (vb === null) {
throw new Error("create vbo failed"); throw new Error("create vbo failed");
} }
this._vbo = vbo;
this._vbo = vb;
//绑定vbo并载入顶点数据 //绑定vbo并载入顶点数据
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._vbo); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._vbo);

6
src/render/webgl/WebGLShaderSource.ts

@ -5,8 +5,8 @@ export const GLShaderSource = {
precision highp float; precision highp float;
#endif #endif
attribute vec3 aPosition
attribute vec4 aColor
attribute vec3 aPosition;
attribute vec4 aColor;
uniform mat4 uMVPMatrix; uniform mat4 uMVPMatrix;
@ -24,7 +24,7 @@ export const GLShaderSource = {
varying vec4 vColor; varying vec4 vColor;
void main(void){ void main(void){
gl_FragCOlor = vColor;
gl_FragColor = vColor;
} }
` `
}, },

10
src/render/webgl/index.ts

@ -0,0 +1,10 @@
export * from './WebGLProgram';
export * from './WebGLApplication';
export * from './WebGLAttribState';
export * from './WebGLHepler';
export * from './WebGLMatrixStack';
export * from './WebGLMesh';
export * from './WebGLProgramCache';
export * from './WebGLShaderSource';
export * from './WebGLTexture';
export * from './WebGLTextureCache';
Loading…
Cancel
Save