webgl_materials_nodes.html 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  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/NodeLib.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 (vec3)
  191. //mtl.alpha = // opacity (float)
  192. //mtl.specular = // specular color (vec3)
  193. //mtl.shininess = // shininess (float)
  194. //mtl.normal = // normalmap (vec3)
  195. //mtl.normalScale = // normalmap scale (vec2)
  196. //mtl.emissive = // emissive color (vec3)
  197. //mtl.ambient = // ambient color (vec3)
  198. //mtl.shadow = // shadowmap (vec3)
  199. //mtl.ao = // ambient occlusion (float)
  200. //mtl.environment = // reflection/refraction (vec3)
  201. //mtl.environmentAlpha = // environment alpha (float)
  202. //mtl.transform = // vertex transformation (vec3)
  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.environmentAlpha = 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 (vec3)
  216. //mtl.alpha = // opacity (float)
  217. //mtl.roughness = // roughness (float)
  218. //mtl.metalness = // metalness (float)
  219. //mtl.normal = // normalmap (vec3)
  220. //mtl.normalScale = // normalmap scale (vec2)
  221. //mtl.emissive = // emissive color (vec3)
  222. //mtl.ambient = // ambient color (vec3)
  223. //mtl.shadow = // shadowmap (vec3)
  224. //mtl.ao = // ambient occlusion (float)
  225. //mtl.environment = // reflection/refraction (vec3)
  226. //mtl.transform = // vertex transformation (vec3)
  227. var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
  228. var normalScale = new THREE.FloatNode( .3 );
  229. var roughnessA = new THREE.FloatNode( .5 );
  230. var metalnessA = new THREE.FloatNode( .5 );
  231. var roughnessB = new THREE.FloatNode( 0 );
  232. var metalnessB = new THREE.FloatNode( 1 );
  233. var roughness = new THREE.Math3Node(
  234. roughnessA,
  235. roughnessB,
  236. mask,
  237. THREE.Math3Node.MIX
  238. );
  239. var metalness = new THREE.Math3Node(
  240. metalnessA,
  241. metalnessB,
  242. mask,
  243. THREE.Math3Node.MIX
  244. );
  245. var normalMask = new THREE.OperatorNode(
  246. new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
  247. normalScale,
  248. THREE.OperatorNode.MUL
  249. );
  250. mtl.color = new THREE.ColorNode( 0xFFFFFF );
  251. mtl.roughness = roughness;
  252. mtl.metalness = metalness;
  253. mtl.environment = new THREE.CubeTextureNode( cubemap );
  254. mtl.normal = new THREE.TextureNode( grassNormal );
  255. mtl.normalScale = normalMask;
  256. // GUI
  257. addGui( 'color', mtl.color.value.getHex(), function( val ) {
  258. mtl.color.value.setHex( val );
  259. }, true );
  260. addGui( 'roughnessA', roughnessA.number, function( val ) {
  261. roughnessA.number = val;
  262. }, false, 0, 1 );
  263. addGui( 'metalnessA', metalnessA.number, function( val ) {
  264. metalnessA.number = val;
  265. }, false, 0, 1 );
  266. addGui( 'roughnessB', roughnessB.number, function( val ) {
  267. roughnessB.number = val;
  268. }, false, 0, 1 );
  269. addGui( 'metalnessB', metalnessB.number, function( val ) {
  270. metalnessB.number = val;
  271. }, false, 0, 1 );
  272. addGui( 'normalScale', normalScale.number, function( val ) {
  273. normalScale.number = val;
  274. }, false, 0, 1 );
  275. break;
  276. case 'wave':
  277. // MATERIAL
  278. mtl = new THREE.PhongNodeMaterial();
  279. var time = new THREE.TimerNode();
  280. var speed = new THREE.FloatNode( 5 );
  281. var scale = new THREE.FloatNode( 1 );
  282. var worldScale = new THREE.FloatNode( .4 );
  283. var colorA = new THREE.ColorNode( 0xFFFFFF );
  284. var colorB = new THREE.ColorNode( 0x0054df );
  285. var uv = new THREE.UVNode();
  286. var timeScale = new THREE.OperatorNode(
  287. time,
  288. speed,
  289. THREE.OperatorNode.MUL
  290. );
  291. var worldScl = new THREE.OperatorNode(
  292. new THREE.PositionNode(),
  293. worldScale,
  294. THREE.OperatorNode.MUL
  295. );
  296. var posContinuous = new THREE.OperatorNode(
  297. worldScl,
  298. timeScale,
  299. THREE.OperatorNode.ADD
  300. );
  301. var wave = new THREE.Math1Node( posContinuous, THREE.Math1Node.SIN );
  302. wave = new THREE.SwitchNode( wave, 'x' );
  303. var waveScale = new THREE.OperatorNode(
  304. wave,
  305. scale,
  306. THREE.OperatorNode.MUL
  307. );
  308. var displaceY = new THREE.JoinNode(
  309. new THREE.FloatNode(),
  310. waveScale,
  311. new THREE.FloatNode()
  312. );
  313. var displace = new THREE.OperatorNode(
  314. new THREE.NormalNode(),
  315. displaceY,
  316. THREE.OperatorNode.MUL
  317. );
  318. var blend = new THREE.OperatorNode(
  319. new THREE.PositionNode(),
  320. displaceY,
  321. THREE.OperatorNode.ADD
  322. );
  323. var color = new THREE.Math3Node(
  324. colorB,
  325. colorA,
  326. wave,
  327. THREE.Math3Node.MIX
  328. );
  329. mtl.color = color;
  330. mtl.transform = blend;
  331. // GUI
  332. addGui( 'speed', speed.number, function( val ) {
  333. speed.number = val;
  334. }, false, 0, 10 );
  335. addGui( 'scale', scale.number, function( val ) {
  336. scale.number = val;
  337. }, false, 0, 3 );
  338. addGui( 'worldScale', worldScale.number, function( val ) {
  339. worldScale.number = val;
  340. }, false, 0, 1 );
  341. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  342. colorA.value.setHex( val );
  343. }, true );
  344. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  345. colorB.value.setHex( val );
  346. }, true );
  347. addGui( 'useNormals', false, function( val ) {
  348. blend.b = val ? displace : displaceY;
  349. mtl.build();
  350. } );
  351. break;
  352. case 'rim':
  353. // MATERIAL
  354. mtl = new THREE.PhongNodeMaterial();
  355. var intensity = 1.3;
  356. var power = new THREE.FloatNode( 3 );
  357. var color = new THREE.ColorNode( 0xFFFFFF );
  358. var viewZ = new THREE.Math2Node(
  359. new THREE.NormalNode( THREE.NormalNode.VIEW ),
  360. new THREE.Vector3Node( 0, 0, - intensity ),
  361. THREE.Math2Node.DOT
  362. );
  363. var rim = new THREE.OperatorNode(
  364. viewZ,
  365. new THREE.FloatNode( intensity ),
  366. THREE.OperatorNode.ADD
  367. );
  368. var rimPower = new THREE.Math2Node(
  369. rim,
  370. power,
  371. THREE.Math2Node.POW
  372. );
  373. var rimColor = new THREE.OperatorNode(
  374. rimPower,
  375. color,
  376. THREE.OperatorNode.MUL
  377. );
  378. mtl.color = new THREE.ColorNode( 0x111111 );
  379. mtl.emissive = rimColor;
  380. // GUI
  381. addGui( 'color', color.value.getHex(), function( val ) {
  382. color.value.setHex( val );
  383. }, true );
  384. addGui( 'intensity', intensity, function( val ) {
  385. intensity = val;
  386. viewZ.b.z = - intensity;
  387. rim.b.number = intensity;
  388. }, false, 0, 3 );
  389. addGui( 'power', power.number, function( val ) {
  390. power.number = val;
  391. }, false, 0, 6 );
  392. addGui( 'xray', false, function( val ) {
  393. if ( val ) {
  394. mtl.emissive = color;
  395. mtl.alpha = rimPower;
  396. mtl.blending = THREE.AdditiveBlending;
  397. mtl.depthWrite = false;
  398. }
  399. else {
  400. mtl.emissive = rimColor;
  401. mtl.alpha = null;
  402. mtl.blending = THREE.NormalBlending;
  403. mtl.depthWrite = true;
  404. }
  405. mtl.build();
  406. } );
  407. break;
  408. case 'fresnel':
  409. // MATERIAL
  410. mtl = new THREE.PhongNodeMaterial();
  411. var reflectance = new THREE.FloatNode( 1.3 );
  412. var power = new THREE.FloatNode( 1 );
  413. var color = new THREE.CubeTextureNode( cubemap );
  414. var viewZ = new THREE.Math2Node(
  415. new THREE.NormalNode( THREE.NormalNode.VIEW ),
  416. new THREE.Vector3Node( 0, 0, - 1 ),
  417. THREE.Math2Node.DOT
  418. );
  419. var theta = new THREE.OperatorNode(
  420. viewZ,
  421. new THREE.FloatNode( 1 ),
  422. THREE.OperatorNode.ADD
  423. );
  424. var thetaPower = new THREE.Math2Node(
  425. theta,
  426. power,
  427. THREE.Math2Node.POW
  428. );
  429. var fresnel = new THREE.OperatorNode(
  430. reflectance,
  431. thetaPower,
  432. THREE.OperatorNode.MUL
  433. );
  434. mtl.color = new THREE.ColorNode( 0x3399FF );
  435. mtl.environment = color;
  436. mtl.environmentAlpha = new THREE.Math1Node( fresnel, THREE.Math1Node.SAT );
  437. // GUI
  438. addGui( 'reflectance', reflectance.number, function( val ) {
  439. reflectance.number = val;
  440. }, false, 0, 3 );
  441. addGui( 'power', power.number, function( val ) {
  442. power.number = val;
  443. }, false, 0, 5 );
  444. break;
  445. case 'layers':
  446. // MATERIAL
  447. mtl = new THREE.PhongNodeMaterial();
  448. var tex1 = new THREE.TextureNode( grass );
  449. var tex2 = new THREE.TextureNode( brick );
  450. var offset = new THREE.FloatNode( 0 );
  451. var scale = new THREE.FloatNode( 1 );
  452. var uv = new THREE.UVNode();
  453. var uvOffset = new THREE.OperatorNode(
  454. offset,
  455. uv,
  456. THREE.OperatorNode.ADD
  457. );
  458. var uvScale = new THREE.OperatorNode(
  459. uvOffset,
  460. scale,
  461. THREE.OperatorNode.MUL
  462. );
  463. var mask = new THREE.TextureNode( decalDiffuse, uvScale );
  464. var maskAlphaChannel = new THREE.SwitchNode( mask, 'w' );
  465. var blend = new THREE.Math3Node(
  466. tex1,
  467. tex2,
  468. maskAlphaChannel,
  469. THREE.Math3Node.MIX
  470. );
  471. mtl.color = blend;
  472. // GUI
  473. addGui( 'offset', offset.number, function( val ) {
  474. offset.number = val;
  475. }, false, 0, 1 );
  476. addGui( 'scale', scale.number, function( val ) {
  477. scale.number = val;
  478. }, false, 0, 10 );
  479. break;
  480. case 'saturation':
  481. // MATERIAL
  482. mtl = new THREE.StandardNodeMaterial();
  483. var tex = new THREE.TextureNode( brick );
  484. var sat = new THREE.FloatNode( 0 );
  485. var satrgb = new THREE.FunctionNode( [
  486. "vec3 satrgb(vec3 rgb, float adjustment) {",
  487. //"const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
  488. "vec3 intensity = vec3(dot(rgb, LUMA));",
  489. "return mix(intensity, rgb, adjustment);",
  490. "}"
  491. ].join( "\n" ) );
  492. var saturation = new THREE.FunctionCallNode( satrgb );
  493. saturation.inputs.rgb = tex;
  494. saturation.inputs.adjustment = sat;
  495. // or try
  496. //saturation.inputs[0] = tex;
  497. //saturation.inputs[1] = sat;
  498. mtl.color = saturation;
  499. mtl.environment = new THREE.CubeTextureNode( cubemap ); // optional
  500. // GUI
  501. addGui( 'saturation', sat.number, function( val ) {
  502. sat.number = val;
  503. }, false, 0, 2 );
  504. break;
  505. case 'top-bottom':
  506. // MATERIAL
  507. mtl = new THREE.PhongNodeMaterial();
  508. var top = new THREE.TextureNode( grass );
  509. var bottom = new THREE.TextureNode( brick );
  510. var normal = new THREE.NormalNode( THREE.NormalNode.WORLD );
  511. var normalY = new THREE.SwitchNode( normal, 'y' );
  512. var hard = new THREE.FloatNode( 9 );
  513. var offset = new THREE.FloatNode( - 2.5 );
  514. var hardClamp = new THREE.OperatorNode(
  515. normalY,
  516. hard,
  517. THREE.OperatorNode.MUL
  518. );
  519. var offsetClamp = new THREE.OperatorNode(
  520. hardClamp,
  521. offset,
  522. THREE.OperatorNode.ADD
  523. );
  524. var clamp0at1 = new THREE.Math1Node( offsetClamp, THREE.Math1Node.SAT );
  525. var blend = new THREE.Math3Node( top, bottom, clamp0at1, THREE.Math3Node.MIX );
  526. mtl.color = blend;
  527. // GUI
  528. addGui( 'hard', hard.number, function( val ) {
  529. hard.number = val;
  530. }, false, 0, 20 );
  531. addGui( 'offset', offset.number, function( val ) {
  532. offset.number = val;
  533. }, false, - 10, 10 );
  534. break;
  535. case 'displace':
  536. // MATERIAL
  537. mtl = new THREE.PhongNodeMaterial();
  538. var time = new THREE.TimerNode();
  539. var scale = new THREE.FloatNode( 2 );
  540. var speed = new THREE.FloatNode( .2 );
  541. var colorA = new THREE.ColorNode( 0xFFFFFF );
  542. var colorB = new THREE.ColorNode( 0x0054df );
  543. var uv = new THREE.UVNode();
  544. var timeScl = new THREE.OperatorNode(
  545. time,
  546. speed,
  547. THREE.OperatorNode.MUL
  548. );
  549. var displaceOffset = new THREE.OperatorNode(
  550. timeScl,
  551. uv,
  552. THREE.OperatorNode.ADD
  553. );
  554. var tex = new THREE.TextureNode( cloud, displaceOffset );
  555. var texArea = new THREE.SwitchNode( tex, 'w' );
  556. var displace = new THREE.OperatorNode(
  557. new THREE.NormalNode(),
  558. texArea,
  559. THREE.OperatorNode.MUL
  560. );
  561. var displaceScale = new THREE.OperatorNode(
  562. displace,
  563. scale,
  564. THREE.OperatorNode.MUL
  565. );
  566. var blend = new THREE.OperatorNode(
  567. new THREE.PositionNode(),
  568. displaceScale,
  569. THREE.OperatorNode.ADD
  570. );
  571. var color = new THREE.Math3Node(
  572. colorB,
  573. colorA,
  574. texArea,
  575. THREE.Math3Node.MIX
  576. );
  577. mtl.color = mtl.specular = new THREE.ColorNode( 0 );
  578. mtl.emissive = color;
  579. mtl.transform = blend;
  580. // GUI
  581. addGui( 'speed', speed.number, function( val ) {
  582. speed.number = val;
  583. }, false, 0, 1 );
  584. addGui( 'scale', scale.number, function( val ) {
  585. scale.number = val;
  586. }, false, 0, 10 );
  587. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  588. colorA.value.setHex( val );
  589. }, true );
  590. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  591. colorB.value.setHex( val );
  592. }, true );
  593. break;
  594. case 'smoke':
  595. // MATERIAL
  596. mtl = new THREE.PhongNodeMaterial();
  597. var time = new THREE.TimerNode();
  598. var uv = new THREE.UVNode();
  599. var timeSpeedA = new THREE.OperatorNode(
  600. time,
  601. new THREE.Vector2Node( 0.3, 0.1 ),
  602. THREE.OperatorNode.MUL
  603. );
  604. var timeSpeedB = new THREE.OperatorNode(
  605. time,
  606. new THREE.Vector2Node( 0.15, 0.4 ),
  607. THREE.OperatorNode.MUL
  608. );
  609. var uvOffsetA = new THREE.OperatorNode(
  610. timeSpeedA,
  611. uv,
  612. THREE.OperatorNode.ADD
  613. );
  614. var uvOffsetB = new THREE.OperatorNode(
  615. timeSpeedB,
  616. uv,
  617. THREE.OperatorNode.ADD
  618. );
  619. var cloudA = new THREE.TextureNode( cloud, uvOffsetA );
  620. var cloudB = new THREE.TextureNode( cloud, uvOffsetB );
  621. var clouds = new THREE.OperatorNode(
  622. cloudA,
  623. cloudB,
  624. THREE.OperatorNode.ADD
  625. );
  626. mtl.environment = new THREE.ColorNode( 0xFFFFFF );
  627. mtl.alpha = clouds;
  628. // GUI
  629. addGui( 'color', mtl.environment.value.getHex(), function( val ) {
  630. mtl.environment.value.setHex( val );
  631. }, true );
  632. break;
  633. case 'camera-depth':
  634. // MATERIAL
  635. var colorA = new THREE.ColorNode( 0xFFFFFF );
  636. var colorB = new THREE.ColorNode( 0x0054df );
  637. var depth = new THREE.CameraNode( THREE.CameraNode.DEPTH );
  638. depth.near.number = 1;
  639. depth.far.number = 200;
  640. var colors = new THREE.Math3Node(
  641. colorB,
  642. colorA,
  643. depth,
  644. THREE.Math3Node.MIX
  645. );
  646. mtl = new THREE.PhongNodeMaterial();
  647. mtl.color = colors;
  648. // GUI
  649. addGui( 'near', depth.near.number, function( val ) {
  650. depth.near.number = val;
  651. }, false, 1, 1200 );
  652. addGui( 'far', depth.far.number, function( val ) {
  653. depth.far.number = val;
  654. }, false, 1, 1200 );
  655. addGui( 'nearColor', colorA.value.getHex(), function( val ) {
  656. colorA.value.setHex( val );
  657. }, true );
  658. addGui( 'farColor', colorB.value.getHex(), function( val ) {
  659. colorB.value.setHex( val );
  660. }, true );
  661. break;
  662. case 'caustic':
  663. // MATERIAL
  664. mtl = new THREE.StandardNodeMaterial();
  665. var hash2 = new THREE.FunctionNode( [
  666. "vec2 hash2(vec2 p) {",
  667. "return fract(sin(vec2(dot(p, vec2(123.4, 748.6)), dot(p, vec2(547.3, 659.3))))*5232.85324);",
  668. "}"
  669. ].join( "\n" ) );
  670. var voronoi = new THREE.FunctionNode( [
  671. // Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
  672. "float voronoi(vec2 p, in float time) {",
  673. "vec2 n = floor(p);",
  674. "vec2 f = fract(p);",
  675. "float md = 5.0;",
  676. "vec2 m = vec2(0.0);",
  677. "for (int i = -1; i <= 1; i++) {",
  678. "for (int j = -1; j <= 1; j++) {",
  679. "vec2 g = vec2(i, j);",
  680. "vec2 o = hash2(n + g);",
  681. "o = 0.5 + 0.5 * sin(time + 5.038 * o);",
  682. "vec2 r = g + o - f;",
  683. "float d = dot(r, r);",
  684. "if (d < md) {",
  685. "md = d;",
  686. "m = n+g+o;",
  687. "}",
  688. "}",
  689. "}",
  690. "return md;",
  691. "}"
  692. ].join( "\n" ), [ hash2 ] ); // define hash2 as dependencies
  693. var voronoiLayers = new THREE.FunctionNode( [
  694. // based on https://www.shadertoy.com/view/4tXSDf
  695. "float voronoiLayers(vec2 p, in float time) {",
  696. "float v = 0.0;",
  697. "float a = 0.4;",
  698. "for (int i = 0; i < 3; i++) {",
  699. "v += voronoi(p, time) * a;",
  700. "p *= 2.0;",
  701. "a *= 0.5;",
  702. "}",
  703. "return v;",
  704. "}"
  705. ].join( "\n" ), [ voronoi ] ); // define voronoi as dependencies
  706. var time = new THREE.TimerNode();
  707. var timeScale = new THREE.FloatNode( 2 );
  708. var alpha = new THREE.FloatNode( 1 );
  709. var scale = new THREE.FloatNode( .1 );
  710. var intensity = new THREE.FloatNode( 1.5 );
  711. var color = new THREE.ColorNode( 0xFFFFFF );
  712. var colorA = new THREE.ColorNode( 0xFFFFFF );
  713. var colorB = new THREE.ColorNode( 0x0054df );
  714. var worldPos = new THREE.PositionNode( THREE.PositionNode.WORLD );
  715. var worldPosTop = new THREE.SwitchNode( worldPos, 'xz' );
  716. var worldNormal = new THREE.NormalNode( THREE.NormalNode.WORLD );
  717. var mask = new THREE.SwitchNode( worldNormal, 'y' );
  718. // clamp0at1
  719. mask = new THREE.Math1Node( mask, THREE.Math1Node.SAT );
  720. var timeOffset = new THREE.OperatorNode(
  721. time,
  722. timeScale,
  723. THREE.OperatorNode.MUL
  724. );
  725. var uvPos = new THREE.OperatorNode(
  726. worldPosTop,
  727. scale,
  728. THREE.OperatorNode.MUL
  729. );
  730. var voronoi = new THREE.FunctionCallNode( voronoiLayers );
  731. voronoi.inputs.p = uvPos;
  732. voronoi.inputs.time = timeOffset;
  733. var maskCaustic = new THREE.OperatorNode(
  734. alpha,
  735. mask,
  736. THREE.OperatorNode.MUL
  737. );
  738. var voronoiIntensity = new THREE.OperatorNode(
  739. voronoi,
  740. intensity,
  741. THREE.OperatorNode.MUL
  742. );
  743. var voronoiColors = new THREE.Math3Node(
  744. colorB,
  745. colorA,
  746. new THREE.Math1Node( voronoiIntensity, THREE.Math1Node.SAT ), // mix needs clamp
  747. THREE.Math3Node.MIX
  748. );
  749. var caustic = new THREE.Math3Node(
  750. color,
  751. voronoiColors,
  752. maskCaustic,
  753. THREE.Math3Node.MIX
  754. );
  755. var causticLights = new THREE.OperatorNode(
  756. voronoiIntensity,
  757. maskCaustic,
  758. THREE.OperatorNode.MUL
  759. );
  760. mtl.color = caustic;
  761. mtl.ambient = causticLights;
  762. // GUI
  763. addGui( 'timeScale', timeScale.number, function( val ) {
  764. timeScale.number = val;
  765. }, false, 0, 5 );
  766. addGui( 'intensity', intensity.number, function( val ) {
  767. intensity.number = val;
  768. }, false, 0, 3 );
  769. addGui( 'scale', scale.number, function( val ) {
  770. scale.number = val;
  771. }, false, 0, 1 );
  772. addGui( 'alpha', alpha.number, function( val ) {
  773. alpha.number = val;
  774. }, false, 0, 1 );
  775. addGui( 'color', color.value.getHex(), function( val ) {
  776. color.value.setHex( val );
  777. }, true );
  778. addGui( 'colorA', colorA.value.getHex(), function( val ) {
  779. colorA.value.setHex( val );
  780. }, true );
  781. addGui( 'colorB', colorB.value.getHex(), function( val ) {
  782. colorB.value.setHex( val );
  783. }, true );
  784. break;
  785. case 'soft-body':
  786. // MATERIAL
  787. move = true;
  788. mtl = new THREE.StandardNodeMaterial();
  789. var scale = new THREE.FloatNode( 2 );
  790. var colorA = new THREE.ColorNode( 0xFF6633 );
  791. var colorB = new THREE.ColorNode( 0x3366FF );
  792. var pos = new THREE.PositionNode();
  793. var posNorm = new THREE.Math1Node( pos, THREE.Math1Node.NORMALIZE );
  794. var mask = new THREE.SwitchNode( posNorm, 'y' );
  795. var velocity = new THREE.VelocityNode( mesh, {
  796. type: 'elastic',
  797. spring: .8,
  798. friction: .9
  799. } );
  800. var velocityArea = new THREE.OperatorNode(
  801. mask,
  802. scale,
  803. THREE.OperatorNode.MUL
  804. );
  805. var softVelocity = new THREE.OperatorNode(
  806. velocity,
  807. velocityArea,
  808. THREE.OperatorNode.MUL
  809. );
  810. var softPosition = new THREE.OperatorNode(
  811. new THREE.PositionNode(),
  812. softVelocity,
  813. THREE.OperatorNode.ADD
  814. );
  815. var colors = new THREE.Math3Node(
  816. colorB,
  817. colorA,
  818. mask,
  819. THREE.Math3Node.MIX
  820. );
  821. mtl.color = colors;
  822. mtl.transform = softPosition;
  823. // GUI
  824. addGui( 'spring', velocity.params.spring, function( val ) {
  825. velocity.params.spring = val;
  826. }, false, 0, .9 );
  827. addGui( 'friction', velocity.params.friction, function( val ) {
  828. velocity.params.friction = val;
  829. }, false, 0, .9 );
  830. addGui( 'scale', scale.number, function( val ) {
  831. scale.number = val;
  832. }, false, 0, 3 );
  833. addGui( 'softBody', colorA.value.getHex(), function( val ) {
  834. colorA.value.setHex( val );
  835. }, true );
  836. addGui( 'hardBody', colorB.value.getHex(), function( val ) {
  837. colorB.value.setHex( val );
  838. }, true );
  839. break;
  840. case 'firefly':
  841. // MATERIAL
  842. mtl = new THREE.PhongNodeMaterial();
  843. var time = new THREE.TimerNode();
  844. var speed = new THREE.FloatNode( .5 );
  845. var color = new THREE.ColorNode( 0x98ff00 );
  846. var timeSpeed = new THREE.OperatorNode(
  847. time,
  848. speed,
  849. THREE.OperatorNode.MUL
  850. );
  851. var sinCycleInSecs = new THREE.OperatorNode(
  852. timeSpeed,
  853. new THREE.ConstNode( THREE.ConstNode.PI2 ),
  854. THREE.OperatorNode.MUL
  855. );
  856. var cycle = new THREE.Math1Node( sinCycleInSecs, THREE.Math1Node.SIN );
  857. var cycleColor = new THREE.OperatorNode(
  858. cycle,
  859. color,
  860. THREE.OperatorNode.MUL
  861. );
  862. var cos = new THREE.Math1Node( cycleColor, THREE.Math1Node.SIN );
  863. mtl.color = new THREE.ColorNode( 0 );
  864. mtl.emissive = cos;
  865. // GUI
  866. addGui( 'speed', speed.number, function( val ) {
  867. speed.number = val;
  868. }, false, 0, 3 );
  869. break;
  870. }
  871. // build shader
  872. mtl.build();
  873. // set material
  874. mesh.material = mtl;
  875. }
  876. function onWindowResize() {
  877. camera.aspect = window.innerWidth / window.innerHeight;
  878. camera.updateProjectionMatrix();
  879. renderer.setSize( window.innerWidth, window.innerHeight );
  880. }
  881. function animate() {
  882. var delta = clock.getDelta();
  883. if ( move ) {
  884. var time = Date.now() * 0.005;
  885. mesh.position.z = Math.cos( time ) * 10;
  886. mesh.position.y = Math.sin( time ) * 10;
  887. }
  888. else {
  889. mesh.position.z = mesh.position.y = 0;
  890. }
  891. //mesh.rotation.z += .01;
  892. // update material animation and/or gpu calcs (pre-renderer)
  893. mesh.material.updateAnimation( delta );
  894. renderer.render( scene, camera );
  895. requestAnimationFrame( animate );
  896. }
  897. </script>
  898. </body>
  899. </html>