bloboland

view sdr/bloboray.p.glsl @ 4:9021a906c5d3

lots of stuff
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Dec 2012 06:13:09 +0200
parents a39c301cdcce
children 2f4406cc341e
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 vec3 refl;
16 };
18 vec3 shade(Ray ray, HitPoint hit);
19 vec3 sky(Ray ray);
20 HitPoint ray_march(Ray ray);
21 float eval_blobs(vec3 pt);
22 vec3 calc_blob_normal(vec3 pt);
23 HitPoint intersect_aabb(Ray ray, AABBox aabb);
24 Ray get_primary_ray(float x, float y);
25 float luminance(vec3 col);
26 float fresnel(float r, float cosa);
27 vec3 get_blob(int i);
29 #define BLOB_THRESHOLD 0.5
30 #define BLOB_SCALE (1.0 / 4.0)
31 #define MAX_ITER 1
33 #define RAY_STEP (0.75 / volsize.z)
35 #define FOV camprop.x
36 #define ASPECT camprop.y
37 uniform vec4 camprop;
38 uniform vec3 volsize;
39 uniform sampler3D voltex;
40 uniform vec3 worldsize;
42 uniform sampler1D blobtex;
43 uniform int num_blobs;
45 void main()
46 {
47 Ray ray = get_primary_ray(gl_TexCoord[0].x, gl_TexCoord[0].y);
49 HitPoint hit;
50 vec3 color = vec3(0.0, 0.0, 0.0);
51 vec3 power = vec3(1.0, 1.0, 1.0);
53 for(int i=0; i<=MAX_ITER; i++) {
54 hit = ray_march(ray);
55 if(hit.hit) {
56 color += shade(ray, hit) * power;
57 } else {
58 color += sky(ray) * power;
59 break;
60 }
62 ray.origin = hit.pos + hit.normal * RAY_STEP;
63 ray.dir = reflect(ray.dir, hit.normal);
64 power *= hit.refl;
66 if(luminance(power) < 0.075) {
67 break;
68 }
69 }
71 gl_FragColor = vec4(color, 1.0);
72 }
74 vec3 shade(Ray ray, HitPoint hit)
75 {
76 const vec3 light_pos = vec3(-2, 3, 2);
77 vec3 ldir = normalize(light_pos - hit.pos);
79 vec3 vdir = normalize(-ray.dir);
80 vec3 hvec = normalize(vdir + ldir);
82 float ndotl = max(dot(hit.normal, ldir), 0.0);
83 float ndoth = max(dot(hit.normal, hvec), 0.0);
85 vec3 diffuse = hit.color.xyz * ndotl;
86 vec3 specular = hit.refl * pow(ndoth, 60.0);
88 vec3 color = diffuse + specular;
90 float fog = 0.0;//smoothstep(4.0, 8.0, hit.t0);
92 //const float fog_density = 0.18;
93 //float fog = exp(-fog_density * fog_density * hit.t0 * hit.t0);
94 //fog = clamp(fog, 0.0, 1.0);
96 return mix(color, sky(ray), fog);
97 }
99 #define M_PI 3.141592653
101 vec3 sky(Ray ray)
102 {
103 const vec3 horiz = vec3(0.64, 0.70, 0.76);
104 const vec3 zenith = vec3(0.65, 0.82, 0.94);
106 float angle = acos(ray.dir.y);
107 float t = 1.0 - angle / (M_PI / 2.0);
109 return mix(horiz, zenith, smoothstep(-0.2, 0.2, t));
110 }
112 vec4 fetch_voxel(vec3 pt)
113 {
114 pt *= 1.0 / worldsize;
115 return texture3D(voltex, pt * 0.5 + 0.5);
116 }
118 vec3 calc_voxel_normal(vec3 pt)
119 {
120 vec3 offs = 6.0 / volsize;
121 float dfdx = fetch_voxel(pt + vec3(offs.x, 0.0, 0.0)).w - fetch_voxel(pt - vec3(offs.x, 0.0, 0.0)).w;
122 float dfdy = fetch_voxel(pt + vec3(0.0, offs.y, 0.0)).w - fetch_voxel(pt - vec3(0.0, offs.y, 0.0)).w;
123 float dfdz = fetch_voxel(pt + vec3(0.0, 0.0, offs.z)).w - fetch_voxel(pt - vec3(0.0, 0.0, offs.z)).w;
125 return -normalize(vec3(dfdx, dfdy, dfdz));
126 }
128 HitPoint ray_march(Ray ray)
129 {
130 HitPoint hit;
131 //AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0));
132 AABBox aabb = AABBox(-worldsize.xzy, worldsize.xzy);
134 hit.hit = false;
135 hit.t0 = hit.t1 = 0.0;
136 hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
137 hit.color = vec4(1.0, 1.0, 1.0, 1.0);
140 hit = intersect_aabb(ray, aabb);
141 if(!hit.hit) {
142 return hit;
143 }
145 /* start tracing from the first intersection, or if it's behind
146 * the viewer, start from 0.
147 */
148 float dist = max(hit.t0, 0.0);
149 float end_dist = hit.t1;
151 while(dist < end_dist) {
152 vec3 pt = ray.origin + ray.dir * dist;
154 // first try evaluating the blob field at this point
155 float blob = eval_blobs(pt);
156 if(blob >= BLOB_THRESHOLD) {
157 hit.t0 = dist;
158 hit.pos = pt;
159 hit.normal = calc_blob_normal(pt);
160 hit.color = vec4(0.0, 0.0, 0.0, 1.0);
161 hit.refl = vec3(1.0, 0.9, 0.75);
162 return hit;
163 }
165 vec4 voxel = fetch_voxel(pt.xzy);
166 if(voxel.a > 0.5) {
167 hit.t0 = dist;
168 hit.pos = pt;
169 hit.normal = calc_voxel_normal(pt.xzy).xzy;
170 hit.color = voxel;
171 hit.refl = vec3(0.0, 0.0, 0.0);
172 return hit;
173 }
175 dist += RAY_STEP;
176 }
178 hit.hit = false;
179 return hit;
180 }
182 float eval_blobs(vec3 pt)
183 {
184 float val = 0.0;
186 for(int i=0; i<num_blobs; i++) {
187 float dist = length(pt - get_blob(i));
188 val += (dist * dist * (3.0 - 2.0 * dist));
189 }
190 return val;
191 }
193 vec3 calc_blob_normal(vec3 pt)
194 {
195 const float offs = 0.01;
196 vec3 grad;
197 grad.x = eval_blobs(pt + vec3(offs, 0.0, 0.0)) - eval_blobs(pt - vec3(offs, 0.0, 0.0));
198 grad.y = eval_blobs(pt + vec3(0.0, offs, 0.0)) - eval_blobs(pt - vec3(0.0, offs, 0.0));
199 grad.z = eval_blobs(pt + vec3(0.0, 0.0, offs)) - eval_blobs(pt - vec3(0.0, 0.0, offs));
201 return -normalize(grad);
202 }
204 HitPoint intersect_aabb(Ray ray, AABBox aabb)
205 {
206 HitPoint res;
208 res.pos = res.normal = vec3(0.0, 0.0, 0.0);
209 res.color = vec4(1.0, 1.0, 1.0, 1.0);
210 res.refl = vec3(0.0, 0.0, 0.0);
212 vec3 invR = 1.0 / ray.dir;
213 vec3 tbot = invR * (aabb.vmin - ray.origin);
214 vec3 ttop = invR * (aabb.vmax - ray.origin);
215 vec3 tmin = min(ttop, tbot);
216 vec3 tmax = max(ttop, tbot);
217 vec2 t = max(tmin.xx, tmin.yz);
218 res.t0 = max(t.x, t.y);
219 t = min(tmax.xx, tmax.yz);
220 res.t1 = min(t.x, t.y);
222 if(res.t0 <= res.t1) {
223 res.hit = true;
224 } else {
225 res.hit = false;
226 }
227 return res;
228 }
230 Ray get_primary_ray(float x, float y)
231 {
232 vec3 dir;
233 dir.x = ASPECT * (2.0 * x - 1.0);
234 dir.y = 2.0 * y - 1.0;
235 dir.z = -1.0 / tan(FOV / 2.0);
237 Ray ray;
238 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
239 ray.dir = gl_NormalMatrix * normalize(dir);
240 return ray;
241 }
243 float luminance(vec3 col)
244 {
245 //const vec3 fact = vec3(0.2126, 0.7152, 0.0722);
246 //return dot(col, fact);
247 return (col.x + col.y + col.z) / 3.0;
248 }
250 float fresnel(float r, float cosa)
251 {
252 float inv_cosa = 1.0 - cosa;
253 float inv_cosa_sq = inv_cosa * inv_cosa;
255 return r + (1.0 - r) * inv_cosa_sq * inv_cosa_sq * inv_cosa;
256 }
258 vec3 get_blob(int i)
259 {
260 float tc = float(i) / float(num_blobs);
261 return texture1D(blobtex, tc).xyz;
262 }