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 +}