1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
import type { VertexBuffer } from './buffer';
import type { Shader } from './shader';
export class VertexBufferElement {
type: number;
amount: number;
type_size: number;
normalized: boolean;
index: string;
constructor(
type: number,
amount: number,
type_size: number,
index: string,
normalized: boolean,
) {
this.type = type;
this.amount = amount;
this.type_size = type_size;
this.normalized = normalized;
this.index = index;
}
}
export class VertexBufferLayout {
elements: VertexBufferElement[];
stride: number;
offset: number;
constructor(offset = 0) {
this.elements = [];
this.stride = 0;
this.offset = offset;
}
// Maybe wrong normalized type
push(
type: number,
amount: number,
type_size: number,
index: string,
normalized = false,
) {
this.elements.push(new VertexBufferElement(type, amount, type_size, index, normalized));
this.stride += amount * type_size;
}
getElements(): VertexBufferElement[] {
return this.elements;
}
getStride(): number {
return this.stride;
}
}
// glEnableVertexAttribArray is to specify what location of the current program the follow data is needed
// glVertexAttribPointer tells gl that that data is at which location in the supplied data
export class VertexArray {
// There is no renderer ID, always at bind buffers and use glVertexAttribPointer
buffers: VertexBuffer[];
layouts: VertexBufferLayout[];
constructor() {
this.buffers = [];
this.layouts = [];
}
addBuffer(vb: VertexBuffer, layout: VertexBufferLayout) {
this.buffers.push(vb);
this.layouts.push(layout);
}
updateBuffer(gl: WebGLRenderingContext, index: number, data: number[]) {
this.buffers[index].updateData(gl, data);
}
/// Bind buffers providing program data
bind(gl: WebGLRenderingContext, shader: Shader) {
shader.bind(gl);
for(let i = 0; i < this.buffers.length; i ++) {
const buffer = this.buffers[i];
const layout = this.layouts[i];
buffer.bind(gl);
const elements = layout.getElements();
let offset = layout.offset;
for (let j = 0; j < elements.length; j ++) {
const element = elements[j];
const location = shader.getAttribLocation(gl, element.index);
if (location >= 0) {
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(
location, element.amount, element.type,
element.normalized, layout.stride, offset
);
}
offset += element.amount * element.type_size;
}
}
}
/// Undo bind operation
unbind(gl: WebGLRenderingContext) {
this.layouts.forEach((layout) => {
layout.getElements().forEach((_, index) => {
gl.disableVertexAttribArray(index);
});
})
}
}
|