JAVASCRIPT   60

FireShader.js

Guest on 29th July 2021 03:14:25 PM

  1. /**
  2.  * @author mattatz / http://mattatz.github.io
  3.  *
  4.  * Ray tracing based real-time procedural volumetric fire shader.
  5.  *
  6.  * Based on
  7.  * Alfred et al. Real-Time procedural volumetric fire / http://dl.acm.org/citation.cfm?id=1230131
  8.  * and
  9.  * webgl-noise / https://github.com/ashima/webgl-noise/blob/master/src/noise3D.glsl
  10.  * and
  11.  * primitive: blog | object space raymarching / https://github.com/ashima/webgl-noise/blob/master/src/noise3D.glsl
  12.  */
  13.  
  14. THREE.FireShader = {
  15.  
  16.     defines: {
  17.         "ITERATIONS"    : "20",
  18.         "OCTIVES"       : "3"
  19.     },
  20.  
  21.     uniforms: {
  22.         "fireTex"       : { type : "t",     value : null },
  23.         "color"         : { type : "c",     value : null },
  24.         "time"          : { type : "f",     value : 0.0 },
  25.         "seed"          : { type : "f",     value : 0.0 },
  26.         "invModelMatrix": { type : "m4",    value : null },
  27.         "scale"         : { type : "v3",    value : null },
  28.  
  29.         "noiseScale"    : { type : "v4",    value : new THREE.Vector4(1, 2, 1, 0.3) },
  30.         "magnitude"     : { type : "f",     value : 1.3 },
  31.         "lacunarity"    : { type : "f",     value : 2.0 },
  32.         "gain"          : { type : "f",     value : 0.5 }
  33.     },
  34.  
  35.     vertexShader: [
  36.         "varying vec3 vWorldPos;",
  37.         "void main() {",
  38.             "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
  39.             "vWorldPos = (modelMatrix * vec4(position, 1.0)).xyz;",
  40.         "}"
  41.     ].join("\n"),
  42.  
  43.     fragmentShader: [
  44.         "uniform vec3 color;",
  45.         "uniform float time;",
  46.         "uniform float seed;",
  47.         "uniform mat4 invModelMatrix;",
  48.         "uniform vec3 scale;",
  49.  
  50.         "uniform vec4 noiseScale;",
  51.         "uniform float magnitude;",
  52.         "uniform float lacunarity;",
  53.         "uniform float gain;",
  54.  
  55.         "uniform sampler2D fireTex;",
  56.  
  57.         "varying vec3 vWorldPos;",
  58.  
  59.         // GLSL simplex noise function by ashima / https://github.com/ashima/webgl-noise/blob/master/src/noise3D.glsl
  60.         // -------- simplex noise
  61.         "vec3 mod289(vec3 x) {",
  62.             "return x - floor(x * (1.0 / 289.0)) * 289.0;",
  63.         "}",
  64.  
  65.         "vec4 mod289(vec4 x) {",
  66.             "return x - floor(x * (1.0 / 289.0)) * 289.0;",
  67.         "}",
  68.  
  69.         "vec4 permute(vec4 x) {",
  70.             "return mod289(((x * 34.0) + 1.0) * x);",
  71.         "}",
  72.  
  73.         "vec4 taylorInvSqrt(vec4 r) {",
  74.             "return 1.79284291400159 - 0.85373472095314 * r;",
  75.         "}",
  76.  
  77.         "float snoise(vec3 v) {",
  78.             "const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0);",
  79.             "const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);",
  80.  
  81.             // First corner
  82.             "vec3 i  = floor(v + dot(v, C.yyy));",
  83.             "vec3 x0 = v - i + dot(i, C.xxx);",
  84.  
  85.             // Other corners
  86.             "vec3 g = step(x0.yzx, x0.xyz);",
  87.             "vec3 l = 1.0 - g;",
  88.             "vec3 i1 = min(g.xyz, l.zxy);",
  89.             "vec3 i2 = max(g.xyz, l.zxy);",
  90.  
  91.             //   x0 = x0 - 0.0 + 0.0 * C.xxx;
  92.             //   x1 = x0 - i1  + 1.0 * C.xxx;
  93.             //   x2 = x0 - i2  + 2.0 * C.xxx;
  94.             //   x3 = x0 - 1.0 + 3.0 * C.xxx;
  95.             "vec3 x1 = x0 - i1 + C.xxx;",
  96.             "vec3 x2 = x0 - i2 + C.yyy;", // 2.0*C.x = 1/3 = C.y
  97.             "vec3 x3 = x0 - D.yyy;",      // -1.0+3.0*C.x = -0.5 = -D.y
  98.  
  99.             // Permutations
  100.             "i = mod289(i); ",
  101.             "vec4 p = permute(permute(permute( ",
  102.                     "i.z + vec4(0.0, i1.z, i2.z, 1.0))",
  103.                     "+ i.y + vec4(0.0, i1.y, i2.y, 1.0)) ",
  104.                     "+ i.x + vec4(0.0, i1.x, i2.x, 1.0));",
  105.  
  106.             // Gradients: 7x7 points over a square, mapped onto an octahedron.
  107.             // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
  108.             "float n_ = 0.142857142857;", // 1.0/7.0
  109.             "vec3  ns = n_ * D.wyz - D.xzx;",
  110.  
  111.             "vec4 j = p - 49.0 * floor(p * ns.z * ns.z);", //  mod(p,7*7)
  112.  
  113.             "vec4 x_ = floor(j * ns.z);",
  114.             "vec4 y_ = floor(j - 7.0 * x_);", // mod(j,N)
  115.  
  116.             "vec4 x = x_ * ns.x + ns.yyyy;",
  117.             "vec4 y = y_ * ns.x + ns.yyyy;",
  118.             "vec4 h = 1.0 - abs(x) - abs(y);",
  119.  
  120.             "vec4 b0 = vec4(x.xy, y.xy);",
  121.             "vec4 b1 = vec4(x.zw, y.zw);",
  122.  
  123.             //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
  124.             //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
  125.             "vec4 s0 = floor(b0) * 2.0 + 1.0;",
  126.             "vec4 s1 = floor(b1) * 2.0 + 1.0;",
  127.             "vec4 sh = -step(h, vec4(0.0));",
  128.  
  129.             "vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;",
  130.             "vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;",
  131.  
  132.             "vec3 p0 = vec3(a0.xy, h.x);",
  133.             "vec3 p1 = vec3(a0.zw, h.y);",
  134.             "vec3 p2 = vec3(a1.xy, h.z);",
  135.             "vec3 p3 = vec3(a1.zw, h.w);",
  136.  
  137.             //Normalise gradients
  138.             "vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));",
  139.             "p0 *= norm.x;",
  140.             "p1 *= norm.y;",
  141.             "p2 *= norm.z;",
  142.             "p3 *= norm.w;",
  143.  
  144.             // Mix final noise value
  145.             "vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);",
  146.             "m = m * m;",
  147.             "return 42.0 * dot(m * m, vec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));",
  148.         "}",
  149.         // simplex noise --------
  150.  
  151.         "float turbulence(vec3 p) {",
  152.             "float sum = 0.0;",
  153.             "float freq = 1.0;",
  154.             "float amp = 1.0;",
  155.            
  156.             "for(int i = 0; i < OCTIVES; i++) {",
  157.                 "sum += abs(snoise(p * freq)) * amp;",
  158.                 "freq *= lacunarity;",
  159.                 "amp *= gain;",
  160.             "}",
  161.  
  162.             "return sum;",
  163.         "}",
  164.  
  165.         "vec4 samplerFire (vec3 p, vec4 scale) {",
  166.             "vec2 st = vec2(sqrt(dot(p.xz, p.xz)), p.y);",
  167.  
  168.             "if(st.x <= 0.0 || st.x >= 1.0 || st.y <= 0.0 || st.y >= 1.0) return vec4(0.0);",
  169.  
  170.             "p.y -= (seed + time) * scale.w;",
  171.             "p *= scale.xyz;",
  172.  
  173.             "st.y += sqrt(st.y) * magnitude * turbulence(p);",
  174.  
  175.             "if(st.y <= 0.0 || st.y >= 1.0) return vec4(0.0);",
  176.            
  177.             "return texture2D(fireTex, st);",
  178.         "}",
  179.  
  180.         "vec3 localize(vec3 p) {",
  181.             "return (invModelMatrix * vec4(p, 1.0)).xyz;",
  182.         "}",
  183.  
  184.         "void main() {",
  185.             "vec3 rayPos = vWorldPos;",
  186.             "vec3 rayDir = normalize(rayPos - cameraPosition);",
  187.             "float rayLen = 0.0288 * length(scale.xyz);",
  188.  
  189.             "vec4 col = vec4(0.0);",
  190.  
  191.             "for(int i = 0; i < ITERATIONS; i++) {",
  192.                 "rayPos += rayDir * rayLen;",
  193.  
  194.                 "vec3 lp = localize(rayPos);",
  195.  
  196.                 "lp.y += 0.5;",
  197.                 "lp.xz *= 2.0;",
  198.                 "col += samplerFire(lp, noiseScale);",
  199.             "}",
  200.  
  201.             "col.a = col.r;",
  202.  
  203.             "gl_FragColor = col;",
  204.         "}",
  205.  
  206.         ].join("\n")
  207.  
  208. };

Raw Paste


Login or Register to edit or fork this paste. It's free.