webgl_materials_nodes.html 30 KB

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