|
@@ -71,6 +71,8 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
//
|
|
|
|
|
|
+ //
|
|
|
+
|
|
|
renderContextData.previousContext = this._currentContext;
|
|
|
this._currentContext = renderContext;
|
|
|
|
|
@@ -79,7 +81,6 @@ class WebGLBackend extends Backend {
|
|
|
this.clear( renderContext.clearColor, renderContext.clearDepth, renderContext.clearStencil, renderContext );
|
|
|
|
|
|
//
|
|
|
-
|
|
|
if ( renderContext.viewport ) {
|
|
|
|
|
|
this.updateViewport( renderContext );
|
|
@@ -110,11 +111,49 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
finishRender( renderContext ) {
|
|
|
|
|
|
+ const { gl } = this;
|
|
|
const renderContextData = this.get( renderContext );
|
|
|
const previousContext = renderContextData.previousContext;
|
|
|
|
|
|
this._currentContext = previousContext;
|
|
|
|
|
|
+
|
|
|
+ if ( renderContext.textures !== null && renderContext.renderTarget ) {
|
|
|
+
|
|
|
+ const renderTargetContextData = this.get( renderContext.renderTarget );
|
|
|
+
|
|
|
+ const { samples, stencilBuffer } = renderContext.renderTarget;
|
|
|
+ const fb = renderTargetContextData.framebuffer;
|
|
|
+
|
|
|
+ if ( samples > 0 ) {
|
|
|
+
|
|
|
+ const invalidationArray = [];
|
|
|
+ const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
|
|
|
+
|
|
|
+ invalidationArray.push( gl.COLOR_ATTACHMENT0 );
|
|
|
+
|
|
|
+ if ( renderTargetContextData.depthBuffer ) {
|
|
|
+
|
|
|
+ invalidationArray.push( depthStyle );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO For loop support MRT
|
|
|
+ const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer;
|
|
|
+
|
|
|
+ gl.bindFramebuffer( gl.READ_FRAMEBUFFER, msaaFrameBuffer );
|
|
|
+ gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb );
|
|
|
+
|
|
|
+
|
|
|
+ gl.blitFramebuffer( 0, 0, renderContext.width, renderContext.height, 0, 0, renderContext.width, renderContext.height, gl.COLOR_BUFFER_BIT, gl.NEAREST );
|
|
|
+
|
|
|
+ gl.invalidateFramebuffer( gl.READ_FRAMEBUFFER, invalidationArray );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
if ( previousContext !== null ) {
|
|
|
|
|
|
this._setFramebuffer( previousContext );
|
|
@@ -133,6 +172,9 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ this._currentContext = renderContext;
|
|
|
+
|
|
|
const occlusionQueryCount = renderContext.occlusionQueryCount;
|
|
|
|
|
|
if ( occlusionQueryCount > 0 ) {
|
|
@@ -151,6 +193,7 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
}
|
|
|
|
|
|
resolveOccludedAsync( renderContext ) {
|
|
@@ -312,7 +355,7 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
draw( renderObject, info ) {
|
|
|
|
|
|
- const { pipeline, material, context } = renderObject;
|
|
|
+ const { pipeline, material, context, isRenderObject } = renderObject;
|
|
|
const { programGPU, vaoGPU } = this.get( pipeline );
|
|
|
|
|
|
const { gl, state } = this;
|
|
@@ -321,6 +364,13 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
//
|
|
|
|
|
|
+ if ( isRenderObject ) {
|
|
|
+
|
|
|
+ // we need to bind the framebuffer per object in multi pass pipeline
|
|
|
+ this._setFramebuffer( context );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
const bindings = renderObject.getBindings();
|
|
|
|
|
|
for ( const binding of bindings ) {
|
|
@@ -334,8 +384,7 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
} else if ( binding.isSampledTexture ) {
|
|
|
|
|
|
- gl.activeTexture( gl.TEXTURE0 + index );
|
|
|
- gl.bindTexture( bindingData.glTextureType, bindingData.textureGPU );
|
|
|
+ state.bindTexture( bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -391,7 +440,20 @@ class WebGLBackend extends Backend {
|
|
|
else if ( object.isLineSegments ) mode = gl.LINES;
|
|
|
else if ( object.isLine ) mode = gl.LINE_STRIP;
|
|
|
else if ( object.isLineLoop ) mode = gl.LINE_LOOP;
|
|
|
- else mode = gl.TRIANGLES;
|
|
|
+ else {
|
|
|
+
|
|
|
+ if ( material.wireframe === true ) {
|
|
|
+
|
|
|
+ state.setLineWidth( material.wireframeLinewidth * this.renderer.getPixelRatio() );
|
|
|
+ mode = gl.LINES;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ mode = gl.TRIANGLES;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
//
|
|
|
|
|
@@ -482,6 +544,7 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
destroyTexture( texture ) {
|
|
|
|
|
|
this.textureUtils.destroyTexture( texture );
|
|
@@ -794,100 +857,107 @@ class WebGLBackend extends Backend {
|
|
|
|
|
|
copyFramebufferToTexture( texture, renderContext ) {
|
|
|
|
|
|
- const { gl } = this;
|
|
|
+ this.textureUtils.copyFramebufferToTexture( texture, renderContext );
|
|
|
|
|
|
- const { textureGPU } = this.get( texture );
|
|
|
+ }
|
|
|
|
|
|
- const width = texture.image.width;
|
|
|
- const height = texture.image.height;
|
|
|
+ _setFramebuffer( renderContext ) {
|
|
|
|
|
|
- gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
|
|
|
+ const { gl, state } = this;
|
|
|
|
|
|
- if ( texture.isDepthTexture ) {
|
|
|
+ let fb = null;
|
|
|
+ let currentFrameBuffer = null;
|
|
|
|
|
|
- const fb = gl.createFramebuffer();
|
|
|
+ if ( renderContext.textures !== null ) {
|
|
|
|
|
|
- gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb );
|
|
|
+ const renderTargetContextData = this.get( renderContext.renderTarget );
|
|
|
+ const { samples } = renderContext.renderTarget;
|
|
|
|
|
|
- gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureGPU, 0 );
|
|
|
+ fb = renderTargetContextData.framebuffer;
|
|
|
+ let msaaFb = renderTargetContextData.msaaFrameBuffer;
|
|
|
+ let depthRenderbuffer = renderTargetContextData.depthRenderbuffer;
|
|
|
|
|
|
- gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, gl.DEPTH_BUFFER_BIT, gl.NEAREST );
|
|
|
|
|
|
- gl.deleteFramebuffer( fb );
|
|
|
+ if ( fb === undefined ) {
|
|
|
|
|
|
+ fb = gl.createFramebuffer();
|
|
|
|
|
|
- } else {
|
|
|
+ state.bindFramebuffer( gl.FRAMEBUFFER, fb );
|
|
|
|
|
|
- gl.bindTexture( gl.TEXTURE_2D, textureGPU );
|
|
|
- gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height );
|
|
|
+ const textures = renderContext.textures;
|
|
|
|
|
|
- gl.bindTexture( gl.TEXTURE_2D, null );
|
|
|
+ for ( let i = 0; i < textures.length; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
+ const texture = textures[ i ];
|
|
|
+ const textureData = this.get( texture );
|
|
|
+ textureData.renderTarget = renderContext.renderTarget;
|
|
|
|
|
|
- if ( texture.generateMipmaps ) this.generateMipmaps( texture );
|
|
|
+ const attachment = gl.COLOR_ATTACHMENT0 + i;
|
|
|
|
|
|
- this._setFramebuffer( renderContext );
|
|
|
|
|
|
- }
|
|
|
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 );
|
|
|
|
|
|
- _setFramebuffer( renderContext ) {
|
|
|
+ }
|
|
|
|
|
|
- const { gl } = this;
|
|
|
+ if ( renderContext.depthTexture !== null ) {
|
|
|
|
|
|
- if ( renderContext.textures !== null ) {
|
|
|
+ const textureData = this.get( renderContext.depthTexture );
|
|
|
|
|
|
- const renderContextData = this.get( renderContext.renderTarget );
|
|
|
+ gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureData.textureGPU, 0 );
|
|
|
|
|
|
- let fb = renderContextData.framebuffer;
|
|
|
+ }
|
|
|
|
|
|
- if ( fb === undefined ) {
|
|
|
|
|
|
- fb = gl.createFramebuffer();
|
|
|
+ renderTargetContextData.framebuffer = fb;
|
|
|
|
|
|
- gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
|
|
|
+ state.drawBuffers( renderContext, fb );
|
|
|
|
|
|
- const textures = renderContext.textures;
|
|
|
+ }
|
|
|
|
|
|
- const drawBuffers = [];
|
|
|
+ if ( samples > 0 ) {
|
|
|
|
|
|
- for ( let i = 0; i < textures.length; i ++ ) {
|
|
|
+ if ( msaaFb === undefined ) {
|
|
|
|
|
|
- const texture = textures[ i ];
|
|
|
- const { textureGPU } = this.get( texture );
|
|
|
+ msaaFb = gl.createFramebuffer();
|
|
|
|
|
|
- const attachment = gl.COLOR_ATTACHMENT0 + i;
|
|
|
+ state.bindFramebuffer( gl.FRAMEBUFFER, msaaFb );
|
|
|
|
|
|
- gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, textureGPU, 0 );
|
|
|
+ // TODO For loop support MRT
|
|
|
+ const msaaRenderbuffer = gl.createRenderbuffer();
|
|
|
+ gl.bindRenderbuffer( gl.RENDERBUFFER, msaaRenderbuffer );
|
|
|
|
|
|
- drawBuffers.push( attachment );
|
|
|
+ const texture = renderContext.textures[ 0 ];
|
|
|
+ const textureData = this.get( texture );
|
|
|
|
|
|
- }
|
|
|
+ gl.renderbufferStorageMultisample( gl.RENDERBUFFER, samples, textureData.glInternalFormat, renderContext.width, renderContext.height );
|
|
|
+ gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msaaRenderbuffer );
|
|
|
|
|
|
- gl.drawBuffers( drawBuffers );
|
|
|
+ renderTargetContextData.msaaRenderbuffer = msaaRenderbuffer;
|
|
|
+ renderTargetContextData.msaaFrameBuffer = msaaFb;
|
|
|
|
|
|
- if ( renderContext.depthTexture !== null ) {
|
|
|
+ if ( depthRenderbuffer === undefined ) {
|
|
|
|
|
|
- const { textureGPU } = this.get( renderContext.depthTexture );
|
|
|
+ depthRenderbuffer = gl.createRenderbuffer();
|
|
|
+ this.textureUtils.setupRenderBufferStorage( depthRenderbuffer, renderContext );
|
|
|
|
|
|
- gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureGPU, 0 );
|
|
|
+ renderTargetContextData.depthRenderbuffer = depthRenderbuffer;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- renderContextData.framebuffer = fb;
|
|
|
+ currentFrameBuffer = renderTargetContextData.msaaFrameBuffer;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
|
|
|
+ currentFrameBuffer = fb;
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
-
|
|
|
- gl.bindFramebuffer( gl.FRAMEBUFFER, null );
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+ state.bindFramebuffer( gl.FRAMEBUFFER, currentFrameBuffer );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|