|
@@ -25,14 +25,14 @@
|
|
|
<script type="module">
|
|
|
|
|
|
import * as THREE from 'three';
|
|
|
- import { mix, modelNormalMatrix, normalGeometry, normalize, outputStruct, step, texture, uniform, uv, varying, vec2, vec4 } from 'three/tsl';
|
|
|
+ import { mix, step, texture, viewportTopLeft, mrt, output, transformedNormalWorld, uv, vec2 } from 'three/tsl';
|
|
|
|
|
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
|
|
|
|
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
|
|
|
|
|
let camera, scene, renderer, torus;
|
|
|
- let quadMesh, renderTarget, readbackTarget, material, readbackMaterial, pixelBuffer, pixelBufferTexture;
|
|
|
+ let quadMesh, sceneMRT, renderTarget, readbackTarget, material, readbackMaterial, pixelBuffer, pixelBufferTexture;
|
|
|
|
|
|
const gui = new GUI();
|
|
|
|
|
@@ -42,54 +42,6 @@
|
|
|
|
|
|
gui.add( options, 'selection', [ 'mrt', 'diffuse', 'normal' ] );
|
|
|
|
|
|
- class WriteGBufferMaterial extends THREE.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 THREE.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() {
|
|
@@ -110,10 +62,9 @@
|
|
|
|
|
|
// Name our G-Buffer attachments for debugging
|
|
|
|
|
|
- renderTarget.textures[ 0 ].name = 'diffuse';
|
|
|
+ renderTarget.textures[ 0 ].name = 'output';
|
|
|
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
|
|
|
|
|
@@ -129,8 +80,14 @@
|
|
|
readbackMaterial = new THREE.MeshBasicNodeMaterial();
|
|
|
readbackMaterial.colorNode = texture( pixelBufferTexture );
|
|
|
|
|
|
+ // MRT
|
|
|
|
|
|
- // Scene setup
|
|
|
+ sceneMRT = mrt( {
|
|
|
+ 'output': output,
|
|
|
+ 'normal': transformedNormalWorld
|
|
|
+ } );
|
|
|
+
|
|
|
+ // Scene
|
|
|
|
|
|
scene = new THREE.Scene();
|
|
|
scene.background = new THREE.Color( 0x222222 );
|
|
@@ -138,7 +95,6 @@
|
|
|
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' );
|
|
@@ -146,15 +102,17 @@
|
|
|
diffuse.wrapS = THREE.RepeatWrapping;
|
|
|
diffuse.wrapT = THREE.RepeatWrapping;
|
|
|
|
|
|
- torus = new THREE.Mesh(
|
|
|
- new THREE.TorusKnotGeometry( 1, 0.3, 128, 32 ),
|
|
|
- new WriteGBufferMaterial( diffuse )
|
|
|
- );
|
|
|
+ const torusMaterial = new THREE.NodeMaterial();
|
|
|
+ torusMaterial.colorNode = texture( diffuse, uv().mul( vec2( 10, 4 ) ) );
|
|
|
|
|
|
+ torus = new THREE.Mesh( new THREE.TorusKnotGeometry( 1, 0.3, 128, 32 ), torusMaterial );
|
|
|
scene.add( torus );
|
|
|
|
|
|
+ // Output
|
|
|
+
|
|
|
+ material = new THREE.NodeMaterial();
|
|
|
+ material.colorNode = mix( texture( renderTarget.textures[ 0 ] ), texture( renderTarget.textures[ 1 ] ), step( 0.5, viewportTopLeft.x ) );
|
|
|
|
|
|
- material = new ReadGBufferMaterial( renderTarget.textures[ 0 ], renderTarget.textures[ 1 ] );
|
|
|
quadMesh = new THREE.QuadMesh( material );
|
|
|
|
|
|
// Controls
|
|
@@ -183,14 +141,18 @@
|
|
|
|
|
|
torus.rotation.y = ( time / 1000 ) * .4;
|
|
|
|
|
|
+ const isMRT = selection === 'mrt';
|
|
|
+
|
|
|
// render scene into target
|
|
|
- renderer.setRenderTarget( selection === 'mrt' ? renderTarget : readbackTarget );
|
|
|
+ renderer.setMRT( isMRT ? sceneMRT : null );
|
|
|
+ renderer.setRenderTarget( isMRT ? renderTarget : readbackTarget );
|
|
|
renderer.render( scene, camera );
|
|
|
|
|
|
// render post FX
|
|
|
+ renderer.setMRT( null );
|
|
|
renderer.setRenderTarget( null );
|
|
|
|
|
|
- if ( selection === 'mrt' ) {
|
|
|
+ if ( isMRT ) {
|
|
|
|
|
|
quadMesh.material = material;
|
|
|
|