|
| 1 | + |
| 2 | +#version 150 |
| 3 | + |
| 4 | +#define SAMPLER0 sampler2D // sampler2D, sampler3D, samplerCube |
| 5 | +#define SAMPLER1 sampler2D // sampler2D, sampler3D, samplerCube |
| 6 | +#define SAMPLER2 sampler2D // sampler2D, sampler3D, samplerCube |
| 7 | +#define SAMPLER3 sampler2D // sampler2D, sampler3D, samplerCube |
| 8 | + |
| 9 | +uniform SAMPLER0 iChannel0; // image/buffer/sound Sampler for input textures 0 |
| 10 | +uniform SAMPLER1 iChannel1; // image/buffer/sound Sampler for input textures 1 |
| 11 | +uniform SAMPLER2 iChannel2; // image/buffer/sound Sampler for input textures 2 |
| 12 | +uniform SAMPLER3 iChannel3; // image/buffer/sound Sampler for input textures 3 |
| 13 | + |
| 14 | +uniform vec3 iResolution; // image/buffer The viewport resolution (z is pixel aspect ratio, usually 1.0) |
| 15 | +uniform float iTime; // image/sound/buffer Current time in seconds |
| 16 | +uniform float iTimeDelta; // image/buffer Time it takes to render a frame, in seconds |
| 17 | +uniform int iFrame; // image/buffer Current frame |
| 18 | +uniform float iFrameRate; // image/buffer Number of frames rendered per second |
| 19 | +uniform vec4 iMouse; // image/buffer xy = current pixel coords (if LMB is down). zw = click pixel |
| 20 | +uniform vec4 iDate; // image/buffer/sound Year, month, day, time in seconds in .xyzw |
| 21 | +uniform float iSampleRate; // image/buffer/sound The sound sample rate (typically 44100) |
| 22 | +uniform float iChannelTime[4]; // image/buffer Time for channel (if video or sound), in seconds |
| 23 | +uniform vec3 iChannelResolution[4]; // image/buffer/sound Input texture resolution for each channel |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | + |
| 28 | +// |
| 29 | +// Shadertoy Demo: https://www.shadertoy.com/view/ldSSzV |
| 30 | +// Shadertoy Author: https://www.shadertoy.com/user/TDM |
| 31 | +// |
| 32 | + |
| 33 | + |
| 34 | +/* |
| 35 | +"Wet stone" by Alexander Alekseev aka TDM - 2014 |
| 36 | +License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. |
| 37 | +Contact: tdmaav@gmail.com |
| 38 | +*/ |
| 39 | + |
| 40 | +#define SMOOTH |
| 41 | + |
| 42 | +const int NUM_STEPS = 32; |
| 43 | +const int AO_SAMPLES = 3; |
| 44 | +const vec2 AO_PARAM = vec2(1.2, 3.8); |
| 45 | +const vec2 CORNER_PARAM = vec2(0.25, 40.0); |
| 46 | +const float INV_AO_SAMPLES = 1.0 / float(AO_SAMPLES); |
| 47 | +const float TRESHOLD = 0.1; |
| 48 | +const float EPSILON = 1e-3; |
| 49 | +const float LIGHT_INTENSITY = 0.25; |
| 50 | +const vec3 RED = vec3(1.0,0.7,0.7) * LIGHT_INTENSITY; |
| 51 | +const vec3 ORANGE = vec3(1.0,0.67,0.43) * LIGHT_INTENSITY; |
| 52 | +const vec3 BLUE = vec3(0.54,0.77,1.0) * LIGHT_INTENSITY; |
| 53 | +const vec3 WHITE = vec3(1.2,1.07,0.98) * LIGHT_INTENSITY; |
| 54 | + |
| 55 | +const float DISPLACEMENT = 0.1; |
| 56 | + |
| 57 | +// math |
| 58 | +mat3 fromEuler(vec3 ang) { |
| 59 | + vec2 a1 = vec2(sin(ang.x),cos(ang.x)); |
| 60 | + vec2 a2 = vec2(sin(ang.y),cos(ang.y)); |
| 61 | + vec2 a3 = vec2(sin(ang.z),cos(ang.z)); |
| 62 | + mat3 m; |
| 63 | + m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x); |
| 64 | + m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x); |
| 65 | + m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y); |
| 66 | + return m; |
| 67 | +} |
| 68 | +float hash11(float p) { |
| 69 | + return fract(sin(p * 727.1)*435.545); |
| 70 | +} |
| 71 | +float hash12(vec2 p) { |
| 72 | + float h = dot(p,vec2(127.1,311.7)); |
| 73 | + return fract(sin(h)*437.545); |
| 74 | +} |
| 75 | +vec3 hash31(float p) { |
| 76 | + vec3 h = vec3(127.231,491.7,718.423) * p; |
| 77 | + return fract(sin(h)*435.543); |
| 78 | +} |
| 79 | + |
| 80 | +// 3d noise |
| 81 | +float noise_3(in vec3 p) { |
| 82 | + vec3 i = floor(p); |
| 83 | + vec3 f = fract(p); |
| 84 | + vec3 u = f*f*(3.0-2.0*f); |
| 85 | + |
| 86 | + vec2 ii = i.xy + i.z * vec2(5.0); |
| 87 | + float a = hash12( ii + vec2(0.0,0.0) ); |
| 88 | + float b = hash12( ii + vec2(1.0,0.0) ); |
| 89 | + float c = hash12( ii + vec2(0.0,1.0) ); |
| 90 | + float d = hash12( ii + vec2(1.0,1.0) ); |
| 91 | + float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y); |
| 92 | + |
| 93 | + ii += vec2(5.0); |
| 94 | + a = hash12( ii + vec2(0.0,0.0) ); |
| 95 | + b = hash12( ii + vec2(1.0,0.0) ); |
| 96 | + c = hash12( ii + vec2(0.0,1.0) ); |
| 97 | + d = hash12( ii + vec2(1.0,1.0) ); |
| 98 | + float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y); |
| 99 | + |
| 100 | + return max(mix(v1,v2,u.z),0.0); |
| 101 | +} |
| 102 | + |
| 103 | +// fBm |
| 104 | +float fbm3(vec3 p, float a, float f) { |
| 105 | + return noise_3(p); |
| 106 | +} |
| 107 | + |
| 108 | +float fbm3_high(vec3 p, float a, float f) { |
| 109 | + float ret = 0.0; |
| 110 | + float amp = 1.0; |
| 111 | + float frq = 1.0; |
| 112 | + for(int i = 0; i < 4; i++) { |
| 113 | + float n = pow(noise_3(p * frq),2.0); |
| 114 | + ret += n * amp; |
| 115 | + frq *= f; |
| 116 | + amp *= a * (pow(n,0.2)); |
| 117 | + } |
| 118 | + return ret; |
| 119 | +} |
| 120 | + |
| 121 | +// lighting |
| 122 | +float diffuse(vec3 n,vec3 l,float p) { return pow(max(dot(n,l),0.0),p); } |
| 123 | +float specular(vec3 n,vec3 l,vec3 e,float s) { |
| 124 | + float nrm = (s + 8.0) / (3.1415 * 8.0); |
| 125 | + return pow(max(dot(reflect(e,n),l),0.0),s) * nrm; |
| 126 | +} |
| 127 | + |
| 128 | +// distance functions |
| 129 | +float plane(vec3 gp, vec4 p) { |
| 130 | + return dot(p.xyz,gp+p.xyz*p.w); |
| 131 | +} |
| 132 | +float sphere(vec3 p,float r) { |
| 133 | + return length(p)-r; |
| 134 | +} |
| 135 | +float capsule(vec3 p,float r,float h) { |
| 136 | + p.y -= clamp(p.y,-h,h); |
| 137 | + return length(p)-r; |
| 138 | +} |
| 139 | +float cylinder(vec3 p,float r,float h) { |
| 140 | + return max(abs(p.y/h),capsule(p,r,h)); |
| 141 | +} |
| 142 | +float box(vec3 p,vec3 s) { |
| 143 | + p = abs(p)-s; |
| 144 | + return max(max(p.x,p.y),p.z); |
| 145 | +} |
| 146 | +float rbox(vec3 p,vec3 s) { |
| 147 | + p = abs(p)-s; |
| 148 | + return length(p-min(p,0.0)); |
| 149 | +} |
| 150 | +float quad(vec3 p,vec2 s) { |
| 151 | + p = abs(p) - vec3(s.x,0.0,s.y); |
| 152 | + return max(max(p.x,p.y),p.z); |
| 153 | +} |
| 154 | + |
| 155 | +// boolean operations |
| 156 | +float boolUnion(float a,float b) { return min(a,b); } |
| 157 | +float boolIntersect(float a,float b) { return max(a,b); } |
| 158 | +float boolSub(float a,float b) { return max(a,-b); } |
| 159 | + |
| 160 | +// smooth operations. thanks to iq |
| 161 | +float boolSmoothIntersect(float a, float b, float k ) { |
| 162 | + float h = clamp(0.5+0.5*(b-a)/k, 0.0, 1.0); |
| 163 | + return mix(a,b,h) + k*h*(1.0-h); |
| 164 | +} |
| 165 | +float boolSmoothSub(float a, float b, float k ) { |
| 166 | + return boolSmoothIntersect(a,-b,k); |
| 167 | +} |
| 168 | + |
| 169 | +// world |
| 170 | +float rock(vec3 p) { |
| 171 | + float d = sphere(p,1.0); |
| 172 | + for(int i = 0; i < 9; i++) { |
| 173 | + float ii = float(i); |
| 174 | + float r = 2.5 + hash11(ii); |
| 175 | + vec3 v = normalize(hash31(ii) * 2.0 - 1.0); |
| 176 | + #ifdef SMOOTH |
| 177 | + d = boolSmoothSub(d,sphere(p+v*r,r * 0.8), 0.03); |
| 178 | + #else |
| 179 | + d = boolSub(d,sphere(p+v*r,r * 0.8)); |
| 180 | + #endif |
| 181 | + } |
| 182 | + return d; |
| 183 | +} |
| 184 | + |
| 185 | +float map(vec3 p) { |
| 186 | + float d = rock(p) + fbm3(p*4.0,0.4,2.96) * DISPLACEMENT; |
| 187 | + d = boolUnion(d,plane(p,vec4(0.0,1.0,0.0,1.0))); |
| 188 | + return d; |
| 189 | +} |
| 190 | + |
| 191 | +float map_detailed(vec3 p) { |
| 192 | + float d = rock(p) + fbm3_high(p*4.0,0.4,2.96) * DISPLACEMENT; |
| 193 | + d = boolUnion(d,plane(p,vec4(0.0,1.0,0.0,1.0))); |
| 194 | + return d; |
| 195 | +} |
| 196 | + |
| 197 | +// tracing |
| 198 | +vec3 getNormal(vec3 p, float dens) { |
| 199 | + vec3 n; |
| 200 | + n.x = map_detailed(vec3(p.x+EPSILON,p.y,p.z)); |
| 201 | + n.y = map_detailed(vec3(p.x,p.y+EPSILON,p.z)); |
| 202 | + n.z = map_detailed(vec3(p.x,p.y,p.z+EPSILON)); |
| 203 | + return normalize(n-map_detailed(p)); |
| 204 | +} |
| 205 | +vec2 getOcclusion(vec3 p, vec3 n) { |
| 206 | + vec2 r = vec2(0.0); |
| 207 | + for(int i = 0; i < AO_SAMPLES; i++) { |
| 208 | + float f = float(i)*INV_AO_SAMPLES; |
| 209 | + float hao = 0.01+f*AO_PARAM.x; |
| 210 | + float hc = 0.01+f*CORNER_PARAM.x; |
| 211 | + float dao = map(p + n * hao) - TRESHOLD; |
| 212 | + float dc = map(p - n * hc) - TRESHOLD; |
| 213 | + r.x += clamp(hao-dao,0.0,1.0) * (1.0-f); |
| 214 | + r.y += clamp(hc+dc,0.0,1.0) * (1.0-f); |
| 215 | + } |
| 216 | + r.x = pow(clamp(1.0-r.x*INV_AO_SAMPLES*AO_PARAM.y,0.0,1.0),0.5); |
| 217 | + r.y = clamp(r.y*INV_AO_SAMPLES*CORNER_PARAM.y,0.0,1.0); |
| 218 | + return r; |
| 219 | +} |
| 220 | +vec2 spheretracing(vec3 ori, vec3 dir, out vec3 p) { |
| 221 | + vec2 td = vec2(0.0); |
| 222 | + for(int i = 0; i < NUM_STEPS; i++) { |
| 223 | + p = ori + dir * td.x; |
| 224 | + td.y = map(p); |
| 225 | + if(td.y < TRESHOLD) break; |
| 226 | + td.x += (td.y-TRESHOLD) * 0.9; |
| 227 | + } |
| 228 | + return td; |
| 229 | +} |
| 230 | + |
| 231 | +// stone |
| 232 | +vec3 getStoneColor(vec3 p, float c, vec3 l, vec3 n, vec3 e) { |
| 233 | + c = min(c + pow(noise_3(vec3(p.x*20.0,0.0,p.z*20.0)),70.0) * 8.0, 1.0); |
| 234 | + float ic = pow(1.0-c,0.5); |
| 235 | + vec3 base = vec3(0.42,0.3,0.2) * 0.6; |
| 236 | + vec3 sand = vec3(0.51,0.41,0.32); |
| 237 | + vec3 color = mix(base,sand,c); |
| 238 | + |
| 239 | + float f = pow(1.0 - max(dot(n,-e),0.0), 1.5) * 0.75 * ic; |
| 240 | + color = mix(color,vec3(1.0),f); |
| 241 | + color += vec3(diffuse(n,l,0.5) * WHITE); |
| 242 | + color += vec3(specular(n,l,e,8.0) * WHITE * 1.5 * ic); |
| 243 | + n = normalize(n - normalize(p) * 0.4); |
| 244 | + color += vec3(specular(n,l,e,80.0) * WHITE * 1.5 * ic); |
| 245 | + return color; |
| 246 | +} |
| 247 | + |
| 248 | +// main |
| 249 | +void mainImage( out vec4 fragColor, in vec2 fragCoord ) { |
| 250 | + vec2 iuv = fragCoord.xy / iResolution.xy * 2.0 - 1.0; |
| 251 | + vec2 uv = iuv; |
| 252 | + uv.x *= iResolution.x / iResolution.y; |
| 253 | + float time = iTime * 0.3; |
| 254 | + |
| 255 | + // ray |
| 256 | + vec3 ang = vec3(0.0,0.2,time); |
| 257 | + if(iMouse.z > 0.0) ang = vec3(0.0,clamp(2.0-iMouse.y*0.01,0.0,3.1415),iMouse.x*0.01); |
| 258 | + mat3 rot = fromEuler(ang); |
| 259 | + |
| 260 | + vec3 ori = vec3(0.0,0.0,2.8); |
| 261 | + vec3 dir = normalize(vec3(uv.xy,-2.0)); |
| 262 | + ori = ori * rot; |
| 263 | + dir = dir * rot; |
| 264 | + |
| 265 | + // tracing |
| 266 | + vec3 p; |
| 267 | + vec2 td = spheretracing(ori,dir,p); |
| 268 | + vec3 n = getNormal(p,td.y); |
| 269 | + vec2 occ = getOcclusion(p,n); |
| 270 | + vec3 light = normalize(vec3(0.0,1.0,0.0)); |
| 271 | + |
| 272 | + // color |
| 273 | + vec3 color = vec3(1.0); |
| 274 | + if(td.x < 3.5 && p.y > -0.89) color = getStoneColor(p,occ.y,light,n,dir); |
| 275 | + color *= occ.x; |
| 276 | + |
| 277 | + // post |
| 278 | + float vgn = smoothstep(1.2,0.7,abs(iuv.y)) * smoothstep(1.1,0.8,abs(iuv.x)); |
| 279 | + color *= 1.0 - (1.0 - vgn) * 0.15; |
| 280 | + fragColor = vec4(color,1.0); |
| 281 | +} |
| 282 | + |
| 283 | + |
| 284 | + |
| 285 | + |
| 286 | + |
| 287 | + |
| 288 | + |
| 289 | + |
| 290 | + |
| 291 | + |
| 292 | + |
0 commit comments