Explorar o código

Nodes: iridescence (#24401)

* Nodes: add support for iridescence

* add example nodes iridescence
sunag %!s(int64=3) %!d(string=hai) anos
pai
achega
37d0263ca6

+ 1 - 0
examples/files.json

@@ -228,6 +228,7 @@
 		"webgl_water_flowmap"
 	],
 	"webgl / nodes": [
+		"webgl_nodes_loader_gltf_iridescence",
 		"webgl_nodes_loader_gltf_sheen",
 		"webgl_nodes_materials_instance_uniform",
 		"webgl_nodes_materials_physical_clearcoat",

+ 8 - 0
examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js

@@ -19,6 +19,10 @@ export default class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 		this.sheenNode = null;
 		this.sheenRoughnessNode = null;
 
+		this.iridescenceNode = null;
+		this.iridescenceIORNode = null;
+		this.iridescenceThicknessNode = null;
+
 		this.sheen = 0;
 		this.clearcoat = 0;
 		this.iridescence = 0;
@@ -39,6 +43,10 @@ export default class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
 		this.sheenNode = source.sheenNode;
 		this.sheenRoughnessNode = source.sheenRoughnessNode;
 
+		this.iridescenceNode = source.iridescenceNode;
+		this.iridescenceIORNode = source.iridescenceIORNode;
+		this.iridescenceThicknessNode = source.iridescenceThicknessNode;
+
 		return super.copy( source );
 
 	}

+ 21 - 15
examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js

@@ -176,23 +176,29 @@ class WebGLNodeBuilder extends NodeBuilder {
 
 			}
 
-		}
+			if ( material.iridescenceNode && material.iridescenceNode.isNode ) {
 
-		if ( material.iridescenceNode && material.iridescenceNode.isNode ) {
+				this.addSlot( 'fragment', new SlotNode( material.iridescenceNode, 'IRIDESCENCE', 'float' ) );
 
-			this.addSlot( 'fragment', new SlotNode( material.iridescenceNode, 'IRIDESCENCE', 'float' ) );
+				if ( material.iridescenceIORNode && material.iridescenceIORNode.isNode ) {
 
-		}
+					this.addSlot( 'fragment', new SlotNode( material.iridescenceIORNode, 'IRIDESCENCE_IOR', 'float' ) );
 
-		if ( material.iridescenceIORNode && material.iridescenceIORNode.isNode ) {
+				}
 
-			this.addSlot( 'fragment', new SlotNode( material.iridescenceIORNode, 'IRIDESCENCE_IOR', 'float' ) );
+				if ( material.iridescenceThicknessNode && material.iridescenceThicknessNode.isNode ) {
 
-		}
+					this.addSlot( 'fragment', new SlotNode( material.iridescenceThicknessNode, 'IRIDESCENCE_THICKNESS', 'float' ) );
+
+				}
+
+				material.defines.USE_IRIDESCENCE = '';
+
+			} else {
 
-		if ( material.iridescenceThicknessNode && material.iridescenceThicknessNode.isNode ) {
+				delete material.defines.USE_IRIDESCENCE;
 
-			this.addSlot( 'fragment', new SlotNode( material.iridescenceThicknessNode, 'IRIDESCENCE_THICKNESS', 'float' ) );
+			}
 
 		}
 
@@ -597,9 +603,9 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
 
 		if ( iridescenceNode !== undefined ) {
 
-			this.addCodeAfterInclude(
+			this.addCodeAfterSnippet(
 				'fragment',
-				'iridescence_fragment',
+				'material.iridescence = iridescence;',
 				`${iridescenceNode.code}\n\tmaterial.iridescence = ${iridescenceNode.result};`
 			);
 
@@ -607,9 +613,9 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
 
 		if ( iridescenceIORNode !== undefined ) {
 
-			this.addCodeAfterInclude(
+			this.addCodeAfterSnippet(
 				'fragment',
-				'iridescence_fragment',
+				'material.iridescenceIOR = iridescenceIOR;',
 				`${iridescenceIORNode.code}\n\tmaterial.iridescenceIOR = ${iridescenceIORNode.result};`
 			);
 
@@ -617,9 +623,9 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
 
 		if ( iridescenceThicknessNode !== undefined ) {
 
-			this.addCodeAfterInclude(
+			this.addCodeAfterSnippet(
 				'fragment',
-				'iridescence_fragment',
+				'material.iridescenceThickness = iridescenceThicknessMaximum;',
 				`${iridescenceThicknessNode.code}\n\tmaterial.iridescenceThickness = ${iridescenceThicknessNode.result};`
 			);
 

BIN=BIN
examples/screenshots/webgl_nodes_loader_gltf_iridescence.jpg


+ 137 - 0
examples/webgl_nodes_loader_gltf_iridescence.html

@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - GLTFloader + Iridescence + Nodes</title>
+		<meta charset="utf-8">
+		<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>
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - GLTFLoader + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence" target="_blank" rel="noopener">KHR_materials_iridescence</a> + Nodes<br />
+			Iridescence Lamp from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/IridescenceLamp" target="_blank" rel="noopener">glTF-Sample-Models</a><br />
+			<a href="https://hdrihaven.com/hdri/?h=venice_sunset" target="_blank" rel="noopener">Venice Sunset</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+		</div>
+
+		<!-- Import maps polyfill -->
+		<!-- Remove this when import maps will be widely supported -->
+		<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
+
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.module.js",
+					"three-nodes/": "./jsm/nodes/"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+
+			import { NodeMaterial, uv, add, mul, vec2, checker, float, timerLocal } from 'three-nodes/Nodes.js';
+
+			import { nodeFrame } from './jsm/renderers/webgl/nodes/WebGLNodes.js';
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
+			import { RGBELoader } from './jsm/loaders/RGBELoader.js';
+
+			let renderer, scene, camera, controls;
+
+			init().catch( function ( err ) {
+
+				console.error( err );
+
+			} );
+
+			async function init() {
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.outputEncoding = THREE.sRGBEncoding;
+				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.setAnimationLoop( render );
+				document.body.appendChild( renderer.domElement );
+
+				scene = new THREE.Scene();
+
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.25, 20 );
+				camera.position.set( 0.35, 0.05, 0.35 );
+
+				controls = new OrbitControls( camera, renderer.domElement );
+				controls.addEventListener( 'change', render );
+				controls.target.set( 0, 0.2, 0 );
+				controls.update();
+
+				const rgbeLoader = new RGBELoader()
+					.setPath( 'textures/equirectangular/' );
+
+				const gltfLoader = new GLTFLoader().setPath( 'models/gltf/' );
+
+				const [ texture, gltf ] = await Promise.all( [
+					rgbeLoader.loadAsync( 'venice_sunset_1k.hdr' ),
+					gltfLoader.loadAsync( 'IridescenceLamp.glb' ),
+				] );
+
+				// nodes
+
+				gltf.scene.traverse( mesh => {
+
+					const material = mesh.material;
+
+					if ( material && material.iridescence > 0 ) {
+
+						const iridescenceFactorNode = checker( mul( add( uv(), vec2( timerLocal( - .05 ), 0 ) ), 20 ) );
+
+						const nodeMaterial = NodeMaterial.fromMaterial( material );
+						nodeMaterial.iridescenceNode = iridescenceFactorNode;
+						nodeMaterial.iridescenceIORNode = float( 1.3 );
+						nodeMaterial.iridescenceThicknessNode = float( 400 );
+
+						mesh.material = nodeMaterial;
+
+					}
+
+				} );
+
+				// environment
+
+				texture.mapping = THREE.EquirectangularReflectionMapping;
+
+				scene.background = texture;
+				scene.environment = texture;
+
+				// model
+
+				scene.add( gltf.scene );
+
+				window.addEventListener( 'resize', onWindowResize );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function render() {
+
+				nodeFrame.update();
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>