forked from LeenkxTeam/LNXSDK
207 lines
5.5 KiB
Haxe
207 lines
5.5 KiB
Haxe
|
package kha.graphics4;
|
||
|
|
||
|
import kha.arrays.Float32Array;
|
||
|
import js.html.webgl.GL;
|
||
|
import kha.arrays.ByteArray;
|
||
|
import kha.graphics4.Usage;
|
||
|
import kha.graphics4.VertexStructure;
|
||
|
|
||
|
class VertexBuffer {
|
||
|
public var _data: ByteArray;
|
||
|
|
||
|
var buffer: Dynamic;
|
||
|
var mySize: Int;
|
||
|
var myStride: Int;
|
||
|
var sizes: Array<Int>;
|
||
|
var offsets: Array<Int>;
|
||
|
var types: Array<Int>;
|
||
|
var instanceDataStepRate: Int;
|
||
|
var lockStart: Int = 0;
|
||
|
var lockEnd: Int = 0;
|
||
|
|
||
|
public function new(vertexCount: Int, structure: VertexStructure, usage: Usage, instanceDataStepRate: Int = 0, canRead: Bool = false) {
|
||
|
this.instanceDataStepRate = instanceDataStepRate;
|
||
|
mySize = vertexCount;
|
||
|
myStride = 0;
|
||
|
for (element in structure.elements) {
|
||
|
myStride += VertexStructure.dataByteSize(element.data);
|
||
|
}
|
||
|
|
||
|
buffer = SystemImpl.gl.createBuffer();
|
||
|
_data = ByteArray.make(vertexCount * myStride);
|
||
|
|
||
|
sizes = new Array<Int>();
|
||
|
offsets = new Array<Int>();
|
||
|
types = new Array<Int>();
|
||
|
sizes[structure.elements.length - 1] = 0;
|
||
|
offsets[structure.elements.length - 1] = 0;
|
||
|
types[structure.elements.length - 1] = 0;
|
||
|
|
||
|
var offset = 0;
|
||
|
var index = 0;
|
||
|
for (element in structure.elements) {
|
||
|
var size;
|
||
|
var type;
|
||
|
switch (element.data) {
|
||
|
case Float32_1X:
|
||
|
size = 1;
|
||
|
type = GL.FLOAT;
|
||
|
case Float32_2X:
|
||
|
size = 2;
|
||
|
type = GL.FLOAT;
|
||
|
case Float32_3X:
|
||
|
size = 3;
|
||
|
type = GL.FLOAT;
|
||
|
case Float32_4X:
|
||
|
size = 4;
|
||
|
type = GL.FLOAT;
|
||
|
case Float32_4X4:
|
||
|
size = 4 * 4;
|
||
|
type = GL.FLOAT;
|
||
|
case Int8_1X, Int8_1X_Normalized:
|
||
|
size = 1;
|
||
|
type = GL.BYTE;
|
||
|
case Int8_2X, Int8_2X_Normalized:
|
||
|
size = 2;
|
||
|
type = GL.BYTE;
|
||
|
case Int8_4X, Int8_4X_Normalized:
|
||
|
size = 4;
|
||
|
type = GL.BYTE;
|
||
|
case UInt8_1X, UInt8_1X_Normalized:
|
||
|
size = 1;
|
||
|
type = GL.UNSIGNED_BYTE;
|
||
|
case UInt8_2X, UInt8_2X_Normalized:
|
||
|
size = 2;
|
||
|
type = GL.UNSIGNED_BYTE;
|
||
|
case UInt8_4X, UInt8_4X_Normalized:
|
||
|
size = 4;
|
||
|
type = GL.UNSIGNED_BYTE;
|
||
|
case Int16_1X, Int16_1X_Normalized:
|
||
|
size = 1;
|
||
|
type = GL.SHORT;
|
||
|
case Int16_2X, Int16_2X_Normalized:
|
||
|
size = 2;
|
||
|
type = GL.SHORT;
|
||
|
case Int16_4X, Int16_4X_Normalized:
|
||
|
size = 4;
|
||
|
type = GL.SHORT;
|
||
|
case UInt16_1X, UInt16_1X_Normalized:
|
||
|
size = 1;
|
||
|
type = GL.UNSIGNED_SHORT;
|
||
|
case UInt16_2X, UInt16_2X_Normalized:
|
||
|
size = 2;
|
||
|
type = GL.UNSIGNED_SHORT;
|
||
|
case UInt16_4X, UInt16_4X_Normalized:
|
||
|
size = 4;
|
||
|
type = GL.UNSIGNED_SHORT;
|
||
|
case Int32_1X:
|
||
|
size = 1;
|
||
|
type = GL.INT;
|
||
|
case Int32_2X:
|
||
|
size = 2;
|
||
|
type = GL.INT;
|
||
|
case Int32_3X:
|
||
|
size = 3;
|
||
|
type = GL.INT;
|
||
|
case Int32_4X:
|
||
|
size = 4;
|
||
|
type = GL.INT;
|
||
|
case UInt32_1X:
|
||
|
size = 1;
|
||
|
type = GL.UNSIGNED_INT;
|
||
|
case UInt32_2X:
|
||
|
size = 2;
|
||
|
type = GL.UNSIGNED_INT;
|
||
|
case UInt32_3X:
|
||
|
size = 3;
|
||
|
type = GL.UNSIGNED_INT;
|
||
|
case UInt32_4X:
|
||
|
size = 4;
|
||
|
type = GL.UNSIGNED_INT;
|
||
|
}
|
||
|
sizes[index] = size;
|
||
|
offsets[index] = offset;
|
||
|
types[index] = type;
|
||
|
offset += VertexStructure.dataByteSize(element.data);
|
||
|
++index;
|
||
|
}
|
||
|
|
||
|
SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer);
|
||
|
SystemImpl.gl.bufferData(GL.ARRAY_BUFFER, _data.subarray(0 * stride(), mySize * stride()),
|
||
|
usage == Usage.DynamicUsage ? GL.DYNAMIC_DRAW : GL.STATIC_DRAW);
|
||
|
}
|
||
|
|
||
|
public function delete(): Void {
|
||
|
_data = null;
|
||
|
SystemImpl.gl.deleteBuffer(buffer);
|
||
|
}
|
||
|
|
||
|
public function lock(?start: Int, ?count: Int): Float32Array {
|
||
|
lockStart = start != null ? start : 0;
|
||
|
lockEnd = count != null ? start + count : mySize;
|
||
|
return _data.subarray(lockStart * stride(), lockEnd * stride());
|
||
|
}
|
||
|
|
||
|
public function unlock(?count: Int): Void {
|
||
|
if (count != null)
|
||
|
lockEnd = lockStart + count;
|
||
|
SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer);
|
||
|
if (SystemImpl.safari) {
|
||
|
SystemImpl.gl.bufferData(GL.ARRAY_BUFFER, _data.subarray(0 * stride(), lockEnd * stride()), GL.DYNAMIC_DRAW);
|
||
|
}
|
||
|
else {
|
||
|
SystemImpl.gl.bufferSubData(GL.ARRAY_BUFFER, lockStart * stride(), _data.subarray(lockStart * stride(), lockEnd * stride()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function stride(): Int {
|
||
|
return myStride;
|
||
|
}
|
||
|
|
||
|
public function count(): Int {
|
||
|
return mySize;
|
||
|
}
|
||
|
|
||
|
public function set(offset: Int): Int {
|
||
|
var ext: Dynamic = SystemImpl.gl2 ? true : SystemImpl.gl.getExtension("ANGLE_instanced_arrays");
|
||
|
SystemImpl.gl.bindBuffer(GL.ARRAY_BUFFER, buffer);
|
||
|
var attributesOffset = 0;
|
||
|
for (i in 0...sizes.length) {
|
||
|
if (sizes[i] > 4) {
|
||
|
var size = sizes[i];
|
||
|
var addonOffset = 0;
|
||
|
while (size > 0) {
|
||
|
SystemImpl.gl.enableVertexAttribArray(offset + attributesOffset);
|
||
|
SystemImpl.gl.vertexAttribPointer(offset + attributesOffset, 4, GL.FLOAT, false, myStride, offsets[i] + addonOffset);
|
||
|
if (ext) {
|
||
|
if (SystemImpl.gl2) {
|
||
|
untyped SystemImpl.gl.vertexAttribDivisor(offset + attributesOffset, instanceDataStepRate);
|
||
|
}
|
||
|
else {
|
||
|
ext.vertexAttribDivisorANGLE(offset + attributesOffset, instanceDataStepRate);
|
||
|
}
|
||
|
}
|
||
|
size -= 4;
|
||
|
addonOffset += 4 * 4;
|
||
|
++attributesOffset;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
var normalized = types[i] == GL.FLOAT ? false : true;
|
||
|
SystemImpl.gl.enableVertexAttribArray(offset + attributesOffset);
|
||
|
SystemImpl.gl.vertexAttribPointer(offset + attributesOffset, sizes[i], types[i], normalized, myStride, offsets[i]);
|
||
|
if (ext) {
|
||
|
if (SystemImpl.gl2) {
|
||
|
untyped SystemImpl.gl.vertexAttribDivisor(offset + attributesOffset, instanceDataStepRate);
|
||
|
}
|
||
|
else {
|
||
|
ext.vertexAttribDivisorANGLE(offset + attributesOffset, instanceDataStepRate);
|
||
|
}
|
||
|
}
|
||
|
++attributesOffset;
|
||
|
}
|
||
|
}
|
||
|
return attributesOffset;
|
||
|
}
|
||
|
}
|