-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WebGLNodes: Uniform instance node example (#22504)
* WebGLNodes: Set nodeFrame renderer * add webgl_materials_instance_uniform_nodes example
Showing
4 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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 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,215 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>three.js webgl - material instance uniform</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> - webgl material instance uniform | ||
</div> | ||
|
||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"three": "../build/three.module.js" | ||
} | ||
} | ||
</script> | ||
<script type="module"> | ||
|
||
import * as THREE from 'three'; | ||
|
||
import Stats from './jsm/libs/stats.module.js'; | ||
|
||
import { nodeFrame } from './jsm/renderers/webgl/nodes/WebGLNodes.js'; | ||
import { NodeUpdateType } from './jsm/renderers/nodes/core/constants.js'; | ||
import Node from './jsm/renderers/nodes/core/Node.js'; | ||
import ColorNode from './jsm/renderers/nodes/inputs/ColorNode.js'; | ||
|
||
class InstanceUniformNode extends Node { | ||
|
||
constructor() { | ||
|
||
super( 'vec3' ); | ||
|
||
this.updateType = NodeUpdateType.Object; | ||
|
||
this.inputNode = new ColorNode(); | ||
|
||
} | ||
|
||
update( frame ) { | ||
|
||
const rendererState = frame.renderer.state; | ||
const mesh = frame.object; | ||
|
||
const meshColor = mesh.color; | ||
|
||
this.inputNode.value.copy( meshColor ); | ||
|
||
// force refresh material uniforms | ||
rendererState.useProgram( null ); | ||
|
||
} | ||
|
||
generate( builder, output ) { | ||
|
||
return this.inputNode.build( builder, output ); | ||
|
||
} | ||
|
||
} | ||
|
||
let stats; | ||
|
||
let camera, scene, renderer; | ||
let pointLight; | ||
|
||
const objects = []; | ||
|
||
init(); | ||
animate(); | ||
|
||
function init() { | ||
|
||
const container = document.createElement( 'div' ); | ||
document.body.appendChild( container ); | ||
|
||
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); | ||
camera.position.set( 0, 200, 800 ); | ||
|
||
scene = new THREE.Scene(); | ||
|
||
// Grid | ||
|
||
const helper = new THREE.GridHelper( 1000, 40, 0x303030, 0x303030 ); | ||
helper.position.y = - 75; | ||
scene.add( helper ); | ||
|
||
// Material | ||
|
||
const instanceUniform = new InstanceUniformNode(); | ||
|
||
const material = new THREE.MeshStandardMaterial(); | ||
material.colorNode = instanceUniform; | ||
|
||
// Spheres geometry | ||
|
||
const geometry = new THREE.SphereGeometry( 70, 32, 16 ); | ||
|
||
for ( let i = 0, l = 12; i < l; i ++ ) { | ||
|
||
addMesh( geometry, material ); | ||
|
||
} | ||
|
||
// Lights | ||
|
||
scene.add( new THREE.AmbientLight( 0x111111 ) ); | ||
|
||
const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.125 ); | ||
|
||
directionalLight.position.x = Math.random() - 0.5; | ||
directionalLight.position.y = Math.random() - 0.5; | ||
directionalLight.position.z = Math.random() - 0.5; | ||
directionalLight.position.normalize(); | ||
|
||
scene.add( directionalLight ); | ||
|
||
pointLight = new THREE.PointLight( 0xffffff, 1 ); | ||
scene.add( pointLight ); | ||
|
||
pointLight.add( new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) ) ); | ||
|
||
// | ||
|
||
renderer = new THREE.WebGLRenderer( { antialias: true } ); | ||
renderer.setPixelRatio( window.devicePixelRatio ); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
container.appendChild( renderer.domElement ); | ||
|
||
// | ||
|
||
stats = new Stats(); | ||
container.appendChild( stats.dom ); | ||
|
||
// | ||
|
||
window.addEventListener( 'resize', onWindowResize ); | ||
|
||
} | ||
|
||
function addMesh( geometry, material ) { | ||
|
||
const mesh = new THREE.Mesh( geometry, material ); | ||
|
||
mesh.color = new THREE.Color( Math.random() * 0xffffff ); | ||
|
||
mesh.position.x = ( objects.length % 4 ) * 200 - 400; | ||
mesh.position.z = Math.floor( objects.length / 4 ) * 200 - 200; | ||
|
||
mesh.rotation.x = Math.random() * 200 - 100; | ||
mesh.rotation.y = Math.random() * 200 - 100; | ||
mesh.rotation.z = Math.random() * 200 - 100; | ||
|
||
objects.push( mesh ); | ||
|
||
scene.add( mesh ); | ||
|
||
} | ||
|
||
function onWindowResize() { | ||
|
||
camera.aspect = window.innerWidth / window.innerHeight; | ||
camera.updateProjectionMatrix(); | ||
|
||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
} | ||
|
||
// | ||
|
||
function animate() { | ||
|
||
requestAnimationFrame( animate ); | ||
|
||
nodeFrame.update(); | ||
|
||
render(); | ||
stats.update(); | ||
|
||
} | ||
|
||
function render() { | ||
|
||
const timer = 0.0001 * Date.now(); | ||
|
||
camera.position.x = Math.cos( timer ) * 1000; | ||
camera.position.z = Math.sin( timer ) * 1000; | ||
|
||
camera.lookAt( scene.position ); | ||
|
||
for ( let i = 0, l = objects.length; i < l; i ++ ) { | ||
|
||
const object = objects[ i ]; | ||
|
||
object.rotation.x += 0.01; | ||
object.rotation.y += 0.005; | ||
|
||
} | ||
|
||
pointLight.position.x = Math.sin( timer * 7 ) * 300; | ||
pointLight.position.y = Math.cos( timer * 5 ) * 400; | ||
pointLight.position.z = Math.cos( timer * 3 ) * 300; | ||
|
||
renderer.render( scene, camera ); | ||
|
||
} | ||
|
||
</script> | ||
|
||
</body> | ||
</html> |