|
@ -39,9 +39,340 @@ export class GLAttribState { |
|
|
public static readonly FLOAT32_SIZE = Float32Array.BYTES_PER_ELEMENT; |
|
|
public static readonly FLOAT32_SIZE = Float32Array.BYTES_PER_ELEMENT; |
|
|
public static readonly UINT16_SIZE = Uint16Array.BYTES_PER_ELEMENT; |
|
|
public static readonly UINT16_SIZE = Uint16Array.BYTES_PER_ELEMENT; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 使用一个number类型的位数去存储attrib的使用情况 |
|
|
|
|
|
* @param useTexcoord0 |
|
|
|
|
|
* @param useTexcoord1 |
|
|
|
|
|
* @param useNormal |
|
|
|
|
|
* @param useTangent |
|
|
|
|
|
* @param useColor |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
public static makeVertexAttribs(useTexcoord0: boolean, useTexcoord1: boolean, useNormal: boolean, useTangent: boolean, useColor: boolean): GLAttribBits { |
|
|
public static makeVertexAttribs(useTexcoord0: boolean, useTexcoord1: boolean, useNormal: boolean, useTangent: boolean, useColor: boolean): GLAttribBits { |
|
|
let bits: GLAttribBits = GLAttribState.POSITION_BIT; // 总是要使用位置属性
|
|
|
let bits: GLAttribBits = GLAttribState.POSITION_BIT; // 总是要使用位置属性
|
|
|
|
|
|
|
|
|
|
|
|
if (useTexcoord0 === true) { |
|
|
|
|
|
bits |= GLAttribState.TEXCOORD_BIT; |
|
|
|
|
|
} |
|
|
|
|
|
if (useTexcoord1 === true) { |
|
|
|
|
|
bits |= GLAttribState.TEXCOORD1_BIT; |
|
|
|
|
|
} |
|
|
|
|
|
if (useNormal === true) { |
|
|
|
|
|
bits |= GLAttribState.NORMAL_BIT; |
|
|
|
|
|
} |
|
|
|
|
|
if (useTangent === true) { |
|
|
|
|
|
bits |= GLAttribState.TANGENT_BIT; |
|
|
|
|
|
} |
|
|
|
|
|
if (useColor === true) { |
|
|
|
|
|
bits |= GLAttribState.COLOR_BIT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return bits; |
|
|
return bits; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了position |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasPosition(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.POSITION_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了normal |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasNormal(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.NORMAL_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了texcoord0 |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasTexCoord_0(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.TEXCOORD_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了texcoord1 |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasTexCoord_1(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.TEXCOORD1_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了color |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasColor(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.COLOR_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 判断是否使用了tangent |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @returns |
|
|
|
|
|
*/ |
|
|
|
|
|
public static hasTangent(attribBits: GLAttribBits): boolean { |
|
|
|
|
|
return (attribBits & GLAttribState.TANGENT_BIT) !== 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 设置Vertex Array Pointer |
|
|
|
|
|
* @param gl |
|
|
|
|
|
* @param offsetMap |
|
|
|
|
|
*/ |
|
|
|
|
|
public static setAttribVertexArrayPointer(gl: WebGLRenderingContext, offsetMap: GLAttribOffsetMap): void { |
|
|
|
|
|
let stride: number = offsetMap[GLAttribState.ATTRIBSTRIDE]; |
|
|
|
|
|
|
|
|
|
|
|
if (stride === 0) { |
|
|
|
|
|
throw new Error("vertex Array ERROR!"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (stride !== offsetMap[GLAttribState.ATTRIBBYTELENGTH]) { |
|
|
|
|
|
stride = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (stride === undefined) { |
|
|
|
|
|
stride = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let offset: number = offsetMap[GLAttribState.POSITION_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.POSITION_LOCATION, GLAttribState.POSITION_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offset = offsetMap[GLAttribState.NORMAL_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.NORMAL_LOCATION, GLAttribState.NORMAL_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offset = offsetMap[GLAttribState.TEXCOORD_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.TEXCOORD_LOCATION, GLAttribState.TEXCOORD_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offset = offsetMap[GLAttribState.TEXCOORD1_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.TEXCOORD1_LOCATION, GLAttribState.TEXCOORD1_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offset = offsetMap[GLAttribState.COLOR_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.COLOR_LOCATION, GLAttribState.COLOR_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offset = offsetMap[GLAttribState.TANGENT_NAME]; |
|
|
|
|
|
if (offset !== undefined) { |
|
|
|
|
|
gl.vertexAttribPointer(GLAttribState.TANGENT_LOCATION, GLAttribState.TANGENT_COMPONENT, gl.FLOAT, false, stride, offset); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 设置各个vertex array 是否开启 |
|
|
|
|
|
* @param gl |
|
|
|
|
|
* @param attribBits |
|
|
|
|
|
* @param enable |
|
|
|
|
|
*/ |
|
|
|
|
|
public static setAttribVertexArrayState(gl: WebGLRenderingContext, attribBits: number, enable: boolean = true): void { |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasPosition(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.POSITION_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.POSITION_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasNormal(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.NORMAL_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.NORMAL_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_0(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.TEXCOORD_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.TEXCOORD_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_1(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.TEXCOORD1_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.TEXCOORD1_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasColor(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.COLOR_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.COLOR_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits) && enable === true) { |
|
|
|
|
|
gl.enableVertexAttribArray(GLAttribState.TANGENT_LOCATION); |
|
|
|
|
|
} else { |
|
|
|
|
|
gl.disableVertexAttribArray(GLAttribState.TANGENT_LOCATION); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static getVertexBytesStride(attribBits: GLAttribBits): number { |
|
|
|
|
|
let byteOffset: number = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasPosition(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.POSITION_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasNormal(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.NORMAL_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_0(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.TEXCOORD_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_1(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.TEXCOORD1_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasColor(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.COLOR_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits)) { |
|
|
|
|
|
byteOffset += GLAttribState.TANGENT_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return byteOffset; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static getSequenceLayoutAttribOffsetMap(attribBits: GLAttribBits, vertexCount: number): GLAttribOffsetMap { |
|
|
|
|
|
let offsets: GLAttribOffsetMap = {}; |
|
|
|
|
|
let byteOffset: number = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasPosition(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.POSITION_NAME] = 0; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.POSITION_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasNormal(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.NORMAL_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.NORMAL_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_0(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.TEXCOORD_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_1(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD1_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.TEXCOORD1_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasColor(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.COLOR_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.COLOR_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TANGENT_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += vertexCount * GLAttribState.TANGENT_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offsets[GLAttribState.ATTRIBSTRIDE] = byteOffset / vertexCount;// 总的字节数 / 顶点数量 = 每个顶点的stride,实际上顺序存储时不需要这个值
|
|
|
|
|
|
offsets[GLAttribState.ATTRIBBYTELENGTH] = byteOffset;// 总的字节数
|
|
|
|
|
|
|
|
|
|
|
|
return offsets; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static getInterleaveLayoutAttribOffsetMap(attribBits: GLAttribBits): GLAttribOffsetMap { |
|
|
|
|
|
|
|
|
|
|
|
let offsets: GLAttribOffsetMap = {}; |
|
|
|
|
|
let byteOffset: number = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasPosition(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.POSITION_NAME] = 0; |
|
|
|
|
|
byteOffset += GLAttribState.POSITION_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasNormal(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.NORMAL_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += GLAttribState.NORMAL_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_0(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += GLAttribState.TEXCOORD_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_1(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD1_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += GLAttribState.TEXCOORD1_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasColor(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.COLOR_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += GLAttribState.COLOR_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TANGENT_NAME] = byteOffset; |
|
|
|
|
|
byteOffset += GLAttribState.TANGENT_COMPONENT * GLAttribState.FLOAT32_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
offsets[GLAttribState.ATTRIBSTRIDE] = byteOffset; |
|
|
|
|
|
offsets[GLAttribState.ATTRIBBYTELENGTH] = byteOffset; |
|
|
|
|
|
|
|
|
|
|
|
return offsets; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static getSepratedLayoutAttribOffsetMap(attribBits: GLAttribBits): GLAttribOffsetMap { |
|
|
|
|
|
let offsets: GLAttribOffsetMap = {}; |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasPosition(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.POSITION_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasNormal(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.NORMAL_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_0(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTexCoord_1(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TEXCOORD1_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasColor(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.COLOR_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits)) { |
|
|
|
|
|
offsets[GLAttribState.TANGENT_NAME] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return offsets; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static isAttribStateValid(attribBits: number): boolean { |
|
|
|
|
|
if (!GLAttribState.hasPosition(attribBits)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
if (GLAttribState.hasTangent(attribBits)) { |
|
|
|
|
|
if (!GLAttribState.hasTexCoord_0(attribBits)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
if (!GLAttribState.hasNormal(attribBits)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |