bloboland

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