rev |
line source |
nuclear@0
|
1 uniform sampler3D volume;
|
nuclear@0
|
2 uniform sampler2D ray_tex;
|
nuclear@4
|
3 uniform sampler1D xfer_tex;
|
nuclear@7
|
4 uniform float ray_step;
|
nuclear@7
|
5 uniform float zclip;
|
nuclear@0
|
6
|
nuclear@0
|
7 struct Ray {
|
nuclear@0
|
8 vec3 origin, dir;
|
nuclear@0
|
9 };
|
nuclear@0
|
10
|
nuclear@4
|
11 struct AABBox {
|
nuclear@4
|
12 vec3 min, max;
|
nuclear@4
|
13 };
|
nuclear@4
|
14
|
nuclear@0
|
15 struct ISect {
|
nuclear@0
|
16 bool hit;
|
nuclear@7
|
17 float t0, t1;
|
nuclear@0
|
18 vec3 pos;
|
nuclear@0
|
19 vec3 normal;
|
nuclear@0
|
20 };
|
nuclear@0
|
21
|
nuclear@1
|
22 vec3 sky(Ray ray);
|
nuclear@7
|
23 vec3 ray_march(Ray ray, float t0, float t1);
|
nuclear@7
|
24 vec3 shade(Ray ray, vec3 pos, vec3 norm);
|
nuclear@0
|
25 Ray get_primary_ray();
|
nuclear@5
|
26 ISect intersect_aabb(Ray ray, AABBox aabb);
|
nuclear@0
|
27
|
nuclear@0
|
28 void main()
|
nuclear@0
|
29 {
|
nuclear@5
|
30 const AABBox aabb = AABBox(vec3(-1.0, -1.0, -1.0), vec3(1.0, 1.0, 1.0));
|
nuclear@0
|
31 Ray ray = get_primary_ray();
|
nuclear@0
|
32
|
nuclear@4
|
33 vec3 color = vec3(0.0, 0.0, 0.0);
|
nuclear@4
|
34
|
nuclear@5
|
35 ISect res = intersect_aabb(ray, aabb);
|
nuclear@5
|
36 if(res.hit) {
|
nuclear@7
|
37 color = ray_march(ray, res.t0, res.t1);
|
nuclear@4
|
38 }
|
nuclear@4
|
39
|
nuclear@4
|
40 gl_FragColor = vec4(color, 1.0);
|
nuclear@0
|
41 }
|
nuclear@0
|
42
|
nuclear@4
|
43 float eval(vec3 pos)
|
nuclear@4
|
44 {
|
nuclear@5
|
45 vec3 tc = pos * 0.5 + 0.5;
|
nuclear@7
|
46
|
nuclear@7
|
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) {
|
nuclear@7
|
48 return 0.0;
|
nuclear@7
|
49 }
|
nuclear@7
|
50
|
nuclear@5
|
51 return texture1D(xfer_tex, texture3D(volume, tc).x).x;
|
nuclear@4
|
52 }
|
nuclear@4
|
53
|
nuclear@7
|
54 #define OFFS 0.01
|
nuclear@7
|
55 vec3 ray_march(Ray ray, float t0, float t1)
|
nuclear@0
|
56 {
|
nuclear@0
|
57 float energy = 1.0;
|
nuclear@7
|
58 float t = t0;
|
nuclear@7
|
59 vec3 col = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
60
|
nuclear@7
|
61
|
nuclear@7
|
62 while(t < t1) {
|
nuclear@7
|
63 vec3 pos = ray.origin + ray.dir * t;
|
nuclear@7
|
64 t += ray_step;
|
nuclear@7
|
65
|
nuclear@4
|
66 float val = eval(pos) * energy;
|
nuclear@7
|
67 vec3 norm;
|
nuclear@7
|
68
|
nuclear@7
|
69 norm.x = eval(pos + vec3(OFFS, 0.0, 0.0)) - val;
|
nuclear@7
|
70 norm.y = eval(pos + vec3(0.0, OFFS, 0.0)) - val;
|
nuclear@7
|
71 norm.z = eval(pos + vec3(0.0, 0.0, OFFS)) - val;
|
nuclear@7
|
72 norm = normalize(norm);
|
nuclear@7
|
73
|
nuclear@7
|
74 col += shade(ray, pos, norm) * val;
|
nuclear@1
|
75 energy -= val;
|
nuclear@1
|
76 if(energy < 0.001) {
|
nuclear@1
|
77 break;
|
nuclear@1
|
78 }
|
nuclear@0
|
79 pos += ray.dir * ray_step;
|
nuclear@0
|
80 }
|
nuclear@0
|
81
|
nuclear@7
|
82 return col;
|
nuclear@0
|
83 }
|
nuclear@0
|
84
|
nuclear@7
|
85 vec3 shade(Ray ray, vec3 pos, vec3 norm)
|
nuclear@0
|
86 {
|
nuclear@7
|
87 vec3 ldir = normalize(vec3(10.0, 10.0, -10.0) - pos);
|
nuclear@0
|
88 vec3 vdir = -ray.dir;
|
nuclear@0
|
89 vec3 hdir = normalize(ldir + vdir);
|
nuclear@0
|
90
|
nuclear@7
|
91 float ndotl = dot(ldir, norm);
|
nuclear@7
|
92 float ndoth = dot(hdir, norm);
|
nuclear@0
|
93
|
nuclear@0
|
94 vec3 dcol = vec3(1.0, 1.0, 1.0) * max(ndotl, 0.0);
|
nuclear@0
|
95 vec3 scol = vec3(0.6, 0.6, 0.6) * pow(max(ndoth, 0.0), 50.0);
|
nuclear@0
|
96
|
nuclear@0
|
97 return vec3(0.01, 0.01, 0.01) + dcol + scol;
|
nuclear@0
|
98 }
|
nuclear@0
|
99
|
nuclear@0
|
100 Ray get_primary_ray()
|
nuclear@0
|
101 {
|
nuclear@0
|
102 Ray ray;
|
nuclear@0
|
103 vec2 tc = gl_TexCoord[0].xy;
|
nuclear@0
|
104 ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz);
|
nuclear@0
|
105 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
nuclear@0
|
106 return ray;
|
nuclear@0
|
107 }
|
nuclear@4
|
108
|
nuclear@5
|
109 ISect intersect_aabb(Ray ray, AABBox aabb)
|
nuclear@4
|
110 {
|
nuclear@5
|
111 ISect res;
|
nuclear@5
|
112 res.hit = false;
|
nuclear@7
|
113 res.t0 = res.t1 = 0.0;
|
nuclear@5
|
114
|
nuclear@4
|
115 if(ray.origin.x >= aabb.min.x && ray.origin.y >= aabb.min.y && ray.origin.z >= aabb.min.z &&
|
nuclear@4
|
116 ray.origin.x < aabb.max.x && ray.origin.y < aabb.max.y && ray.origin.z < aabb.max.z) {
|
nuclear@5
|
117 res.hit = true;
|
nuclear@5
|
118 return res;
|
nuclear@4
|
119 }
|
nuclear@4
|
120
|
nuclear@4
|
121 vec4 bbox[2];
|
nuclear@4
|
122 bbox[0] = vec4(aabb.min.x, aabb.min.y, aabb.min.z, 0);
|
nuclear@4
|
123 bbox[1] = vec4(aabb.max.x, aabb.max.y, aabb.max.z, 0);
|
nuclear@4
|
124
|
nuclear@4
|
125 int xsign = int(ray.dir.x < 0.0);
|
nuclear@4
|
126 float invdirx = 1.0 / ray.dir.x;
|
nuclear@4
|
127 float tmin = (bbox[xsign].x - ray.origin.x) * invdirx;
|
nuclear@4
|
128 float tmax = (bbox[1 - xsign].x - ray.origin.x) * invdirx;
|
nuclear@4
|
129
|
nuclear@4
|
130 int ysign = int(ray.dir.y < 0.0);
|
nuclear@4
|
131 float invdiry = 1.0 / ray.dir.y;
|
nuclear@4
|
132 float tymin = (bbox[ysign].y - ray.origin.y) * invdiry;
|
nuclear@4
|
133 float tymax = (bbox[1 - ysign].y - ray.origin.y) * invdiry;
|
nuclear@4
|
134
|
nuclear@4
|
135 if(tmin > tymax || tymin > tmax) {
|
nuclear@5
|
136 return res;
|
nuclear@4
|
137 }
|
nuclear@4
|
138
|
nuclear@4
|
139 if(tymin > tmin) tmin = tymin;
|
nuclear@4
|
140 if(tymax < tmax) tmax = tymax;
|
nuclear@4
|
141
|
nuclear@4
|
142 int zsign = int(ray.dir.z < 0.0);
|
nuclear@4
|
143 float invdirz = 1.0 / ray.dir.z;
|
nuclear@4
|
144 float tzmin = (bbox[zsign].z - ray.origin.z) * invdirz;
|
nuclear@4
|
145 float tzmax = (bbox[1 - zsign].z - ray.origin.z) * invdirz;
|
nuclear@4
|
146
|
nuclear@4
|
147 if(tmin > tzmax || tzmin > tmax) {
|
nuclear@5
|
148 return res;
|
nuclear@4
|
149 }
|
nuclear@4
|
150
|
nuclear@7
|
151 res.t0 = tmin;
|
nuclear@7
|
152 res.t1 = tmax;
|
nuclear@5
|
153 res.hit = true;
|
nuclear@5
|
154 return res;
|
nuclear@4
|
155 }
|
nuclear@4
|
156
|