Skip to content

Commit

Permalink
WebGPURenderer: Support multiple render targets (mrdoob#26808)
Browse files Browse the repository at this point in the history
* less var access (mrdoob#26817)

actually use the framebuffer we have cached

update examples

update screenshots

MRT

allow example to run

fix WGSL code

address comments

update screenshot

* remove unused var

* cleanup

---------

Co-authored-by: ycw <ycw7788@gmail.com>
Co-authored-by: aardgoose <angus.sawyer@email.com>
Co-authored-by: sunag <sunagbrasil@gmail.com>
  • Loading branch information
4 people committed Sep 22, 2023
1 parent 309e5f6 commit 2ac424c
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 10 deletions.
6 changes: 5 additions & 1 deletion examples/jsm/nodes/core/OutputStructNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@ class OutputStructNode extends Node {
generate( builder, output ) {

const nodeVar = builder.getVarFromNode( this, this.nodeType );
nodeVar.isOutputStructVar = true;

const propertyName = builder.getPropertyName( nodeVar );

const members = this.members;

const structPrefix = propertyName !== '' ? propertyName + '.' : '';

for ( let i = 0; i < members.length; i++ ) {

const snippet = members[ i ].build( builder, output );

builder.addLineFlowCode( `${propertyName}.m${i} = ${snippet}` );
builder.addLineFlowCode( `${structPrefix}m${i} = ${snippet}` );

}

Expand Down
30 changes: 28 additions & 2 deletions examples/jsm/renderers/webgl/WebGLBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,26 @@ class WebGLBackend extends Backend {

const clearColor = renderContext.clearColorValue;

gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a );
gl.clear( clear );
if ( clear !== 0 ) {

if ( renderContext.textures === null ) {

gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a );
gl.clear( clear );

} else {

for ( let i = 0; i < renderContext.textures.length; i ++ ) {

gl.clearBufferfv( gl.COLOR, i, [ clearColor.r, clearColor.g, clearColor.b, clearColor.a ] );

}

gl.clearBufferfi( gl.DEPTH_STENCIL, 0, 1, 1 );

}

}

//

Expand Down Expand Up @@ -638,15 +656,23 @@ class WebGLBackend extends Backend {

const textures = renderContext.textures;

const drawBuffers = [];

for ( let i = 0; i < textures.length; i++ ) {

const texture = textures[ i ];
const { textureGPU } = this.get( texture );

const attachment = gl.COLOR_ATTACHMENT0 + i;

gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, textureGPU, 0 );

drawBuffers.push( attachment );

}

gl.drawBuffers( drawBuffers );

if ( renderContext.depthTexture !== null ) {

const { textureGPU } = this.get( renderContext.depthTexture );
Expand Down
66 changes: 62 additions & 4 deletions examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ class GLSLNodeBuilder extends NodeBuilder {

}

getPropertyName( node, shaderStage ) {

if ( node.isOutputStructVar ) return '';

return super.getPropertyName( node, shaderStage );

}

getTexture( texture, textureProperty, uvSnippet ) {

if ( texture.isTextureCube ) {
Expand Down Expand Up @@ -62,6 +70,8 @@ class GLSLNodeBuilder extends NodeBuilder {

for ( const variable of vars ) {

if ( variable.isOutputStructVar ) continue;

snippets.push( `${ this.getVar( variable.type, variable.name ) };` );

}
Expand Down Expand Up @@ -160,6 +170,49 @@ class GLSLNodeBuilder extends NodeBuilder {

}

getStructMembers( struct ) {

const snippets = [];
const members = struct.getMemberTypes();

for ( let i = 0; i < members.length; i ++ ) {

const member = members[ i ];
snippets.push( `layout( location = ${i} ) out ${ member} m${i};` );

}

return snippets.join( '\n' );

}

getStructs( shaderStage ) {

const snippets = [];
const structs = this.structs[ shaderStage ];

if ( structs.length === 0 ) {

return "layout( location = 0 ) out vec4 fragColor;\n";

}

for ( let index = 0, length = structs.length; index < length; index ++ ) {

const struct = structs[ index ];

let snippet = `\n`;
snippet += this.getStructMembers( struct );
snippet += '\n';

snippets.push( snippet );

}

return snippets.join( '\n\n' );

}

getVaryings( shaderStage ) {

let snippet = '';
Expand Down Expand Up @@ -281,7 +334,7 @@ ${shaderData.varyings}
// codes
${shaderData.codes}
layout( location = 0 ) out vec4 fragColor;
${shaderData.structs}
void main() {
Expand Down Expand Up @@ -330,14 +383,18 @@ void main() {
if ( shaderStage === 'vertex' ) {

flow += 'gl_Position = ';
flow += `${ flowSlotData.result };`;

} else if ( shaderStage === 'fragment' ) {

flow += 'fragColor = ';
if ( ! node.outputNode.isOutputStructNode ) {

}
flow += 'fragColor = ';
flow += `${ flowSlotData.result };`;

flow += `${ flowSlotData.result };`;
}

}

}

Expand All @@ -349,6 +406,7 @@ void main() {
stageData.attributes = this.getAttributes( shaderStage );
stageData.varyings = this.getVaryings( shaderStage );
stageData.vars = this.getVars( shaderStage );
stageData.structs = this.getStructs( shaderStage );
stageData.codes = this.getCodes( shaderStage );
stageData.flow = flow;

Expand Down
Binary file modified examples/screenshots/webgpu_multiple_rendertargets.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions examples/webgpu_multiple_rendertargets.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

import { NodeMaterial, MeshBasicNodeMaterial, mix, modelNormalMatrix, normalGeometry, normalize, outputStruct, step, texture, uniform, uv, varying, vec2, vec4 } from 'three/nodes';
import WebGPU from 'three/addons/capabilities/WebGPU.js';
import WebGL from 'three/addons/capabilities/WebGL.js';

import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';

let camera, scene, renderer, torus;
Expand Down Expand Up @@ -101,11 +103,11 @@

function init() {

if ( WebGPU.isAvailable() === false ) {
if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) {

document.body.appendChild( WebGPU.getErrorMessage() );

throw new Error( 'No WebGPU support' );
throw new Error( 'No WebGPU or WebGL2 support' );

}

Expand Down
1 change: 0 additions & 1 deletion test/e2e/puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ const exceptionList = [
'webgpu_materials',
'webgpu_materials_video',
'webgpu_morphtargets',
"webgpu_multiple_rendertargets",
'webgpu_occlusion',
'webgpu_particles',
'webgpu_sandbox',
Expand Down

0 comments on commit 2ac424c

Please sign in to comment.