fc197f67e42b429e3985da2b608e33ada9e37205
[demo_prior] / sdr / whitted.p.glsl
1 struct Material {
2         vec3 diffuse, specular;
3         float shin;
4 };
5
6 struct HitPoint {
7         float dist;
8         vec3 pos, norm;
9         vec2 surfpos;
10         Material mtl;
11 };
12
13 varying vec3 v_rorg, v_rdir;
14
15
16 vec3 shade(in vec3 ro, in vec3 rd, in HitPoint hit);
17 vec3 backdrop(in vec3 dir);
18
19 bool isect_scene(in vec3 ro, in vec3 rd, out HitPoint hit);
20
21 bool isect_floor(in vec3 ro, in vec3 rd, float rad, out HitPoint hit);
22 bool isect_plane(in vec3 ro, in vec3 rd, in vec4 plane, out HitPoint hit);
23 bool isect_sphere(in vec3 ro, in vec3 rd, in vec3 pos, float rad, out HitPoint hit);
24
25
26 void main()
27 {
28         vec3 rdir = normalize(v_rdir);
29         gl_FragColor.rgb = backdrop(rdir);
30
31         HitPoint hit;
32         if(isect_scene(v_rorg, rdir, hit)) {
33                 gl_FragColor.rgb = shade(v_rorg, rdir, hit);
34         } else {
35                 gl_FragColor.rgb = backdrop(rdir);
36         }
37         gl_FragColor.a = 1.0;
38 }
39
40 vec3 shade(in vec3 ro, in vec3 rd, in HitPoint hit)
41 {
42         return (hit.norm * 0.5 + 0.5) * hit.mtl.diffuse;
43 }
44
45 #define M_PI    3.1415926
46 #define M_2PI   (M_PI * 2.0)
47
48 vec3 backdrop(in vec3 dir)
49 {
50         return mix(vec3(0.8, 0.3, 0.2), vec3(0.2, 0.3, 0.8), smoothstep(-0.1, 0.1, dir.y));
51 }
52
53 const Material mtl_sph = Material(vec3(1.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0), 80.0);
54 const Material mtl_floor = Material(vec3(0.5, 0.5, 0.5), vec3(0.0, 0.0, 0.0), 1.0);
55
56 bool isect_scene(in vec3 ro, in vec3 rd, out HitPoint hit_res)
57 {
58         HitPoint hit, nearest;
59
60         nearest.dist = 10000.0;
61
62         if(isect_sphere(ro, rd, vec3(0.0, 0.0, 0.0), 1.0, hit)) {
63                 nearest = hit;
64                 nearest.mtl = mtl_sph;
65         }
66
67         if(isect_floor(ro, rd, 5.0, hit) && hit.dist < nearest.dist) {
68                 nearest = hit;
69                 nearest.mtl = mtl_floor;
70         }
71
72         if(nearest.dist >= 10000.0) {
73                 return false;
74         }
75
76         hit_res = nearest;
77         return true;
78 }
79
80 bool isect_floor(in vec3 ro, in vec3 rd, float rad, out HitPoint hit)
81 {
82         if(!isect_plane(ro, rd, vec4(0.0, 1.0, 0.0, -1.0), hit)) {
83                 return false;
84         }
85
86         float d = max(abs(hit.pos.x), abs(hit.pos.z));
87         if(d >= rad) return false;
88
89         return true;
90 }
91
92 bool isect_plane(in vec3 ro, in vec3 rd, in vec4 plane, out HitPoint hit)
93 {
94         float ndotrd = dot(rd, plane.xyz);
95
96         if(abs(ndotrd) < 1e-6) {
97                 return false;
98         }
99
100         vec3 pp = plane.xyz * plane.w;
101         vec3 pdir = pp - ro;
102         float t = dot(pdir, plane.xyz) / ndotrd;
103
104         hit.dist = t;
105         hit.pos = ro + rd * t;
106         hit.norm = plane.xyz;
107         hit.surfpos = hit.pos.xz;       /* XXX */
108         return true;
109 }
110
111 bool isect_sphere(in vec3 ro, in vec3 rd, in vec3 pos, float rad, out HitPoint hit)
112 {
113         float a = dot(rd, rd);
114         float b = dot(rd * 2.0, (ro - pos));
115         float c = dot(ro, ro) + dot(pos, pos) - 2.0 * dot(ro, pos) - rad * rad;
116
117         float d = b * b - 4.0 * a * c;
118         if(d < 1e-6) {
119                 return false;
120         }
121
122         float t0 = (-b + sqrt(d)) / (2.0 * a);
123         float t1 = (-b - sqrt(d)) / (2.0 * a);
124
125         if(t0 < 0.0) t0 = t1;
126         if(t1 < 0.0) t1 = t0;
127         float t = min(t0, t1);
128
129         if(t < 1e-6) {
130                 return false;
131         }
132
133         hit.dist = t;
134         hit.pos = ro + rd * t;
135         hit.norm = normalize(hit.pos - pos);
136         hit.surfpos.x = atan(hit.norm.z, hit.norm.x);
137         hit.surfpos.y = acos(hit.norm.y);
138         return true;
139 }