bloboland
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/sdr/bloboray.p.glsl Sun Dec 16 14:24:16 2012 +0200 1.3 @@ -0,0 +1,152 @@ 1.4 +struct Ray { 1.5 + vec3 origin; 1.6 + vec3 dir; 1.7 +}; 1.8 + 1.9 +struct AABBox { 1.10 + vec3 vmin, vmax; 1.11 +}; 1.12 + 1.13 +struct HitPoint { 1.14 + bool hit; 1.15 + float t0, t1; 1.16 + vec3 pos, normal; 1.17 + vec4 color; 1.18 +}; 1.19 + 1.20 +vec3 shade(Ray ray, HitPoint hit); 1.21 +HitPoint intersect_voxels(Ray ray); 1.22 +HitPoint intersect_aabb(Ray ray, AABBox aabb); 1.23 +Ray get_primary_ray(float x, float y); 1.24 + 1.25 +#define RAY_STEP 0.001 1.26 + 1.27 +#define FOV camprop.x 1.28 +#define ASPECT camprop.y 1.29 +uniform vec4 camprop; 1.30 +uniform vec3 volsize; 1.31 +uniform sampler3D voltex; 1.32 + 1.33 +//const vec3 worldsize = vec3(4.0, 4.0, 2.0); 1.34 +const vec3 worldsize = vec3(1.0, 1.0, 0.5); 1.35 + 1.36 +void main() 1.37 +{ 1.38 + Ray ray = get_primary_ray(gl_TexCoord[0].x, gl_TexCoord[0].y); 1.39 + 1.40 + vec3 color = vec3(0.0, 0.0, 0.0); 1.41 + HitPoint hit = intersect_voxels(ray); 1.42 + if(hit.hit) { 1.43 + color = shade(ray, hit); 1.44 + } 1.45 + 1.46 + gl_FragColor = vec4(color, 1.0); 1.47 +} 1.48 + 1.49 +vec3 shade(Ray ray, HitPoint hit) 1.50 +{ 1.51 + const vec3 light_pos = vec3(-2, 3, 2); 1.52 + vec3 ldir = normalize(light_pos - hit.pos); 1.53 + 1.54 + vec3 vdir = normalize(-ray.dir); 1.55 + vec3 hvec = normalize(vdir + ldir); 1.56 + 1.57 + float ndotl = max(dot(hit.normal, ldir), 0.0); 1.58 + float ndoth = max(dot(hit.normal, hvec), 0.0); 1.59 + 1.60 + vec3 diffuse = hit.color.xyz * ndotl; 1.61 + vec3 specular = vec3(0.4, 0.4, 0.4) * pow(ndoth, 60.0); 1.62 + 1.63 + return diffuse + specular; 1.64 +} 1.65 + 1.66 +vec4 fetch_voxel(vec3 pt) 1.67 +{ 1.68 + pt *= 1.0 / worldsize; 1.69 + return texture3D(voltex, pt * 0.5 + 0.5); 1.70 +} 1.71 + 1.72 +vec3 calc_voxel_normal(vec3 pt) 1.73 +{ 1.74 + vec3 offs = 1.8 / volsize; 1.75 + float dfdx = fetch_voxel(pt + vec3(offs.x, 0.0, 0.0)).w - fetch_voxel(pt - vec3(offs.x, 0.0, 0.0)).w; 1.76 + float dfdy = fetch_voxel(pt + vec3(0.0, offs.y, 0.0)).w - fetch_voxel(pt - vec3(0.0, offs.y, 0.0)).w; 1.77 + float dfdz = fetch_voxel(pt + vec3(0.0, 0.0, offs.z)).w - fetch_voxel(pt - vec3(0.0, 0.0, offs.z)).w; 1.78 + 1.79 + return -normalize(vec3(dfdx, dfdy, dfdz)); 1.80 +} 1.81 + 1.82 +HitPoint intersect_voxels(Ray ray) 1.83 +{ 1.84 + HitPoint hit; 1.85 + //AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0)); 1.86 + AABBox aabb = AABBox(-worldsize.xzy, worldsize.xzy); 1.87 + 1.88 + 1.89 + hit = intersect_aabb(ray, aabb); 1.90 + if(!hit.hit) { 1.91 + return hit; 1.92 + } 1.93 + 1.94 + /* start tracing from the first intersection, or if it's behind 1.95 + * the viewer, start from 0. 1.96 + */ 1.97 + float dist = max(hit.t0, 0.0); 1.98 + float end_dist = hit.t1; 1.99 + 1.100 + while(dist < end_dist) { 1.101 + vec3 pt = ray.origin + ray.dir * dist; 1.102 + vec4 voxel = fetch_voxel(pt.xzy); 1.103 + 1.104 + 1.105 + if(voxel.a > 0.5) { 1.106 + hit.t0 = dist; 1.107 + hit.pos = pt; 1.108 + hit.normal = calc_voxel_normal(pt.xzy).xzy; 1.109 + hit.color = voxel; 1.110 + return hit; 1.111 + } 1.112 + 1.113 + dist += RAY_STEP; 1.114 + } 1.115 + 1.116 + hit.hit = false; 1.117 + return hit; 1.118 +} 1.119 + 1.120 +HitPoint intersect_aabb(Ray ray, AABBox aabb) 1.121 +{ 1.122 + HitPoint res; 1.123 + 1.124 + vec3 invR = 1.0 / ray.dir; 1.125 + vec3 tbot = invR * (aabb.vmin - ray.origin); 1.126 + vec3 ttop = invR * (aabb.vmax - ray.origin); 1.127 + vec3 tmin = min(ttop, tbot); 1.128 + vec3 tmax = max(ttop, tbot); 1.129 + vec2 t = max(tmin.xx, tmin.yz); 1.130 + float t0 = max(t.x, t.y); 1.131 + t = min(tmax.xx, tmax.yz); 1.132 + float t1 = min(t.x, t.y); 1.133 + 1.134 + if(t0 <= t1) { 1.135 + res.hit = true; 1.136 + res.t0 = t0; 1.137 + res.t1 = t1; 1.138 + } else { 1.139 + res.hit = false; 1.140 + } 1.141 + return res; 1.142 +} 1.143 + 1.144 +Ray get_primary_ray(float x, float y) 1.145 +{ 1.146 + vec3 dir; 1.147 + dir.x = ASPECT * (2.0 * x - 1.0); 1.148 + dir.y = 2.0 * y - 1.0; 1.149 + dir.z = -1.0 / tan(FOV / 2.0); 1.150 + 1.151 + Ray ray; 1.152 + ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; 1.153 + ray.dir = gl_NormalMatrix * normalize(dir); 1.154 + return ray; 1.155 +}