1// Compatibility #ifdefs needed for parameters
2#ifdef GL_ES
3#define COMPAT_PRECISION mediump
4#else
5#define COMPAT_PRECISION
6#endif
7
8// Parameter lines go here:
9#pragma parameter RETRO_PIXEL_SIZE "Retro Pixel Size" 0.84 0.0 1.0 0.01
10#ifdef PARAMETER_UNIFORM
11// All parameter floats need to have COMPAT_PRECISION in front of them
12uniform COMPAT_PRECISION float RETRO_PIXEL_SIZE;
13#else
14#define RETRO_PIXEL_SIZE 0.84
15#endif
16
17#if defined(VERTEX)
18
19#if __VERSION__ >= 130
20#define COMPAT_VARYING out
21#define COMPAT_ATTRIBUTE in
22#define COMPAT_TEXTURE texture
23#else
24#define COMPAT_VARYING varying
25#define COMPAT_ATTRIBUTE attribute
26#define COMPAT_TEXTURE texture2D
27#endif
28
29#ifdef GL_ES
30#define COMPAT_PRECISION mediump
31#else
32#define COMPAT_PRECISION
33#endif
34
35COMPAT_ATTRIBUTE vec4 VertexCoord;
36COMPAT_ATTRIBUTE vec4 COLOR;
37COMPAT_ATTRIBUTE vec4 TexCoord;
38COMPAT_VARYING vec4 COL0;
39COMPAT_VARYING vec4 TEX0;
40// out variables go here as COMPAT_VARYING whatever
41
42vec4 _oPosition1;
43uniform mat4 MVPMatrix;
44uniform COMPAT_PRECISION int FrameDirection;
45uniform COMPAT_PRECISION int FrameCount;
46uniform COMPAT_PRECISION vec2 OutputSize;
47uniform COMPAT_PRECISION vec2 TextureSize;
48uniform COMPAT_PRECISION vec2 InputSize;
49
50// compatibility #defines
51#define vTexCoord TEX0.xy
52#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
53#define OutSize vec4(OutputSize, 1.0 / OutputSize)
54
55void main()
56{
57    gl_Position = MVPMatrix * VertexCoord;
58    TEX0.xy = VertexCoord.xy;
59// Paste vertex contents here:
60}
61
62#elif defined(FRAGMENT)
63
64#if __VERSION__ >= 130
65#define COMPAT_VARYING in
66#define COMPAT_TEXTURE texture
67out vec4 FragColor;
68#else
69#define COMPAT_VARYING varying
70#define FragColor gl_FragColor
71#define COMPAT_TEXTURE texture2D
72#endif
73
74#ifdef GL_ES
75#ifdef GL_FRAGMENT_PRECISION_HIGH
76precision highp float;
77#else
78precision mediump float;
79#endif
80#define COMPAT_PRECISION mediump
81#else
82#define COMPAT_PRECISION
83#endif
84
85uniform COMPAT_PRECISION int FrameDirection;
86uniform COMPAT_PRECISION int FrameCount;
87uniform COMPAT_PRECISION vec2 OutputSize;
88uniform COMPAT_PRECISION vec2 TextureSize;
89uniform COMPAT_PRECISION vec2 InputSize;
90uniform sampler2D Texture;
91COMPAT_VARYING vec4 TEX0;
92// in variables go here as COMPAT_VARYING whatever
93
94// compatibility #defines
95#define Source Texture
96#define vTexCoord TEX0.xy
97
98#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
99#define OutSize vec4(OutputSize, 1.0 / OutputSize)
100
101// delete all 'params.' or 'registers.' or whatever in the fragment
102float iGlobalTime = float(FrameCount)*0.025;
103vec2 iResolution = OutputSize.xy;
104
105// Wet Stone -  TDM - 2014-10-20
106// https://www.shadertoy.com/view/ldSSzV
107
108// stone generation
109
110/*
111"Wet stone" by Alexander Alekseev aka TDM - 2014
112License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
113Contact: tdmaav@gmail.com
114*/
115
116#define SMOOTH
117
118const int NUM_STEPS = 32;
119const int AO_SAMPLES = 3;
120const vec2 AO_PARAM = vec2(1.2, 3.8);
121const vec2 CORNER_PARAM = vec2(0.25, 40.0);
122const float INV_AO_SAMPLES = 1.0 / float(AO_SAMPLES);
123const float TRESHOLD 	= 0.1;
124const float EPSILON 	= 1e-3;
125const float LIGHT_INTENSITY = 0.25;
126const vec3 RED 		= vec3(1.0,0.7,0.7) * LIGHT_INTENSITY;
127const vec3 ORANGE 	= vec3(1.0,0.67,0.43) * LIGHT_INTENSITY;
128const vec3 BLUE 	= vec3(0.54,0.77,1.0) * LIGHT_INTENSITY;
129const vec3 WHITE 	= vec3(1.2,1.07,0.98) * LIGHT_INTENSITY;
130
131const float DISPLACEMENT = 0.1;
132
133// math
134mat3 fromEuler(vec3 ang) {
135	vec2 a1 = vec2(sin(ang.x),cos(ang.x));
136    vec2 a2 = vec2(sin(ang.y),cos(ang.y));
137    vec2 a3 = vec2(sin(ang.z),cos(ang.z));
138    mat3 m;
139    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);
140	m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
141	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);
142	return m;
143}
144float hash11(float p) {
145    return fract(sin(p * 727.1)*435.545);
146}
147float hash12(vec2 p) {
148	float h = dot(p,vec2(127.1,311.7));
149    return fract(sin(h)*437.545);
150}
151vec3 hash31(float p) {
152	vec3 h = vec3(127.231,491.7,718.423) * p;
153    return fract(sin(h)*435.543);
154}
155
156// 3d noise
157float noise_3(in vec3 p) {
158    vec3 i = floor(p);
159    vec3 f = fract(p);
160	vec3 u = f*f*(3.0-2.0*f);
161
162    vec2 ii = i.xy + i.z * vec2(5.0);
163    float a = hash12( ii + vec2(0.0,0.0) );
164	float b = hash12( ii + vec2(1.0,0.0) );
165    float c = hash12( ii + vec2(0.0,1.0) );
166	float d = hash12( ii + vec2(1.0,1.0) );
167    float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
168
169    ii += vec2(5.0);
170    a = hash12( ii + vec2(0.0,0.0) );
171	b = hash12( ii + vec2(1.0,0.0) );
172    c = hash12( ii + vec2(0.0,1.0) );
173	d = hash12( ii + vec2(1.0,1.0) );
174    float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
175
176    return max(mix(v1,v2,u.z),0.0);
177}
178
179// fBm
180float fbm3(vec3 p, float a, float f) {
181    return noise_3(p);
182}
183
184float fbm3_high(vec3 p, float a, float f) {
185    float ret = 0.0;
186    float amp = 1.0;
187    float frq = 1.0;
188    for(int i = 0; i < 4; i++) {
189        float n = pow(noise_3(p * frq),2.0);
190        ret += n * amp;
191        frq *= f;
192        amp *= a * (pow(n,0.2));
193    }
194    return ret;
195}
196
197// lighting
198float diffuse(vec3 n,vec3 l,float p) { return pow(max(dot(n,l),0.0),p); }
199float specular(vec3 n,vec3 l,vec3 e,float s) {
200    float nrm = (s + 8.0) / (3.1415 * 8.0);
201    return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
202}
203
204// distance functions
205float plane(vec3 gp, vec4 p) {
206	return dot(p.xyz,gp+p.xyz*p.w);
207}
208float sphere(vec3 p,float r) {
209	return length(p)-r;
210}
211float capsule(vec3 p,float r,float h) {
212    p.y -= clamp(p.y,-h,h);
213	return length(p)-r;
214}
215float cylinder(vec3 p,float r,float h) {
216	return max(abs(p.y/h),capsule(p,r,h));
217}
218float box(vec3 p,vec3 s) {
219	p = abs(p)-s;
220    return max(max(p.x,p.y),p.z);
221}
222float rbox(vec3 p,vec3 s) {
223	p = abs(p)-s;
224    return length(p-min(p,0.0));
225}
226float quad(vec3 p,vec2 s) {
227	p = abs(p) - vec3(s.x,0.0,s.y);
228    return max(max(p.x,p.y),p.z);
229}
230
231// boolean operations
232float boolUnion(float a,float b) { return min(a,b); }
233float boolIntersect(float a,float b) { return max(a,b); }
234float boolSub(float a,float b) { return max(a,-b); }
235
236// smooth operations. thanks to iq
237float boolSmoothIntersect(float a, float b, float k ) {
238    float h = clamp(0.5+0.5*(b-a)/k, 0.0, 1.0);
239    return mix(a,b,h) + k*h*(1.0-h);
240}
241float boolSmoothSub(float a, float b, float k ) {
242    return boolSmoothIntersect(a,-b,k);
243}
244
245// world
246float rock(vec3 p) {
247    float d = sphere(p,1.0);
248    for(int i = 0; i < 9; i++) {
249        float ii = float(i);
250        float r = 2.5 + hash11(ii);
251        vec3 v = normalize(hash31(ii) * 2.0 - 1.0);
252        #ifdef SMOOTH
253        d = boolSmoothSub(d,sphere(p+v*r,r * 0.8), 0.03);
254        #else
255    	d = boolSub(d,sphere(p+v*r,r * 0.8));
256        #endif
257    }
258    return d;
259}
260
261float map(vec3 p) {
262    float d = rock(p) + fbm3(p*4.0,0.4,2.96) * DISPLACEMENT;
263    d = boolUnion(d,plane(p,vec4(0.0,1.0,0.0,1.0)));
264    return d;
265}
266
267float map_detailed(vec3 p) {
268    float d = rock(p) + fbm3_high(p*4.0,0.4,2.96) * DISPLACEMENT;
269    d = boolUnion(d,plane(p,vec4(0.0,1.0,0.0,1.0)));
270    return d;
271}
272
273// tracing
274vec3 getNormal(vec3 p, float dens) {
275    vec3 n;
276    n.x = map_detailed(vec3(p.x+EPSILON,p.y,p.z));
277    n.y = map_detailed(vec3(p.x,p.y+EPSILON,p.z));
278    n.z = map_detailed(vec3(p.x,p.y,p.z+EPSILON));
279    return normalize(n-map_detailed(p));
280}
281vec2 getOcclusion(vec3 p, vec3 n) {
282    vec2 r = vec2(0.0);
283    for(int i = 0; i < AO_SAMPLES; i++) {
284        float f = float(i)*INV_AO_SAMPLES;
285        float hao = 0.01+f*AO_PARAM.x;
286        float hc = 0.01+f*CORNER_PARAM.x;
287        float dao = map(p + n * hao) - TRESHOLD;
288        float dc = map(p - n * hc) - TRESHOLD;
289        r.x += clamp(hao-dao,0.0,1.0) * (1.0-f);
290        r.y += clamp(hc+dc,0.0,1.0) * (1.0-f);
291    }
292    r.x = pow(clamp(1.0-r.x*INV_AO_SAMPLES*AO_PARAM.y,0.0,1.0),0.5);
293    r.y = clamp(r.y*INV_AO_SAMPLES*CORNER_PARAM.y,0.0,1.0);
294    return r;
295}
296vec2 spheretracing(vec3 ori, vec3 dir, out vec3 p) {
297    vec2 td = vec2(0.0);
298    for(int i = 0; i < NUM_STEPS; i++) {
299        p = ori + dir * td.x;
300        td.y = map(p);
301        if(td.y < TRESHOLD) break;
302        td.x += (td.y-TRESHOLD) * 0.9;
303    }
304    return td;
305}
306
307// stone
308vec3 getStoneColor(vec3 p, float c, vec3 l, vec3 n, vec3 e) {
309    c = min(c + pow(noise_3(vec3(p.x*20.0,0.0,p.z*20.0)),70.0) * 8.0, 1.0);
310    float ic = pow(1.0-c,0.5);
311    vec3 base = vec3(0.42,0.3,0.2) * 0.6;
312    vec3 sand = vec3(0.51,0.41,0.32);
313    vec3 color = mix(base,sand,c);
314
315    float f = pow(1.0 - max(dot(n,-e),0.0), 1.5) * 0.75 * ic;
316    color = mix(color,vec3(1.0),f);
317    color += vec3(diffuse(n,l,0.5) * WHITE);
318    color += vec3(specular(n,l,e,8.0) * WHITE * 1.5 * ic);
319    n = normalize(n - normalize(p) * 0.4);
320    color += vec3(specular(n,l,e,80.0) * WHITE * 1.5 * ic);
321    return color;
322}
323
324// main
325void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
326	vec2 iuv = fragCoord.xy / iResolution.xy * 2.0 - 1.0;
327    vec2 uv = iuv;
328    uv.x *= iResolution.x / iResolution.y;
329    float time = iGlobalTime * 0.3;
330
331    // ray
332    vec3 ang = vec3(0.0,0.2,time);
333#ifdef MOUSE
334    if(iMouse.z > 0.0) ang = vec3(0.0,clamp(2.0-iMouse.y*0.01,0.0,3.1415),iMouse.x*0.01);
335#endif
336	mat3 rot = fromEuler(ang);
337
338    vec3 ori = vec3(0.0,0.0,2.8);
339    vec3 dir = normalize(vec3(uv.xy,-2.0));
340    ori = ori * rot;
341    dir = dir * rot;
342
343    // tracing
344    vec3 p;
345    vec2 td = spheretracing(ori,dir,p);
346    vec3 n = getNormal(p,td.y);
347    vec2 occ = getOcclusion(p,n);
348    vec3 light = normalize(vec3(0.0,1.0,0.0));
349
350    // color
351    vec3 color = vec3(1.0);
352    if(td.x < 3.5 && p.y > -0.89) color = getStoneColor(p,occ.y,light,n,dir);
353    color *= occ.x;
354
355    // post
356    float vgn = smoothstep(1.2,0.7,abs(iuv.y)) * smoothstep(1.1,0.8,abs(iuv.x));
357    color *= 1.0 - (1.0 - vgn) * 0.15;
358	fragColor = vec4(color,1.0);
359}
360
361void main(void)
362{
363  //just some shit to wrap shadertoy's stuff
364  vec2 FragCoord = vTexCoord.xy*OutputSize.xy;
365  mainImage(FragColor,FragCoord);
366}
367#endif
368