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