|
@@ -11,20 +11,6 @@
|
|
return shader;
|
|
return shader;
|
|
};
|
|
};
|
|
|
|
|
|
- var HALF_FLOAT_OES = 0x8D61;
|
|
|
|
-
|
|
|
|
- var getWebGLTextureType = (gl: WebGLRenderingContext, type: number): number => {
|
|
|
|
- if (type === Engine.TEXTURETYPE_FLOAT) {
|
|
|
|
- return gl.FLOAT;
|
|
|
|
- }
|
|
|
|
- else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
|
|
|
|
- // Add Half Float Constant.
|
|
|
|
- return HALF_FLOAT_OES;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return gl.UNSIGNED_BYTE;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
var getSamplingParameters = (samplingMode: number, generateMipMaps: boolean, gl: WebGLRenderingContext): { min: number; mag: number } => {
|
|
var getSamplingParameters = (samplingMode: number, generateMipMaps: boolean, gl: WebGLRenderingContext): { min: number; mag: number } => {
|
|
var magFilter = gl.NEAREST;
|
|
var magFilter = gl.NEAREST;
|
|
var minFilter = gl.NEAREST;
|
|
var minFilter = gl.NEAREST;
|
|
@@ -197,6 +183,7 @@
|
|
public textureHalfFloatRender: boolean;
|
|
public textureHalfFloatRender: boolean;
|
|
public textureLOD: boolean;
|
|
public textureLOD: boolean;
|
|
public drawBuffersExtension;
|
|
public drawBuffersExtension;
|
|
|
|
+ public colorBufferFloat: boolean;
|
|
}
|
|
}
|
|
|
|
|
|
export interface EngineOptions extends WebGLContextAttributes {
|
|
export interface EngineOptions extends WebGLContextAttributes {
|
|
@@ -244,6 +231,10 @@
|
|
private static _GEQUAL = 0x0206; // Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
|
|
private static _GEQUAL = 0x0206; // Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is greater than or equal to the stored value.
|
|
private static _NOTEQUAL = 0x0205; // Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
|
|
private static _NOTEQUAL = 0x0205; // Passed to depthFunction or stencilFunction to specify depth or stencil tests will pass if the new depth value is not equal to the stored value.
|
|
|
|
|
|
|
|
+ private static HALF_FLOAT_OES = 0x8D61; // Half floating-point type (16-bit).
|
|
|
|
+ private static RGBA16F = 0x881A; // RGBA 16-bit floating-point color-renderable internal sized format.
|
|
|
|
+ private static RGBA32F = 0x8814; // RGBA 32-bit floating-point color-renderable internal sized format.
|
|
|
|
+
|
|
public static get NEVER(): number {
|
|
public static get NEVER(): number {
|
|
return Engine._NEVER;
|
|
return Engine._NEVER;
|
|
}
|
|
}
|
|
@@ -560,10 +551,6 @@
|
|
if (!this._gl) {
|
|
if (!this._gl) {
|
|
throw new Error("WebGL not supported");
|
|
throw new Error("WebGL not supported");
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Checks if some of the format renders first to allow the use of webgl inspector.
|
|
|
|
- var renderToFullFloat = this._canRenderToFloatTexture();
|
|
|
|
- var renderToHalfFloat = this._canRenderToHalfFloatTexture();
|
|
|
|
|
|
|
|
this._onBlur = () => {
|
|
this._onBlur = () => {
|
|
this._windowIsBackground = true;
|
|
this._windowIsBackground = true;
|
|
@@ -621,20 +608,25 @@
|
|
this._gl.getExtension('WEBGL_compressed_texture_es3_0'); // also a requirement of OpenGL ES 3
|
|
this._gl.getExtension('WEBGL_compressed_texture_es3_0'); // also a requirement of OpenGL ES 3
|
|
this._caps.atc = this._gl.getExtension('WEBGL_compressed_texture_atc' ) || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_atc' );
|
|
this._caps.atc = this._gl.getExtension('WEBGL_compressed_texture_atc' ) || this._gl.getExtension('WEBKIT_WEBGL_compressed_texture_atc' );
|
|
|
|
|
|
- this._caps.textureFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_float') !== null);
|
|
|
|
this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
|
|
this._caps.textureAnisotropicFilterExtension = this._gl.getExtension('EXT_texture_filter_anisotropic') || this._gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') || this._gl.getExtension('MOZ_EXT_texture_filter_anisotropic');
|
|
this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
|
|
this._caps.maxAnisotropy = this._caps.textureAnisotropicFilterExtension ? this._gl.getParameter(this._caps.textureAnisotropicFilterExtension.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 0;
|
|
this._caps.uintIndices = this._webGLVersion > 1 || this._gl.getExtension('OES_element_index_uint') !== null;
|
|
this._caps.uintIndices = this._webGLVersion > 1 || this._gl.getExtension('OES_element_index_uint') !== null;
|
|
this._caps.fragmentDepthSupported = this._webGLVersion > 1 || this._gl.getExtension('EXT_frag_depth') !== null;
|
|
this._caps.fragmentDepthSupported = this._webGLVersion > 1 || this._gl.getExtension('EXT_frag_depth') !== null;
|
|
this._caps.highPrecisionShaderSupported = true;
|
|
this._caps.highPrecisionShaderSupported = true;
|
|
this._caps.drawBuffersExtension = this._webGLVersion > 1 || this._gl.getExtension('WEBGL_draw_buffers');
|
|
this._caps.drawBuffersExtension = this._webGLVersion > 1 || this._gl.getExtension('WEBGL_draw_buffers');
|
|
|
|
+
|
|
|
|
+ // Checks if some of the format renders first to allow the use of webgl inspector.
|
|
|
|
+ this._caps.colorBufferFloat = this._webGLVersion > 1 && this._gl.getExtension('EXT_color_buffer_float')
|
|
|
|
+
|
|
|
|
+ this._caps.textureFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_float') !== null);
|
|
this._caps.textureFloatLinearFiltering = this._gl.getExtension('OES_texture_float_linear');
|
|
this._caps.textureFloatLinearFiltering = this._gl.getExtension('OES_texture_float_linear');
|
|
- this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
|
|
|
|
- this._caps.textureFloatRender = renderToFullFloat;
|
|
|
|
|
|
+ this._caps.textureFloatRender = this._caps.textureFloat && this._canRenderToFloatFramebuffer();
|
|
|
|
|
|
this._caps.textureHalfFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_half_float') !== null);
|
|
this._caps.textureHalfFloat = this._webGLVersion > 1 || (this._gl.getExtension('OES_texture_half_float') !== null);
|
|
this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float_linear');
|
|
this._caps.textureHalfFloatLinearFiltering = this._webGLVersion > 1 || this._gl.getExtension('OES_texture_half_float_linear');
|
|
- this._caps.textureHalfFloatRender = renderToHalfFloat;
|
|
|
|
|
|
+ this._caps.textureHalfFloatRender = this._caps.textureHalfFloat && this._canRenderToHalfFloatFramebuffer();
|
|
|
|
+
|
|
|
|
+ this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
|
|
|
|
|
|
// Vertex array object
|
|
// Vertex array object
|
|
if ( this._webGLVersion > 1) {
|
|
if ( this._webGLVersion > 1) {
|
|
@@ -2439,7 +2431,7 @@
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
|
|
|
|
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, getWebGLTextureType(gl, type), null);
|
|
|
|
|
|
+ gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), width, height, 0, gl.RGBA, this._getWebGLTextureType(type), null);
|
|
|
|
|
|
var depthStencilBuffer: WebGLRenderbuffer;
|
|
var depthStencilBuffer: WebGLRenderbuffer;
|
|
|
|
|
|
@@ -2733,13 +2725,14 @@
|
|
texture.references = 1;
|
|
texture.references = 1;
|
|
texture.url = url;
|
|
texture.url = url;
|
|
|
|
|
|
- var internalFormat = this._getInternalFormat(format);
|
|
|
|
-
|
|
|
|
var textureType = gl.UNSIGNED_BYTE;
|
|
var textureType = gl.UNSIGNED_BYTE;
|
|
if (type === Engine.TEXTURETYPE_FLOAT) {
|
|
if (type === Engine.TEXTURETYPE_FLOAT) {
|
|
textureType = gl.FLOAT;
|
|
textureType = gl.FLOAT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ var internalFormat = this._getInternalFormat(format);
|
|
|
|
+ var internalSizedFomat = this._getRGBABufferInternalSizedFormat(type);
|
|
|
|
+
|
|
var width = size;
|
|
var width = size;
|
|
var height = width;
|
|
var height = width;
|
|
var isPot = (Tools.IsExponentOfTwo(width) && Tools.IsExponentOfTwo(height));
|
|
var isPot = (Tools.IsExponentOfTwo(width) && Tools.IsExponentOfTwo(height));
|
|
@@ -2784,30 +2777,19 @@
|
|
var mipSize = width >> level;
|
|
var mipSize = width >> level;
|
|
|
|
|
|
// mipData is order in +X -X +Y -Y +Z -Z
|
|
// mipData is order in +X -X +Y -Y +Z -Z
|
|
- gl.texImage2D(facesIndex[0], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
|
|
|
|
- gl.texImage2D(facesIndex[1], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
|
|
|
|
- gl.texImage2D(facesIndex[2], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
|
|
|
|
- gl.texImage2D(facesIndex[3], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
|
|
|
|
- gl.texImage2D(facesIndex[4], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
|
|
|
|
- gl.texImage2D(facesIndex[5], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
|
|
|
|
|
|
+ gl.texImage2D(facesIndex[0], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
|
|
|
|
+ gl.texImage2D(facesIndex[1], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
|
|
|
|
+ gl.texImage2D(facesIndex[2], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
|
|
|
|
+ gl.texImage2D(facesIndex[3], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
|
|
|
|
+ gl.texImage2D(facesIndex[4], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
|
|
|
|
+ gl.texImage2D(facesIndex[5], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- // Data are known to be in +X +Y +Z -X -Y -Z
|
|
|
|
- for (let index = 0; index < facesIndex.length; index++) {
|
|
|
|
- let faceData = rgbeDataArrays[index];
|
|
|
|
- gl.texImage2D(facesIndex[index], 0, internalFormat, width, height, 0, internalFormat, textureType, faceData);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
|
|
|
|
-
|
|
|
|
- // Workaround firefox bug fix https://bugzilla.mozilla.org/show_bug.cgi?id=1221822
|
|
|
|
- // By following the webgl standard changes from Revision 7, 2014/11/24
|
|
|
|
- // Firefox Removed the support for RGB32F, since it is not natively supported on all platforms where WebGL is implemented.
|
|
|
|
- if (textureType === gl.FLOAT && internalFormat === gl.RGB && gl.getError() === 1282) {
|
|
|
|
- Tools.Log("RGB32F not renderable on Firefox, trying fallback to RGBA32F.");
|
|
|
|
|
|
+ if (internalFormat === gl.RGB) {
|
|
|
|
+ internalFormat = gl.RGBA;
|
|
|
|
|
|
- // Data are known to be in +X +Y +Z -X -Y -Z
|
|
|
|
|
|
+ // Data are known to be in +X +Y +Z -X -Y -Z
|
|
for (let index = 0; index < facesIndex.length; index++) {
|
|
for (let index = 0; index < facesIndex.length; index++) {
|
|
let faceData = <Float32Array>rgbeDataArrays[index];
|
|
let faceData = <Float32Array>rgbeDataArrays[index];
|
|
|
|
|
|
@@ -2829,12 +2811,18 @@
|
|
}
|
|
}
|
|
|
|
|
|
// Reupload the face.
|
|
// Reupload the face.
|
|
- gl.texImage2D(facesIndex[index], 0, gl.RGBA, width, height, 0, gl.RGBA, textureType, newFaceData);
|
|
|
|
|
|
+ gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, newFaceData);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ // Data are known to be in +X +Y +Z -X -Y -Z
|
|
|
|
+ for (let index = 0; index < facesIndex.length; index++) {
|
|
|
|
+ let faceData = rgbeDataArrays[index];
|
|
|
|
+ gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, faceData);
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Try to generate mipmap again.
|
|
|
|
- gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
@@ -2845,7 +2833,7 @@
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
}
|
|
}
|
|
- else if (textureType === HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
|
|
|
|
|
|
+ else if (textureType === Engine.HALF_FLOAT_OES && !this._caps.textureHalfFloatLinearFiltering) {
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
}
|
|
}
|
|
@@ -3274,130 +3262,97 @@
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private _canRenderToFloatTexture(): boolean {
|
|
|
|
|
|
+ private _canRenderToFloatFramebuffer(): boolean {
|
|
if (this._webGLVersion > 1) {
|
|
if (this._webGLVersion > 1) {
|
|
- return true;
|
|
|
|
|
|
+ return this._caps.colorBufferFloat;
|
|
}
|
|
}
|
|
- return this._canRenderToTextureOfType(BABYLON.Engine.TEXTURETYPE_FLOAT, 'OES_texture_float');
|
|
|
|
|
|
+ return this._canRenderToFramebuffer(BABYLON.Engine.TEXTURETYPE_FLOAT);
|
|
}
|
|
}
|
|
|
|
|
|
- private _canRenderToHalfFloatTexture(): boolean {
|
|
|
|
|
|
+ private _canRenderToHalfFloatFramebuffer(): boolean {
|
|
if (this._webGLVersion > 1) {
|
|
if (this._webGLVersion > 1) {
|
|
- return true;
|
|
|
|
|
|
+ return this._caps.colorBufferFloat;
|
|
}
|
|
}
|
|
- return this._canRenderToTextureOfType(BABYLON.Engine.TEXTURETYPE_HALF_FLOAT, 'OES_texture_half_float');
|
|
|
|
|
|
+ return this._canRenderToFramebuffer(BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
|
|
}
|
|
}
|
|
|
|
|
|
// Thank you : http://stackoverflow.com/questions/28827511/webgl-ios-render-to-floating-point-texture
|
|
// Thank you : http://stackoverflow.com/questions/28827511/webgl-ios-render-to-floating-point-texture
|
|
- private _canRenderToTextureOfType(format: number, extension: string): boolean {
|
|
|
|
- try {
|
|
|
|
- var tempcanvas = document.createElement("canvas");
|
|
|
|
- tempcanvas.height = 16;
|
|
|
|
- tempcanvas.width = 16;
|
|
|
|
- var gl = <WebGLRenderingContext>(tempcanvas.getContext("webgl") || tempcanvas.getContext("experimental-webgl"));
|
|
|
|
-
|
|
|
|
- // extension.
|
|
|
|
- var ext = gl.getExtension(extension);
|
|
|
|
- if (!ext) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ private _canRenderToFramebuffer(type: number): boolean {
|
|
|
|
+ let gl = this._gl;
|
|
|
|
|
|
- // setup GLSL program
|
|
|
|
- var vertexCode = `attribute vec4 a_position;
|
|
|
|
- void main() {
|
|
|
|
- gl_Position = a_position;
|
|
|
|
- }`;
|
|
|
|
- var fragmentCode = `precision mediump float;
|
|
|
|
- uniform vec4 u_color;
|
|
|
|
- uniform sampler2D u_texture;
|
|
|
|
-
|
|
|
|
- void main() {
|
|
|
|
- gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;
|
|
|
|
- }`;
|
|
|
|
- var program = this.createShaderProgram(vertexCode, fragmentCode, null, gl);
|
|
|
|
- gl.useProgram(program);
|
|
|
|
-
|
|
|
|
- // look up where the vertex data needs to go.
|
|
|
|
- var positionLocation = gl.getAttribLocation(program, "a_position");
|
|
|
|
- var colorLoc = gl.getUniformLocation(program, "u_color");
|
|
|
|
-
|
|
|
|
- // provide texture coordinates for the rectangle.
|
|
|
|
- var positionBuffer = gl.createBuffer();
|
|
|
|
- gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
|
|
|
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
|
|
- -1.0, -1.0,
|
|
|
|
- 1.0, -1.0,
|
|
|
|
- -1.0, 1.0,
|
|
|
|
- -1.0, 1.0,
|
|
|
|
- 1.0, -1.0,
|
|
|
|
- 1.0, 1.0]), gl.STATIC_DRAW);
|
|
|
|
- gl.enableVertexAttribArray(positionLocation);
|
|
|
|
- gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
-
|
|
|
|
- var whiteTex = gl.createTexture();
|
|
|
|
- gl.bindTexture(gl.TEXTURE_2D, whiteTex);
|
|
|
|
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));
|
|
|
|
-
|
|
|
|
- var tex = gl.createTexture();
|
|
|
|
- gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
|
|
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, getWebGLTextureType(gl, format), null);
|
|
|
|
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
|
|
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
|
|
-
|
|
|
|
- var fb = gl.createFramebuffer();
|
|
|
|
- gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
|
|
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
|
|
|
- gl.viewport(0, 0, 1, 1);
|
|
|
|
-
|
|
|
|
- var cleanup = () => {
|
|
|
|
- gl.deleteProgram(program);
|
|
|
|
- gl.disableVertexAttribArray(positionLocation);
|
|
|
|
- gl.deleteBuffer(positionBuffer);
|
|
|
|
- gl.deleteFramebuffer(fb);
|
|
|
|
- gl.deleteTexture(whiteTex);
|
|
|
|
- gl.deleteTexture(tex);
|
|
|
|
- };
|
|
|
|
|
|
+ //clear existing errors
|
|
|
|
+ while(gl.getError() !== gl.NO_ERROR){}
|
|
|
|
|
|
- var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
|
|
- if (status !== gl.FRAMEBUFFER_COMPLETE) {
|
|
|
|
- Tools.Log("GL Support: can **NOT** render to " + format + " texture");
|
|
|
|
- cleanup();
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ let successful = true;
|
|
|
|
|
|
- // Draw the rectangle.
|
|
|
|
- gl.bindTexture(gl.TEXTURE_2D, whiteTex);
|
|
|
|
- gl.uniform4fv(colorLoc, <any>[0, 10, 20, 1]);
|
|
|
|
- gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
|
|
|
|
+ let texture = gl.createTexture();
|
|
|
|
+ gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
|
|
+ gl.texImage2D(gl.TEXTURE_2D, 0, this._getRGBABufferInternalSizedFormat(type), 1, 1, 0, gl.RGBA, this._getWebGLTextureType(type), null);
|
|
|
|
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
|
|
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
|
|
|
|
- gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
|
|
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
|
|
|
|
+ let fb = gl.createFramebuffer();
|
|
|
|
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
|
|
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
|
|
|
+ let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
|
|
+
|
|
|
|
+ successful = successful && (status === gl.FRAMEBUFFER_COMPLETE);
|
|
|
|
+ successful = successful && (gl.getError() === gl.NO_ERROR);
|
|
|
|
|
|
- gl.clearColor(1, 0, 0, 1);
|
|
|
|
|
|
+ //try render by clearing frame buffer's color buffer
|
|
|
|
+ if(successful){
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
+ successful = successful && (gl.getError() === gl.NO_ERROR);
|
|
|
|
+ }
|
|
|
|
|
|
- gl.uniform4fv(colorLoc, <any>[0, 1 / 10, 1 / 20, 1]);
|
|
|
|
- gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
|
|
-
|
|
|
|
- var pixel = new Uint8Array(4);
|
|
|
|
- gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
|
|
|
|
- if (pixel[0] !== 0 ||
|
|
|
|
- pixel[1] < 248 ||
|
|
|
|
- pixel[2] < 248 ||
|
|
|
|
- pixel[3] < 254) {
|
|
|
|
- BABYLON.Tools.Log("GL Support: Was not able to actually render to " + format + " texture");
|
|
|
|
- cleanup();
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ //try reading from frame to ensure render occurs (just creating the FBO is not sufficient to determine if rendering is supported)
|
|
|
|
+ if(successful){
|
|
|
|
+ //in practice it's sufficient to just read from the backbuffer rather than handle potentially issues reading from the texture
|
|
|
|
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
|
|
+ let readFormat = gl.RGBA;
|
|
|
|
+ let readType = gl.UNSIGNED_BYTE;
|
|
|
|
+ let buffer = new Uint8Array(4);
|
|
|
|
+ gl.readPixels(0, 0, 1, 1, readFormat, readType, buffer);
|
|
|
|
+ successful = successful && (gl.getError() === gl.NO_ERROR);
|
|
|
|
+ }
|
|
|
|
|
|
- // Succesfully rendered to "format" texture.
|
|
|
|
- cleanup();
|
|
|
|
- return true;
|
|
|
|
|
|
+ //clean up
|
|
|
|
+ gl.deleteTexture(texture);
|
|
|
|
+ gl.deleteFramebuffer(fb);
|
|
|
|
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
|
|
+
|
|
|
|
+ //clear accumulated errors
|
|
|
|
+ while(!successful && (gl.getError() !== gl.NO_ERROR)) { }
|
|
|
|
+
|
|
|
|
+ return successful;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private _getWebGLTextureType(type: number) : number {
|
|
|
|
+ if (type === Engine.TEXTURETYPE_FLOAT) {
|
|
|
|
+ return this._gl.FLOAT;
|
|
}
|
|
}
|
|
- catch (e) {
|
|
|
|
- return false;
|
|
|
|
|
|
+ else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
|
|
|
|
+ // Add Half Float Constant.
|
|
|
|
+ return Engine.HALF_FLOAT_OES;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ return this._gl.UNSIGNED_BYTE;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ private _getRGBABufferInternalSizedFormat(type: number) : number {
|
|
|
|
+ if (this._webGLVersion === 1) {
|
|
|
|
+ return this._gl.RGBA;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (type === Engine.TEXTURETYPE_FLOAT) {
|
|
|
|
+ return Engine.RGBA32F;
|
|
|
|
+ }
|
|
|
|
+ else if (type === Engine.TEXTURETYPE_HALF_FLOAT) {
|
|
|
|
+ return Engine.RGBA16F;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this._gl.RGBA;
|
|
|
|
+ };
|
|
|
|
|
|
// Statics
|
|
// Statics
|
|
public static isSupported(): boolean {
|
|
public static isSupported(): boolean {
|