make the test scene vaguely more interesting
[zinnia.git] / examples / test / shaders / test.frag
blob81f0743ff61cf00a287060b930afc8b217ca9bf3
1 #version 330 core
3 #define FOV 24
5 #define EPSILON 0.01
6 #define MAX_STEPS 128
7 #define NEAR_D 0.1
8 #define FAR_D 120.
10 #define GRAD_EPSILON 0.0001
12 #define saturate(x) clamp(x, 0, 1)
14 uniform vec2 u_Resolution;
15 uniform vec4 u_Mouse;
16 uniform float u_Time;
18 out vec4 color;
20 #include "hg_sdf.glsl"
21 #include "utils.glsl"
22 #include "march_prolog.glsl"
23 #include "colormap_cool.glsl"
25 #define MAT_NORMALS 1.
27 vec3 ray_dir(float fov, vec2 uv) {
28         float z = 1./tan(radians(fov)/2.);
29         return normalize(vec3(uv, z));
32 SceneResult scene_f(vec3 p) {
33         SceneResult ball = SceneResult(length(p-vec3(0, 2, 0)) - 2, 3.);
34         SceneResult ball2 = SceneResult(length(p-vec3(2*sin(u_Time), 2-2*cos(u_Time), 0)) - 1, 3.);
35         SceneResult plane = SceneResult(p.y+5, 2.);
37         // SceneResult box = SceneResult(
38         //      fOpUnionRound(fBox(p, vec3(1)), fSphere(p-vec3(.8), 1.), .2), 0.);
40         //SceneResult res = SceneResult(
41         //      mix(fBox(p, vec3(1.)), fSphere(p, 1.),
42         //              pow(sin(.5*TAU*u_Time), 0.8)),
43         //      1.);
45         // SceneResult res = SceneResult(-p.z, 1.);
47         // SceneResult res = SceneResult(
48         //      fBox(p, vec3(1)),
49         //      1.);
51         SceneResult res = min_sr(min_sr(ball, ball2), plane);
53         return res;
56 vec3 estimate_scene_normal(vec3 p) {
57         vec3 dx = vec3(GRAD_EPSILON, 0, 0);
58         vec3 dy = vec3(0, GRAD_EPSILON, 0);
59         vec3 dz = vec3(0, 0, GRAD_EPSILON);
61         return normalize(vec3(
62                 scene_f(p + dx).d - scene_f(p - dx).d,
63                 scene_f(p + dy).d - scene_f(p - dy).d,
64                 scene_f(p + dz).d - scene_f(p - dz).d
65         ));
68 vec3 raymarch(vec3 o, vec3 d, float start, float end) {
69         float t = start;
70         for (int i = 0; i < MAX_STEPS; i++) {
71                 SceneResult sr = scene_f(o + d*t);
72                 if (sr.d < EPSILON || t > end)
73                         return vec3(t, sr.mat_idx, i);
75                 t += sr.d;
76         }
77         return vec3(end, N_HIT_FAR_PLANE, MAX_STEPS);
80 float checker(vec2 uv) {
81         return sign(mod(floor(uv.x) + floor(uv.y), 2.0));
84 vec4 shade_material(vec3 p, vec3 norm, float mat_idx) {
85         if (mat_idx <= 0.0) {
86                 return vec4(0);
87         }
88         if (mat_idx <= 1.0) {
89                 // return colormap((mod(p.x, 3.) + 1)/2.5);
90                 return vec4(norm, 1.0);
91         }
92         if (mat_idx <= 2.0) {
93                 return vec4(vec3(mix(0.8, 1.0, checker(p.xz))), 1);
94         }
95         if (mat_idx <= 3.0) {
96                 return vec4(mix(vec3(0), vec3(0.05, 0, 0.1), dot(vec3(3, 3, 3), norm)), 1);
97         }
99         return vec4(1, 0, 0, 1);
100         //return
103 vec4 shade(vec3 p, float mat_idx) {
104         vec3 norm = estimate_scene_normal(p);
105         vec4 color_mat = shade_material(p, norm, mat_idx);
107         return color_mat;
110 void main() {
111         vec2 mouse_uv = u_Mouse.xy * 2.0 / u_Resolution.xy - 1.0;
113         vec2 uv = gl_FragCoord.xy * 2.0 / u_Resolution.xy - 1.0;
114         uv.x *= u_Resolution.x/u_Resolution.y;
116         float an = 0.;
117         float d = 5.;
118         vec3 eye = vec3(3. * sin(an), 3., 3. * cos(an)) * d;
119         vec3 target = vec3(0., 2., 0.);
120         mat3 lookAt = look_mat(eye, target, 0);
121         vec3 dir = normalize(lookAt * ray_dir(FOV, uv));
123         color = vec4(0.);
125         vec3 result = raymarch(eye, dir, NEAR_D, FAR_D);
126         float depth = result.x;
127         float mat_idx = result.y;
128         float iters = result.z;
129         if (depth >= FAR_D) {
130         //      color = vec4(.1, .3, .9, 1.);
131                 return;
132         }
134         //color = colormap(iters/MAX_STEPS+0.5);
135         vec3 p = eye + dir * depth; // recast the ray
136         color = shade(p, mat_idx);
137         //color = vec4(vec3(depth/FAR_D), 1);
139         // gamma
140         color = vec4(pow(clamp(color.xyz, 0.0, 1.0), vec3(0.4545)), 1.0);