1 | import assert from 'assert';
|
2 |
|
3 | import type {
|
4 | StructArray,
|
5 | StructArrayMember
|
6 | } from '../util/struct_array';
|
7 |
|
8 | import type Program from '../render/program';
|
9 | import type Context from '../gl/context';
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const 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 |
|
28 |
|
29 |
|
30 |
|
31 | class VertexBuffer {
|
32 | length: number;
|
33 | attributes: ReadonlyArray<StructArrayMember>;
|
34 | itemSize: number;
|
35 | dynamicDraw: boolean;
|
36 | context: Context;
|
37 | buffer: WebGLBuffer;
|
38 |
|
39 | |
40 |
|
41 |
|
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 |
|
83 |
|
84 |
|
85 |
|
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 |
|
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 |
|
117 | export default VertexBuffer;
|