113 lines
3 KiB
TypeScript
113 lines
3 KiB
TypeScript
|
import { Buffer, VertexBuffer } from './buffer';
|
||
|
import { 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: Buffer[];
|
||
|
layouts: VertexBufferLayout[];
|
||
|
|
||
|
constructor() {
|
||
|
this.buffers = [];
|
||
|
this.layouts = [];
|
||
|
}
|
||
|
|
||
|
addBuffer(vb: VertexBuffer, layout: VertexBufferLayout) {
|
||
|
this.buffers.push(vb);
|
||
|
this.layouts.push(layout);
|
||
|
}
|
||
|
|
||
|
/// 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);
|
||
|
});
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|