|
@@ -123,6 +123,34 @@
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ export class InstancingAttributeInfo {
|
|
|
|
+ /**
|
|
|
|
+ * Index/offset of the attribute in the vertex shader
|
|
|
|
+ */
|
|
|
|
+ index: number;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * size of the attribute, 1, 2, 3 or 4
|
|
|
|
+ */
|
|
|
|
+ attributeSize: number;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * type of the attribute, gl.BYTE, gl.UNSIGNED_BYTE, gl.SHORT, gl.UNSIGNED_SHORT, gl.FIXED, gl.FLOAT.
|
|
|
|
+ * default is FLOAT
|
|
|
|
+ */
|
|
|
|
+ attribyteType: number;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * normalization of fixed-point data. behavior unclear, use FALSE, default is FALSE
|
|
|
|
+ */
|
|
|
|
+ normalized: boolean;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Offset of the data in the Vertex Buffer acting as the instancing buffer
|
|
|
|
+ */
|
|
|
|
+ offset: number;
|
|
|
|
+ }
|
|
|
|
+
|
|
export class EngineCapabilities {
|
|
export class EngineCapabilities {
|
|
public maxTexturesImageUnits: number;
|
|
public maxTexturesImageUnits: number;
|
|
public maxTextureSize: number;
|
|
public maxTextureSize: number;
|
|
@@ -960,25 +988,48 @@
|
|
this._gl.deleteBuffer(buffer);
|
|
this._gl.deleteBuffer(buffer);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public updateAndBindInstancesBuffer(instancesBuffer: WebGLBuffer, data: Float32Array, offsetLocations: number[]): void {
|
|
|
|
|
|
+ public updateAndBindInstancesBuffer(instancesBuffer: WebGLBuffer, data: Float32Array, offsetLocations: number[] | InstancingAttributeInfo[]): void {
|
|
this._gl.bindBuffer(this._gl.ARRAY_BUFFER, instancesBuffer);
|
|
this._gl.bindBuffer(this._gl.ARRAY_BUFFER, instancesBuffer);
|
|
- this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, data);
|
|
|
|
|
|
+ if (data) {
|
|
|
|
+ this._gl.bufferSubData(this._gl.ARRAY_BUFFER, 0, data);
|
|
|
|
+ }
|
|
|
|
|
|
- for (var index = 0; index < 4; index++) {
|
|
|
|
- var offsetLocation = offsetLocations[index];
|
|
|
|
- this._gl.enableVertexAttribArray(offsetLocation);
|
|
|
|
- this._gl.vertexAttribPointer(offsetLocation, 4, this._gl.FLOAT, false, 64, index * 16);
|
|
|
|
- this._caps.instancedArrays.vertexAttribDivisorANGLE(offsetLocation, 1);
|
|
|
|
|
|
+ if (offsetLocations[0] instanceof InstancingAttributeInfo) {
|
|
|
|
+ let stride = 0;
|
|
|
|
+ for (let i = 0; i < offsetLocations.length; i++) {
|
|
|
|
+ let ai = <InstancingAttributeInfo>offsetLocations[i];
|
|
|
|
+ stride += ai.attributeSize * 4;
|
|
|
|
+ }
|
|
|
|
+ for (let i = 0; i < offsetLocations.length; i++) {
|
|
|
|
+ let ai = <InstancingAttributeInfo>offsetLocations[i];
|
|
|
|
+ this._gl.enableVertexAttribArray(ai.index);
|
|
|
|
+ this._gl.vertexAttribPointer(ai.index, ai.attributeSize, ai.attribyteType || this._gl.FLOAT, ai.normalized || false, stride, ai.offset);
|
|
|
|
+ this._caps.instancedArrays.vertexAttribDivisorANGLE(ai.index, 1);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ for (let index = 0; index < 4; index++) {
|
|
|
|
+ let offsetLocation = <number>offsetLocations[index];
|
|
|
|
+ this._gl.enableVertexAttribArray(offsetLocation);
|
|
|
|
+ this._gl.vertexAttribPointer(offsetLocation, 4, this._gl.FLOAT, false, 64, index * 16);
|
|
|
|
+ this._caps.instancedArrays.vertexAttribDivisorANGLE(offsetLocation, 1);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public unBindInstancesBuffer(instancesBuffer: WebGLBuffer, offsetLocations: number[]): void {
|
|
|
|
|
|
+ public unBindInstancesBuffer(instancesBuffer: WebGLBuffer, offsetLocations: number[] | InstancingAttributeInfo[]): void {
|
|
this._gl.bindBuffer(this._gl.ARRAY_BUFFER, instancesBuffer);
|
|
this._gl.bindBuffer(this._gl.ARRAY_BUFFER, instancesBuffer);
|
|
- for (var index = 0; index < 4; index++) {
|
|
|
|
- var offsetLocation = offsetLocations[index];
|
|
|
|
- this._gl.disableVertexAttribArray(offsetLocation);
|
|
|
|
- this._caps.instancedArrays.vertexAttribDivisorANGLE(offsetLocation, 0);
|
|
|
|
|
|
+ if (offsetLocations[0] instanceof InstancingAttributeInfo) {
|
|
|
|
+ for (let i = 0; i < offsetLocations.length; i++) {
|
|
|
|
+ let ai = <InstancingAttributeInfo>offsetLocations[i];
|
|
|
|
+ this._gl.disableVertexAttribArray(ai.index);
|
|
|
|
+ this._caps.instancedArrays.vertexAttribDivisorANGLE(ai.index, 0);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ for (let index = 0; index < 4; index++) {
|
|
|
|
+ let offsetLocation = <number>offsetLocations[index];
|
|
|
|
+ this._gl.disableVertexAttribArray(offsetLocation);
|
|
|
|
+ this._caps.instancedArrays.vertexAttribDivisorANGLE(offsetLocation, 0);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1618,9 +1669,12 @@
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean): void {
|
|
|
|
|
|
+ public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean, premulAlpha: boolean = false): void {
|
|
this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
|
|
this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
|
|
this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
|
|
this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
|
|
|
|
+ if (premulAlpha) {
|
|
|
|
+ this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
|
|
|
+ }
|
|
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, canvas);
|
|
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, this._gl.RGBA, this._gl.RGBA, this._gl.UNSIGNED_BYTE, canvas);
|
|
if (texture.generateMipMaps) {
|
|
if (texture.generateMipMaps) {
|
|
this._gl.generateMipmap(this._gl.TEXTURE_2D);
|
|
this._gl.generateMipmap(this._gl.TEXTURE_2D);
|