bloboland

view sdr/bloboray.p.glsl @ 3:a39c301cdcce

terrain raytracing pretty much done
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 16 Dec 2012 14:24:16 +0200
parents
children 9021a906c5d3
line source
1 struct Ray {
2 vec3 origin;
3 vec3 dir;
4 };
6 struct AABBox {
7 vec3 vmin, vmax;
8 };
10 struct HitPoint {
11 bool hit;
12 float t0, t1;
13 vec3 pos, normal;
14 vec4 color;
15 };
17 vec3 shade(Ray ray, HitPoint hit);
18 HitPoint intersect_voxels(Ray ray);
19 HitPoint intersect_aabb(Ray ray, AABBox aabb);
20 Ray get_primary_ray(float x, float y);
22 #define RAY_STEP 0.001
24 #define FOV camprop.x
25 #define ASPECT camprop.y
26 uniform vec4 camprop;
27 uniform vec3 volsize;
28 uniform sampler3D voltex;
30 //const vec3 worldsize = vec3(4.0, 4.0, 2.0);
31 const vec3 worldsize = vec3(1.0, 1.0, 0.5);
33 void main()
34 {
35 Ray ray = get_primary_ray(gl_TexCoord[0].x, gl_TexCoord[0].y);
37 vec3 color = vec3(0.0, 0.0, 0.0);
38 HitPoint hit = intersect_voxels(ray);
39 if(hit.hit) {
40 color = shade(ray, hit);
41 }
43 gl_FragColor = vec4(color, 1.0);
44 }
46 vec3 shade(Ray ray, HitPoint hit)
47 {
48 const vec3 light_pos = vec3(-2, 3, 2);
49 vec3 ldir = normalize(light_pos - hit.pos);
51 vec3 vdir = normalize(-ray.dir);
52 vec3 hvec = normalize(vdir + ldir);
54 float ndotl = max(dot(hit.normal, ldir), 0.0);
55 float ndoth = max(dot(hit.normal, hvec), 0.0);
57 vec3 diffuse = hit.color.xyz * ndotl;
58 vec3 specular = vec3(0.4, 0.4, 0.4) * pow(ndoth, 60.0);
60 return diffuse + specular;
61 }
63 vec4 fetch_voxel(vec3 pt)
64 {
65 pt *= 1.0 / worldsize;
66 return texture3D(voltex, pt * 0.5 + 0.5);
67 }
69 vec3 calc_voxel_normal(vec3 pt)
70 {
71 vec3 offs = 1.8 / volsize;
72 float dfdx = fetch_voxel(pt + vec3(offs.x, 0.0, 0.0)).w - fetch_voxel(pt - vec3(offs.x, 0.0, 0.0)).w;
73 float dfdy = fetch_voxel(pt + vec3(0.0, offs.y, 0.0)).w - fetch_voxel(pt - vec3(0.0, offs.y, 0.0)).w;
74 float dfdz = fetch_voxel(pt + vec3(0.0, 0.0, offs.z)).w - fetch_voxel(pt - vec3(0.0, 0.0, offs.z)).w;
76 return -normalize(vec3(dfdx, dfdy, dfdz));
77 }
79 HitPoint intersect_voxels(Ray ray)
80 {
81 HitPoint hit;
82 //AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0));
83 AABBox aabb = AABBox(-worldsize.xzy, worldsize.xzy);
86 hit = intersect_aabb(ray, aabb);
87 if(!hit.hit) {
88 return hit;
89 }
91 /* start tracing from the first intersection, or if it's behind
92 * the viewer, start from 0.
93 */
94 float dist = max(hit.t0, 0.0);
95 float end_dist = hit.t1;
97 while(dist < end_dist) {
98 vec3 pt = ray.origin + ray.dir * dist;
99 vec4 voxel = fetch_voxel(pt.xzy);
102 if(voxel.a > 0.5) {
103 hit.t0 = dist;
104 hit.pos = pt;
105 hit.normal = calc_voxel_normal(pt.xzy).xzy;
106 hit.color = voxel;
107 return hit;
108 }
110 dist += RAY_STEP;
111 }
113 hit.hit = false;
114 return hit;
115 }
117 HitPoint intersect_aabb(Ray ray, AABBox aabb)
118 {
119 HitPoint res;
121 vec3 invR = 1.0 / ray.dir;
122 vec3 tbot = invR * (aabb.vmin - ray.origin);
123 vec3 ttop = invR * (aabb.vmax - ray.origin);
124 vec3 tmin = min(ttop, tbot);
125 vec3 tmax = max(ttop, tbot);
126 vec2 t = max(tmin.xx, tmin.yz);
127 float t0 = max(t.x, t.y);
128 t = min(tmax.xx, tmax.yz);
129 float t1 = min(t.x, t.y);
131 if(t0 <= t1) {
132 res.hit = true;
133 res.t0 = t0;
134 res.t1 = t1;
135 } else {
136 res.hit = false;
137 }
138 return res;
139 }
141 Ray get_primary_ray(float x, float y)
142 {
143 vec3 dir;
144 dir.x = ASPECT * (2.0 * x - 1.0);
145 dir.y = 2.0 * y - 1.0;
146 dir.z = -1.0 / tan(FOV / 2.0);
148 Ray ray;
149 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
150 ray.dir = gl_NormalMatrix * normalize(dir);
151 return ray;
152 }