Modified the WebGLContext to be used independantly

This commit is contained in:
Olivier Guyot
2018-11-13 16:54:30 +01:00
parent 36cf7227c0
commit 0a0d6c22f5

View File

@@ -9,6 +9,15 @@ import {listen, unlistenAll} from '../events.js';
import {clear} from '../obj.js'; import {clear} from '../obj.js';
import {ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, TEXTURE_2D, TEXTURE_WRAP_S, TEXTURE_WRAP_T} from '../webgl.js'; import {ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, TEXTURE_2D, TEXTURE_WRAP_S, TEXTURE_WRAP_T} from '../webgl.js';
import ContextEventType from '../webgl/ContextEventType.js'; import ContextEventType from '../webgl/ContextEventType.js';
import {TRIANGLES, UNSIGNED_INT, UNSIGNED_SHORT} from "../webgl";
import {
create as createTransform,
reset as resetTransform,
rotate as rotateTransform,
scale as scaleTransform,
translate as translateTransform
} from "../transform";
import {create, fromTransform} from "../vec/mat4";
/** /**
@@ -17,6 +26,13 @@ import ContextEventType from '../webgl/ContextEventType.js';
* @property {WebGLBuffer} buffer * @property {WebGLBuffer} buffer
*/ */
export const DefaultUniform = {
PROJECTION_MATRIX: 'u_projectionMatrix',
SCALE_MATRIX: 'u_offsetScaleMatrix',
OFFSET_ROTATION_MATRIX: 'u_offsetRotateMatrix',
OPACITY: 'u_opacity'
};
/** /**
* @classdesc * @classdesc
@@ -26,9 +42,8 @@ class WebGLContext extends Disposable {
/** /**
* @param {HTMLCanvasElement} canvas Canvas. * @param {HTMLCanvasElement} canvas Canvas.
* @param {WebGLRenderingContext} gl GL.
*/ */
constructor(canvas, gl) { constructor(canvas) {
super(); super();
/** /**
@@ -41,7 +56,7 @@ class WebGLContext extends Disposable {
* @private * @private
* @type {WebGLRenderingContext} * @type {WebGLRenderingContext}
*/ */
this.gl_ = gl; this.gl_ = canvas.getContext('webgl');
/** /**
* @private * @private
@@ -67,24 +82,6 @@ class WebGLContext extends Disposable {
*/ */
this.currentProgram_ = null; this.currentProgram_ = null;
/**
* @private
* @type {WebGLFramebuffer}
*/
this.hitDetectionFramebuffer_ = null;
/**
* @private
* @type {WebGLTexture}
*/
this.hitDetectionTexture_ = null;
/**
* @private
* @type {WebGLRenderbuffer}
*/
this.hitDetectionRenderbuffer_ = null;
/** /**
* @type {boolean} * @type {boolean}
*/ */
@@ -92,7 +89,7 @@ class WebGLContext extends Disposable {
// use the OES_element_index_uint extension if available // use the OES_element_index_uint extension if available
if (this.hasOESElementIndexUint) { if (this.hasOESElementIndexUint) {
gl.getExtension('OES_element_index_uint'); this.gl_.getExtension('OES_element_index_uint');
} }
listen(this.canvas_, ContextEventType.LOST, listen(this.canvas_, ContextEventType.LOST,
@@ -100,12 +97,34 @@ class WebGLContext extends Disposable {
listen(this.canvas_, ContextEventType.RESTORED, listen(this.canvas_, ContextEventType.RESTORED,
this.handleWebGLContextRestored, this); this.handleWebGLContextRestored, this);
/**
* @private
* @type {import("../transform.js").Transform}
*/
this.projectionMatrix_ = createTransform();
/**
* @private
* @type {import("../transform.js").Transform}
*/
this.offsetRotateMatrix_ = createTransform();
/**
* @private
* @type {import("../transform.js").Transform}
*/
this.offsetScaleMatrix_ = createTransform();
this.tmpMat4_ = create();
this.locations_ = {};
} }
/** /**
* Just bind the buffer if it's in the cache. Otherwise create * Just bind the buffer if it's in the cache. Otherwise create
* the WebGL buffer, bind it, populate it, and add an entry to * the WebGL buffer, bind it, populate it, and add an entry to
* the cache. * the cache.
* TODO: improve this, the logic is unclear: we want A/ to bind a buffer and B/ to flush data in it
* @param {number} target Target. * @param {number} target Target.
* @param {import("./Buffer.js").default} buf Buffer. * @param {import("./Buffer.js").default} buf Buffer.
*/ */
@@ -163,13 +182,24 @@ class WebGLContext extends Disposable {
for (const key in this.shaderCache_) { for (const key in this.shaderCache_) {
gl.deleteShader(this.shaderCache_[key]); gl.deleteShader(this.shaderCache_[key]);
} }
// delete objects for hit-detection
gl.deleteFramebuffer(this.hitDetectionFramebuffer_);
gl.deleteRenderbuffer(this.hitDetectionRenderbuffer_);
gl.deleteTexture(this.hitDetectionTexture_);
} }
} }
/**
* @protected
* @param {number} start Start index.
* @param {number} end End index.
*/
drawElements(start, end) {
const elementType = this.hasOESElementIndexUint ?
UNSIGNED_INT : UNSIGNED_SHORT;
const elementSize = this.hasOESElementIndexUint ? 4 : 2;
const numItems = end - start;
const offsetInBytes = start * elementSize;
this.getGL().drawElements(TRIANGLES, numItems, elementType, offsetInBytes);
}
/** /**
* @return {HTMLCanvasElement} Canvas. * @return {HTMLCanvasElement} Canvas.
*/ */
@@ -186,17 +216,6 @@ class WebGLContext extends Disposable {
return this.gl_; return this.gl_;
} }
/**
* Get the frame buffer for hit detection.
* @return {WebGLFramebuffer} The hit detection frame buffer.
*/
getHitDetectionFramebuffer() {
if (!this.hitDetectionFramebuffer_) {
this.initHitDetectionFramebuffer_();
}
return this.hitDetectionFramebuffer_;
}
/** /**
* Get shader from the cache if it's in the cache. Otherwise, create * Get shader from the cache if it's in the cache. Otherwise, create
* the WebGL shader, compile it, and add entry to cache. * the WebGL shader, compile it, and add entry to cache.
@@ -240,6 +259,48 @@ class WebGLContext extends Disposable {
} }
} }
/**
* Sets the matrices uniforms for a given frame state
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
*/
applyFrameState(frameState) {
const size = frameState.size;
const rotation = frameState.viewState.rotation;
const resolution = frameState.viewState.resolution;
const center = frameState.viewState.center;
// set the "uniform" values (coordinates 0,0 are the center of the view
const projectionMatrix = resetTransform(this.projectionMatrix_);
scaleTransform(projectionMatrix, 2 / (resolution * size[0]), 2 / (resolution * size[1]));
rotateTransform(projectionMatrix, -rotation);
translateTransform(projectionMatrix, -center[0], -center[1]);
const offsetScaleMatrix = resetTransform(this.offsetScaleMatrix_);
scaleTransform(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
const offsetRotateMatrix = resetTransform(this.offsetRotateMatrix_);
if (rotation !== 0) {
rotateTransform(offsetRotateMatrix, -rotation);
}
this.getGL().uniformMatrix4fv(locations.u_projectionMatrix, false,
fromTransform(this.tmpMat4_, projectionMatrix));
this.getGL().uniformMatrix4fv(locations.u_offsetScaleMatrix, false,
fromTransform(this.tmpMat4_, offsetScaleMatrix));
this.getGL().uniformMatrix4fv(locations.u_offsetRotateMatrix, false,
fromTransform(this.tmpMat4_, offsetRotateMatrix));
}
/**
* Give a value for a standard float uniform
* @param {string} uniform Uniform name
* @param {number} value Value
*/
setUniformFloatValue(uniform, value) {
this.getGL().uniformMatrix4fv(this.locations_[uniform], false, value);
}
/** /**
* FIXME empty description for jsdoc * FIXME empty description for jsdoc
*/ */
@@ -248,9 +309,6 @@ class WebGLContext extends Disposable {
clear(this.shaderCache_); clear(this.shaderCache_);
clear(this.programCache_); clear(this.programCache_);
this.currentProgram_ = null; this.currentProgram_ = null;
this.hitDetectionFramebuffer_ = null;
this.hitDetectionTexture_ = null;
this.hitDetectionRenderbuffer_ = null;
} }
/** /**
@@ -259,33 +317,6 @@ class WebGLContext extends Disposable {
handleWebGLContextRestored() { handleWebGLContextRestored() {
} }
/**
* Creates a 1x1 pixel framebuffer for the hit-detection.
* @private
*/
initHitDetectionFramebuffer_() {
const gl = this.gl_;
const framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
const texture = createEmptyTexture(gl, 1, 1);
const renderbuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
gl.framebufferTexture2D(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER, renderbuffer);
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
this.hitDetectionFramebuffer_ = framebuffer;
this.hitDetectionTexture_ = texture;
this.hitDetectionRenderbuffer_ = renderbuffer;
}
/** /**
* Use a program. If the program is already in use, this will return `false`. * Use a program. If the program is already in use, this will return `false`.
* @param {WebGLProgram} program Program. * @param {WebGLProgram} program Program.