webgl_materials_nodes.html 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <title>WebGL NodeMaterial</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <style>
  8. body {
  9. color: #fff;
  10. font-family:Monospace;
  11. font-size:13px;
  12. margin: 0px;
  13. text-align:center;
  14. overflow: hidden;
  15. }
  16. #info {
  17. color: #fff;
  18. position: absolute;
  19. top: 10px;
  20. width: 100%;
  21. text-align: center;
  22. display:block;
  23. }
  24. a { color: white }
  25. </style>
  26. </head>
  27. <body>
  28. <div id="container"></div>
  29. <div id="info">
  30. <a href="http://threejs.org" target="_blank">three.js</a> - Node-Based Material
  31. </div>
  32. <script src="../build/three.min.js"></script>
  33. <script src='js/geometries/TeapotBufferGeometry.js'></script>
  34. <script src="js/controls/OrbitControls.js"></script>
  35. <script src="js/libs/dat.gui.min.js"></script>
  36. <!-- NodeLibrary -->
  37. <script src="js/nodes/GLNode.js"></script>
  38. <script src="js/nodes/RawNode.js"></script>
  39. <script src="js/nodes/TempNode.js"></script>
  40. <script src="js/nodes/InputNode.js"></script>
  41. <script src="js/nodes/ConstNode.js"></script>
  42. <script src="js/nodes/FunctionNode.js"></script>
  43. <script src="js/nodes/FunctionCallNode.js"></script>
  44. <script src="js/nodes/BuilderNode.js"></script>
  45. <script src="js/nodes/LibNode.js"></script>
  46. <script src="js/nodes/NodeMaterial.js"></script>
  47. <!-- Accessors -->
  48. <script src="js/nodes/accessors/PositionNode.js"></script>
  49. <script src="js/nodes/accessors/NormalNode.js"></script>
  50. <script src="js/nodes/accessors/UVNode.js"></script>
  51. <script src="js/nodes/accessors/ColorsNode.js"></script>
  52. <script src="js/nodes/accessors/CameraNode.js"></script>
  53. <script src="js/nodes/accessors/ReflectNode.js"></script>
  54. <!-- Inputs -->
  55. <script src="js/nodes/inputs/IntNode.js"></script>
  56. <script src="js/nodes/inputs/FloatNode.js"></script>
  57. <script src="js/nodes/inputs/ColorNode.js"></script>
  58. <script src="js/nodes/inputs/Vector2Node.js"></script>
  59. <script src="js/nodes/inputs/Vector3Node.js"></script>
  60. <script src="js/nodes/inputs/Vector4Node.js"></script>
  61. <script src="js/nodes/inputs/TextureNode.js"></script>
  62. <script src="js/nodes/inputs/CubeTextureNode.js"></script>
  63. <!-- Math -->
  64. <script src="js/nodes/math/Math1Node.js"></script>
  65. <script src="js/nodes/math/Math2Node.js"></script>
  66. <script src="js/nodes/math/Math3Node.js"></script>
  67. <script src="js/nodes/math/OperatorNode.js"></script>
  68. <!-- Utils -->
  69. <script src="js/nodes/utils/SwitchNode.js"></script>
  70. <script src="js/nodes/utils/JoinNode.js"></script>
  71. <script src="js/nodes/utils/TimerNode.js"></script>
  72. <script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
  73. <script src="js/nodes/utils/VelocityNode.js"></script>
  74. <!-- Phong Material -->
  75. <script src="js/nodes/materials/PhongNode.js"></script>
  76. <script src="js/nodes/materials/PhongNodeMaterial.js"></script>
  77. <!-- Standard Material -->
  78. <script src="js/nodes/materials/StandardNode.js"></script>
  79. <script src="js/nodes/materials/StandardNodeMaterial.js"></script>
  80. <script>
  81. var container = document.getElementById( 'container' );
  82. var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
  83. var teapot, mesh;
  84. var controls;
  85. var move = false;
  86. var gui, guiElements = [];
  87. var param = { example: 'standard' };
  88. var brick = new THREE.TextureLoader().load( 'textures/brick_diffuse.jpg' );
  89. var grass = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big.jpg' );
  90. var grassNormal = new THREE.TextureLoader().load( 'textures/terrain/grasslight-big-nm.jpg' );
  91. var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
  92. decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
  93. var cloud = new THREE.TextureLoader().load( 'textures/lava/cloud.png' );
  94. cloud.wrapS = cloud.wrapT = THREE.RepeatWrapping;
  95. var cubemap = function() {
  96. var path = "textures/cube/Park2/";
  97. var format = '.jpg';
  98. var urls = [
  99. path + 'posx' + format, path + 'negx' + format,
  100. path + 'posy' + format, path + 'negy' + format,
  101. path + 'posz' + format, path + 'negz' + format
  102. ];
  103. var textureCube = new THREE.CubeTextureLoader().load( urls );
  104. textureCube.format = THREE.RGBFormat;
  105. return textureCube;
  106. }();
  107. window.addEventListener( 'load', init );
  108. function init() {
  109. renderer = new THREE.WebGLRenderer( { antialias: true } );
  110. renderer.setPixelRatio( window.devicePixelRatio );
  111. renderer.setSize( window.innerWidth, window.innerHeight );
  112. container.appendChild( renderer.domElement );
  113. scene = new THREE.Scene();
  114. camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
  115. camera.position.x = 50;
  116. camera.position.z = - 50;
  117. camera.position.y = 30;
  118. camera.target = new THREE.Vector3();
  119. controls = new THREE.OrbitControls( camera, renderer.domElement );
  120. controls.minDistance = 50;
  121. controls.maxDistance = 200;
  122. scene.add( new THREE.AmbientLight( 0x464646 ) );
  123. var light = new THREE.DirectionalLight( 0xffddcc, 1 );
  124. light.position.set( 1, 0.75, 0.5 );
  125. scene.add( light );
  126. var light = new THREE.DirectionalLight( 0xccccff, 1 );
  127. light.position.set( - 1, 0.75, - 0.5 );
  128. scene.add( light );
  129. teapot = new THREE.TeapotBufferGeometry( 15, 18 );
  130. mesh = new THREE.Mesh( teapot );
  131. scene.add( mesh );
  132. window.addEventListener( 'resize', onWindowResize, false );
  133. updateMaterial();
  134. onWindowResize();
  135. animate();
  136. }
  137. function clearGui() {
  138. if ( gui ) gui.destroy();
  139. gui = new dat.GUI();
  140. var example = gui.add( param, 'example', {
  141. 'basic / standard (PBR)': 'standard',
  142. 'basic / phong': 'phong',
  143. 'basic / layers': 'layers',
  144. 'basic / rim': 'rim',
  145. 'adv / fresnel': 'fresnel',
  146. 'adv / saturation': 'saturation',
  147. 'adv / top-bottom': 'top-bottom',
  148. 'adv / caustic': 'caustic',
  149. 'adv / displace': 'displace',
  150. 'adv / camera-depth': 'camera-depth',
  151. 'adv / soft-body': 'soft-body',
  152. 'adv / wave': 'wave',
  153. 'misc / smoke' : 'smoke',
  154. 'misc / firefly' : 'firefly'
  155. } ).onFinishChange( function() {
  156. updateMaterial();
  157. } );
  158. gui.open();
  159. }
  160. function addGui( name, value, callback, isColor, min, max ) {
  161. var node;
  162. param[ name ] = value;
  163. if ( isColor ) {
  164. node = gui.addColor( param, name ).onChange( function() {
  165. callback( param[ name ] );
  166. } );
  167. }
  168. else if (typeof value == 'object') {
  169. node = gui.add( param, name, value ).onChange( function() {
  170. callback( param[ name ] );
  171. } );
  172. }
  173. else {
  174. node = gui.add( param, name, min, max ).onChange( function() {
  175. callback( param[ name ] );
  176. } );
  177. }
  178. return node;
  179. }
  180. function updateMaterial() {
  181. move = false;
  182. if ( mesh.material ) mesh.material.dispose();
  183. var name = param.example;
  184. var mtl;
  185. clearGui();
  186. switch ( name ) {
  187. case 'phong':
  188. // MATERIAL
  189. mtl = new THREE.PhongNodeMaterial();
  190. //mtl.color = // albedo color
  191. //mtl.alpha = // opacity (0 at 1)
  192. //mtl.specular = // specular color
  193. //mtl.shininess = // shininess (float)
  194. //mtl.normal = // normalmap
  195. //mtl.normalScale = // normalmap scale
  196. //mtl.emissive = // emissive color
  197. //mtl.ambient = // ambient color
  198. //mtl.shadow = // shadowmap
  199. //mtl.ao = // ambient occlusion
  200. //mtl.environment = // reflection map (CubeMap recommended)
  201. //mtl.reflectivity = // environment intensity
  202. //mtl.transform = // vertex transformation
  203. var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
  204. mtl.color = new THREE.TextureNode( grass );
  205. mtl.specular = new THREE.FloatNode( .5 );
  206. mtl.shininess = new THREE.FloatNode( 15 );
  207. mtl.environment = new THREE.CubeTextureNode( cubemap );
  208. mtl.reflectivity = mask;
  209. mtl.normal = new THREE.TextureNode( grassNormal );
  210. mtl.normalScale = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
  211. break;
  212. case 'standard':
  213. // MATERIAL
  214. mtl = new THREE.StandardNodeMaterial();
  215. //mtl.color = // albedo color
  216. //mtl.alpha = // opacity (0 at 1)
  217. //mtl.roughness = // roughness (float)
  218. //mtl.metalness = // metalness (float)
  219. //mtl.normal = // normalmap
  220. //mtl.normalScale = // normalmap scale
  221. //mtl.emissive = // emissive color
  222. //mtl.ambient = // ambient color
  223. //mtl.shadow = // shadowmap
  224. //mtl.ao = // ambient occlusion
  225. //mtl.environment = // reflection map (CubeMap recommended)
  226. //mtl.reflectivity = // environment intensity
  227. //mtl.transform = // vertex transformation
  228. var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
  229. var normalScale = new THREE.FloatNode( .3 );
  230. var roughnessA = new THREE.FloatNode( .5 );
  231. var metalnessA = new THREE.FloatNode( .5 );
  232. var roughnessB = new THREE.FloatNode( 0 );
  233. var metalnessB = new THREE.FloatNode( 1 );
  234. var roughness = new THREE.Math3Node(
  235. roughnessA,
  236. roughnessB,
  237. mask,
  238. THREE.Math3Node.MIX
  239. );
  240. var metalness = new THREE.Math3Node(
  241. metalnessA,
  242. metalnessB,
  243. mask,
  244. THREE.Math3Node.MIX
  245. );
  246. var normalMask = new THREE.OperatorNode(
  247. new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
  248. normalScale,
  249. THREE.OperatorNode.MUL
  250. );
  251. mtl.color = new THREE.ColorNode( 0xFFFFFF );
  252. mtl.roughness = roughness;
  253. mtl.metalness = metalness;
  254. mtl.environment = new THREE.CubeTextureNode( cubemap );
  255. mtl.normal = new THREE.TextureNode( grassNormal );
  256. mtl.normalScale = normalMask;
  257. // GUI
  258. addGui( 'color', mtl.color.value.getHex(), function( val ) {
  259. mtl.color.value.setHex( val );
  260. }, true );
  261. addGui( 'roughnessA', roughnessA.number, function( val ) {
  262. roughnessA.number = val;
  263. }, false, 0, 1 );
  264. addGui( 'metalnessA', metalnessA.number, function( val ) {
  265. metalnessA.number = val;
  266. }, false, 0, 1 );
  267. addGui( 'roughnessB', roughnessB.number, function( val ) {
  268. roughnessB.number = val;
  269. }, false, 0, 1 );
  270. addGui( 'metalnessB', metalnessB.number, function( val ) {
  271. metalnessB.number = val;
  272. }, false, 0, 1 );
  273. addGui( 'normalScale', normalScale.number, function( val ) {
  274. normalScale.number = val;
  275. }, false, 0, 1 );
  276. break;
  277. case 'wave':
  278. // MATERIAL
  279. mtl = new THREE.PhongNodeMaterial();
  280. var time = new THREE.TimerNode();
  281. var speed = new THREE.FloatNode( 5 );
  282. var scale = new THREE.FloatNode( 1 );
  283. var worldScale = new THREE.FloatNode( .4 );
  284. var colorA = new THREE.ColorNode( 0xFFFFFF );
  285. var colorB = new THREE.ColorNode( 0x0054df );
  286. var uv = new THREE.UVNode();
  287. var timeScale = new THREE.OperatorNode(
  288. time,
  289. speed,
  290. THREE.OperatorNode.MUL
  291. );
  292. var worldScl = new THREE.OperatorNode(
  293. new THREE.PositionNode(),
  294. worldScale,
  295. THREE.OperatorNode.MUL
  296. );
  297. var posContinuous = new THREE.OperatorNode(
  298. worldScl,
  299. timeScale,
  300. THREE.OperatorNode.ADD
  301. );
  302. var wave = new THREE.Math1Node( posContinuous, THREE.Math1Node.SIN );
  303. wave = new THREE.SwitchNode( wave, 'x' );
  304. var waveScale = new THREE.OperatorNode(
  305. wave,
  306. scale,
  307. THREE.OperatorNode.MUL
  308. );
  309. var displaceY = new THREE.JoinNode(
  310. new THREE.FloatNode(),
  311. waveScale,
  312. new THREE.FloatNode()
  313. );
  314. var displace = new THREE.OperatorNode(
  315. new THREE.NormalNode(),
  316. displaceY,
  317. THREE.OperatorNode.MUL
  318. );
  319. var blend = new THREE.OperatorNode(
  320. new THREE.PositionNode(),
  321. displaceY,
  322. THREE.OperatorNode.ADD
  323. );
  324. var color = new THREE.Math3Node(
  325. colorB,
  326. colorA,
  327. wave,
  328. THREE.Math3Node.MIX
  329. );
  330. mtl.color = color;
  331. mtl.transform = blend;
  332. // GUI
  333. addGui( 'speed', speed.number, function( val ) {
  334. speed.number = val;
  335. }, false, 0, 10 );
  336. addGui( 'scale', scale.number, function( val ) {
  337. scale.number = val;
  338. }, false, 0, 3 );
  339. addGui( 'worldScale', worldScale.number, function( val ) {
  340. worldScale.number = val;
  341. }, false, 0, 1 );
  342. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  343. colorA.value.setHex( val );
  344. }, true );
  345. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  346. colorB.value.setHex( val );
  347. }, true );
  348. addGui( 'useNormals', false, function( val ) {
  349. blend.b = val ? displace : displaceY;
  350. mtl.build();
  351. } );
  352. break;
  353. case 'rim':
  354. // MATERIAL
  355. mtl = new THREE.PhongNodeMaterial();
  356. var intensity = 1.3;
  357. var power = new THREE.FloatNode( 3 );
  358. var color = new THREE.ColorNode( 0xFFFFFF );
  359. var viewZ = new THREE.Math2Node(
  360. new THREE.NormalNode( THREE.NormalNode.VIEW ),
  361. new THREE.Vector3Node( 0, 0, - intensity ),
  362. THREE.Math2Node.DOT
  363. );
  364. var rim = new THREE.OperatorNode(
  365. viewZ,
  366. new THREE.FloatNode( intensity ),
  367. THREE.OperatorNode.ADD
  368. );
  369. var rimPower = new THREE.Math2Node(
  370. rim,
  371. power,
  372. THREE.Math2Node.POW
  373. );
  374. var rimColor = new THREE.OperatorNode(
  375. rimPower,
  376. color,
  377. THREE.OperatorNode.MUL
  378. );
  379. mtl.color = new THREE.ColorNode( 0x111111 );
  380. mtl.emissive = rimColor;
  381. // GUI
  382. addGui( 'color', color.value.getHex(), function( val ) {
  383. color.value.setHex( val );
  384. }, true );
  385. addGui( 'intensity', intensity, function( val ) {
  386. intensity = val;
  387. viewZ.b.z = - intensity;
  388. rim.b.number = intensity;
  389. }, false, 0, 3 );
  390. addGui( 'power', power.number, function( val ) {
  391. power.number = val;
  392. }, false, 0, 6 );
  393. addGui( 'xray', false, function( val ) {
  394. if ( val ) {
  395. mtl.emissive = color;
  396. mtl.alpha = rimPower;
  397. mtl.blending = THREE.AdditiveBlending;
  398. mtl.depthWrite = false;
  399. }
  400. else {
  401. mtl.emissive = rimColor;
  402. mtl.alpha = null;
  403. mtl.blending = THREE.NormalBlending;
  404. mtl.depthWrite = true;
  405. }
  406. mtl.build();
  407. } );
  408. break;
  409. case 'fresnel':
  410. // MATERIAL
  411. mtl = new THREE.PhongNodeMaterial();
  412. var reflectance = new THREE.FloatNode( 1.3 );
  413. var power = new THREE.FloatNode( 1 );
  414. var color = new THREE.CubeTextureNode( cubemap );
  415. var viewZ = new THREE.Math2Node(
  416. new THREE.NormalNode( THREE.NormalNode.VIEW ),
  417. new THREE.Vector3Node( 0, 0, - 1 ),
  418. THREE.Math2Node.DOT
  419. );
  420. var theta = new THREE.OperatorNode(
  421. viewZ,
  422. new THREE.FloatNode( 1 ),
  423. THREE.OperatorNode.ADD
  424. );
  425. var thetaPower = new THREE.Math2Node(
  426. theta,
  427. power,
  428. THREE.Math2Node.POW
  429. );
  430. var fresnel = new THREE.OperatorNode(
  431. reflectance,
  432. thetaPower,
  433. THREE.OperatorNode.MUL
  434. );
  435. mtl.color = new THREE.ColorNode( 0x3399FF );
  436. mtl.environment = color;
  437. mtl.reflectivity = new THREE.Math1Node( fresnel, THREE.Math1Node.SAT );
  438. // GUI
  439. addGui( 'reflectance', reflectance.number, function( val ) {
  440. reflectance.number = val;
  441. }, false, 0, 3 );
  442. addGui( 'power', power.number, function( val ) {
  443. power.number = val;
  444. }, false, 0, 5 );
  445. break;
  446. case 'layers':
  447. // MATERIAL
  448. mtl = new THREE.PhongNodeMaterial();
  449. var tex1 = new THREE.TextureNode( grass );
  450. var tex2 = new THREE.TextureNode( brick );
  451. var offset = new THREE.FloatNode( 0 );
  452. var scale = new THREE.FloatNode( 1 );
  453. var uv = new THREE.UVNode();
  454. var uvOffset = new THREE.OperatorNode(
  455. offset,
  456. uv,
  457. THREE.OperatorNode.ADD
  458. );
  459. var uvScale = new THREE.OperatorNode(
  460. uvOffset,
  461. scale,
  462. THREE.OperatorNode.MUL
  463. );
  464. var mask = new THREE.TextureNode( decalDiffuse, uvScale );
  465. var maskAlphaChannel = new THREE.SwitchNode( mask, 'w' );
  466. var blend = new THREE.Math3Node(
  467. tex1,
  468. tex2,
  469. maskAlphaChannel,
  470. THREE.Math3Node.MIX
  471. );
  472. mtl.color = blend;
  473. // GUI
  474. addGui( 'offset', offset.number, function( val ) {
  475. offset.number = val;
  476. }, false, 0, 1 );
  477. addGui( 'scale', scale.number, function( val ) {
  478. scale.number = val;
  479. }, false, 0, 10 );
  480. break;
  481. case 'saturation':
  482. // MATERIAL
  483. mtl = new THREE.StandardNodeMaterial();
  484. var tex = new THREE.TextureNode( brick );
  485. var sat = new THREE.FloatNode( 0 );
  486. var satrgb = new THREE.FunctionNode( [
  487. "vec3 satrgb(vec3 rgb, float adjustment) {",
  488. //"const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
  489. "vec3 intensity = vec3(dot(rgb, LUMA));",
  490. "return mix(intensity, rgb, adjustment);",
  491. "}"
  492. ].join( "\n" ) );
  493. var saturation = new THREE.FunctionCallNode( satrgb );
  494. saturation.inputs.rgb = tex;
  495. saturation.inputs.adjustment = sat;
  496. // or try
  497. //saturation.inputs[0] = tex;
  498. //saturation.inputs[1] = sat;
  499. mtl.color = saturation;
  500. mtl.environment = new THREE.CubeTextureNode( cubemap ); // optional
  501. // GUI
  502. addGui( 'saturation', sat.number, function( val ) {
  503. sat.number = val;
  504. }, false, 0, 2 );
  505. break;
  506. case 'top-bottom':
  507. // MATERIAL
  508. mtl = new THREE.PhongNodeMaterial();
  509. var top = new THREE.TextureNode( grass );
  510. var bottom = new THREE.TextureNode( brick );
  511. var normal = new THREE.NormalNode( THREE.NormalNode.WORLD );
  512. var normalY = new THREE.SwitchNode( normal, 'y' );
  513. var hard = new THREE.FloatNode( 9 );
  514. var offset = new THREE.FloatNode( - 2.5 );
  515. var hardClamp = new THREE.OperatorNode(
  516. normalY,
  517. hard,
  518. THREE.OperatorNode.MUL
  519. );
  520. var offsetClamp = new THREE.OperatorNode(
  521. hardClamp,
  522. offset,
  523. THREE.OperatorNode.ADD
  524. );
  525. var clamp0at1 = new THREE.Math1Node( offsetClamp, THREE.Math1Node.SAT );
  526. var blend = new THREE.Math3Node( top, bottom, clamp0at1, THREE.Math3Node.MIX );
  527. mtl.color = blend;
  528. // GUI
  529. addGui( 'hard', hard.number, function( val ) {
  530. hard.number = val;
  531. }, false, 0, 20 );
  532. addGui( 'offset', offset.number, function( val ) {
  533. offset.number = val;
  534. }, false, - 10, 10 );
  535. break;
  536. case 'displace':
  537. // MATERIAL
  538. mtl = new THREE.PhongNodeMaterial();
  539. var time = new THREE.TimerNode();
  540. var scale = new THREE.FloatNode( 2 );
  541. var speed = new THREE.FloatNode( .2 );
  542. var colorA = new THREE.ColorNode( 0xFFFFFF );
  543. var colorB = new THREE.ColorNode( 0x0054df );
  544. var uv = new THREE.UVNode();
  545. var timeScl = new THREE.OperatorNode(
  546. time,
  547. speed,
  548. THREE.OperatorNode.MUL
  549. );
  550. var displaceOffset = new THREE.OperatorNode(
  551. timeScl,
  552. uv,
  553. THREE.OperatorNode.ADD
  554. );
  555. var tex = new THREE.TextureNode( cloud, displaceOffset );
  556. var texArea = new THREE.SwitchNode( tex, 'w' );
  557. var displace = new THREE.OperatorNode(
  558. new THREE.NormalNode(),
  559. texArea,
  560. THREE.OperatorNode.MUL
  561. );
  562. var displaceScale = new THREE.OperatorNode(
  563. displace,
  564. scale,
  565. THREE.OperatorNode.MUL
  566. );
  567. var blend = new THREE.OperatorNode(
  568. new THREE.PositionNode(),
  569. displaceScale,
  570. THREE.OperatorNode.ADD
  571. );
  572. var color = new THREE.Math3Node(
  573. colorB,
  574. colorA,
  575. texArea,
  576. THREE.Math3Node.MIX
  577. );
  578. mtl.color = mtl.specular = new THREE.ColorNode( 0 );
  579. mtl.emissive = color;
  580. mtl.transform = blend;
  581. // GUI
  582. addGui( 'speed', speed.number, function( val ) {
  583. speed.number = val;
  584. }, false, 0, 1 );
  585. addGui( 'scale', scale.number, function( val ) {
  586. scale.number = val;
  587. }, false, 0, 10 );
  588. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  589. colorA.value.setHex( val );
  590. }, true );
  591. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  592. colorB.value.setHex( val );
  593. }, true );
  594. break;
  595. case 'smoke':
  596. // MATERIAL
  597. mtl = new THREE.PhongNodeMaterial();
  598. var time = new THREE.TimerNode();
  599. var uv = new THREE.UVNode();
  600. var timeSpeedA = new THREE.OperatorNode(
  601. time,
  602. new THREE.Vector2Node( 0.3, 0.1 ),
  603. THREE.OperatorNode.MUL
  604. );
  605. var timeSpeedB = new THREE.OperatorNode(
  606. time,
  607. new THREE.Vector2Node( 0.15, 0.4 ),
  608. THREE.OperatorNode.MUL
  609. );
  610. var uvOffsetA = new THREE.OperatorNode(
  611. timeSpeedA,
  612. uv,
  613. THREE.OperatorNode.ADD
  614. );
  615. var uvOffsetB = new THREE.OperatorNode(
  616. timeSpeedB,
  617. uv,
  618. THREE.OperatorNode.ADD
  619. );
  620. var cloudA = new THREE.TextureNode( cloud, uvOffsetA );
  621. var cloudB = new THREE.TextureNode( cloud, uvOffsetB );
  622. var clouds = new THREE.OperatorNode(
  623. cloudA,
  624. cloudB,
  625. THREE.OperatorNode.ADD
  626. );
  627. mtl.environment = new THREE.ColorNode( 0xFFFFFF );
  628. mtl.alpha = clouds;
  629. // GUI
  630. addGui( 'color', mtl.environment.value.getHex(), function( val ) {
  631. mtl.environment.value.setHex( val );
  632. }, true );
  633. break;
  634. case 'camera-depth':
  635. // MATERIAL
  636. var colorA = new THREE.ColorNode( 0xFFFFFF );
  637. var colorB = new THREE.ColorNode( 0x0054df );
  638. var depth = new THREE.CameraNode( THREE.CameraNode.DEPTH );
  639. depth.near.number = 1;
  640. depth.far.number = 200;
  641. var colors = new THREE.Math3Node(
  642. colorB,
  643. colorA,
  644. depth,
  645. THREE.Math3Node.MIX
  646. );
  647. mtl = new THREE.PhongNodeMaterial();
  648. mtl.color = colors;
  649. // GUI
  650. addGui( 'near', depth.near.number, function( val ) {
  651. depth.near.number = val;
  652. }, false, 1, 1200 );
  653. addGui( 'far', depth.far.number, function( val ) {
  654. depth.far.number = val;
  655. }, false, 1, 1200 );
  656. addGui( 'nearColor', colorA.value.getHex(), function( val ) {
  657. colorA.value.setHex( val );
  658. }, true );
  659. addGui( 'farColor', colorB.value.getHex(), function( val ) {
  660. colorB.value.setHex( val );
  661. }, true );
  662. break;
  663. case 'caustic':
  664. // MATERIAL
  665. mtl = new THREE.StandardNodeMaterial();
  666. var hash2 = new THREE.FunctionNode( [
  667. "vec2 hash2(vec2 p) {",
  668. "return fract(sin(vec2(dot(p, vec2(123.4, 748.6)), dot(p, vec2(547.3, 659.3))))*5232.85324);",
  669. "}"
  670. ].join( "\n" ) );
  671. var voronoi = new THREE.FunctionNode( [
  672. // Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
  673. "float voronoi(vec2 p, in float time) {",
  674. "vec2 n = floor(p);",
  675. "vec2 f = fract(p);",
  676. "float md = 5.0;",
  677. "vec2 m = vec2(0.0);",
  678. "for (int i = -1; i <= 1; i++) {",
  679. "for (int j = -1; j <= 1; j++) {",
  680. "vec2 g = vec2(i, j);",
  681. "vec2 o = hash2(n + g);",
  682. "o = 0.5 + 0.5 * sin(time + 5.038 * o);",
  683. "vec2 r = g + o - f;",
  684. "float d = dot(r, r);",
  685. "if (d < md) {",
  686. "md = d;",
  687. "m = n+g+o;",
  688. "}",
  689. "}",
  690. "}",
  691. "return md;",
  692. "}"
  693. ].join( "\n" ), [ hash2 ] ); // define hash2 as dependencies
  694. var voronoiLayers = new THREE.FunctionNode( [
  695. // based on https://www.shadertoy.com/view/4tXSDf
  696. "float voronoiLayers(vec2 p, in float time) {",
  697. "float v = 0.0;",
  698. "float a = 0.4;",
  699. "for (int i = 0; i < 3; i++) {",
  700. "v += voronoi(p, time) * a;",
  701. "p *= 2.0;",
  702. "a *= 0.5;",
  703. "}",
  704. "return v;",
  705. "}"
  706. ].join( "\n" ), [ voronoi ] ); // define voronoi as dependencies
  707. var time = new THREE.TimerNode();
  708. var timeScale = new THREE.FloatNode( 2 );
  709. var alpha = new THREE.FloatNode( 1 );
  710. var scale = new THREE.FloatNode( .1 );
  711. var intensity = new THREE.FloatNode( 1.5 );
  712. var color = new THREE.ColorNode( 0xFFFFFF );
  713. var colorA = new THREE.ColorNode( 0xFFFFFF );
  714. var colorB = new THREE.ColorNode( 0x0054df );
  715. var worldPos = new THREE.PositionNode( THREE.PositionNode.WORLD );
  716. var worldPosTop = new THREE.SwitchNode( worldPos, 'xz' );
  717. var worldNormal = new THREE.NormalNode( THREE.NormalNode.WORLD );
  718. var mask = new THREE.SwitchNode( worldNormal, 'y' );
  719. // clamp0at1
  720. mask = new THREE.Math1Node( mask, THREE.Math1Node.SAT );
  721. var timeOffset = new THREE.OperatorNode(
  722. time,
  723. timeScale,
  724. THREE.OperatorNode.MUL
  725. );
  726. var uvPos = new THREE.OperatorNode(
  727. worldPosTop,
  728. scale,
  729. THREE.OperatorNode.MUL
  730. );
  731. var voronoi = new THREE.FunctionCallNode( voronoiLayers );
  732. voronoi.inputs.p = uvPos;
  733. voronoi.inputs.time = timeOffset;
  734. var maskCaustic = new THREE.OperatorNode(
  735. alpha,
  736. mask,
  737. THREE.OperatorNode.MUL
  738. );
  739. var voronoiIntensity = new THREE.OperatorNode(
  740. voronoi,
  741. intensity,
  742. THREE.OperatorNode.MUL
  743. );
  744. var voronoiColors = new THREE.Math3Node(
  745. colorB,
  746. colorA,
  747. new THREE.Math1Node( voronoiIntensity, THREE.Math1Node.SAT ), // mix needs clamp
  748. THREE.Math3Node.MIX
  749. );
  750. var caustic = new THREE.Math3Node(
  751. color,
  752. voronoiColors,
  753. maskCaustic,
  754. THREE.Math3Node.MIX
  755. );
  756. var causticLights = new THREE.OperatorNode(
  757. voronoiIntensity,
  758. maskCaustic,
  759. THREE.OperatorNode.MUL
  760. );
  761. mtl.color = caustic;
  762. mtl.ambient = causticLights;
  763. // GUI
  764. addGui( 'timeScale', timeScale.number, function( val ) {
  765. timeScale.number = val;
  766. }, false, 0, 5 );
  767. addGui( 'intensity', intensity.number, function( val ) {
  768. intensity.number = val;
  769. }, false, 0, 3 );
  770. addGui( 'scale', scale.number, function( val ) {
  771. scale.number = val;
  772. }, false, 0, 1 );
  773. addGui( 'alpha', alpha.number, function( val ) {
  774. alpha.number = val;
  775. }, false, 0, 1 );
  776. addGui( 'color', color.value.getHex(), function( val ) {
  777. color.value.setHex( val );
  778. }, true );
  779. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  780. colorA.value.setHex( val );
  781. }, true );
  782. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  783. colorB.value.setHex( val );
  784. }, true );
  785. break;
  786. case 'soft-body':
  787. // MATERIAL
  788. move = true;
  789. mtl = new THREE.StandardNodeMaterial();
  790. var scale = new THREE.FloatNode( 2 );
  791. var colorA = new THREE.ColorNode( 0xFF6633 );
  792. var colorB = new THREE.ColorNode( 0x3366FF );
  793. var pos = new THREE.PositionNode();
  794. var posNorm = new THREE.Math1Node( pos, THREE.Math1Node.NORMALIZE );
  795. var mask = new THREE.SwitchNode( posNorm, 'y' );
  796. var velocity = new THREE.VelocityNode( mesh, {
  797. type: 'elastic',
  798. spring: .8,
  799. friction: .9
  800. } );
  801. var velocityArea = new THREE.OperatorNode(
  802. mask,
  803. scale,
  804. THREE.OperatorNode.MUL
  805. );
  806. var softVelocity = new THREE.OperatorNode(
  807. velocity,
  808. velocityArea,
  809. THREE.OperatorNode.MUL
  810. );
  811. var softPosition = new THREE.OperatorNode(
  812. new THREE.PositionNode(),
  813. softVelocity,
  814. THREE.OperatorNode.ADD
  815. );
  816. var colors = new THREE.Math3Node(
  817. colorB,
  818. colorA,
  819. mask,
  820. THREE.Math3Node.MIX
  821. );
  822. mtl.color = colors;
  823. mtl.transform = softPosition;
  824. // GUI
  825. addGui( 'spring', velocity.params.spring, function( val ) {
  826. velocity.params.spring = val;
  827. }, false, 0, .9 );
  828. addGui( 'friction', velocity.params.friction, function( val ) {
  829. velocity.params.friction = val;
  830. }, false, 0, .9 );
  831. addGui( 'scale', scale.number, function( val ) {
  832. scale.number = val;
  833. }, false, 0, 3 );
  834. addGui( 'softBody', colorA.value.getHex(), function( val ) {
  835. colorA.value.setHex( val );
  836. }, true );
  837. addGui( 'hardBody', colorB.value.getHex(), function( val ) {
  838. colorB.value.setHex( val );
  839. }, true );
  840. break;
  841. case 'firefly':
  842. // MATERIAL
  843. mtl = new THREE.PhongNodeMaterial();
  844. var time = new THREE.TimerNode();
  845. var speed = new THREE.FloatNode( .5 );
  846. var color = new THREE.ColorNode( 0x98ff00 );
  847. var timeSpeed = new THREE.OperatorNode(
  848. time,
  849. speed,
  850. THREE.OperatorNode.MUL
  851. );
  852. var sinCycleInSecs = new THREE.OperatorNode(
  853. timeSpeed,
  854. new THREE.ConstNode( THREE.ConstNode.PI2 ),
  855. THREE.OperatorNode.MUL
  856. );
  857. var cycle = new THREE.Math1Node( sinCycleInSecs, THREE.Math1Node.SIN );
  858. var cycleColor = new THREE.OperatorNode(
  859. cycle,
  860. color,
  861. THREE.OperatorNode.MUL
  862. );
  863. var cos = new THREE.Math1Node( cycleColor, THREE.Math1Node.SIN );
  864. mtl.color = new THREE.ColorNode( 0 );
  865. mtl.emissive = cos;
  866. // GUI
  867. addGui( 'speed', speed.number, function( val ) {
  868. speed.number = val;
  869. }, false, 0, 3 );
  870. break;
  871. }
  872. // build shader
  873. mtl.build();
  874. // set material
  875. mesh.material = mtl;
  876. }
  877. function onWindowResize() {
  878. camera.aspect = window.innerWidth / window.innerHeight;
  879. camera.updateProjectionMatrix();
  880. renderer.setSize( window.innerWidth, window.innerHeight );
  881. }
  882. function animate() {
  883. var delta = clock.getDelta();
  884. if ( move ) {
  885. var time = Date.now() * 0.005;
  886. mesh.position.z = Math.cos( time ) * 10;
  887. mesh.position.y = Math.sin( time ) * 10;
  888. }
  889. else {
  890. mesh.position.z = mesh.position.y = 0;
  891. }
  892. //mesh.rotation.z += .01;
  893. // update material animation and/or gpu calcs (pre-renderer)
  894. mesh.material.updateAnimation( delta );
  895. renderer.render( scene, camera );
  896. requestAnimationFrame( animate );
  897. }
  898. </script>
  899. </body>
  900. </html>