blobt
4 years ago
1 changed files with 722 additions and 0 deletions
@ -1,3 +1,725 @@ |
|||
import { GLAttribBits, GLAttribState, GLAttribOffsetMap } from "./WebGLAttribState"; |
|||
import { vec2, vec3, vec4, mat4 } from "../math"; |
|||
import { TypedArrayList } from "../ds/TypedArrayList"; |
|||
import { GLProgram } from "./WebGLProgram"; |
|||
import { GLTexture } from "./WebGLTexture" |
|||
|
|||
export abstract class GLMeshBase { |
|||
|
|||
/** |
|||
* @var WebGL渲染上下文 |
|||
*/ |
|||
public gl: WebGLRenderingContext; |
|||
|
|||
/** |
|||
* @var 7中基本图元 |
|||
*/ |
|||
public drawMode: number |
|||
|
|||
/** |
|||
* @var 顶点属性格式 |
|||
*/ |
|||
protected _attribState: GLAttribBits; |
|||
|
|||
/** |
|||
* @var 顶点属性的stride字节数 |
|||
*/ |
|||
protected _attribStride: number; |
|||
|
|||
/** |
|||
* @var VAO |
|||
*/ |
|||
protected _vao: OES_vertex_array_object; |
|||
|
|||
/** |
|||
* @var VAO对象 |
|||
*/ |
|||
protected _vaoTarget: WebGLVertexArrayObjectOES; |
|||
|
|||
public constructor(gl: WebGLRenderingContext, attribState: GLAttribBits, drawMode: number = gl.TRIANGLES) { |
|||
|
|||
this.gl = gl; |
|||
|
|||
//创建 VAO
|
|||
let vao: OES_vertex_array_object | null = this.gl.getExtension("OES_vertex_array_object"); |
|||
if (vao === null) { |
|||
throw new Error("Not support OES_vertex_array_object"); |
|||
} |
|||
this._vao = vao; |
|||
|
|||
let vaoTarget: WebGLVertexArrayObjectOES | null = this._vao.createVertexArrayOES(); |
|||
if (vaoTarget === null) { |
|||
throw new Error("Not support WebGLVertexArrayObjectOES"); |
|||
} |
|||
this._vaoTarget = vaoTarget; |
|||
|
|||
this._attribState = attribState; |
|||
this._attribStride = GLAttribState.getVertexBytesStride(this._attribState); |
|||
this.drawMode = drawMode; |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 绑定vao |
|||
*/ |
|||
public bind(): void { |
|||
this._vao.bindVertexArrayOES(this._vaoTarget); |
|||
} |
|||
|
|||
/** |
|||
* 解绑vao |
|||
*/ |
|||
public unbind(): void { |
|||
this._vao.bindVertexArrayOES(null); |
|||
} |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
public get vertexStride(): number { |
|||
return this._attribStride; |
|||
} |
|||
} |
|||
|
|||
export class GLStaticMesh extends GLMeshBase { |
|||
|
|||
/** |
|||
* @var 顶点缓冲区 |
|||
*/ |
|||
protected _vbo: WebGLBuffer; |
|||
|
|||
/** |
|||
* @var 顶点数量 |
|||
*/ |
|||
protected _vertCount: number = 0; |
|||
|
|||
/** |
|||
* @var 索引缓冲区 |
|||
*/ |
|||
protected _ibo: WebGLBuffer | null = null; |
|||
|
|||
/** |
|||
* @var 索引数量 |
|||
*/ |
|||
protected _indexCount: number = 0; |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
public mins: vec3; |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
public maxs: vec3; |
|||
|
|||
public constructor(gl: WebGLRenderingContext, attribState: GLAttribBits, vbo: Float32Array | ArrayBuffer, ibo: Uint16Array | null = null, drawMode: number = gl.TRIANGLES) { |
|||
|
|||
super(gl, attribState, drawMode); |
|||
|
|||
//要先绑定vao才能使用vao来管理vbo
|
|||
this.bind(); |
|||
|
|||
//创建vbo
|
|||
let vb: WebGLBuffer | null = gl.createBuffer(); |
|||
if (vb === null) { |
|||
throw new Error("create vbo failed"); |
|||
} |
|||
this._vbo = vbo; |
|||
|
|||
//绑定vbo并载入顶点数据
|
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._vbo); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, vbo, this.gl.STATIC_DRAW); |
|||
|
|||
// 然后计算出交错存储的顶点属性attribOffsetMap相关的值
|
|||
let offsetMap: GLAttribOffsetMap = GLAttribState.getInterleaveLayoutAttribOffsetMap(this._attribState); |
|||
|
|||
//计算顶点数量
|
|||
this._vertCount = vbo.byteLength / offsetMap[GLAttribState.ATTRIBSTRIDE]; |
|||
|
|||
// 使用VAO后,我们只要初始化时设置一次setAttribVertexArrayPointer和setAttribVertexArrayState就行了
|
|||
// 当我们后续调用基类的bind方法绑定VAO对象后,VAO会自动处理顶点地址绑定和顶点属性寄存器开启相关操作,这就简化了很多操作
|
|||
GLAttribState.setAttribVertexArrayPointer(gl, offsetMap); |
|||
GLAttribState.setAttribVertexArrayState(gl, this._attribState); |
|||
|
|||
this.setIBO(ibo); |
|||
|
|||
this.unbind(); |
|||
|
|||
this.mins = new vec3(); |
|||
this.maxs = new vec3(); |
|||
} |
|||
|
|||
/** |
|||
* 配置ibo |
|||
* @param ibo |
|||
* @returns |
|||
*/ |
|||
protected setIBO(ibo: Uint16Array | null): void { |
|||
if (ibo === null) { |
|||
return; |
|||
} |
|||
|
|||
this._ibo = this.gl.createBuffer(); |
|||
if (this._ibo === null) { |
|||
throw new Error("create ibo failed!"); |
|||
} |
|||
|
|||
//绑定ibo 并赋值
|
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, ibo, this.gl.STATIC_DRAW); |
|||
|
|||
this._indexCount = ibo.length; |
|||
} |
|||
|
|||
/** |
|||
* 绘制图形 |
|||
*/ |
|||
public draw(): void { |
|||
this.bind(); |
|||
if (this._ibo !== null) { |
|||
// 如果有IBO,使用drawElements方法绘制静态网格对象
|
|||
this.gl.drawElements(this.drawMode, this._indexCount, this.gl.UNSIGNED_SHORT, 0); |
|||
} else { |
|||
// 如果没有IBO,则使用drawArrays方法绘制静态网格对象
|
|||
this.gl.drawArrays(this.drawMode, 0, this._vertCount); |
|||
} |
|||
this.unbind(); |
|||
} |
|||
|
|||
/** |
|||
* 注1:drawElement的offset是以字节为单位的,count是以索引个数为单位的 |
|||
* 注2:drawRange内部并没有调用bind和unbind方法,因此要调用drawRange方法的话,必须如下方式: |
|||
* mesh.bind(); // 绑定VAO
|
|||
* mesh.drawRange( 2, 5); // 调用drawRange方法
|
|||
* mesh.unbind(); // 解绑VAO
|
|||
* |
|||
* drawRange绘制从offset开始,绘制count个索引 |
|||
* @param offset |
|||
* @param count |
|||
*/ |
|||
public drawRange(offset: number, count: number) { |
|||
if (this._ibo !== null) { |
|||
this.gl.drawElements(this.drawMode, count, this.gl.UNSIGNED_SHORT, offset); |
|||
} else { |
|||
this.gl.drawArrays(this.drawMode, offset, count); |
|||
} |
|||
} |
|||
} |
|||
|
|||
export class GLIndexedStaticMesh extends GLStaticMesh { |
|||
|
|||
private _indices: TypedArrayList<Uint16Array>; |
|||
|
|||
public constructor(gl: WebGLRenderingContext, attribState: GLAttribBits, vbo: Float32Array | ArrayBuffer, drawMode: number = gl.TRIANGLES) { |
|||
super(gl, attribState, vbo, null, drawMode); |
|||
this._indices = new TypedArrayList<Uint16Array>(Uint16Array, 90); |
|||
} |
|||
|
|||
/** |
|||
* 添加一个索引 |
|||
* @param idx |
|||
* @returns |
|||
*/ |
|||
public addIndex(idx: number): GLIndexedStaticMesh { |
|||
this._indices.push(idx); |
|||
this._indexCount = this._indices.length; |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 清除所有索引 |
|||
* @returns |
|||
*/ |
|||
public clearIndices(): GLIndexedStaticMesh { |
|||
this._indices.clear(); |
|||
this._indexCount = 0; |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 设置ibo |
|||
* @param ibo |
|||
*/ |
|||
protected setIBO(ibo: Uint16Array | null): void { |
|||
this._ibo = this.gl.createBuffer(); |
|||
if (this._ibo === null) { |
|||
throw new Error("create ibo falied!"); |
|||
} |
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
} |
|||
|
|||
/** |
|||
* 绘制 |
|||
*/ |
|||
public draw(): void { |
|||
this.bind(); |
|||
if (this._ibo !== null) { |
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this._indexCount, this.gl.UNSIGNED_SHORT); |
|||
this.gl.drawElements(this.drawMode, this._indexCount, this.gl.UNSIGNED_SHORT, 0); |
|||
} else { |
|||
this.gl.drawArrays(this.drawMode, 0, this._vertCount); |
|||
} |
|||
this.unbind(); |
|||
} |
|||
|
|||
/** |
|||
* |
|||
* @param offset 以字节为单位 |
|||
* @param count 以索引个数为单位 |
|||
*/ |
|||
public drawRange(offset: number, count: number) { |
|||
if (this._ibo !== null) { |
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, this._indices.subArray(), this._indexCount); |
|||
this.gl.drawElements(this.drawMode, count, this.gl.UNSIGNED_SHORT, offset); |
|||
} else { |
|||
this.gl.drawArrays(this.drawMode, offset, count); |
|||
} |
|||
} |
|||
} |
|||
|
|||
export enum EVertexLayout { |
|||
INTERLEAVED, |
|||
SEQUENCED, |
|||
SEPARATED |
|||
} |
|||
|
|||
export class GLMeshBuilder extends GLMeshBase { |
|||
|
|||
private static SEQUENCED: string = "SEQUENCED"; |
|||
private static INTERLEAVED: string = "INVERLEAVED"; |
|||
|
|||
/** |
|||
* @var 顶点在内存或显示中的布局方式 |
|||
*/ |
|||
private _layout: EVertexLayout; |
|||
|
|||
/* 为了简单,目前只支持顶点位置坐标,纹理坐标,颜色,法线这四种顶点属性格式 */ |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
private _color: vec4 = new vec4([0, 0, 0, 0]); |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
private _texCoord: vec2 = new vec2([0, 0]); |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
private _normal: vec3 = new vec3([0, 0, 1]); |
|||
|
|||
/** |
|||
* @var 是否有颜色 |
|||
*/ |
|||
private _hasColor: boolean; |
|||
|
|||
/** |
|||
* @var 是否有texcoord |
|||
*/ |
|||
private _hasTexcoord: boolean; |
|||
|
|||
|
|||
/** |
|||
* @var 是否有法线 |
|||
*/ |
|||
private _hasNormal: boolean; |
|||
|
|||
/** |
|||
* @var 渲染的数据原 |
|||
*/ |
|||
private _lists: { [key: string]: TypedArrayList<Float32Array> } = {} |
|||
|
|||
/** |
|||
* 渲染用的VBO |
|||
*/ |
|||
private _buffers: { [key: string]: WebGLBuffer } = {}; |
|||
|
|||
/** |
|||
* 顶点数量 |
|||
*/ |
|||
private _vertCount: number = 0; |
|||
|
|||
/** |
|||
* @var |
|||
*/ |
|||
public program: GLProgram; |
|||
|
|||
/** |
|||
* @var 纹理 |
|||
*/ |
|||
public texture: WebGLTexture | null; |
|||
|
|||
/** |
|||
* @var ibo |
|||
*/ |
|||
private _ibo: WebGLBuffer | null; |
|||
|
|||
/** |
|||
* @var 索引数量 |
|||
*/ |
|||
private _indexCount: number = -1; |
|||
|
|||
/** |
|||
* 设置贴图 |
|||
* @param tex |
|||
*/ |
|||
public setTexture(tex: GLTexture): void { |
|||
this.texture = tex; |
|||
} |
|||
|
|||
/** |
|||
* 设置ibo数据 |
|||
* @param data |
|||
*/ |
|||
public setIBO(data: Uint16Array): void { |
|||
this._ibo = this.gl.createBuffer(); |
|||
if (this._ibo === null) { |
|||
throw new Error("create ibo falied!"); |
|||
} |
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, data, this.gl.STATIC_DRAW); |
|||
this._indexCount = data.length; |
|||
} |
|||
|
|||
public constructor(gl: WebGLRenderingContext, state: GLAttribBits, program: GLProgram, texture: GLTexture | null = null, layout: EVertexLayout = EVertexLayout.INTERLEAVED) { |
|||
super(gl, state); |
|||
|
|||
this._hasColor = GLAttribState.hasColor(this._attribState); |
|||
this._hasTexcoord = GLAttribState.hasTexCoord_0(this._attribState); |
|||
this._hasNormal = GLAttribState.hasNormal(this._attribState); |
|||
|
|||
this._ibo = null; |
|||
|
|||
this._layout = layout; |
|||
|
|||
this.program = program; |
|||
this.texture = texture; |
|||
|
|||
//先绑定vao对象
|
|||
this.bind(); |
|||
|
|||
let buffer: WebGLBuffer | null = this.gl.createBuffer(); |
|||
if (buffer === null) { |
|||
throw new Error("create webgl buffer failed!"); |
|||
} |
|||
|
|||
if (this._layout === EVertexLayout.INTERLEAVED) { |
|||
//interleaved 使用一个arraylist 和一个 顶点缓存,调用的是GLAttribState.getInterleavedLayoutAttribOffsetMap方法
|
|||
this._lists[GLMeshBuilder.INTERLEAVED] = new TypedArrayList<Float32Array>(Float32Array); |
|||
|
|||
this._buffers[GLMeshBuilder.INTERLEAVED] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
|
|||
let map: GLAttribOffsetMap = GLAttribState.getInterleaveLayoutAttribOffsetMap(this._attribState); |
|||
GLAttribState.setAttribVertexArrayPointer(this.gl, map); |
|||
GLAttribState.setAttribVertexArrayState(this.gl, this._attribState); |
|||
} else if (this._layout === EVertexLayout.SEQUENCED) { |
|||
//sequenced 使用n个arraylist和一个顶点缓存
|
|||
this._lists[GLAttribState.POSITION_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
|
|||
if (this._hasColor) { |
|||
this._lists[GLAttribState.COLOR_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
} |
|||
if (this._hasTexcoord) { |
|||
this._lists[GLAttribState.TEXCOORD_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
} |
|||
if (this._hasNormal) { |
|||
this._lists[GLAttribState.NORMAL_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
} |
|||
|
|||
buffer = this.gl.createBuffer(); |
|||
if (buffer === null) { |
|||
throw new Error("create webgl buffer failed!"); |
|||
} |
|||
this._buffers[GLMeshBuilder.SEQUENCED] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
|
|||
//因为是动态的,seqnenced 没法预先设置指针,但是可以预先设置顶点状态
|
|||
GLAttribState.setAttribVertexArrayState(this.gl, this._attribState); |
|||
} else { |
|||
//seperated 使用n个arraylist和n个顶点缓存
|
|||
this._lists[GLAttribState.POSITION_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
this._buffers[GLAttribState.POSITION_NAME] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.vertexAttribPointer(GLAttribState.POSITION_LOCATION, 3, gl.FLOAT, false, 0, 0); |
|||
this.gl.enableVertexAttribArray(GLAttribState.POSITION_LOCATION); |
|||
|
|||
if (this._hasColor) { |
|||
this._lists[GLAttribState.COLOR_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
buffer = this.gl.createBuffer(); |
|||
if (buffer === null) { |
|||
throw new Error("create webgl buffer failed!"); |
|||
} |
|||
this._buffers[GLAttribState.COLOR_NAME] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.vertexAttribPointer(GLAttribState.COLOR_LOCATION, 4, gl.FLOAT, false, 0, 0); |
|||
this.gl.enableVertexAttribArray(GLAttribState.COLOR_LOCATION); |
|||
} |
|||
|
|||
if (this._hasTexcoord) { |
|||
this._lists[GLAttribState.TEXCOORD_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
buffer = this.gl.createBuffer(); |
|||
if (buffer === null) { |
|||
throw new Error("create webgl buffer failed!"); |
|||
} |
|||
this._buffers[GLAttribState.TEXCOORD_NAME] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.vertexAttribPointer(GLAttribState.TEXCOORD_BIT, 2, gl.FLOAT, false, 0, 0); |
|||
this.gl.enableVertexAttribArray(GLAttribState.TEXCOORD_BIT); |
|||
} |
|||
|
|||
if (this._hasNormal) { |
|||
this._lists[GLAttribState.NORMAL_NAME] = new TypedArrayList<Float32Array>(Float32Array); |
|||
buffer = this.gl.createBuffer(); |
|||
if (buffer === null) { |
|||
throw new Error("create webgl buffer failed!"); |
|||
} |
|||
this._buffers[GLAttribState.NORMAL_NAME] = buffer; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.vertexAttribPointer(GLAttribState.NORMAL_LOCATION, 3, gl.FLOAT, false, 0, 0); |
|||
this.gl.enableVertexAttribArray(GLAttribState.NORMAL_LOCATION); |
|||
} |
|||
} |
|||
|
|||
|
|||
this.unbind(); |
|||
} |
|||
|
|||
/** |
|||
* 设置颜色 |
|||
* @param r |
|||
* @param g |
|||
* @param b |
|||
* @param a |
|||
* @returns |
|||
*/ |
|||
public color(r: number, g: number, b: number, a: number = 1.0): GLMeshBuilder { |
|||
if (this._hasColor) { |
|||
this._color.r = r; |
|||
this._color.g = g; |
|||
this._color.b = b; |
|||
this._color.a = a; |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 设置texcoord |
|||
* @param u |
|||
* @param v |
|||
* @returns |
|||
* |
|||
*/ |
|||
public texcoord(u: number, v: number): GLMeshBuilder { |
|||
if (this._hasTexcoord) { |
|||
this._texCoord.x = u; |
|||
this._texCoord.y = v; |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 设置法向 |
|||
* @param x |
|||
* @param y |
|||
* @param z |
|||
* @returns |
|||
*/ |
|||
public normal(x: number, y: number, z: number): GLMeshBuilder { |
|||
if (this._hasNormal) { |
|||
this._normal.x = x; |
|||
this._normal.y = y; |
|||
this._normal.z = z; |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 设置vertex |
|||
* @param x |
|||
* @param y |
|||
* @param z |
|||
* @returns |
|||
*/ |
|||
public vertex(x: number, y: number, z: number): GLMeshBuilder { |
|||
if (this._layout === EVertexLayout.INTERLEAVED) { |
|||
let list: TypedArrayList<Float32Array> = this._lists[GLMeshBuilder.INTERLEAVED]; |
|||
list.push(x); |
|||
list.push(y); |
|||
list.push(z); |
|||
|
|||
if (this._hasTexcoord) { |
|||
list.push(this._texCoord.x); |
|||
list.push(this._texCoord.y) |
|||
} |
|||
|
|||
if (this._hasNormal) { |
|||
list.push(this._normal.x); |
|||
list.push(this._normal.y); |
|||
list.push(this._normal.z); |
|||
} |
|||
|
|||
if (this._hasColor) { |
|||
list.push(this._color.r); |
|||
list.push(this._color.g); |
|||
list.push(this._color.b); |
|||
list.push(this._color.a); |
|||
} |
|||
} else { //sequenced separated 都是多个ArrayList
|
|||
let list: TypedArrayList<Float32Array> = this._lists[GLAttribState.POSITION_NAME]; |
|||
list.push(x); |
|||
list.push(y); |
|||
list.push(z); |
|||
|
|||
if (this._hasTexcoord) { |
|||
list = this._lists[GLAttribState.TEXCOORD_NAME]; |
|||
list.push(this._texCoord.x); |
|||
list.push(this._texCoord.y); |
|||
} |
|||
|
|||
if (this._hasNormal) { |
|||
list = this._lists[GLAttribState.NORMAL_NAME]; |
|||
list.push(this._normal.x); |
|||
list.push(this._normal.y); |
|||
list.push(this._normal.z); |
|||
} |
|||
|
|||
if (this._hasColor) { |
|||
list = this._lists[GLAttribState.COLOR_NAME]; |
|||
list.push(this._color.r); |
|||
list.push(this._color.g); |
|||
list.push(this._color.b); |
|||
list.push(this._color.a); |
|||
} |
|||
} |
|||
|
|||
//更新顶点数量
|
|||
this._vertCount++; |
|||
return this; |
|||
} |
|||
|
|||
/** |
|||
* 每次调用上述几个添加顶点属性的方法之前,必须要先调用begin方法,返回this指针,链式操作 |
|||
* @param drawMode |
|||
*/ |
|||
public begin(drawMode: number = this.gl.TRIANGLES): GLMeshBuilder { |
|||
this.drawMode = drawMode; |
|||
this._vertCount = 0; //清空顶点
|
|||
|
|||
if (this._layout === EVertexLayout.INTERLEAVED) { |
|||
let list: TypedArrayList<Float32Array> = this._lists[GLMeshBuilder.INTERLEAVED]; |
|||
list.clear(); |
|||
} else { |
|||
let list: TypedArrayList<Float32Array> = this._lists[GLMeshBuilder.INTERLEAVED]; |
|||
list.clear(); |
|||
|
|||
if (this._hasTexcoord) { |
|||
list = this._lists[GLAttribState.TEXCOORD_NAME]; |
|||
list.clear(); |
|||
} |
|||
|
|||
if (this._hasNormal) { |
|||
list = this._lists[GLAttribState.NORMAL_NAME]; |
|||
list.clear(); |
|||
} |
|||
|
|||
if (this._hasColor) { |
|||
list = this._lists[GLAttribState.COLOR_NAME]; |
|||
list.clear(); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
public end(mvp: mat4): void { |
|||
this.program.bind(); |
|||
|
|||
//载入MVPMatrix uniform变量
|
|||
this.program.setMatrix4(GLProgram.MVPMatrix, mvp); |
|||
|
|||
//载入texture
|
|||
if (this.texture !== null) { |
|||
this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture); |
|||
this.program.loadSampler(); |
|||
} |
|||
|
|||
//绑定vao
|
|||
this.bind(); |
|||
|
|||
if (this._layout === EVertexLayout.INTERLEAVED) { |
|||
//获取数据源
|
|||
let list: TypedArrayList<Float32Array> = this._lists[GLMeshBuilder.INTERLEAVED]; |
|||
|
|||
//获取vbo
|
|||
let buffer: WebGLBuffer = this._buffers[GLMeshBuilder.INTERLEAVED]; |
|||
|
|||
//绑定vbo 上传渲染数据到vbo
|
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, list.subArray(), this.gl.DYNAMIC_DRAW); |
|||
} else if (this._layout === EVertexLayout.SEQUENCED) { |
|||
let buffer: WebGLBuffer = this._buffers[GLMeshBuilder.SEQUENCED]; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, this._attribStride * this._vertCount, this.gl.DYNAMIC_DRAW); |
|||
|
|||
let list: TypedArrayList<Float32Array> = this._lists[GLAttribState.POSITION_NAME]; |
|||
this.gl.bufferSubData(this.gl.ARRAY_BUFFER, 0, list.subArray()); |
|||
|
|||
let map: GLAttribOffsetMap = GLAttribState.getSequenceLayoutAttribOffsetMap(this._attribState, this._vertCount); |
|||
if (this._hasTexcoord) { |
|||
list = this._lists[GLAttribState.TEXCOORD_NAME]; |
|||
this.gl.bufferSubData(this.gl.ARRAY_BUFFER, map[GLAttribState.TEXCOORD_NAME], list.subArray()); |
|||
} |
|||
if (this._hasNormal) { |
|||
list = this._lists[GLAttribState.NORMAL_NAME]; |
|||
this.gl.bufferSubData(this.gl.ARRAY_BUFFER, map[GLAttribState.NORMAL_NAME], list.subArray()); |
|||
} |
|||
if (this._hasColor) { |
|||
list = this._lists[GLAttribState.COLOR_NAME]; |
|||
this.gl.bufferSubData(this.gl.ARRAY_BUFFER, map[GLAttribState.COLOR_NAME], list.subArray()); |
|||
} |
|||
//每次都要重新计算和绑定顶点属性的首地址
|
|||
GLAttribState.setAttribVertexArrayPointer(this.gl, map); |
|||
} else { |
|||
let buffer: WebGLBuffer = this._buffers[GLAttribState.POSITION_NAME]; |
|||
let list: TypedArrayList<Float32Array> = this._lists[GLAttribState.POSITION_NAME]; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, list.subArray(), this.gl.DYNAMIC_DRAW); |
|||
|
|||
if (this._hasTexcoord) { |
|||
buffer = this._buffers[GLAttribState.TEXCOORD_NAME]; |
|||
list = this._lists[GLAttribState.TEXCOORD_NAME]; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, list.subArray(), this.gl.DYNAMIC_DRAW); |
|||
} |
|||
|
|||
if (this._hasNormal) { |
|||
buffer = this._buffers[GLAttribState.NORMAL_NAME]; |
|||
list = this._lists[GLAttribState.NORMAL_NAME]; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, list.subArray(), this.gl.DYNAMIC_DRAW); |
|||
} |
|||
|
|||
if (this._hasColor) { |
|||
buffer = this._buffers[GLAttribState.COLOR_NAME]; |
|||
list = this._lists[GLAttribState.COLOR_NAME]; |
|||
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer); |
|||
this.gl.bufferData(this.gl.ARRAY_BUFFER, list.subArray(), this.gl.DYNAMIC_DRAW); |
|||
} |
|||
} |
|||
|
|||
if (this._ibo !== null) { |
|||
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this._ibo); |
|||
this.gl.drawElements(this.drawMode, this._indexCount, this.gl.UNSIGNED_SHORT, 0); |
|||
} else { |
|||
this.gl.drawArrays(this.drawMode, 0, this._vertCount); |
|||
} |
|||
|
|||
this.unbind(); |
|||
this.program.unbind(); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue