|
@@ -0,0 +1,1314 @@
|
|
|
+<!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>
|
|
|
+
|
|
|
+ <!-- NodeMaterial Base -->
|
|
|
+ <script src="js/materials/nodes/NodeGL.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeBuilder.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeRaw.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeTemp.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeInput.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeMaterial.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeConst.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeFunction.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeFunctionCall.js"></script>
|
|
|
+ <script src="js/materials/nodes/NodeLib.js"></script>
|
|
|
+
|
|
|
+ <!-- Accessors -->
|
|
|
+ <script src="js/materials/nodes/accessors/NodeColors.js"></script>
|
|
|
+ <script src="js/materials/nodes/accessors/NodeCamera.js"></script>
|
|
|
+ <script src="js/materials/nodes/accessors/NodeNormal.js"></script>
|
|
|
+ <script src="js/materials/nodes/accessors/NodePosition.js"></script>
|
|
|
+ <script src="js/materials/nodes/accessors/NodeReflect.js"></script>
|
|
|
+ <script src="js/materials/nodes/accessors/NodeUV.js"></script>
|
|
|
+
|
|
|
+ <!-- Inputs -->
|
|
|
+ <script src="js/materials/nodes/inputs/NodeColor.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeFloat.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeInt.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeVector2.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeVector3.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeVector4.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeTexture.js"></script>
|
|
|
+ <script src="js/materials/nodes/inputs/NodeCubeTexture.js"></script>
|
|
|
+
|
|
|
+ <!-- Math -->
|
|
|
+ <script src="js/materials/nodes/math/NodeMath1.js"></script>
|
|
|
+ <script src="js/materials/nodes/math/NodeMath2.js"></script>
|
|
|
+ <script src="js/materials/nodes/math/NodeMath3.js"></script>
|
|
|
+ <script src="js/materials/nodes/math/NodeOperator.js"></script>
|
|
|
+
|
|
|
+ <!-- Utils -->
|
|
|
+ <script src="js/materials/nodes/utils/NodeJoin.js"></script>
|
|
|
+ <script src="js/materials/nodes/utils/NodeSwitch.js"></script>
|
|
|
+ <script src="js/materials/nodes/utils/NodeTime.js"></script>
|
|
|
+ <script src="js/materials/nodes/utils/NodeRoughnessToBlinnExponent.js"></script>
|
|
|
+
|
|
|
+ <!-- Interfaces -->
|
|
|
+ <script src="js/materials/nodes/interfaces/NodePhong.js"></script>
|
|
|
+ <script src="js/materials/nodes/interfaces/NodePhongMaterial.js"></script>
|
|
|
+ <script src="js/materials/nodes/interfaces/NodeStandard.js"></script>
|
|
|
+ <script src="js/materials/nodes/interfaces/NodeStandardMaterial.js"></script>
|
|
|
+
|
|
|
+ <!-- Extras -->
|
|
|
+ <script src="js/materials/nodes/extras/NodeVelocity.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 decalNormal = new THREE.TextureLoader().load( 'textures/decal/decal-normal.jpg' );
|
|
|
+
|
|
|
+ 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 {
|
|
|
+
|
|
|
+ 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.NodePhongMaterial();
|
|
|
+
|
|
|
+ //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.NodeSwitch(new THREE.NodeTexture(decalDiffuse), 'w');
|
|
|
+
|
|
|
+ mtl.color = new THREE.NodeTexture(grass);
|
|
|
+ mtl.specular = new THREE.NodeFloat(.5);
|
|
|
+ mtl.shininess = new THREE.NodeFloat(15);
|
|
|
+ mtl.environment = new THREE.NodeCubeTexture(cubemap);
|
|
|
+ mtl.reflectivity = mask;
|
|
|
+ mtl.normal = new THREE.NodeTexture(grassNormal);
|
|
|
+ mtl.normalScale = new THREE.NodeMath1( mask, THREE.NodeMath1.INVERT );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'standard':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.NodeStandardMaterial();
|
|
|
+
|
|
|
+ //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.NodeSwitch(new THREE.NodeTexture(decalDiffuse), 'w');
|
|
|
+
|
|
|
+ var normalScale = new THREE.NodeFloat(.3);
|
|
|
+
|
|
|
+ var roughnessA = new THREE.NodeFloat(.5);
|
|
|
+ var metalnessA = new THREE.NodeFloat(.5);
|
|
|
+
|
|
|
+ var roughnessB = new THREE.NodeFloat(0);
|
|
|
+ var metalnessB = new THREE.NodeFloat(1);
|
|
|
+
|
|
|
+ var roughness = new THREE.NodeMath3(
|
|
|
+ roughnessA,
|
|
|
+ roughnessB,
|
|
|
+ mask,
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var metalness = new THREE.NodeMath3(
|
|
|
+ metalnessA,
|
|
|
+ metalnessB,
|
|
|
+ mask,
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var normalMask = new THREE.NodeOperator(
|
|
|
+ new THREE.NodeMath1( mask, THREE.NodeMath1.INVERT ),
|
|
|
+ normalScale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.NodeColor(0xFFFFFF);
|
|
|
+ mtl.roughness = roughness;
|
|
|
+ mtl.metalness = metalness;
|
|
|
+ mtl.environment = new THREE.NodeCubeTexture(cubemap);
|
|
|
+ mtl.normal = new THREE.NodeTexture(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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.NodeTime();
|
|
|
+ var speed = new THREE.NodeFloat(5);
|
|
|
+ var scale = new THREE.NodeFloat(1);
|
|
|
+ var worldScale = new THREE.NodeFloat(.4);
|
|
|
+ var colorA = new THREE.NodeColor(0xFFFFFF);
|
|
|
+ var colorB = new THREE.NodeColor(0x0054df);
|
|
|
+
|
|
|
+ var uv = new THREE.NodeUV();
|
|
|
+
|
|
|
+ var timeScale = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var worldScl = new THREE.NodeOperator(
|
|
|
+ new THREE.NodePosition(),
|
|
|
+ worldScale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var posContinuous = new THREE.NodeOperator(
|
|
|
+ worldScl,
|
|
|
+ timeScale,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var wave = new THREE.NodeMath1(posContinuous, THREE.NodeMath1.SIN);
|
|
|
+ wave = new THREE.NodeSwitch(wave, 'x');
|
|
|
+
|
|
|
+ var waveScale = new THREE.NodeOperator(
|
|
|
+ wave,
|
|
|
+ scale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceY = new THREE.NodeJoin(
|
|
|
+ new THREE.NodeFloat(),
|
|
|
+ waveScale,
|
|
|
+ new THREE.NodeFloat()
|
|
|
+ );
|
|
|
+
|
|
|
+ var displace = new THREE.NodeOperator(
|
|
|
+ new THREE.NodeNormal(),
|
|
|
+ displaceY,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var blend = new THREE.NodeOperator(
|
|
|
+ new THREE.NodePosition(),
|
|
|
+ displaceY,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var color = new THREE.NodeMath3(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ wave,
|
|
|
+ THREE.NodeMath3.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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var intensity = 1.3;
|
|
|
+ var power = new THREE.NodeFloat(3);
|
|
|
+ var color = new THREE.NodeColor(0xFFFFFF);
|
|
|
+
|
|
|
+ var viewZ = new THREE.NodeMath2(
|
|
|
+ new THREE.NodeNormal( THREE.NodeNormal.VIEW ),
|
|
|
+ new THREE.NodeVector3(0, 0, -intensity),
|
|
|
+ THREE.NodeMath2.DOT
|
|
|
+ );
|
|
|
+
|
|
|
+ var rim = new THREE.NodeOperator(
|
|
|
+ viewZ,
|
|
|
+ new THREE.NodeFloat(intensity),
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var rimPower = new THREE.NodeMath2(
|
|
|
+ rim,
|
|
|
+ power,
|
|
|
+ THREE.NodeMath2.POW
|
|
|
+ );
|
|
|
+
|
|
|
+ var rimColor = new THREE.NodeOperator(
|
|
|
+ rimPower,
|
|
|
+ color,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.NodeColor(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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var reflectance = new THREE.NodeFloat(1.3);
|
|
|
+ var power = new THREE.NodeFloat(1);
|
|
|
+ var color = new THREE.NodeCubeTexture(cubemap);
|
|
|
+
|
|
|
+ var viewZ = new THREE.NodeMath2(
|
|
|
+ new THREE.NodeNormal( THREE.NodeNormal.VIEW ),
|
|
|
+ new THREE.NodeVector3(0, 0, -1),
|
|
|
+ THREE.NodeMath2.DOT
|
|
|
+ );
|
|
|
+
|
|
|
+ var theta = new THREE.NodeOperator(
|
|
|
+ viewZ,
|
|
|
+ new THREE.NodeFloat(1),
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var thetaPower = new THREE.NodeMath2(
|
|
|
+ theta,
|
|
|
+ power,
|
|
|
+ THREE.NodeMath2.POW
|
|
|
+ );
|
|
|
+
|
|
|
+ var fresnel = new THREE.NodeOperator(
|
|
|
+ reflectance,
|
|
|
+ thetaPower,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = new THREE.NodeColor(0x3399FF);
|
|
|
+ mtl.environment = color;
|
|
|
+ mtl.reflectivity = new THREE.NodeMath1( fresnel, THREE.NodeMath1.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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var tex1 = new THREE.NodeTexture(grass);
|
|
|
+ var tex2 = new THREE.NodeTexture(brick);
|
|
|
+
|
|
|
+ var offset = new THREE.NodeFloat(0);
|
|
|
+ var scale = new THREE.NodeFloat(1);
|
|
|
+ var uv = new THREE.NodeUV();
|
|
|
+
|
|
|
+ var uvOffset = new THREE.NodeOperator(
|
|
|
+ offset,
|
|
|
+ uv,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvScale = new THREE.NodeOperator(
|
|
|
+ uvOffset,
|
|
|
+ scale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var mask = new THREE.NodeTexture(decalDiffuse, uvScale);
|
|
|
+ var maskAlphaChannel = new THREE.NodeSwitch(mask, 'w');
|
|
|
+
|
|
|
+ var blend = new THREE.NodeMath3(
|
|
|
+ tex1,
|
|
|
+ tex2,
|
|
|
+ maskAlphaChannel,
|
|
|
+ THREE.NodeMath3.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.NodeStandardMaterial();
|
|
|
+
|
|
|
+ var tex = new THREE.NodeTexture(brick);
|
|
|
+ var sat = new THREE.NodeFloat(0);
|
|
|
+
|
|
|
+ var satrgb = new THREE.NodeFunction([
|
|
|
+ "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.NodeFunctionCall(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.NodeCubeTexture(cubemap); // optional
|
|
|
+
|
|
|
+ // GUI
|
|
|
+
|
|
|
+ addGui( 'saturation', sat.number, function( val ) {
|
|
|
+
|
|
|
+ sat.number = val;
|
|
|
+
|
|
|
+ }, false, 0, 2 );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'top-bottom':
|
|
|
+
|
|
|
+ // MATERIAL
|
|
|
+
|
|
|
+ mtl = new THREE.NodePhongMaterial();
|
|
|
+
|
|
|
+ var top = new THREE.NodeTexture(grass);
|
|
|
+ var bottom = new THREE.NodeTexture(brick);
|
|
|
+
|
|
|
+ var normal = new THREE.NodeNormal( THREE.NodeNormal.WORLD );
|
|
|
+ var normalY = new THREE.NodeSwitch(normal, 'y');
|
|
|
+
|
|
|
+ var hard = new THREE.NodeFloat(9);
|
|
|
+ var offset = new THREE.NodeFloat(-2.5);
|
|
|
+
|
|
|
+ var hardClamp = new THREE.NodeOperator(
|
|
|
+ normalY,
|
|
|
+ hard,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var offsetClamp = new THREE.NodeOperator(
|
|
|
+ hardClamp,
|
|
|
+ offset,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var clamp0at1 = new THREE.NodeMath1( offsetClamp, THREE.NodeMath1.SAT );
|
|
|
+
|
|
|
+ var blend = new THREE.NodeMath3(top,bottom,clamp0at1,THREE.NodeMath3.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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.NodeTime();
|
|
|
+ var scale = new THREE.NodeFloat(2);
|
|
|
+ var speed = new THREE.NodeFloat(.2);
|
|
|
+ var colorA = new THREE.NodeColor(0xFFFFFF);
|
|
|
+ var colorB = new THREE.NodeColor(0x0054df);
|
|
|
+
|
|
|
+ var uv = new THREE.NodeUV();
|
|
|
+
|
|
|
+ var timeScl = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceOffset = new THREE.NodeOperator(
|
|
|
+ timeScl,
|
|
|
+ uv,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var tex = new THREE.NodeTexture(cloud, displaceOffset);
|
|
|
+ var texArea = new THREE.NodeSwitch(tex, 'w');
|
|
|
+
|
|
|
+ var displace = new THREE.NodeOperator(
|
|
|
+ new THREE.NodeNormal(),
|
|
|
+ texArea,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var displaceScale = new THREE.NodeOperator(
|
|
|
+ displace,
|
|
|
+ scale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var blend = new THREE.NodeOperator(
|
|
|
+ new THREE.NodePosition(),
|
|
|
+ displaceScale,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var color = new THREE.NodeMath3(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ texArea,
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.color = mtl.specular = new THREE.NodeColor(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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.NodeTime();
|
|
|
+ var uv = new THREE.NodeUV();
|
|
|
+
|
|
|
+ var timeSpeedA = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ new THREE.NodeVector2(0.3, 0.1),
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var timeSpeedB = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ new THREE.NodeVector2(0.15, 0.4),
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvOffsetA = new THREE.NodeOperator(
|
|
|
+ timeSpeedA,
|
|
|
+ uv,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvOffsetB = new THREE.NodeOperator(
|
|
|
+ timeSpeedB,
|
|
|
+ uv,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var cloudA = new THREE.NodeTexture(cloud, uvOffsetA);
|
|
|
+ var cloudB = new THREE.NodeTexture(cloud, uvOffsetB);
|
|
|
+
|
|
|
+ var clouds = new THREE.NodeOperator(
|
|
|
+ cloudA,
|
|
|
+ cloudB,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl.environment = new THREE.NodeColor(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.NodeColor(0xFFFFFF);
|
|
|
+ var colorB = new THREE.NodeColor(0x0054df);
|
|
|
+
|
|
|
+ var depth = new THREE.NodeCamera( THREE.NodeCamera.DEPTH );
|
|
|
+ depth.near.number = 1;
|
|
|
+ depth.far.number = 200;
|
|
|
+
|
|
|
+ var colors = new THREE.NodeMath3(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ depth,
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ mtl = new THREE.NodePhongMaterial();
|
|
|
+ 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.NodeStandardMaterial();
|
|
|
+
|
|
|
+ var hash2 = new THREE.NodeFunction([
|
|
|
+ "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.NodeFunction([
|
|
|
+ // 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.NodeFunction([
|
|
|
+ // 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.NodeTime();
|
|
|
+ var timeScale = new THREE.NodeFloat(2);
|
|
|
+
|
|
|
+ var alpha = new THREE.NodeFloat(1);
|
|
|
+ var scale = new THREE.NodeFloat(.1);
|
|
|
+ var intensity = new THREE.NodeFloat(1.5);
|
|
|
+
|
|
|
+ var color = new THREE.NodeColor(0xFFFFFF);
|
|
|
+ var colorA = new THREE.NodeColor(0xFFFFFF);
|
|
|
+ var colorB = new THREE.NodeColor(0x0054df);
|
|
|
+
|
|
|
+ var worldPos = new THREE.NodePosition( THREE.NodePosition.WORLD );
|
|
|
+ var worldPosTop = new THREE.NodeSwitch(worldPos, 'xz');
|
|
|
+
|
|
|
+ var pos = new THREE.NodePosition( THREE.NodePosition.WORLD );
|
|
|
+ var posNorm = new THREE.NodeMath1(pos, THREE.NodeMath1.NORMALIZE);
|
|
|
+
|
|
|
+ var mask = new THREE.NodeSwitch(posNorm, 'y');
|
|
|
+
|
|
|
+ // clamp0at1
|
|
|
+ mask = new THREE.NodeMath1( mask, THREE.NodeMath1.SAT );
|
|
|
+
|
|
|
+ var timeOffset = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ timeScale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var uvPos = new THREE.NodeOperator(
|
|
|
+ worldPosTop,
|
|
|
+ scale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoi = new THREE.NodeFunctionCall(voronoiLayers);
|
|
|
+ voronoi.input.p = uvPos;
|
|
|
+ voronoi.input.time = timeOffset;
|
|
|
+
|
|
|
+ var maskCaustic = new THREE.NodeOperator(
|
|
|
+ alpha,
|
|
|
+ mask,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoiIntensity = new THREE.NodeOperator(
|
|
|
+ voronoi,
|
|
|
+ intensity,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var voronoiColors = new THREE.NodeMath3(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ new THREE.NodeMath1( voronoiIntensity, THREE.NodeMath1.SAT ), // mix needs clamp
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var caustic = new THREE.NodeMath3(
|
|
|
+ color,
|
|
|
+ voronoiColors,
|
|
|
+ maskCaustic,
|
|
|
+ THREE.NodeMath3.MIX
|
|
|
+ );
|
|
|
+
|
|
|
+ var causticLights = new THREE.NodeOperator(
|
|
|
+ voronoiIntensity,
|
|
|
+ maskCaustic,
|
|
|
+ THREE.NodeOperator.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.NodeStandardMaterial();
|
|
|
+
|
|
|
+ var scale = new THREE.NodeFloat(2);
|
|
|
+ var colorA = new THREE.NodeColor(0xFF6633);
|
|
|
+ var colorB = new THREE.NodeColor(0x3366FF);
|
|
|
+
|
|
|
+ var pos = new THREE.NodePosition();
|
|
|
+ var posNorm = new THREE.NodeMath1(pos, THREE.NodeMath1.NORMALIZE);
|
|
|
+
|
|
|
+ var mask = new THREE.NodeSwitch(posNorm, 'y');
|
|
|
+
|
|
|
+ var velocity = new THREE.NodeVelocity( mesh, {
|
|
|
+ type:'elastic',
|
|
|
+ spring:.8,
|
|
|
+ friction:.9
|
|
|
+ } );
|
|
|
+
|
|
|
+ var velocityArea = new THREE.NodeOperator(
|
|
|
+ mask,
|
|
|
+ scale,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var softVelocity = new THREE.NodeOperator(
|
|
|
+ velocity,
|
|
|
+ velocityArea,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var softPosition = new THREE.NodeOperator(
|
|
|
+ new THREE.NodePosition(),
|
|
|
+ softVelocity,
|
|
|
+ THREE.NodeOperator.ADD
|
|
|
+ );
|
|
|
+
|
|
|
+ var colors = new THREE.NodeMath3(
|
|
|
+ colorB,
|
|
|
+ colorA,
|
|
|
+ mask,
|
|
|
+ THREE.NodeMath3.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.NodePhongMaterial();
|
|
|
+
|
|
|
+ var time = new THREE.NodeTime();
|
|
|
+ var speed = new THREE.NodeFloat(.5);
|
|
|
+
|
|
|
+ var color = new THREE.NodeColor(0x98ff00);
|
|
|
+
|
|
|
+ var timeSpeed = new THREE.NodeOperator(
|
|
|
+ time,
|
|
|
+ speed,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var sinCycleInSecs = new THREE.NodeOperator(
|
|
|
+ timeSpeed,
|
|
|
+ new THREE.NodeConst( THREE.NodeConst.PI2 ),
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var cycle = new THREE.NodeMath1(sinCycleInSecs, THREE.NodeMath1.SIN);
|
|
|
+
|
|
|
+ var cycleColor = new THREE.NodeOperator(
|
|
|
+ cycle,
|
|
|
+ color,
|
|
|
+ THREE.NodeOperator.MUL
|
|
|
+ );
|
|
|
+
|
|
|
+ var cos = new THREE.NodeMath1(cycleColor, THREE.NodeMath1.SIN);
|
|
|
+
|
|
|
+ mtl.color = new THREE.NodeColor(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>
|