qvolray

view sdr/volray.p.glsl @ 20:68c6eb619d1c

normals from gradient map
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 11 Apr 2012 06:43:34 +0300
parents a6765984e057
children 4c62be57fc1a
line source
1 uniform sampler3D volume;
2 uniform sampler2D ray_tex;
3 uniform sampler1D xfer_tex;
4 uniform float ray_step;
5 uniform float zclip;
7 struct Ray {
8 vec3 origin, dir;
9 };
11 struct AABBox {
12 vec3 min, max;
13 };
15 struct ISect {
16 bool hit;
17 float t0, t1;
18 vec3 pos;
19 vec3 normal;
20 };
22 vec3 sky(Ray ray);
23 vec3 ray_march(Ray ray, float t0, float t1);
24 vec3 shade(Ray ray, vec3 pos, vec3 norm);
25 Ray get_primary_ray();
26 ISect intersect_aabb(Ray ray, AABBox aabb);
28 void main()
29 {
30 const AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0));
31 Ray ray = get_primary_ray();
33 vec3 color = vec3(0.0, 0.0, 0.0);
35 ISect res = intersect_aabb(ray, aabb);
36 if(res.hit) {
37 color = ray_march(ray, res.t0, res.t1);
38 }
40 gl_FragColor = vec4(color, 1.0);
41 }
43 float eval(vec3 pos, out vec3 grad)
44 {
45 vec3 tc = pos * 0.5 + 0.5;
47 if(tc.x < 0.0 || tc.y < 0.0 || tc.z < zclip || tc.x > 1.0 || tc.y > 1.0 || tc.z > 1.0) {
48 grad = vec3(0.0, 0.0, 0.0);
49 return 0.0;
50 }
52 vec4 texel = texture3D(volume, tc);
53 grad = texel.xyz;
55 return texture1D(xfer_tex, texel.a).x;
56 }
58 #define OFFS 0.01
59 vec3 ray_march(Ray ray, float t0, float t1)
60 {
61 float energy = 1.0;
62 float t = t0;
63 vec3 col = vec3(0.0, 0.0, 0.0);
66 while(t < t1) {
67 vec3 pos = ray.origin + ray.dir * t;
68 t += ray_step;
70 vec3 norm;
71 float val = eval(pos, norm);
73 col += /*shade(ray, pos, normalize(norm))*/ norm * val * energy;
74 energy -= val;
75 if(energy < 0.001) {
76 break;
77 }
78 pos += ray.dir * ray_step;
79 }
81 return col;
82 }
84 vec3 shade(Ray ray, vec3 pos, vec3 norm)
85 {
86 vec3 ldir = -pos;//normalize(vec3(10.0, 10.0, -10.0) - pos);
87 vec3 vdir = -ray.dir;
88 vec3 hdir = normalize(ldir + vdir);
90 float ndotl = dot(ldir, norm);
91 float ndoth = dot(hdir, norm);
93 vec3 dcol = vec3(0.9, 0.9, 0.9) * max(ndotl, 0.0);
94 vec3 scol = vec3(0.5, 0.5, 0.5) * pow(max(ndoth, 0.0), 50.0);
96 return vec3(0.01, 0.01, 0.01) + dcol + scol;
97 }
99 Ray get_primary_ray()
100 {
101 Ray ray;
102 vec2 tc = gl_TexCoord[0].xy;
103 ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz);
104 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
105 return ray;
106 }
108 ISect intersect_aabb(Ray ray, AABBox aabb)
109 {
110 ISect res;
111 res.hit = false;
112 res.t0 = res.t1 = 0.0;
114 if(ray.origin.x >= aabb.min.x && ray.origin.y >= aabb.min.y && ray.origin.z >= aabb.min.z &&
115 ray.origin.x < aabb.max.x && ray.origin.y < aabb.max.y && ray.origin.z < aabb.max.z) {
116 res.hit = true;
117 return res;
118 }
120 vec4 bbox[2];
121 bbox[0] = vec4(aabb.min.x, aabb.min.y, aabb.min.z, 0);
122 bbox[1] = vec4(aabb.max.x, aabb.max.y, aabb.max.z, 0);
124 int xsign = int(ray.dir.x < 0.0);
125 float invdirx = 1.0 / ray.dir.x;
126 float tmin = (bbox[xsign].x - ray.origin.x) * invdirx;
127 float tmax = (bbox[1 - xsign].x - ray.origin.x) * invdirx;
129 int ysign = int(ray.dir.y < 0.0);
130 float invdiry = 1.0 / ray.dir.y;
131 float tymin = (bbox[ysign].y - ray.origin.y) * invdiry;
132 float tymax = (bbox[1 - ysign].y - ray.origin.y) * invdiry;
134 if(tmin > tymax || tymin > tmax) {
135 return res;
136 }
138 if(tymin > tmin) tmin = tymin;
139 if(tymax < tmax) tmax = tymax;
141 int zsign = int(ray.dir.z < 0.0);
142 float invdirz = 1.0 / ray.dir.z;
143 float tzmin = (bbox[zsign].z - ray.origin.z) * invdirz;
144 float tzmax = (bbox[1 - zsign].z - ray.origin.z) * invdirz;
146 if(tmin > tzmax || tzmin > tmax) {
147 return res;
148 }
150 res.t0 = tmin;
151 res.t1 = tmax;
152 res.hit = true;
153 return res;
154 }