@awayjs/stage
Version:
Stage for AwayJS
126 lines (97 loc) • 3.15 kB
text/typescript
import { IVao } from '../base/IVao';
import { ContextWebGL } from './ContextWebGL';
import { IndexBufferWebGL } from './IndexBufferWebGL';
type TWebGLVao = WebGLVertexArrayObjectOES | WebGLVertexArrayObject;
export class VaoContextWebGL {
public static isSupported(gl: WebGLRenderingContext | WebGL2RenderingContext) {
if (window.WebGL2RenderingContext && gl instanceof window.WebGL2RenderingContext) {
return true;
}
if (gl.getSupportedExtensions().indexOf('OES_vertex_array_object') > -1) {
return true;
}
return false;
}
private readonly _createVertexArray: () => TWebGLVao;
private readonly _deleteVertexArray: (e: TWebGLVao) => void;
private readonly _bindVertexArray: (e: TWebGLVao) => void;
/* internal */ _lastBoundedVao: VaoWebGL;
/* internal */ _isRequireUnbound: boolean = false;
constructor (private _context: ContextWebGL) {
const gl = _context._gl;
if (!VaoContextWebGL.isSupported(gl)) {
throw '[VaoContextWebGL] VAO not supported!';
}
if (window.WebGL2RenderingContext && gl instanceof window.WebGL2RenderingContext) {
this._createVertexArray = gl.createVertexArray.bind(gl);
this._deleteVertexArray = gl.deleteVertexArray.bind(gl);
this._bindVertexArray = gl.bindVertexArray.bind(gl);
} else {
const ext = gl.getExtension('OES_vertex_array_object');
this._createVertexArray = ext.createVertexArrayOES.bind(ext);
this._deleteVertexArray = ext.deleteVertexArrayOES.bind(ext);
this._bindVertexArray = ext.bindVertexArrayOES.bind(ext);
}
}
createVertexArray(): TWebGLVao {
this._context.stats.counter.vao++;
return this._createVertexArray();
}
unbindVertexArrays() {
this._bindVertexArray(null);
this._lastBoundedVao = null;
this._isRequireUnbound = false;
}
bindVertexArray (v: VaoWebGL) {
this._context.stateChangeCallback && this._context.stateChangeCallback('bindVertexArray');
// not unbound vao, to reduce bound flips
if (v === this._lastBoundedVao) {
return;
}
if (!v) {
// mark that we require a unbound VAO as fast as possible
this._isRequireUnbound = true;
return;
}
this._isRequireUnbound = false;
this._lastBoundedVao = v;
this._bindVertexArray(v._vao);
}
deleteVertexArray (v: VaoWebGL) {
if (this._lastBoundedVao === v) {
this._bindVertexArray(null);
}
this._deleteVertexArray(v._vao);
this._lastBoundedVao = null;
this._context.stats.counter.vao--;
}
}
export class VaoWebGL implements IVao {
/* internal */ _vao: TWebGLVao;
/* internal */ _indexBuffer: IndexBufferWebGL;
constructor (private _context: ContextWebGL) {
this._vao = _context._vaoContext.createVertexArray();
}
attachIndexBuffer(buffer: IndexBufferWebGL) {
if (this._indexBuffer) {
return;
}
this.bind();
this._context.bindIndexBuffer(buffer);
this._indexBuffer = buffer;
}
bind() {
this._context._vaoContext.bindVertexArray(this);
}
unbind(force = false) {
if (force) {
this._context._vaoContext.unbindVertexArrays();
return;
}
this._context._vaoContext.bindVertexArray(null);
}
dispose() {
this._context._vaoContext.deleteVertexArray(this);
this._vao = null;
}
}