UNPKG

3.46 kBPlain TextView Raw
1import assert from 'assert';
2
3import type {
4 StructArray,
5 StructArrayMember
6} from '../util/struct_array';
7
8import type Program from '../render/program';
9import type Context from '../gl/context';
10
11/**
12 * @enum {string} AttributeType
13 * @private
14 * @readonly
15 */
16const AttributeType = {
17 Int8: 'BYTE',
18 Uint8: 'UNSIGNED_BYTE',
19 Int16: 'SHORT',
20 Uint16: 'UNSIGNED_SHORT',
21 Int32: 'INT',
22 Uint32: 'UNSIGNED_INT',
23 Float32: 'FLOAT'
24};
25
26/**
27 * The `VertexBuffer` class turns a `StructArray` into a WebGL buffer. Each member of the StructArray's
28 * Struct type is converted to a WebGL atribute.
29 * @private
30 */
31class VertexBuffer {
32 length: number;
33 attributes: ReadonlyArray<StructArrayMember>;
34 itemSize: number;
35 dynamicDraw: boolean;
36 context: Context;
37 buffer: WebGLBuffer;
38
39 /**
40 * @param dynamicDraw Whether this buffer will be repeatedly updated.
41 * @private
42 */
43 constructor(context: Context, array: StructArray, attributes: ReadonlyArray<StructArrayMember>, dynamicDraw?: boolean) {
44 this.length = array.length;
45 this.attributes = attributes;
46 this.itemSize = array.bytesPerElement;
47 this.dynamicDraw = dynamicDraw;
48
49 this.context = context;
50 const gl = context.gl;
51 this.buffer = gl.createBuffer();
52 context.bindVertexBuffer.set(this.buffer);
53 gl.bufferData(gl.ARRAY_BUFFER, array.arrayBuffer, this.dynamicDraw ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW);
54
55 if (!this.dynamicDraw) {
56 delete array.arrayBuffer;
57 }
58 }
59
60 bind() {
61 this.context.bindVertexBuffer.set(this.buffer);
62 }
63
64 updateData(array: StructArray) {
65 assert(array.length === this.length);
66 const gl = this.context.gl;
67 this.bind();
68 gl.bufferSubData(gl.ARRAY_BUFFER, 0, array.arrayBuffer);
69 }
70
71 enableAttributes(gl: WebGLRenderingContext, program: Program<any>) {
72 for (let j = 0; j < this.attributes.length; j++) {
73 const member = this.attributes[j];
74 const attribIndex: number | void = program.attributes[member.name];
75 if (attribIndex !== undefined) {
76 gl.enableVertexAttribArray(attribIndex);
77 }
78 }
79 }
80
81 /**
82 * Set the attribute pointers in a WebGL context
83 * @param gl The WebGL context
84 * @param program The active WebGL program
85 * @param vertexOffset Index of the starting vertex of the segment
86 */
87 setVertexAttribPointers(gl: WebGLRenderingContext, program: Program<any>, vertexOffset?: number | null) {
88 for (let j = 0; j < this.attributes.length; j++) {
89 const member = this.attributes[j];
90 const attribIndex: number | void = program.attributes[member.name];
91
92 if (attribIndex !== undefined) {
93 gl.vertexAttribPointer(
94 attribIndex,
95 member.components,
96 (gl as any)[AttributeType[member.type]],
97 false,
98 this.itemSize,
99 member.offset + (this.itemSize * (vertexOffset || 0))
100 );
101 }
102 }
103 }
104
105 /**
106 * Destroy the GL buffer bound to the given WebGL context
107 */
108 destroy() {
109 const gl = this.context.gl;
110 if (this.buffer) {
111 gl.deleteBuffer(this.buffer);
112 delete this.buffer;
113 }
114 }
115}
116
117export default VertexBuffer;