Modified the WebGLContext to be used independantly
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user