1// https://www.shadertoy.com/view/4ssGzn 2 3// ray marched fireball 4// http://http.download.nvidia.com/developer/presentations/2005/GDC/Sponsored_Day/GDC_2005_VolumeRenderingForGames.pdf 5 6// sgreen 7const int _VolumeSteps = 32; 8const float _StepSize = 0.1; 9uniform float _Density = 0.2; // Density, min=0., max=1. 10 11uniform float _SphereRadius = 2.0; // Sphere Radius, min=0., max=2. 12uniform float _NoiseFreq = 1.0; // Noise Frequency, min=0., max=5. 13uniform float _NoiseAmp = 3.0; // Noise Amplitude, min=0., max=10. 14const vec3 _NoiseAnim = vec3(0, -1, 0); 15 16// iq's nice integer-less noise function 17 18// matrix to rotate the noise octaves 19mat3 m = mat3( 0.00, 0.80, 0.60, 20 -0.80, 0.36, -0.48, 21 -0.60, -0.48, 0.64 ); 22 23float hash( float n ) 24{ 25 return fract(sin(n)*43758.5453); 26} 27 28 29float noise( in vec3 x ) 30{ 31 vec3 p = floor(x); 32 vec3 f = fract(x); 33 34 f = f*f*(3.0-2.0*f); 35 36 float n = p.x + p.y*57.0 + 113.0*p.z; 37 38 float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), 39 mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y), 40 mix(mix( hash(n+113.0), hash(n+114.0),f.x), 41 mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z); 42 return res; 43} 44 45float fbm( vec3 p ) 46{ 47 float f; 48 f = 0.5000*noise( p ); p = m*p*2.02; 49 f += 0.2500*noise( p ); p = m*p*2.03; 50 f += 0.1250*noise( p ); p = m*p*2.01; 51 f += 0.0625*noise( p ); 52 //p = m*p*2.02; f += 0.03125*abs(noise( p )); 53 return f; 54} 55 56// returns signed distance to surface 57float distanceFunc(vec3 p) 58{ 59 float d = length(p) - _SphereRadius; // distance to sphere 60 61 // offset distance with pyroclastic noise 62 //p = normalize(p) * _SphereRadius; // project noise point to sphere surface 63 d += fbm(p*_NoiseFreq + _NoiseAnim*iTime) * _NoiseAmp; 64 return d; 65} 66 67// color gradient 68// this should be in a 1D texture really 69vec4 gradient(float x) 70{ 71 // no constant array initializers allowed in GLES SL! 72 const vec4 c0 = vec4(2, 2, 1, 1); // yellow 73 const vec4 c1 = vec4(1, 0, 0, 1); // red 74 const vec4 c2 = vec4(0, 0, 0, 0); // black 75 const vec4 c3 = vec4(0, 0.5, 1, 0.5); // blue 76 const vec4 c4 = vec4(0, 0, 0, 0); // black 77 78 x = clamp(x, 0.0, 0.999); 79 float t = fract(x*4.0); 80 vec4 c; 81 if (x < 0.25) { 82 c = mix(c0, c1, t); 83 } else if (x < 0.5) { 84 c = mix(c1, c2, t); 85 } else if (x < 0.75) { 86 c = mix(c2, c3, t); 87 } else { 88 c = mix(c3, c4, t); 89 } 90 //return vec4(x); 91 //return vec4(t); 92 return c; 93} 94 95// shade a point based on distance 96vec4 shade(float d) 97{ 98 // lookup in color gradient 99 return gradient(d); 100 //return mix(vec4(1, 1, 1, 1), vec4(0, 0, 0, 0), smoothstep(1.0, 1.1, d)); 101} 102 103// procedural volume 104// maps position to color 105vec4 volumeFunc(vec3 p) 106{ 107 float d = distanceFunc(p); 108 return shade(d); 109} 110 111// ray march volume from front to back 112// returns color 113vec4 rayMarch(vec3 rayOrigin, vec3 rayStep, out vec3 pos) 114{ 115 vec4 sum = vec4(0, 0, 0, 0); 116 pos = rayOrigin; 117 for(int i=0; i<_VolumeSteps; i++) { 118 vec4 col = volumeFunc(pos); 119 col.a *= _Density; 120 //col.a = min(col.a, 1.0); 121 122 // pre-multiply alpha 123 col.rgb *= col.a; 124 sum = sum + col*(1.0 - sum.a); 125#if 0 126 // exit early if opaque 127 if (sum.a > _OpacityThreshold) 128 break; 129#endif 130 pos += rayStep; 131 } 132 return sum; 133} 134 135void mainImage( out vec4 fragColor, in vec2 fragCoord ) 136{ 137 vec2 p = (fragCoord.xy / iResolution.xy)*2.0-1.0; 138 p.x *= iResolution.x/ iResolution.y; 139 vec3 v = iResolution / 2.0; 140 float rotx = (v.y / iResolution.y)*4.0; 141 float roty = -(v.x / iResolution.x)*4.0; 142 143 float zoom = 4.0; 144 145 // camera 146 vec3 ro = zoom*normalize(vec3(cos(roty), cos(rotx), sin(roty))); 147 vec3 ww = normalize(vec3(0.0,0.0,0.0) - ro); 148 vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww )); 149 vec3 vv = normalize(cross(ww,uu)); 150 vec3 rd = normalize( p.x*uu + p.y*vv + 1.5*ww ); 151 152 ro += rd*2.0; 153 154 // volume render 155 vec3 hitPos; 156 vec4 col = rayMarch(ro, rd*_StepSize, hitPos); 157 //vec4 col = gradient(p.x); 158 159 fragColor = col; 160}