blobt
3 years ago
27 changed files with 956 additions and 21638 deletions
-
BINdata/pic0.png
-
BINdata/pic1.jpg
-
1data/test.txt
-
BINdata/textureUV.jpg
-
20102package-lock.json
-
1public/index.html
-
BINpublic/pic0.png
-
BINpublic/pic1.jpg
-
13src/App.tsx
-
299src/examples/Demo1.ts
-
7src/render/common.ts
-
347src/render/common/DrawHelper.ts
-
78src/render/common/HttpRequest.ts
-
9src/render/common/ImageInfo.ts
-
6src/render/core/Application.ts
-
53src/render/core/CameraApplication.ts
-
2src/render/core/Event.ts
-
2src/render/core/Primitives.ts
-
4src/render/ds/TypedArrayList.ts
-
2src/render/math/Mat4.ts
-
1545src/render/math/TSM.ts
-
5src/render/math/Util.ts
-
91src/render/webgl/WebGLApplication.ts
-
2src/render/webgl/WebGLMatrixStack.ts
-
3src/render/webgl/WebGLMesh.ts
-
6src/render/webgl/WebGLShaderSource.ts
-
10src/render/webgl/index.ts
After Width: 886 | Height: 584 | Size: 100 KiB |
After Width: 256 | Height: 192 | Size: 25 KiB |
@ -0,0 +1 @@ |
|||
test.txt测试文件 |
After Width: 1024 | Height: 1024 | Size: 636 KiB |
20102
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
After Width: 886 | Height: 584 | Size: 100 KiB |
After Width: 256 | Height: 192 | Size: 25 KiB |
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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点(下图中的顶点2,左下后)和maxs(下图中的顶点5,右上前)点的坐标,使用参数指定的颜色绘制线框绑定盒,它是一个立方体 |
|||
* /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); |
|||
} |
|||
} |
@ -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(); |
|||
}); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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的update,这样才能实时计算camera的投影和视图矩阵,这样才能保证计算机的正常运行 |
|||
* 如果要做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轴旋转
|
|||
} |
|||
|
|||
} |
|||
} |
1545
src/render/math/TSM.ts
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,10 +1,99 @@ |
|||
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 { |
|||
/** |
|||
* @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; |
|||
} |
|||
} |
|||
} |
@ -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'; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue