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; | ||
|  | 	} | ||
|  | } |