webgpu_shadertoy.html 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <html lang="en">
  2. <head>
  3. <title>three.js webgpu - shadertoy</title>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  6. <link type="text/css" rel="stylesheet" href="main.css">
  7. </head>
  8. <body>
  9. <div id="info">
  10. <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - shadertoy
  11. <br />Shader created by <a href="https://www.shadertoy.com/view/Mt2SzR" target="_blank" rel="noopener">jackdavenport</a> and <a href="https://www.shadertoy.com/view/3tcBzH" target="_blank" rel="noopener">trinketMage</a>.
  12. </div>
  13. <script type="importmap">
  14. {
  15. "imports": {
  16. "three": "../build/three.webgpu.js",
  17. "three/tsl": "../build/three.webgpu.js",
  18. "three/addons/": "./jsm/"
  19. }
  20. }
  21. </script>
  22. <script type="x-shader/x-fragment" id="example1">
  23. // https://www.shadertoy.com/view/Mt2SzR
  24. float random(float x) {
  25. return fract(sin(x) * 10000.);
  26. }
  27. float noise(vec2 p) {
  28. return random(p.x + p.y * 10000.);
  29. }
  30. vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
  31. vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
  32. vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
  33. vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }
  34. float smoothNoise(vec2 p) {
  35. vec2 interp = smoothstep(0., 1., fract(p));
  36. float s = mix(noise(sw(p)), noise(se(p)), interp.x);
  37. float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
  38. return mix(s, n, interp.y);
  39. }
  40. float fractalNoise(vec2 p) {
  41. float x = 0.;
  42. x += smoothNoise(p );
  43. x += smoothNoise(p * 2. ) / 2.;
  44. x += smoothNoise(p * 4. ) / 4.;
  45. x += smoothNoise(p * 8. ) / 8.;
  46. x += smoothNoise(p * 16.) / 16.;
  47. x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
  48. return x;
  49. }
  50. float movingNoise(vec2 p) {
  51. float x = fractalNoise(p + iTime);
  52. float y = fractalNoise(p - iTime);
  53. return fractalNoise(p + vec2(x, y));
  54. }
  55. // call this for water noise function
  56. float nestedNoise(vec2 p) {
  57. float x = movingNoise(p);
  58. float y = movingNoise(p + 100.);
  59. return movingNoise(p + vec2(x, y));
  60. }
  61. void mainImage( out vec4 fragColor, in vec2 fragCoord )
  62. {
  63. vec2 uv = fragCoord.xy / iResolution.xy;
  64. float n = nestedNoise(uv * 6.);
  65. fragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
  66. }
  67. </script>
  68. <script type="x-shader/x-fragment" id="example2">
  69. // https://www.shadertoy.com/view/3tcBzH
  70. float rand(vec2 co){
  71. return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
  72. }
  73. float hermite(float t)
  74. {
  75. return t * t * (3.0 - 2.0 * t);
  76. }
  77. float noise(vec2 co, float frequency)
  78. {
  79. vec2 v = vec2(co.x * frequency, co.y * frequency);
  80. float ix1 = floor(v.x);
  81. float iy1 = floor(v.y);
  82. float ix2 = floor(v.x + 1.0);
  83. float iy2 = floor(v.y + 1.0);
  84. float fx = hermite(fract(v.x));
  85. float fy = hermite(fract(v.y));
  86. float fade1 = mix(rand(vec2(ix1, iy1)), rand(vec2(ix2, iy1)), fx);
  87. float fade2 = mix(rand(vec2(ix1, iy2)), rand(vec2(ix2, iy2)), fx);
  88. return mix(fade1, fade2, fy);
  89. }
  90. float pnoise(vec2 co, float freq, int steps, float persistence)
  91. {
  92. float value = 0.0;
  93. float ampl = 1.0;
  94. float sum = 0.0;
  95. for(int i=0 ; i<steps ; i++)
  96. {
  97. sum += ampl;
  98. value += noise(co, freq) * ampl;
  99. freq *= 2.0;
  100. ampl *= persistence;
  101. }
  102. return value / sum;
  103. }
  104. void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
  105. vec2 uv = fragCoord.xy / iResolution.xy;
  106. float gradient = 1.0 - uv.y;
  107. float gradientStep = 0.2;
  108. vec2 pos = fragCoord.xy / iResolution.x;
  109. pos.y -= iTime * 0.3125;
  110. vec4 brighterColor = vec4(1.0, 0.65, 0.1, 0.25);
  111. vec4 darkerColor = vec4(1.0, 0.0, 0.15, 0.0625);
  112. vec4 middleColor = mix(brighterColor, darkerColor, 0.5);
  113. float noiseTexel = pnoise(pos, 10.0, 5, 0.5);
  114. float firstStep = smoothstep(0.0, noiseTexel, gradient);
  115. float darkerColorStep = smoothstep(0.0, noiseTexel, gradient - gradientStep);
  116. float darkerColorPath = firstStep - darkerColorStep;
  117. vec4 color = mix(brighterColor, darkerColor, darkerColorPath);
  118. float middleColorStep = smoothstep(0.0, noiseTexel, gradient - 0.2 * 2.0);
  119. color = mix(color, middleColor, darkerColorStep - middleColorStep);
  120. color = mix(vec4(0.0), color, firstStep);
  121. fragColor = color;
  122. }
  123. </script>
  124. <script type="module">
  125. import * as THREE from 'three';
  126. import * as TSL from 'three/tsl';
  127. import Transpiler from 'three/addons/transpiler/Transpiler.js';
  128. import ShaderToyDecoder from 'three/addons/transpiler/ShaderToyDecoder.js';
  129. import TSLEncoder from 'three/addons/transpiler/TSLEncoder.js';
  130. class ShaderToyNode extends THREE.Node {
  131. constructor() {
  132. super( 'vec4' );
  133. this.mainImage = null;
  134. }
  135. transpile( glsl, iife = false ) {
  136. const decoder = new ShaderToyDecoder();
  137. const encoder = new TSLEncoder();
  138. encoder.iife = iife;
  139. encoder.uniqueNames = true;
  140. const jsCode = new Transpiler( decoder, encoder ).parse( glsl );
  141. return jsCode;
  142. }
  143. parse( glsl ) {
  144. const jsCode = this.transpile( glsl, true );
  145. const { mainImage } = eval( jsCode )( TSL );
  146. this.mainImage = mainImage;
  147. }
  148. async parseAsync( glsl ) {
  149. const jsCode = this.transpile( glsl );
  150. const { mainImage } = await import( `data:text/javascript,${ encodeURIComponent( jsCode ) }` );
  151. this.mainImage = mainImage;
  152. }
  153. setup( builder ) {
  154. if ( this.mainImage === null ) {
  155. throw new Error( 'ShaderToyNode: .parse() must be called first.' );
  156. }
  157. return this.mainImage();
  158. }
  159. }
  160. let renderer, camera, scene;
  161. const dpr = window.devicePixelRatio;
  162. init();
  163. function init() {
  164. const example1Code = document.getElementById( 'example1' ).textContent;
  165. const example2Code = document.getElementById( 'example2' ).textContent;
  166. const shaderToy1Node = new ShaderToyNode();
  167. shaderToy1Node.parse( example1Code );
  168. const shaderToy2Node = new ShaderToyNode();
  169. shaderToy2Node.parse( example2Code );
  170. //
  171. camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  172. scene = new THREE.Scene();
  173. const geometry = new THREE.PlaneGeometry( 2, 2 );
  174. const material = new THREE.MeshBasicNodeMaterial();
  175. material.colorNode = TSL.oscSine( TSL.timerLocal( .3 ) ).mix( shaderToy1Node, shaderToy2Node );
  176. const quad = new THREE.Mesh( geometry, material );
  177. scene.add( quad );
  178. //
  179. renderer = new THREE.WebGPURenderer( { antialias: true } );
  180. renderer.setPixelRatio( dpr );
  181. renderer.setSize( window.innerWidth, window.innerHeight );
  182. renderer.setAnimationLoop( animate );
  183. renderer.outputColorSpace = THREE.LinearSRGBColorSpace;
  184. document.body.appendChild( renderer.domElement );
  185. window.addEventListener( 'resize', onWindowResize );
  186. }
  187. function onWindowResize() {
  188. camera.aspect = window.innerWidth / window.innerHeight;
  189. camera.updateProjectionMatrix();
  190. renderer.setSize( window.innerWidth, window.innerHeight );
  191. }
  192. function animate() {
  193. renderer.render( scene, camera );
  194. }
  195. </script>
  196. </body>
  197. </html>