-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Examples: Added webgpu_multiple_rendertargets_readback
#28211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
3fed696
Add new example and update files.json
Spiri0 53b2199
Update files.json
Spiri0 6a1958f
Update webgpu_mrt_readback.html
Spiri0 b29b659
Update webgpu_mrt_readback.html
Spiri0 9b829e6
Update webgpu_mrt_readback.html
Spiri0 36be5ba
Update webgpu_mrt_readback.html
Spiri0 1da31f6
Update webgpu_mrt_readback.html
Spiri0 cc2ed16
Update webgpu_mrt_readback.html
Spiri0 fa22784
Update webgpu_mrt_readback.html
Spiri0 1a93f26
Update webgpu_mrt_readback.html
Spiri0 3ab68fe
Merge branch 'dev' into pr/28211
sunag b221a7f
reuse texture() node
sunag b35411f
revision
sunag 7696c8f
cleanup
sunag b767a9c
cleanup
sunag c7e0f3e
cleanup
sunag bb9a281
added info
sunag 7eb4566
rename webgpu_mrt_readback -> webgpu_multiple_rendertargets_readback
sunag 836296a
add tags
sunag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,256 @@ | ||
| <html lang="en"> | ||
| <head> | ||
| <title>three.js - WebGPU - MultipleRenderTargets with GPU ReadBack</title> | ||
| <meta charset="utf-8"> | ||
| <link rel="shortcut icon" href="#"> | ||
| <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
| <link type="text/css" rel="stylesheet" href="main.css"> | ||
| </head> | ||
| <body> | ||
|
|
||
|
|
||
| <script type="importmap"> | ||
| { | ||
| "imports": { | ||
| "three": "../build/three.module.js", | ||
| "three/addons/": "./jsm/", | ||
| "three/nodes": "./jsm/nodes/Nodes.js" | ||
| } | ||
| } | ||
| </script> | ||
|
|
||
| <script type="module"> | ||
|
|
||
| import * as THREE from 'three'; | ||
|
|
||
| import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | ||
| import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; | ||
|
|
||
| import { MeshBasicNodeMaterial, NodeMaterial, mix, modelNormalMatrix, normalGeometry, normalize, outputStruct, step, texture, uniform, uv, varying, vec2, vec4, attribute } 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'; | ||
|
|
||
| import QuadMesh from 'three/addons/objects/QuadMesh.js'; | ||
|
|
||
| let camera, scene, renderer, torus; | ||
| let quadMesh, renderTarget, readbackTarget, material, readbackMaterial, pixelBuffer, pixelBufferTexture; | ||
|
|
||
| const gui = new GUI(); | ||
|
|
||
| const options = { | ||
| selection: 'mrt', | ||
| }; | ||
|
|
||
| gui.add( options, 'selection', [ 'mrt', 'diffuse', 'normal' ] ); | ||
|
|
||
| class WriteGBufferMaterial extends NodeMaterial { | ||
|
|
||
| constructor( diffuseTexture ) { | ||
|
|
||
| super(); | ||
|
|
||
| this.lights = false; | ||
| this.fog = false; | ||
| this.colorSpaced = false; | ||
|
|
||
| this.diffuseTexture = diffuseTexture; | ||
|
|
||
| const vUv = varying( uv() ); | ||
|
|
||
| const transformedNormal = modelNormalMatrix.mul( normalGeometry ); | ||
| const vNormal = varying( normalize( transformedNormal ) ); | ||
|
|
||
| const repeat = uniform( vec2( 5, 0.5 ) ); | ||
|
|
||
| const gColor = texture( this.diffuseTexture, vUv.mul( repeat ) ); | ||
| const gNormal = vec4( normalize( vNormal ), 1.0 ); | ||
|
|
||
| this.fragmentNode = outputStruct( gColor, gNormal ); | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| class ReadGBufferMaterial extends NodeMaterial { | ||
|
|
||
| constructor( tDiffuse, tNormal ) { | ||
|
|
||
| super(); | ||
|
|
||
| this.lights = false; | ||
| this.fog = false; | ||
|
|
||
| const vUv = varying( uv() ); | ||
|
|
||
| const diffuse = texture( tDiffuse, vUv ); | ||
| const normal = texture( tNormal, vUv ); | ||
|
|
||
| this.fragmentNode = mix( diffuse, normal, step( 0.5, vUv.x ) ); | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| init(); | ||
|
|
||
| function init() { | ||
|
|
||
| if ( WebGPU.isAvailable() === false && WebGL.isWebGL2Available() === false ) { | ||
|
|
||
| document.body.appendChild( WebGPU.getErrorMessage() ); | ||
|
|
||
| throw new Error( 'No WebGPU or WebGL2 support' ); | ||
|
|
||
| } | ||
|
|
||
| renderer = new WebGPURenderer( { antialias: true } ); | ||
| renderer.setPixelRatio( window.devicePixelRatio ); | ||
| renderer.setSize( window.innerWidth, window.innerHeight ); | ||
| renderer.setAnimationLoop( render ); | ||
| document.body.appendChild( renderer.domElement ); | ||
|
|
||
| // Create a multi render target with Float buffers | ||
|
|
||
| renderTarget = new THREE.RenderTarget( | ||
| window.innerWidth * window.devicePixelRatio, | ||
| window.innerHeight * window.devicePixelRatio, | ||
| { count: 2, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter } | ||
| ); | ||
|
|
||
| // Name our G-Buffer attachments for debugging | ||
|
|
||
| renderTarget.textures[ 0 ].name = 'diffuse'; | ||
| renderTarget.textures[ 1 ].name = 'normal'; | ||
|
|
||
|
|
||
| // Init readback render target, readback data texture, readback material | ||
| // Be careful with the size! 512 is already big. Reading data back from the GPU is computationally intensive | ||
|
|
||
| const size = 512; | ||
|
|
||
| readbackTarget = new THREE.RenderTarget( size, size, { count: 2 } ); | ||
|
|
||
| pixelBuffer = new Uint8Array( size ** 2 * 4 ).fill( 0 ); | ||
| pixelBufferTexture = new THREE.DataTexture( pixelBuffer, size, size ); | ||
| pixelBufferTexture.type = THREE.UnsignedByteType; | ||
| pixelBufferTexture.format = THREE.RGBAFormat; | ||
|
|
||
| readbackMaterial = new MeshBasicNodeMaterial(); | ||
| readbackMaterial.colorNode = texture(); | ||
|
|
||
|
|
||
| // Scene setup | ||
|
|
||
| scene = new THREE.Scene(); | ||
| scene.background = new THREE.Color( 0x222222 ); | ||
|
|
||
| camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 50 ); | ||
| camera.position.z = 4; | ||
|
|
||
|
|
||
| const loader = new THREE.TextureLoader(); | ||
|
|
||
| const diffuse = loader.load( 'textures/hardwood2_diffuse.jpg' ); | ||
| diffuse.colorSpace = THREE.SRGBColorSpace; | ||
| diffuse.wrapS = THREE.RepeatWrapping; | ||
| diffuse.wrapT = THREE.RepeatWrapping; | ||
|
|
||
| torus = new THREE.Mesh( | ||
| new THREE.TorusKnotGeometry( 1, 0.3, 128, 32 ), | ||
| new WriteGBufferMaterial( diffuse ) | ||
| ); | ||
|
|
||
| scene.add( torus ); | ||
|
|
||
|
|
||
| material = new ReadGBufferMaterial( renderTarget.textures[ 0 ], renderTarget.textures[ 1 ] ); | ||
| quadMesh = new QuadMesh( material ); | ||
|
|
||
| // Controls | ||
|
|
||
| new OrbitControls( camera, renderer.domElement ); | ||
|
|
||
| window.addEventListener( 'resize', onWindowResize ); | ||
|
|
||
| } | ||
|
|
||
| function onWindowResize() { | ||
|
|
||
| camera.aspect = window.innerWidth / window.innerHeight; | ||
| camera.updateProjectionMatrix(); | ||
|
|
||
| renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
|
||
| const dpr = renderer.getPixelRatio(); | ||
| renderTarget.setSize( window.innerWidth * dpr, window.innerHeight * dpr ); | ||
|
|
||
| } | ||
|
|
||
| async function render( time ) { | ||
|
|
||
| torus.rotation.y = ( time / 1000 ) * .4; | ||
|
|
||
| // render scene into target | ||
| renderer.setRenderTarget( renderTarget ); | ||
| renderer.render( scene, camera ); | ||
|
|
||
| // render post FX | ||
| renderer.setRenderTarget( null ); | ||
|
|
||
| if ( options.selection === 'mrt' ) { | ||
|
|
||
| quadMesh.material = material; | ||
|
|
||
| } else { | ||
|
|
||
| await readback(); | ||
|
|
||
| } | ||
|
|
||
| quadMesh.render( renderer ); | ||
|
|
||
| } | ||
|
|
||
| async function readback() { | ||
|
|
||
| renderer.setRenderTarget( readbackTarget ); | ||
| renderer.render( scene, camera ); | ||
| renderer.setRenderTarget( null ); | ||
|
|
||
| const width = readbackTarget.width; | ||
| const height = readbackTarget.height; | ||
|
|
||
| const selection = options.selection; | ||
|
|
||
| if ( selection === 'diffuse' ) { | ||
|
|
||
| pixelBuffer = await renderer.readRenderTargetPixelsAsync( readbackTarget, 0, 0, width, height, 0 ); //zero is optional | ||
|
|
||
| pixelBufferTexture.image.data = pixelBuffer; | ||
| pixelBufferTexture.needsUpdate = true; | ||
|
|
||
| readbackMaterial.colorNode.value = pixelBufferTexture; | ||
|
|
||
| quadMesh.material = readbackMaterial; | ||
|
|
||
| } else if ( selection === 'normal' ) { | ||
|
|
||
| pixelBuffer = await renderer.readRenderTargetPixelsAsync( readbackTarget, 0, 0, width, height, 1 ); | ||
|
|
||
| pixelBufferTexture.image.data = pixelBuffer; | ||
| pixelBufferTexture.needsUpdate = true; | ||
|
|
||
| readbackMaterial.colorNode.value = pixelBufferTexture; | ||
|
|
||
| quadMesh.material = readbackMaterial; | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| </script> | ||
|
|
||
| </body> | ||
| </html> | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.