|
@@ -0,0 +1,1320 @@
|
|
|
+<!doctype html>
|
|
|
+<html lang="en">
|
|
|
+ <head>
|
|
|
+ <title>WebGL NodeMaterial</title>
|
|
|
+ <meta charset="utf-8">
|
|
|
+ <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
|
+ <style>
|
|
|
+ body {
|
|
|
+ color: #fff;
|
|
|
+ font-family:Monospace;
|
|
|
+ font-size:13px;
|
|
|
+ margin: 0px;
|
|
|
+ text-align:center;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ #info {
|
|
|
+ color: #fff;
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ display:block;
|
|
|
+ }
|
|
|
+
|
|
|
+ a { color: white }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+
|
|
|
+ <div id="container"></div>
|
|
|
+ <div id="info">
|
|
|
+ <a href="http://threejs.org" target="_blank">three.js</a> - Node-Based Material
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script src="../build/three.min.js"></script>
|
|
|
+
|
|
|
+ <script src='js/geometries/TeapotBufferGeometry.js'></script>
|
|
|
+ <script src="js/controls/OrbitControls.js"></script>
|
|
|
+ <script src="js/libs/dat.gui.min.js"></script>
|
|
|
+
|
|
|
+ <!-- NodeLibrary -->
|
|
|
+ <script src="js/nodes/GLNode.js"></script>
|
|
|
+ <script src="js/nodes/RawNode.js"></script>
|
|
|
+ <script src="js/nodes/TempNode.js"></script>
|
|
|
+ <script src="js/nodes/InputNode.js"></script>
|
|
|
+ <script src="js/nodes/ConstNode.js"></script>
|
|
|
+ <script src="js/nodes/FunctionNode.js"></script>
|
|
|
+ <script src="js/nodes/FunctionCallNode.js"></script>
|
|
|
+ <script src="js/nodes/BuilderNode.js"></script>
|
|
|
+ <script src="js/nodes/LibNode.js"></script>
|
|
|
+ <script src="js/nodes/NodeMaterial.js"></script>
|
|
|
+
|
|
|
+ <!-- Accessors -->
|
|
|
+ <script src="js/nodes/accessors/PositionNode.js"></script>
|
|
|
+ <script src="js/nodes/accessors/NormalNode.js"></script>
|
|
|
+ <script src="js/nodes/accessors/UVNode.js"></script>
|
|
|
+ <script src="js/nodes/accessors/ColorsNode.js"></script>
|
|
|
+ <script src="js/nodes/accessors/CameraNode.js"></script>
|
|
|
+ <script src="js/nodes/accessors/ReflectNode.js"></script>
|
|
|
+
|
|
|
+ <!-- Inputs -->
|
|
|
+ <script src="js/nodes/inputs/IntNode.js"></script>
|
|
|
+ <script src="js/nodes/inputs/FloatNode.js"></script>
|
|
|
+ <script src="js/nodes/inputs/ColorNode.js"></script>
|
|
|
+ <script src="js/nodes/inputs/Vector2Node.js"></script>
|
|
|
+ <script src="js/nodes/inputs/Vector3Node.js"></script>
|
|
|
+ <script src="js/nodes/inputs/Vector4Node.js"></script>
|
|
|
+ <script src="js/nodes/inputs/TextureNode.js"></script>
|
|
|
+ <script src="js/nodes/inputs/CubeTextureNode.js"></script>
|
|
|
+
|
|
|
+ <!-- Math -->
|
|
|
+ <script src="js/nodes/math/Math1Node.js"></script>
|
|
|
+ <script src="js/nodes/math/Math2Node.js"></script>
|
|
|
+ <script src="js/nodes/math/Math3Node.js"></script>
|
|
|
+ <script src="js/nodes/math/OperatorNode.js"></script>
|
|
|
+
|
|
|
+ <!-- Utils -->
|
|
|
+ <script src="js/nodes/utils/SwitchNode.js"></script>
|
|
|
+ <script src="js/nodes/utils/JoinNode.js"></script>
|
|
|
+ <script src="js/nodes/utils/TimeNode.js"></script>
|
|
|
+ <script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
|
|
|
+ <script src="js/nodes/utils/VelocityNode.js"></script>
|
|
|
+
|
|
|
+ <!-- Phong Material -->
|
|
|
+ <script src="js/nodes/materials/PhongNode.js"></script>
|
|
|
+ <script src="js/nodes/materials/PhongNodeMaterial.js"></script>
|
|
|
+
|
|
|
+ <!-- Standard Material -->
|
|
|
+ <script src="js/nodes/materials/StandardNode.js"></script>
|
|
|
+ <script src="js/nodes/materials/StandardNodeMaterial.js"></script>
|
|
|
+
|
|
|
+ <script>
|
|
|
+
|
|
|
+ var container = document.getElementById( 'container' );
|
|
|
+
|
|
|
+ var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
|
|
|
+ var teapot, mesh;
|
|
|
+ var controls;
|
|
|
+ var move = false;
|
|
|
+ var gui, guiElements = [];
|
|
|
+
|
|
|
+ var param = { example: 'standard' };
|
|
|
+
|
|
|
+ var brick = new THREE.TextureLoader().load( 'textures/brick_diffuse.jpg' );
|
|
|
+ var grass = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big.jpg' );
|
|
|
+ var grassNormal = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big-nm.jpg' );
|
|
|
+
|
|
|
+ var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
|
|
|
+ decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
|
|
|
+
|
|
|
+ var cloud = new THREE.TextureLoader().load( 'textures/lava/cloud.png' );
|
|
|
+ cloud.wrapS = cloud.wrapT = THREE.RepeatWrapping;
|
|
|
+
|
|
|
+ var cubemap = function() {
|
|
|
+
|
|
|
+ var path = "textures/cube/Park2/";
|
|
|
+ var format = '.jpg';
|
|
|
+ var urls = [
|
|
|
+ path + 'posx' + format, path + 'negx' + format,
|
|
|
+ path + 'posy' + format, path + 'negy' + format,
|
|
|
+ path + 'posz' + format, path + 'negz' + format
|
|
|
+ ];
|
|
|
+
|
|
|
+ var textureCube = new THREE.CubeTextureLoader().load( urls );
|
|
|
+ textureCube.format = THREE.RGBFormat;
|
|
|
+
|
|
|
+ return textureCube;
|
|
|
+
|
|
|
+ }();
|
|
|
+
|
|
|
+ window.addEventListener( 'load', init );
|
|
|
+
|
|
|
+ function init() {
|
|
|
+
|
|
|
+ renderer = new THREE.WebGLRenderer( { antialias: true } );
|
|
|
+ renderer.setPixelRatio( window.devicePixelRatio );
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+ container.appendChild( renderer.domElement );
|
|
|
+
|
|
|
+ scene = new THREE.Scene();
|
|
|
+
|
|
|
+ camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
|
|
|
+ camera.position.x = 50;
|
|
|
+ camera.position.z = - 50;
|
|
|
+ camera.position.y = 30;
|
|
|
+ camera.target = new THREE.Vector3();
|
|
|
+
|
|
|
+ controls = new THREE.OrbitControls( camera, renderer.domElement );
|
|
|
+ controls.minDistance = 50;
|
|
|
+ controls.maxDistance = 200;
|
|
|
+
|
|
|
+ scene.add( new THREE.AmbientLight( 0x464646 ) );
|
|
|
+
|
|
|
+ var light = new THREE.DirectionalLight( 0xffddcc, 1 );
|
|
|
+ light.position.set( 1, 0.75, 0.5 );
|
|
|
+ scene.add( light );
|
|
|
+
|
|
|
+ var light = new THREE.DirectionalLight( 0xccccff, 1 );
|
|
|
+ light.position.set( - 1, 0.75, - 0.5 );
|
|
|
+ scene.add( light );
|
|
|
+
|
|
|
+ teapot = new THREE.TeapotBufferGeometry( 15, 18 );
|
|
|
+
|
|
|
+ mesh = new THREE.Mesh( teapot );
|
|
|
+ scene.add( mesh );
|
|
|
+
|
|
|
+ window.addEventListener( 'resize', onWindowResize, false );
|
|
|
+
|
|
|
+ updateMaterial();
|
|
|
+
|
|
|
+ onWindowResize();
|
|
|
+ animate();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function clearGui() {
|
|
|
+
|
|
|
+ if ( gui ) gui.destroy();
|
|
|
+
|
|
|
+ gui = new dat.GUI();
|
|
|
+
|
|
|
+ var example = gui.add( param, 'example', {
|
|
|
+ 'basic / standard (PBR)': 'standard',
|
|
|
+ 'basic / phong': 'phong',
|
|
|
+ 'basic / layers': 'layers',
|
|
|
+ 'basic / rim': 'rim',
|
|
|
+ 'adv / fresnel': 'fresnel',
|
|
|
+ 'adv / saturation': 'saturation',
|
|
|
+ 'adv / top-bottom': 'top-bottom',
|
|
|
+ 'adv / caustic': 'caustic',
|
|
|
+ 'adv / displace': 'displace',
|
|
|
+ 'adv / camera-depth': 'camera-depth',
|
|
|
+ 'adv / soft-body': 'soft-body',
|
|
|
+ 'adv / wave': 'wave',
|
|
|
+ 'misc / smoke' : 'smoke',
|
|
|
+ 'misc / firefly' : 'firefly'
|
|
|
+ } ).onFinishChange( function() {
|
|
|
+
|
|
|
+ updateMaterial();
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ gui.open();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function addGui( name, value, callback, isColor, min, max ) {
|
|
|
+
|
|
|
+ var node;
|
|
|
+
|
|
|
+ param[ name ] = value;
|
|
|
+
|
|
|
+ if ( isColor ) {
|
|
|
+
|
|
|
+ node = gui.addColor( param, name ).onChange( function() {
|
|
|
+
|
|
|
+ callback( param[ name ] );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+ else if (typeof value == 'object') {
|
|
|
+
|
|
|
+ node = gui.add( param, name, value ).onChange( function() {
|
|
|
+
|
|
|
+ callback( param[ name ] );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ node = gui.add( param, name, min, max ).onChange( function() {
|
|
|
+
|
|
|
+ callback( param[ name ] );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return node;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateMaterial() {
|
|
|
+
|
|
|
+ move = false;
|
|
|
+
|
|
|
+ if ( mesh.material ) mesh.material.dispose();
|
|
|
+
|
|
|
+ var name = param.example;
|
|
|
+ var mtl;
|
|
|
+
|
|
|
+ clearGui();
|
|
|
+
|
|
|
+ switch ( name ) {
|
|
|
+
|
|
|
+ case 'phong':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ //mtl.color = // albedo color
|
|
|
+ //mtl.alpha = // opacity (0 at 1)
|
|
|
+ //mtl.specular = // specular color
|
|
|
+ //mtl.shininess = // shininess (float)
|
|
|
+ //mtl.normal = // normalmap
|
|
|
+ //mtl.normalScale = // normalmap scale
|
|
|
+ //mtl.emissive = // emissive color
|
|
|
+ //mtl.ambient = // ambient color
|
|
|
+ //mtl.shadow = // shadowmap
|
|
|
+ //mtl.ao = // ambient occlusion
|
|
|
+ //mtl.environment = // reflection map (CubeMap recommended)
|
|
|
+ //mtl.reflectivity = // environment intensity
|
|
|
+ //mtl.transform = // vertex transformation
|
|
|
+
|
|
|
+ var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
|
|
|
+
|
|
|
+ mtl.color = new THREE.TextureNode( grass );
|
|
|
+ mtl.specular = new THREE.FloatNode( .5 );
|
|
|
+ mtl.shininess = new THREE.FloatNode( 15 );
|
|
|
+ mtl.environment = new THREE.CubeTextureNode( cubemap );
|
|
|
+ mtl.reflectivity = mask;
|
|
|
+ mtl.normal = new THREE.TextureNode( grassNormal );
|
|
|
+ mtl.normalScale = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'standard':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.StandardNodeMaterial();
|
|
|
+
|
|
|
+ //mtl.color = // albedo color
|
|
|
+ //mtl.alpha = // opacity (0 at 1)
|
|
|
+ //mtl.roughness = // roughness (float)
|
|
|
+ //mtl.metalness = // metalness (float)
|
|
|
+ //mtl.normal = // normalmap
|
|
|
+ //mtl.normalScale = // normalmap scale
|
|
|
+ //mtl.emissive = // emissive color
|
|
|
+ //mtl.ambient = // ambient color
|
|
|
+ //mtl.shadow = // shadowmap
|
|
|
+ //mtl.ao = // ambient occlusion
|
|
|
+ //mtl.environment = // reflection map (CubeMap recommended)
|
|
|
+ //mtl.reflectivity = // environment intensity
|
|
|
+ //mtl.transform = // vertex transformation
|
|
|
+
|
|
|
+ var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
|
|
|
+
|
|
|
+ var normalScale = new THREE.FloatNode( .3 );
|
|
|
+
|
|
|
+ var roughnessA = new THREE.FloatNode( .5 );
|
|
|
+ var metalnessA = new THREE.FloatNode( .5 );
|
|
|
+
|
|
|
+ var roughnessB = new THREE.FloatNode( 0 );
|
|
|
+ var metalnessB = new THREE.FloatNode( 1 );
|
|
|
+
|
|
|
+ var roughness = new THREE.Math3Node(
|
|
|
+ roughnessA,
|
|
|
+ roughnessB,
|
|
|
+ mask,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var metalness = new THREE.Math3Node(
|
|
|
+ metalnessA,
|
|
|
+ metalnessB,
|
|
|
+ mask,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var normalMask = new THREE.OperatorNode(
|
|
|
+ new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
|
|
|
+ normalScale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ mtl.roughness = roughness;
|
|
|
+ mtl.metalness = metalness;
|
|
|
+ mtl.environment = new THREE.CubeTextureNode( cubemap );
|
|
|
+ mtl.normal = new THREE.TextureNode( grassNormal );
|
|
|
+ mtl.normalScale = normalMask;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'color', mtl.color.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ mtl.color.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'roughnessA', roughnessA.number, function( val ) {
|
|
|
+
|
|
|
+ roughnessA.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'metalnessA', metalnessA.number, function( val ) {
|
|
|
+
|
|
|
+ metalnessA.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'roughnessB', roughnessB.number, function( val ) {
|
|
|
+
|
|
|
+ roughnessB.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'metalnessB', metalnessB.number, function( val ) {
|
|
|
+
|
|
|
+ metalnessB.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'normalScale', normalScale.number, function( val ) {
|
|
|
+
|
|
|
+ normalScale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'wave':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.TimeNode();
|
|
|
+ var speed = new THREE.FloatNode( 5 );
|
|
|
+ var scale = new THREE.FloatNode( 1 );
|
|
|
+ var worldScale = new THREE.FloatNode( .4 );
|
|
|
+ var colorA = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ var colorB = new THREE.ColorNode( 0x0054df );
|
|
|
+
|
|
|
+ var uv = new THREE.UVNode();
|
|
|
+
|
|
|
+ var timeScale = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var worldScl = new THREE.OperatorNode(
|
|
|
+ new THREE.PositionNode(),
|
|
|
+ worldScale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var posContinuous = new THREE.OperatorNode(
|
|
|
+ worldScl,
|
|
|
+ timeScale,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var wave = new THREE.Math1Node( posContinuous, THREE.Math1Node.SIN );
|
|
|
+ wave = new THREE.SwitchNode( wave, 'x' );
|
|
|
+
|
|
|
+ var waveScale = new THREE.OperatorNode(
|
|
|
+ wave,
|
|
|
+ scale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceY = new THREE.JoinNode(
|
|
|
+ new THREE.FloatNode(),
|
|
|
+ waveScale,
|
|
|
+ new THREE.FloatNode()
|
|
|
+ );
|
|
|
+
|
|
|
+ var displace = new THREE.OperatorNode(
|
|
|
+ new THREE.NormalNode(),
|
|
|
+ displaceY,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var blend = new THREE.OperatorNode(
|
|
|
+ new THREE.PositionNode(),
|
|
|
+ displaceY,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var color = new THREE.Math3Node(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ wave,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = color;
|
|
|
+ mtl.transform = blend;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'speed', speed.number, function( val ) {
|
|
|
+
|
|
|
+ speed.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 10 );
|
|
|
+
|
|
|
+ addGui( 'scale', scale.number, function( val ) {
|
|
|
+
|
|
|
+ scale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ addGui( 'worldScale', worldScale.number, function( val ) {
|
|
|
+
|
|
|
+ worldScale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'colorA', colorA.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorA.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'colorB', colorB.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorB.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'useNormals', false, function( val ) {
|
|
|
+
|
|
|
+ blend.b = val ? displace : displaceY;
|
|
|
+
|
|
|
+ mtl.build();
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'rim':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var intensity = 1.3;
|
|
|
+ var power = new THREE.FloatNode( 3 );
|
|
|
+ var color = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+
|
|
|
+ var viewZ = new THREE.Math2Node(
|
|
|
+ new THREE.NormalNode( THREE.NormalNode.VIEW ),
|
|
|
+ new THREE.Vector3Node( 0, 0, - intensity ),
|
|
|
+ THREE.Math2Node.DOT
|
|
|
+ );
|
|
|
+
|
|
|
+ var rim = new THREE.OperatorNode(
|
|
|
+ viewZ,
|
|
|
+ new THREE.FloatNode( intensity ),
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var rimPower = new THREE.Math2Node(
|
|
|
+ rim,
|
|
|
+ power,
|
|
|
+ THREE.Math2Node.POW
|
|
|
+ );
|
|
|
+
|
|
|
+ var rimColor = new THREE.OperatorNode(
|
|
|
+ rimPower,
|
|
|
+ color,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.ColorNode( 0x111111 );
|
|
|
+ mtl.emissive = rimColor;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'color', color.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ color.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'intensity', intensity, function( val ) {
|
|
|
+
|
|
|
+ intensity = val;
|
|
|
+
|
|
|
+ viewZ.b.z = - intensity;
|
|
|
+ rim.b.number = intensity;
|
|
|
+
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ addGui( 'power', power.number, function( val ) {
|
|
|
+
|
|
|
+ power.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 6 );
|
|
|
+
|
|
|
+ addGui( 'xray', false, function( val ) {
|
|
|
+
|
|
|
+ if ( val ) {
|
|
|
+
|
|
|
+ mtl.emissive = color;
|
|
|
+ mtl.alpha = rimPower;
|
|
|
+ mtl.blending = THREE.AdditiveBlending;
|
|
|
+ mtl.depthWrite = false;
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ mtl.emissive = rimColor;
|
|
|
+ mtl.alpha = null;
|
|
|
+ mtl.blending = THREE.NormalBlending;
|
|
|
+ mtl.depthWrite = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ mtl.build();
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'fresnel':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var reflectance = new THREE.FloatNode( 1.3 );
|
|
|
+ var power = new THREE.FloatNode( 1 );
|
|
|
+ var color = new THREE.CubeTextureNode( cubemap );
|
|
|
+
|
|
|
+ var viewZ = new THREE.Math2Node(
|
|
|
+ new THREE.NormalNode( THREE.NormalNode.VIEW ),
|
|
|
+ new THREE.Vector3Node( 0, 0, - 1 ),
|
|
|
+ THREE.Math2Node.DOT
|
|
|
+ );
|
|
|
+
|
|
|
+ var theta = new THREE.OperatorNode(
|
|
|
+ viewZ,
|
|
|
+ new THREE.FloatNode( 1 ),
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var thetaPower = new THREE.Math2Node(
|
|
|
+ theta,
|
|
|
+ power,
|
|
|
+ THREE.Math2Node.POW
|
|
|
+ );
|
|
|
+
|
|
|
+ var fresnel = new THREE.OperatorNode(
|
|
|
+ reflectance,
|
|
|
+ thetaPower,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.ColorNode( 0x3399FF );
|
|
|
+ mtl.environment = color;
|
|
|
+ mtl.reflectivity = new THREE.Math1Node( fresnel, THREE.Math1Node.SAT );
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'reflectance', reflectance.number, function( val ) {
|
|
|
+
|
|
|
+ reflectance.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ addGui( 'power', power.number, function( val ) {
|
|
|
+
|
|
|
+ power.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 5 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'layers':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var tex1 = new THREE.TextureNode( grass );
|
|
|
+ var tex2 = new THREE.TextureNode( brick );
|
|
|
+
|
|
|
+ var offset = new THREE.FloatNode( 0 );
|
|
|
+ var scale = new THREE.FloatNode( 1 );
|
|
|
+ var uv = new THREE.UVNode();
|
|
|
+
|
|
|
+ var uvOffset = new THREE.OperatorNode(
|
|
|
+ offset,
|
|
|
+ uv,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvScale = new THREE.OperatorNode(
|
|
|
+ uvOffset,
|
|
|
+ scale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var mask = new THREE.TextureNode( decalDiffuse, uvScale );
|
|
|
+ var maskAlphaChannel = new THREE.SwitchNode( mask, 'w' );
|
|
|
+
|
|
|
+ var blend = new THREE.Math3Node(
|
|
|
+ tex1,
|
|
|
+ tex2,
|
|
|
+ maskAlphaChannel,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = blend;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'offset', offset.number, function( val ) {
|
|
|
+
|
|
|
+ offset.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'scale', scale.number, function( val ) {
|
|
|
+
|
|
|
+ scale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 10 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'saturation':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.StandardNodeMaterial();
|
|
|
+
|
|
|
+ var tex = new THREE.TextureNode( brick );
|
|
|
+ var sat = new THREE.FloatNode( 0 );
|
|
|
+
|
|
|
+ var satrgb = new THREE.FunctionNode( [
|
|
|
+ "vec3 satrgb(vec3 rgb, float adjustment) {",
|
|
|
+ //"const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
|
|
|
+ "vec3 intensity = vec3(dot(rgb, LUMA));",
|
|
|
+ "return mix(intensity, rgb, adjustment);",
|
|
|
+ "}"
|
|
|
+ ].join( "\n" ) );
|
|
|
+
|
|
|
+ var saturation = new THREE.FunctionCallNode( satrgb );
|
|
|
+ saturation.input.rgb = tex;
|
|
|
+ saturation.input.adjustment = sat;
|
|
|
+
|
|
|
+ // or try
|
|
|
+
|
|
|
+ //saturation.input[0] = tex;
|
|
|
+ //saturation.input[1] = sat;
|
|
|
+
|
|
|
+ mtl.color = saturation;
|
|
|
+ mtl.environment = new THREE.CubeTextureNode( cubemap ); // optional
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'saturation', sat.number, function( val ) {
|
|
|
+
|
|
|
+ sat.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 2 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'top-bottom':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var top = new THREE.TextureNode( grass );
|
|
|
+ var bottom = new THREE.TextureNode( brick );
|
|
|
+
|
|
|
+ var normal = new THREE.NormalNode( THREE.NormalNode.WORLD );
|
|
|
+ var normalY = new THREE.SwitchNode( normal, 'y' );
|
|
|
+
|
|
|
+ var hard = new THREE.FloatNode( 9 );
|
|
|
+ var offset = new THREE.FloatNode( - 2.5 );
|
|
|
+
|
|
|
+ var hardClamp = new THREE.OperatorNode(
|
|
|
+ normalY,
|
|
|
+ hard,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var offsetClamp = new THREE.OperatorNode(
|
|
|
+ hardClamp,
|
|
|
+ offset,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var clamp0at1 = new THREE.Math1Node( offsetClamp, THREE.Math1Node.SAT );
|
|
|
+
|
|
|
+ var blend = new THREE.Math3Node( top, bottom, clamp0at1, THREE.Math3Node.MIX );
|
|
|
+
|
|
|
+ mtl.color = blend;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'hard', hard.number, function( val ) {
|
|
|
+
|
|
|
+ hard.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 20 );
|
|
|
+
|
|
|
+ addGui( 'offset', offset.number, function( val ) {
|
|
|
+
|
|
|
+ offset.number = val;
|
|
|
+
|
|
|
+ }, false, - 10, 10 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'displace':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.TimeNode();
|
|
|
+ var scale = new THREE.FloatNode( 2 );
|
|
|
+ var speed = new THREE.FloatNode( .2 );
|
|
|
+ var colorA = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ var colorB = new THREE.ColorNode( 0x0054df );
|
|
|
+
|
|
|
+ var uv = new THREE.UVNode();
|
|
|
+
|
|
|
+ var timeScl = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceOffset = new THREE.OperatorNode(
|
|
|
+ timeScl,
|
|
|
+ uv,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var tex = new THREE.TextureNode( cloud, displaceOffset );
|
|
|
+ var texArea = new THREE.SwitchNode( tex, 'w' );
|
|
|
+
|
|
|
+ var displace = new THREE.OperatorNode(
|
|
|
+ new THREE.NormalNode(),
|
|
|
+ texArea,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceScale = new THREE.OperatorNode(
|
|
|
+ displace,
|
|
|
+ scale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var blend = new THREE.OperatorNode(
|
|
|
+ new THREE.PositionNode(),
|
|
|
+ displaceScale,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var color = new THREE.Math3Node(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ texArea,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = mtl.specular = new THREE.ColorNode( 0 );
|
|
|
+ mtl.emissive = color;
|
|
|
+ mtl.transform = blend;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'speed', speed.number, function( val ) {
|
|
|
+
|
|
|
+ speed.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'scale', scale.number, function( val ) {
|
|
|
+
|
|
|
+ scale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 10 );
|
|
|
+
|
|
|
+ addGui( 'colorA', colorA.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorA.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'colorB', colorB.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorB.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'smoke':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.TimeNode();
|
|
|
+ var uv = new THREE.UVNode();
|
|
|
+
|
|
|
+ var timeSpeedA = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ new THREE.Vector2Node( 0.3, 0.1 ),
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var timeSpeedB = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ new THREE.Vector2Node( 0.15, 0.4 ),
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvOffsetA = new THREE.OperatorNode(
|
|
|
+ timeSpeedA,
|
|
|
+ uv,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvOffsetB = new THREE.OperatorNode(
|
|
|
+ timeSpeedB,
|
|
|
+ uv,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var cloudA = new THREE.TextureNode( cloud, uvOffsetA );
|
|
|
+ var cloudB = new THREE.TextureNode( cloud, uvOffsetB );
|
|
|
+
|
|
|
+ var clouds = new THREE.OperatorNode(
|
|
|
+ cloudA,
|
|
|
+ cloudB,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.environment = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ mtl.alpha = clouds;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'color', mtl.environment.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ mtl.environment.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'camera-depth':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ var colorA = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ var colorB = new THREE.ColorNode( 0x0054df );
|
|
|
+
|
|
|
+ var depth = new THREE.CameraNode( THREE.CameraNode.DEPTH );
|
|
|
+ depth.near.number = 1;
|
|
|
+ depth.far.number = 200;
|
|
|
+
|
|
|
+ var colors = new THREE.Math3Node(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ depth,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+ mtl.color = colors;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'near', depth.near.number, function( val ) {
|
|
|
+
|
|
|
+ depth.near.number = val;
|
|
|
+
|
|
|
+ }, false, 1, 1200 );
|
|
|
+
|
|
|
+ addGui( 'far', depth.far.number, function( val ) {
|
|
|
+
|
|
|
+ depth.far.number = val;
|
|
|
+
|
|
|
+ }, false, 1, 1200 );
|
|
|
+
|
|
|
+ addGui( 'nearColor', colorA.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorA.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'farColor', colorB.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorB.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'caustic':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.StandardNodeMaterial();
|
|
|
+
|
|
|
+ var hash2 = new THREE.FunctionNode( [
|
|
|
+ "vec2 hash2(vec2 p) {",
|
|
|
+ "return fract(sin(vec2(dot(p, vec2(123.4, 748.6)), dot(p, vec2(547.3, 659.3))))*5232.85324);",
|
|
|
+ "}"
|
|
|
+ ].join( "\n" ) );
|
|
|
+
|
|
|
+ var voronoi = new THREE.FunctionNode( [
|
|
|
+ // Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
|
|
|
+ "float voronoi(vec2 p, in float time) {",
|
|
|
+ "vec2 n = floor(p);",
|
|
|
+ "vec2 f = fract(p);",
|
|
|
+ "float md = 5.0;",
|
|
|
+ "vec2 m = vec2(0.0);",
|
|
|
+ "for (int i = -1; i <= 1; i++) {",
|
|
|
+ "for (int j = -1; j <= 1; j++) {",
|
|
|
+ "vec2 g = vec2(i, j);",
|
|
|
+ "vec2 o = hash2(n + g);",
|
|
|
+ "o = 0.5 + 0.5 * sin(time + 5.038 * o);",
|
|
|
+ "vec2 r = g + o - f;",
|
|
|
+ "float d = dot(r, r);",
|
|
|
+ "if (d < md) {",
|
|
|
+ "md = d;",
|
|
|
+ "m = n+g+o;",
|
|
|
+ "}",
|
|
|
+ "}",
|
|
|
+ "}",
|
|
|
+ "return md;",
|
|
|
+ "}"
|
|
|
+ ].join( "\n" ), [ hash2 ] ); // define hash2 as dependencies
|
|
|
+
|
|
|
+ var voronoiLayers = new THREE.FunctionNode( [
|
|
|
+ // based on https://www.shadertoy.com/view/4tXSDf
|
|
|
+ "float voronoiLayers(vec2 p, in float time) {",
|
|
|
+ "float v = 0.0;",
|
|
|
+ "float a = 0.4;",
|
|
|
+ "for (int i = 0; i < 3; i++) {",
|
|
|
+ "v += voronoi(p, time) * a;",
|
|
|
+ "p *= 2.0;",
|
|
|
+ "a *= 0.5;",
|
|
|
+ "}",
|
|
|
+ "return v;",
|
|
|
+ "}"
|
|
|
+ ].join( "\n" ), [ voronoi ] ); // define voronoi as dependencies
|
|
|
+
|
|
|
+ var time = new THREE.TimeNode();
|
|
|
+ var timeScale = new THREE.FloatNode( 2 );
|
|
|
+
|
|
|
+ var alpha = new THREE.FloatNode( 1 );
|
|
|
+ var scale = new THREE.FloatNode( .1 );
|
|
|
+ var intensity = new THREE.FloatNode( 1.5 );
|
|
|
+
|
|
|
+ var color = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ var colorA = new THREE.ColorNode( 0xFFFFFF );
|
|
|
+ var colorB = new THREE.ColorNode( 0x0054df );
|
|
|
+
|
|
|
+ var worldPos = new THREE.PositionNode( THREE.PositionNode.WORLD );
|
|
|
+ var worldPosTop = new THREE.SwitchNode( worldPos, 'xz' );
|
|
|
+
|
|
|
+ var worldNormal = new THREE.NormalNode( THREE.NormalNode.WORLD );
|
|
|
+
|
|
|
+ var mask = new THREE.SwitchNode( worldNormal, 'y' );
|
|
|
+
|
|
|
+ // clamp0at1
|
|
|
+ mask = new THREE.Math1Node( mask, THREE.Math1Node.SAT );
|
|
|
+
|
|
|
+ var timeOffset = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ timeScale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvPos = new THREE.OperatorNode(
|
|
|
+ worldPosTop,
|
|
|
+ scale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoi = new THREE.FunctionCallNode( voronoiLayers );
|
|
|
+ voronoi.input.p = uvPos;
|
|
|
+ voronoi.input.time = timeOffset;
|
|
|
+
|
|
|
+ var maskCaustic = new THREE.OperatorNode(
|
|
|
+ alpha,
|
|
|
+ mask,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoiIntensity = new THREE.OperatorNode(
|
|
|
+ voronoi,
|
|
|
+ intensity,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoiColors = new THREE.Math3Node(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ new THREE.Math1Node( voronoiIntensity, THREE.Math1Node.SAT ), // mix needs clamp
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var caustic = new THREE.Math3Node(
|
|
|
+ color,
|
|
|
+ voronoiColors,
|
|
|
+ maskCaustic,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var causticLights = new THREE.OperatorNode(
|
|
|
+ voronoiIntensity,
|
|
|
+ maskCaustic,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = caustic;
|
|
|
+ mtl.ambient = causticLights;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'timeScale', timeScale.number, function( val ) {
|
|
|
+
|
|
|
+ timeScale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 5 );
|
|
|
+
|
|
|
+ addGui( 'intensity', intensity.number, function( val ) {
|
|
|
+
|
|
|
+ intensity.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ addGui( 'scale', scale.number, function( val ) {
|
|
|
+
|
|
|
+ scale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'alpha', alpha.number, function( val ) {
|
|
|
+
|
|
|
+ alpha.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 1 );
|
|
|
+
|
|
|
+ addGui( 'color', color.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ color.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'colorA', colorA.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorA.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'colorB', colorB.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorB.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'soft-body':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ move = true;
|
|
|
+
|
|
|
+ mtl = new THREE.StandardNodeMaterial();
|
|
|
+
|
|
|
+ var scale = new THREE.FloatNode( 2 );
|
|
|
+ var colorA = new THREE.ColorNode( 0xFF6633 );
|
|
|
+ var colorB = new THREE.ColorNode( 0x3366FF );
|
|
|
+
|
|
|
+ var pos = new THREE.PositionNode();
|
|
|
+ var posNorm = new THREE.Math1Node( pos, THREE.Math1Node.NORMALIZE );
|
|
|
+
|
|
|
+ var mask = new THREE.SwitchNode( posNorm, 'y' );
|
|
|
+
|
|
|
+ var velocity = new THREE.VelocityNode( mesh, {
|
|
|
+ type: 'elastic',
|
|
|
+ spring: .8,
|
|
|
+ friction: .9
|
|
|
+ } );
|
|
|
+
|
|
|
+ var velocityArea = new THREE.OperatorNode(
|
|
|
+ mask,
|
|
|
+ scale,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var softVelocity = new THREE.OperatorNode(
|
|
|
+ velocity,
|
|
|
+ velocityArea,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var softPosition = new THREE.OperatorNode(
|
|
|
+ new THREE.PositionNode(),
|
|
|
+ softVelocity,
|
|
|
+ THREE.OperatorNode.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var colors = new THREE.Math3Node(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ mask,
|
|
|
+ THREE.Math3Node.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = colors;
|
|
|
+ mtl.transform = softPosition;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'spring', velocity.params.spring, function( val ) {
|
|
|
+
|
|
|
+ velocity.params.spring = val;
|
|
|
+
|
|
|
+ }, false, 0, .9 );
|
|
|
+
|
|
|
+ addGui( 'friction', velocity.params.friction, function( val ) {
|
|
|
+
|
|
|
+ velocity.params.friction = val;
|
|
|
+
|
|
|
+ }, false, 0, .9 );
|
|
|
+
|
|
|
+ addGui( 'scale', scale.number, function( val ) {
|
|
|
+
|
|
|
+ scale.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ addGui( 'softBody', colorA.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorA.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ addGui( 'hardBody', colorB.value.getHex(), function( val ) {
|
|
|
+
|
|
|
+ colorB.value.setHex( val );
|
|
|
+
|
|
|
+ }, true );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'firefly':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.PhongNodeMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.TimeNode();
|
|
|
+ var speed = new THREE.FloatNode( .5 );
|
|
|
+
|
|
|
+ var color = new THREE.ColorNode( 0x98ff00 );
|
|
|
+
|
|
|
+ var timeSpeed = new THREE.OperatorNode(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var sinCycleInSecs = new THREE.OperatorNode(
|
|
|
+ timeSpeed,
|
|
|
+ new THREE.ConstNode( THREE.ConstNode.PI2 ),
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var cycle = new THREE.Math1Node( sinCycleInSecs, THREE.Math1Node.SIN );
|
|
|
+
|
|
|
+ var cycleColor = new THREE.OperatorNode(
|
|
|
+ cycle,
|
|
|
+ color,
|
|
|
+ THREE.OperatorNode.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var cos = new THREE.Math1Node( cycleColor, THREE.Math1Node.SIN );
|
|
|
+
|
|
|
+ mtl.color = new THREE.ColorNode( 0 );
|
|
|
+ mtl.emissive = cos;
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'speed', speed.number, function( val ) {
|
|
|
+
|
|
|
+ speed.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 3 );
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // build shader
|
|
|
+ mtl.build();
|
|
|
+
|
|
|
+ // set material
|
|
|
+ mesh.material = mtl;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function onWindowResize() {
|
|
|
+
|
|
|
+ camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
+ camera.updateProjectionMatrix();
|
|
|
+
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function animate() {
|
|
|
+
|
|
|
+ var delta = clock.getDelta();
|
|
|
+
|
|
|
+ if ( move ) {
|
|
|
+
|
|
|
+ var time = Date.now() * 0.005;
|
|
|
+
|
|
|
+ mesh.position.z = Math.cos( time ) * 10;
|
|
|
+ mesh.position.y = Math.sin( time ) * 10;
|
|
|
+
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ mesh.position.z = mesh.position.y = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //mesh.rotation.z += .01;
|
|
|
+
|
|
|
+ // update material animation and/or gpu calcs (pre-renderer)
|
|
|
+ mesh.material.updateAnimation( delta );
|
|
|
+
|
|
|
+ renderer.render( scene, camera );
|
|
|
+
|
|
|
+ requestAnimationFrame( animate );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ </script>
|
|
|
+
|
|
|
+ </body>
|
|
|
+</html>
|