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