I am in the process of integrating post processing effects into my 3D engine. I have hit a roadblock with capturing depth data using a FrameBuffer Object with WebGL. There has been no issue capturing color data into the FrameBuffer. However, I am not able to get any Depth data even with the Depth Extension enabled for Chrome/Firefox.
var DepthEXT = webGLContext.getExtension( "WEBKIT_WEBGL_depth_texture" ) ||
webGLContext.getExtension( "MOZ_WEBGL_depth_texture" );
I have tried many different settings to see if it was a configuration issue, but no matter what I try I just see a white texture. The screenshot at the end of the post shows the color attachment rendered as a texture and the depth attachment rendered as a texture. Is there a problem with my initialization of the FrameBuffer or should I be looking elsewhere to solve this issue?
Below is my code for initializing the FrameBuffer Object:
// Frame Buffer
this.m_frameBuffer = gl.createFramebuffer();
gl.bindFramebuffer( gl.FRAMEBUFFER, this.m_frameBuffer );
// Render Buffer
this.m_renderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer( gl.RENDERBUFFER, this.m_renderBuffer );
gl.renderbufferStorage(
gl.RENDERBUFFER,
gl.DEPTH_COMPONENT16,
sharedRenderer.canvasDOMElement.width,
sharedRenderer.canvasDOMElement.height );
// Diffuse Component
this.m_diffuseComponentTexture = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D, this.m_diffuseComponentTexture );
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_MAG_FILTER,
gl.LINEAR );
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_MIN_FILTER,
gl.LINEAR );
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.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
sharedRenderer.canvasDOMElement.width,
sharedRenderer.canvasDOMElement.height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
null );
// Depth
this.m_depthComponentTexture = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D, this.m_depthComponentTexture );
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_MAG_FILTER,
gl.NEAREST );
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_MIN_FILTER,
gl.NEAREST );
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.texImage2D(
gl.TEXTURE_2D,
0,
gl.DEPTH_COMPONENT,
sharedRenderer.canvasDOMElement.width,
sharedRenderer.canvasDOMElement.height,
0,
gl.DEPTH_COMPONENT,
gl.UNSIGNED_SHORT,
null );
// FrameBuffer
// Diffuse
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D,
this.m_diffuseComponentTexture,
0 );
// Depth
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D,
this.m_depthComponentTexture,
0 );
// RenderBuffer
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER,
gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER,
this.m_renderBuffer );
// Unbind buffers and textures
gl.bindTexture( gl.TEXTURE_2D, null );
gl.bindRenderbuffer( gl.RENDERBUFFER, null );
gl.bindFramebuffer( gl.FRAMEBUFFER, null );
Here is the code where I render the current scene to the FrameBuffer.
CBRenderer.prototype.renderSceneToGBuffer = function( sceneToRender, GBufferTarget, deltaSeconds )
{
CBMatrixStack.clearMatrixStackAndPushIdentityMatrix();
this.applyProjectionMatrix();
GBufferTarget.bindGBufferFrameBuffer();
this.renderer.enable( this.renderer.DEPTH_TEST );
this.renderer.depthMask( true );
this.renderer.clearDepth( 1.0 );
this.renderer.clearColor( 0.1, 0.1, 0.1, 0.0 );
this.renderer.clear( this.renderer.COLOR_BUFFER_BIT | this.renderer.DEPTH_BUFFER_BIT );
sceneToRender.render( deltaSeconds );
this.renderer.flush();
GBufferTarget.m_dirty = false;
GBufferTarget.unbindGBufferFrameBuffer();
this.renderer.clearColor( 0.0, 0.0, 0.0, 0.0 );
this.renderer.clear( this.renderer.COLOR_BUFFER_BIT | this.renderer.DEPTH_BUFFER_BIT );
this.renderer.bindTexture( this.renderer.TEXTURE_2D, null );
}
You don't have the depth texture attached to your FBO at the end of setting it up. You do set the texture as the depth attachment at some point:
// Depth
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D,
this.m_depthComponentTexture,
0 );
But immediately following that, you set a renderbuffer as the depth attachment instead:
// RenderBuffer
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER,
gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER,
this.m_renderBuffer );
You can have only one target attached to each FBO attachment point. So the second call sets a new depth attachment, replacing the one you just set in the first call. So at the end of this, m_depthComponentTexture is not attached to the FBO anymore.
If you want to use a depth texture, I don't see why you would want to create a depth renderbuffer as well. You should only need one of the two. You would normally use a renderbuffer for the depth if you don't need it for sampling later. If you want to sample from the result, you need a texture instead, and there's no need for a renderbuffer anymore.
Related
const depthTextures = gl => {
const depthTexture = gl.createTexture();
const depthTextureSize = 512;
gl.bindTexture(gl.TEXTURE_2D, depthTexture);
gl.texImage2D(gl.TEXTURE_2D, // target
0, // mip level
gl.DEPTH_COMPONENT, // internal format
depthTextureSize, // width
depthTextureSize, // height
0, // border
gl.DEPTH_COMPONENT, // format
gl.UNSIGNED_INT, // type
null); // data
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
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);
const depthFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, depthFramebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, // target
gl.DEPTH_ATTACHMENT, // attachment point
gl.TEXTURE_2D, // texture target
depthTexture, // texture
0); // mip level
// create a color texture of the same size as the depth texture
// see article why this is needed_
const unusedTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, unusedTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, depthTextureSize, depthTextureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
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); // attach it to the framebuffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, // target
gl.COLOR_ATTACHMENT0, // attachment point
gl.TEXTURE_2D, // texture target
unusedTexture, // texture
0); // mip level
return [depthFramebuffer, unusedTexture];
};
I found
Note: This extension is only available to WebGL1 contexts. In WebGL2,
the functionality of this extension is available on the WebGL2 context
by default. The constant in WebGL2 is gl.UNSIGNED_INT_24_8.
I change DEPTH_COMPONENT with RGBA but still no attaced framebuffer...
In other combination i get :
gl.texImage2D(
gl.TEXTURE_2D, // target
0, // mip level
gl.RGBA, // internal format
depthTextureSize, // width
depthTextureSize, // height
0, // border
gl.RGBA, // format
gl.UNSIGNED_INT_24_8, // type
null); // data
GL_INVALID_OPERATION: Invalid combination of format, type and internalFormat.
GL_INVALID_OPERATION: Only array uniforms may have count > 1.
Any suggestion ?
This is source which i wanna implement in my own already exist glmatrix project...
The internal format of a depth texture cannot be RGBA, it must be one of the size internal formats e.g. (GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F) . If the source format is GL_DEPTH_COMPONENT, the source type must be either FLOAT or one of the unsigned integral types. The internal format must be one of the valid combinations together with the format and type, (see OpenGL ES 3.0 glTexImage2D). Valid textures for an gl.DEPTH_ATTACHMENT are therefore e.g.:
gl.texImage2D(
gl.TEXTURE_2D, 0,
gl.GL_DEPTH_COMPONENT24,
depthTextureSize, depthTextureSize, 0,
gl.GL_DEPTH_COMPONENT, gl.GL_UNSIGNED_INT,
null);
gl.texImage2D(
gl.TEXTURE_2D, 0,
gl.GL_DEPTH_COMPONENT32F,
depthTextureSize, depthTextureSize, 0,
gl.GL_DEPTH_COMPONENT, gl.GL_FLOAT,
null);
Alternatively, you can use a combined depth and stencil texture (in this case it is a gl.DEPTH_STENCIL_ATTACHMENT instead of a gl.DEPTH_ATTACHMENT), e.g:
gl.texImage2D(
gl.TEXTURE_2D, 0,
gl.GL_DEPTH24_STENCIL8,
depthTextureSize, depthTextureSize, 0,
gl.GL_DEPTH_STENCIL, gl.GL_UNSIGNED_INT_24_8,
null);
I'm porting a C++/OpenGL application into WebGL and I'm trying to create and configure a framebuffer.
The framebuffer has 3 textures we can write into of types : vec2, vec2, uint. (gl.RG32F, gl.RG32F, gl.R32UI)
Here is how I initialize the framebuffer :
var gbuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, gbuffer);
var z0_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, z0_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, output_canvas.width, output_canvas.height, 0, gl.RG, gl.FLOAT, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, z0_texture, 0);
var zn_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, zn_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, output_canvas.width, output_canvas.height, 0, gl.RG, gl.FLOAT, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, zn_texture, 0);
var n_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, n_texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32UI, output_canvas.width, output_canvas.height, 0, gl.RED_INTEGER, gl.UNSIGNED_INT, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, n_texture, 0);
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
The framebuffer is incomplete : gl.checkFramebufferStatus(gl.FRAMEBUFFER) returns gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT and shows a warning : Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT1: Attachment has an effective format of RG32F, which is not renderable.
Any idea on what's wrong with my code?
I don't want to render these textures. I am using them in post-processing. That's what I did in C++ but can't do the same in WebGL.
No. You cannot do the same in WebGL.
The error meassage "Attachment has an effective format of RG32F, which is not renderable" - means that gl.RG32F is not a renderable format. Therefore you cannot use it for a framebuffer. You must use a color renderable format. See OpenGL ES 3.0 Specification - Table 3.13 (WebGL 2.0 conforms closely to OpenGL ES 3.0).
You can't do the same thing in WebGL as you can in desktop OpenGL. In desktop OpenGL RG32F is color renderable. However, WebGL is based on OpenGL ES. In OpenGL ES RG32 is not a color renderable format. "color renderable" does not mean that you can render these textures. That means you can render into a texture using this format.
When you only want the color part of the frame, you can store depth in a render buffer.
This works fine for me on both webgl1 and webgl2.
When you also need to use the depth part you can't use a render buffer, you need to store it in a texture.
In webgl1 you need to get an extension to support it.
This also works fine for me in webgl1.
const gl = canvas.getContext('webgl');
const depthTextureExtension = gl.getExtension('WEBGL_depth_texture');
if (!depthTextureExtension) {
alert('Depth textures not supported');
}
This feature should be available by default in webgl2.
Yet when I replace the code above with this:
const gl = canvas.getContext('webgl2');
My code fails to render and I can not find any explanation why.
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
this.depth = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.depth);
checkGLErrors(gl); // OK
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
checkGLErrors(gl); // for webgl2: 1281 INVALID_VALUE
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
this.framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depth, 0);
In WebGL2 DEPTH_COMPONENT is not a valid internal format. Use DEPTH_COMPONENT16, DEPTH_COMPONENT24 or DEPTH_COMPONENT32F
Example from here
const level = 0;
const internalFormat = gl.DEPTH_COMPONENT24;
const border = 0;
const format = gl.DEPTH_COMPONENT;
const type = gl.UNSIGNED_INT;
const data = null;
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
targetTextureWidth, targetTextureHeight, border,
format, type, data);
When opening my (JS HTML5) project in firefox, I get the warning: "Error: WebGL warning: drawArrays: This operation requires zeroing texture data. This is slow."
I have been told it's due to trying to read pixels out of range or something of the sort.
Here's my code:
var gl = Gra.gl
// texture
var tex = gl.createTexture()
gl.bindTexture( gl.TEXTURE_2D, tex )
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, AppImg )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR )
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 )
var bff_pos = BufferFromArr([
-1, -1,
1, -1,
-1, 1,
1, 1
])
var bff_tex = BufferFromArr([
0, 1,
1, 1,
0, 0,
1, 0
])
// buffer
var wd = 200
var ht = 200
// texture
var tex2 = gl.createTexture()
gl.bindTexture( gl.TEXTURE_2D, tex2 )
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, wd, ht, 0, gl.RGBA, gl.UNSIGNED_BYTE, null )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR )
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR )
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 )
// framebuffer
var frame = gl.createFramebuffer()
gl.bindFramebuffer( gl.FRAMEBUFFER, frame )
gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0 )
gl.viewport( 0, 0, wd, ht )
gl.bindTexture( gl.TEXTURE_2D, tex )
gl.bindBuffer( gl.ARRAY_BUFFER, bff_pos )
gl.vertexAttribPointer( Gra.shd_a_pos, 2, gl.FLOAT, 0, 0, 0 )
gl.bindBuffer( gl.ARRAY_BUFFER, bff_tex )
gl.vertexAttribPointer( Gra.shd_a_tex, 2, gl.FLOAT, 0, 0, 0 )
gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 )
gl.bindFramebuffer( gl.FRAMEBUFFER, null )
gl.viewport( 0, 0, Gra.cv.width, Gra.cv.height )
Vertex Shader:
attribute vec2 a_pos;
attribute vec2 a_tex;
varying vec2 v_tex;
void main (void)
{
gl_Position = vec4( a_pos.x, a_pos.y, 1.0, 1.0 );
v_tex = a_tex;
}
Fragment Shader:
precision mediump float;
uniform sampler2D u_smp;
varying vec2 v_tex;
void main (void)
{
gl_FragColor = texture2D( u_smp, vec2( v_tex.x, v_tex.y ) );
}
Here's the live page: http://ssjstash.net/webgl_error
You can also download the source: http://ssjstash.net/webgl_error.zip
I'm not sure exactly what the issue is, thinking it could be a firefox issue.
If anyone is aware of how to fix the problem (if it's fixable) I'd appreciate
It's a nonsense message and Mozilla claims to be fixing or have fixed it
https://bugzilla.mozilla.org/show_bug.cgi?id=1478216
The fix might not have shipped to stable firefox yet
If you'd like to get rid of it don't call gl.texImage2D with null
Why it's nonsense.
If you do this
gl.texImage2D(target, level, format, width, height, 0, format, type, null);
Then the browser will allocate a width * height * format * type size piece of memory, clear it to 0 and pass it to the OpenGL driver. The warning is this allocation and clearing of memory is slow.
The reason the message is nonsense is the only fix possible in JavaScript is actually slower.
The fix would be to allocate a buffer yourself in JavaScript so for example
const zero = new Uint8Array(
width * height * bytesPerPixelForFormatType(format, type));
gl.texImage2D(target, level, format, width, height, 0, format, type, zero);
So what happens in this case? Well, you allocated a buffer the same size the browser would have allocated anyway. That buffer gets zeroed out just as the browser would have anyway, but on top of that you now have a Uint8Array ArrayBufferView the browser had to create. It also had to create the underlying ArrayBuffer, both javascript objects with full prototype chains etc. Those objects have reference counters too which have to be checked by the garbage collector over time to see if and when they are safe to free.
In other words, there much much more work going on when doing this from JavaScript so the warning is nonsense.
I'm working on a WebGL OpenGL ES project that renders my scene to a texture and then uses that texture to render to the window.
I noticed that this causes an odd shimmering on the edges of textures. When I revert the project back to rendering directly to the window the shimmering goes away.
The FBO is set to the same size as the window and the texture is drawn to the window pixel for pixel.
What is causing this to happen? Is it fixable? I am using GL_NEAREST on the FBO texture and GL_LINEAR on all other textures. I'd rather not use GL_CLAMP_TO_EDGE as that would cause other problems.
[
Framebuffer creation
/* Returns true if a framebuffer object is created */
Display.prototype.createFramebuffer = function(name) {
var gl = this.gl; // Sanity Save
var size = 1024;
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
fb.width = size;
fb.height = size;
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
var rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) { return false; }
this.fbo[name] = {fb: fb, rb: rb, tex: tex};
gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
return true;
};
Before drawing scene
/* Draw Geometry */
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo.world.fb); // Enable world framebuffer
gl.viewport(0, 0, this.window.width, this.window.height); // Resize to canvas
gl.clearColor(0.5, 0.5, 0.5, 1.0); // Opaque grey backdrop
After a push in the right direction (and plenty of trial and error) I figured out the problem.
The reason this is happening is because hardware anti-aliasing is disabled when rendering to an FBO texture. In order to fix it you need to implement your own AA.
To fix this for my project I attempted a crude MSAA post shader in combination with upscaling my FBO render to 2x the window resolution and that reduced the shimmering to a nearly unnoticeable level.
FXAA might be another good solution but I couldn't get it to work for me personally.
If there are some better ways to go about this let me know!