rev |
line source |
nuclear@0
|
1 /* vi:set filetype=glsl ts=4 sw=4: */
|
nuclear@0
|
2 #version 120
|
nuclear@0
|
3 #extension GL_ARB_gpu_shader5 : enable
|
nuclear@0
|
4
|
nuclear@0
|
5 #define M_PI 3.1415926
|
nuclear@0
|
6
|
nuclear@0
|
7 #define INIT_EVERYTHING
|
nuclear@0
|
8 #define USE_XFORM
|
nuclear@0
|
9 #define OBJ_LINE_WIDTH 16.0
|
nuclear@0
|
10
|
nuclear@0
|
11 struct Ray {
|
nuclear@0
|
12 vec3 origin, dir;
|
nuclear@0
|
13 };
|
nuclear@0
|
14
|
nuclear@0
|
15 struct Material {
|
nuclear@0
|
16 vec3 diffuse, specular;
|
nuclear@0
|
17 float shininess;
|
nuclear@0
|
18 vec4 megatex_rect;
|
nuclear@0
|
19 float reflectivity;
|
nuclear@0
|
20 };
|
nuclear@0
|
21
|
nuclear@0
|
22 struct HitPoint {
|
nuclear@0
|
23 float dist;
|
nuclear@0
|
24 vec3 pos, normal;
|
nuclear@0
|
25 vec2 texcoord;
|
nuclear@0
|
26 struct Material mat;
|
nuclear@0
|
27 };
|
nuclear@0
|
28
|
nuclear@0
|
29 struct Sphere {
|
nuclear@0
|
30 float index;
|
nuclear@0
|
31 vec3 pos;
|
nuclear@0
|
32 float radius;
|
nuclear@0
|
33 struct Material mat;
|
nuclear@0
|
34 };
|
nuclear@0
|
35
|
nuclear@0
|
36 struct Plane {
|
nuclear@0
|
37 float index;
|
nuclear@0
|
38 vec3 normal;
|
nuclear@0
|
39 float dist;
|
nuclear@0
|
40 struct Material mat;
|
nuclear@0
|
41 };
|
nuclear@0
|
42
|
nuclear@0
|
43 struct Box {
|
nuclear@0
|
44 float index;
|
nuclear@0
|
45 vec3 min, max;
|
nuclear@0
|
46 struct Material mat;
|
nuclear@0
|
47 };
|
nuclear@0
|
48
|
nuclear@0
|
49 struct Light {
|
nuclear@0
|
50 vec3 pos, color;
|
nuclear@0
|
51 };
|
nuclear@0
|
52
|
nuclear@0
|
53 vec3 shade(in Ray ray, in HitPoint hit);
|
nuclear@0
|
54 bool find_intersection(in Ray ray, out HitPoint hit);
|
nuclear@0
|
55 bool sphere_intersect(in Sphere sph, in Ray ray, out HitPoint pt);
|
nuclear@0
|
56 bool plane_intersect(in Plane plane, in Ray ray, out HitPoint pt);
|
nuclear@0
|
57 bool box_intersect(in Box box, in Ray ray, out HitPoint pt);
|
nuclear@0
|
58 vec3 transform(in vec3 v, in mat4 inv_xform);
|
nuclear@0
|
59 Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform);
|
nuclear@0
|
60 Ray get_primary_ray();
|
nuclear@0
|
61
|
nuclear@0
|
62 Sphere read_sphere(in float idx);
|
nuclear@0
|
63 Plane read_plane(in float idx);
|
nuclear@0
|
64 Box read_box(in float idx);
|
nuclear@0
|
65 Material read_material(in sampler2D tex, in float ty);
|
nuclear@0
|
66 void read_xform(in float idx, out mat4 xform, out mat4 inv_xform);
|
nuclear@0
|
67
|
nuclear@0
|
68 uniform sampler2D tex_raydir;
|
nuclear@0
|
69 uniform sampler2D tex_spheres, tex_planes, tex_boxes;
|
nuclear@0
|
70 uniform sampler2D tex_megatex;
|
nuclear@0
|
71 uniform sampler2D tex_xforms;
|
nuclear@0
|
72 uniform samplerCube tex_env;
|
nuclear@0
|
73 uniform vec2 fog;
|
nuclear@0
|
74
|
nuclear@0
|
75 uniform Light lights[8];
|
nuclear@0
|
76 uniform int num_lights;
|
nuclear@0
|
77
|
nuclear@0
|
78 int num_spheres, num_planes, num_boxes;
|
nuclear@0
|
79 float sph_tex_sz, plane_tex_sz, box_tex_sz, xform_tex_sz;
|
nuclear@0
|
80
|
nuclear@0
|
81 #ifdef INIT_EVERYTHING
|
nuclear@0
|
82 Material default_material;
|
nuclear@0
|
83 #endif
|
nuclear@0
|
84
|
nuclear@0
|
85 void main()
|
nuclear@0
|
86 {
|
nuclear@0
|
87 #ifdef INIT_EVERYTHING
|
nuclear@0
|
88 default_material.diffuse = default_material.specular = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
89 default_material.shininess = 1.0;
|
nuclear@0
|
90 default_material.reflectivity = 0.0;
|
nuclear@0
|
91 default_material.megatex_rect = vec4(0.0, 0.0, 0.0, 0.0);
|
nuclear@0
|
92 #endif
|
nuclear@0
|
93
|
nuclear@0
|
94 Ray ray = get_primary_ray();
|
nuclear@0
|
95
|
nuclear@0
|
96 /* read the various descriptors specifying dimensions and counts for
|
nuclear@0
|
97 * all the relevant data textures
|
nuclear@0
|
98 */
|
nuclear@0
|
99 vec4 desc = texture2D(tex_spheres, vec2(0.0, 0.0));
|
nuclear@0
|
100 num_spheres = int(desc.x);
|
nuclear@0
|
101 sph_tex_sz = desc.y;
|
nuclear@0
|
102
|
nuclear@0
|
103 desc = texture2D(tex_planes, vec2(0.0, 0.0));
|
nuclear@0
|
104 num_planes = int(desc.x);
|
nuclear@0
|
105 plane_tex_sz = desc.y;
|
nuclear@0
|
106
|
nuclear@0
|
107 desc = texture2D(tex_boxes, vec2(0.0, 0.0));
|
nuclear@0
|
108 num_boxes = int(desc.x);
|
nuclear@0
|
109 box_tex_sz = desc.y;
|
nuclear@0
|
110
|
nuclear@0
|
111 xform_tex_sz = texture2D(tex_xforms, vec2(0.0, 0.0)).x;
|
nuclear@0
|
112
|
nuclear@0
|
113
|
nuclear@0
|
114 HitPoint hit;
|
nuclear@0
|
115 #ifdef INIT_EVERYTHING
|
nuclear@0
|
116 hit.dist = 0.0;
|
nuclear@0
|
117 hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
118 #endif
|
nuclear@0
|
119
|
nuclear@0
|
120 vec3 color = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
121 float energy = 1.0;
|
nuclear@0
|
122
|
nuclear@0
|
123 int iter = 0;
|
nuclear@0
|
124 while(energy > 0.01 && iter++ < 4) {
|
nuclear@0
|
125 vec3 envcol = textureCube(tex_env, ray.dir).xyz;
|
nuclear@0
|
126
|
nuclear@0
|
127 if(find_intersection(ray, hit)) {
|
nuclear@0
|
128 float fog_t = clamp((hit.dist - fog.x) / (fog.y - fog.x), 0.0, 1.0);
|
nuclear@0
|
129 color += mix(shade(ray, hit), envcol, fog_t) * energy;
|
nuclear@0
|
130 energy *= hit.mat.reflectivity * (1.0 - fog_t);
|
nuclear@0
|
131 ray.origin = hit.pos;
|
nuclear@0
|
132 ray.dir = reflect(ray.dir, hit.normal);
|
nuclear@0
|
133 } else {
|
nuclear@0
|
134 color += envcol * energy;
|
nuclear@0
|
135 energy = 0.0;
|
nuclear@0
|
136 iter = 100;
|
nuclear@0
|
137 }
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 gl_FragColor.xyz = color;
|
nuclear@0
|
141 gl_FragColor.w = 1.0;
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@0
|
144 vec3 shade(in Ray ray, in HitPoint hit)
|
nuclear@0
|
145 {
|
nuclear@0
|
146 vec3 normal = faceforward(hit.normal, ray.dir, hit.normal);
|
nuclear@0
|
147
|
nuclear@0
|
148 vec3 vdir = normalize(ray.dir);
|
nuclear@0
|
149 vec3 vref = reflect(vdir, normal);
|
nuclear@0
|
150
|
nuclear@0
|
151 /* if there's no texture rect.zw will be (0, 0, 0, 0) so this will map onto
|
nuclear@0
|
152 * the top-left 1x1 null texture which is all white (having no effect)
|
nuclear@0
|
153 */
|
nuclear@0
|
154 vec2 tc = mod(hit.texcoord, vec2(1.0, 1.0)) * hit.mat.megatex_rect.zw + hit.mat.megatex_rect.xy;
|
nuclear@0
|
155
|
nuclear@0
|
156 vec3 diffuse_color = hit.mat.diffuse * texture2D(tex_megatex, tc).xyz;
|
nuclear@0
|
157
|
nuclear@0
|
158 vec3 color = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
159 for(int i=0; i<num_lights; i++) {
|
nuclear@0
|
160 Ray shadow_ray;
|
nuclear@0
|
161 shadow_ray.origin = hit.pos;
|
nuclear@0
|
162 shadow_ray.dir = lights[i].pos - hit.pos;
|
nuclear@0
|
163
|
nuclear@0
|
164 HitPoint shadow_hit;
|
nuclear@0
|
165 if(!find_intersection(shadow_ray, shadow_hit) || shadow_hit.dist > 1.0) {
|
nuclear@0
|
166 vec3 ldir = normalize(shadow_ray.dir);
|
nuclear@0
|
167
|
nuclear@0
|
168 float diffuse = max(dot(ldir, normal), 0.0);
|
nuclear@0
|
169 float specular = pow(max(dot(ldir, vref), 0.0), hit.mat.shininess);
|
nuclear@0
|
170
|
nuclear@0
|
171 color += (diffuse_color * diffuse + hit.mat.specular * specular) * lights[i].color;
|
nuclear@0
|
172 }
|
nuclear@0
|
173 }
|
nuclear@0
|
174
|
nuclear@0
|
175 return color;
|
nuclear@0
|
176 }
|
nuclear@0
|
177
|
nuclear@0
|
178 bool find_intersection(in Ray ray, out HitPoint hit)
|
nuclear@0
|
179 {
|
nuclear@0
|
180 hit.dist = 100000.0;
|
nuclear@0
|
181 #ifdef INIT_EVERYTHING
|
nuclear@0
|
182 hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
183 hit.mat = default_material;
|
nuclear@0
|
184 hit.texcoord = vec2(0.0, 0.0);
|
nuclear@0
|
185 #endif
|
nuclear@0
|
186 bool found = false;
|
nuclear@0
|
187
|
nuclear@0
|
188 for(int i=0; i<num_spheres; i++) {
|
nuclear@0
|
189 Sphere sph = read_sphere(i);
|
nuclear@0
|
190
|
nuclear@0
|
191 HitPoint tmphit;
|
nuclear@0
|
192 if(sphere_intersect(sph, ray, tmphit) && tmphit.dist < hit.dist) {
|
nuclear@0
|
193 hit = tmphit;
|
nuclear@0
|
194 found = true;
|
nuclear@0
|
195 }
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 for(int i=0; i<num_planes; i++) {
|
nuclear@0
|
199 Plane plane = read_plane(i);
|
nuclear@0
|
200
|
nuclear@0
|
201 HitPoint tmphit;
|
nuclear@0
|
202 if(plane_intersect(plane, ray, tmphit) && tmphit.dist < hit.dist) {
|
nuclear@0
|
203 hit = tmphit;
|
nuclear@0
|
204 found = true;
|
nuclear@0
|
205 }
|
nuclear@0
|
206 }
|
nuclear@0
|
207
|
nuclear@0
|
208 for(int i=0; i<num_boxes; i++) {
|
nuclear@0
|
209 Box box = read_box(i);
|
nuclear@0
|
210
|
nuclear@0
|
211 HitPoint tmphit;
|
nuclear@0
|
212 if(box_intersect(box, ray, tmphit) && tmphit.dist < hit.dist) {
|
nuclear@0
|
213 hit = tmphit;
|
nuclear@0
|
214 found = true;
|
nuclear@0
|
215 }
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 return found;
|
nuclear@0
|
219 }
|
nuclear@0
|
220
|
nuclear@0
|
221 #define EPSILON 1e-4
|
nuclear@0
|
222 #define SQ(x) ((x) * (x))
|
nuclear@0
|
223
|
nuclear@0
|
224 bool sphere_intersect(in Sphere sph, in Ray inray, out HitPoint pt)
|
nuclear@0
|
225 {
|
nuclear@0
|
226 #ifdef USE_XFORM
|
nuclear@0
|
227 mat4 xform, inv_xform;
|
nuclear@0
|
228 read_xform(sph.index, xform, inv_xform);
|
nuclear@0
|
229
|
nuclear@0
|
230 Ray ray = transform(inray, inv_xform, xform);
|
nuclear@0
|
231 #else
|
nuclear@0
|
232 Ray ray = inray;
|
nuclear@0
|
233 #endif
|
nuclear@0
|
234
|
nuclear@0
|
235 #ifdef INIT_EVERYTHING
|
nuclear@0
|
236 pt.dist = 0.0;
|
nuclear@0
|
237 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
238 pt.mat = default_material;
|
nuclear@0
|
239 pt.texcoord = vec2(0.0, 0.0);
|
nuclear@0
|
240 #endif
|
nuclear@0
|
241
|
nuclear@0
|
242 float a = dot(ray.dir, ray.dir);
|
nuclear@0
|
243 float b = dot(ray.dir, ray.origin - sph.pos) * 2.0;
|
nuclear@0
|
244 float c = dot(ray.origin, ray.origin) + dot(sph.pos, sph.pos) -
|
nuclear@0
|
245 2.0 * dot(ray.origin, sph.pos) - sph.radius * sph.radius;
|
nuclear@0
|
246
|
nuclear@0
|
247 float discr = b * b - 4.0 * a * c;
|
nuclear@0
|
248 if(discr < EPSILON)
|
nuclear@0
|
249 return false;
|
nuclear@0
|
250
|
nuclear@0
|
251 float sqrt_discr = sqrt(discr);
|
nuclear@0
|
252 float t0 = (-b + sqrt_discr) / (2.0 * a);
|
nuclear@0
|
253 float t1 = (-b - sqrt_discr) / (2.0 * a);
|
nuclear@0
|
254
|
nuclear@0
|
255 if(t0 < EPSILON)
|
nuclear@0
|
256 t0 = t1;
|
nuclear@0
|
257 if(t1 < EPSILON)
|
nuclear@0
|
258 t1 = t0;
|
nuclear@0
|
259
|
nuclear@0
|
260 float t = min(t0, t1);
|
nuclear@0
|
261 if(t < EPSILON)
|
nuclear@0
|
262 return false;
|
nuclear@0
|
263
|
nuclear@0
|
264 // fill the HitPoint structure
|
nuclear@0
|
265 pt.dist = t;
|
nuclear@0
|
266 pt.pos = ray.origin + ray.dir * t;
|
nuclear@0
|
267 pt.normal = (pt.pos - sph.pos) / sph.radius;
|
nuclear@0
|
268 pt.mat = sph.mat;
|
nuclear@0
|
269
|
nuclear@0
|
270 pt.texcoord.x = 0.5 * atan(pt.normal.z, pt.normal.x) / M_PI + 0.5;
|
nuclear@0
|
271 pt.texcoord.y = acos(pt.normal.y) / M_PI;
|
nuclear@0
|
272
|
nuclear@0
|
273 #ifdef USE_XFORM
|
nuclear@0
|
274 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
|
nuclear@0
|
275 pt.normal = normalize(transform(pt.normal, xform));
|
nuclear@0
|
276 #endif
|
nuclear@0
|
277 return true;
|
nuclear@0
|
278 }
|
nuclear@0
|
279
|
nuclear@0
|
280 bool plane_intersect(in Plane plane, in Ray inray, out HitPoint pt)
|
nuclear@0
|
281 {
|
nuclear@0
|
282 #ifdef USE_XFORM
|
nuclear@0
|
283 mat4 xform, inv_xform;
|
nuclear@0
|
284 read_xform(plane.index, xform, inv_xform);
|
nuclear@0
|
285
|
nuclear@0
|
286 Ray ray = transform(inray, inv_xform, xform);
|
nuclear@0
|
287 #else
|
nuclear@0
|
288 Ray ray = inray;
|
nuclear@0
|
289 #endif
|
nuclear@0
|
290
|
nuclear@0
|
291 #ifdef INIT_EVERYTHING
|
nuclear@0
|
292 pt.dist = 0.0;
|
nuclear@0
|
293 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
294 pt.mat = default_material;
|
nuclear@0
|
295 pt.texcoord = vec2(0.0, 0.0);
|
nuclear@0
|
296 #endif
|
nuclear@0
|
297
|
nuclear@0
|
298 float ndotdir = dot(plane.normal, ray.dir);
|
nuclear@0
|
299 if(abs(ndotdir) < EPSILON) {
|
nuclear@0
|
300 return false;
|
nuclear@0
|
301 }
|
nuclear@0
|
302
|
nuclear@0
|
303 vec3 planept = plane.normal * plane.dist;
|
nuclear@0
|
304 vec3 pptdir = planept - ray.origin;
|
nuclear@0
|
305
|
nuclear@0
|
306 float t = dot(plane.normal, pptdir) / ndotdir;
|
nuclear@0
|
307 if(t < EPSILON) {
|
nuclear@0
|
308 return false;
|
nuclear@0
|
309 }
|
nuclear@0
|
310
|
nuclear@0
|
311 pt.dist = t;
|
nuclear@0
|
312 pt.pos = ray.origin + ray.dir * t;
|
nuclear@0
|
313 pt.normal = plane.normal;
|
nuclear@0
|
314 pt.mat = plane.mat;
|
nuclear@0
|
315 pt.texcoord.x = pt.pos.x;
|
nuclear@0
|
316 pt.texcoord.y = pt.pos.z;
|
nuclear@0
|
317
|
nuclear@0
|
318 #ifdef USE_XFORM
|
nuclear@0
|
319 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
|
nuclear@0
|
320 pt.normal = normalize(transform(pt.normal, xform));
|
nuclear@0
|
321 #endif
|
nuclear@0
|
322 return true;
|
nuclear@0
|
323 }
|
nuclear@0
|
324
|
nuclear@0
|
325 bool box_intersect(in Box box, in Ray inray, out HitPoint pt)
|
nuclear@0
|
326 {
|
nuclear@0
|
327 #ifdef USE_XFORM
|
nuclear@0
|
328 mat4 xform, inv_xform;
|
nuclear@0
|
329 read_xform(box.index, xform, inv_xform);
|
nuclear@0
|
330
|
nuclear@0
|
331 Ray ray = transform(inray, inv_xform, xform);
|
nuclear@0
|
332 #else
|
nuclear@0
|
333 Ray ray = inray;
|
nuclear@0
|
334 #endif
|
nuclear@0
|
335
|
nuclear@0
|
336 #ifdef INIT_EVERYTHING
|
nuclear@0
|
337 pt.dist = 0.0;
|
nuclear@0
|
338 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
|
nuclear@0
|
339 pt.mat = default_material;
|
nuclear@0
|
340 pt.texcoord = vec2(0.0, 0.0);
|
nuclear@0
|
341 #endif
|
nuclear@0
|
342
|
nuclear@0
|
343 vec3 param[2];
|
nuclear@0
|
344 param[0] = box.min;
|
nuclear@0
|
345 param[1] = box.max;
|
nuclear@0
|
346
|
nuclear@0
|
347 vec3 inv_dir = 1.0 / ray.dir;
|
nuclear@0
|
348 int sgn[3];
|
nuclear@0
|
349 sgn[0] = inv_dir.x < 0.0 ? 1 : 0;
|
nuclear@0
|
350 sgn[1] = inv_dir.y < 0.0 ? 1 : 0;
|
nuclear@0
|
351 sgn[2] = inv_dir.z < 0.0 ? 1 : 0;
|
nuclear@0
|
352
|
nuclear@0
|
353 float tmin = (param[sgn[0]].x - ray.origin.x) * inv_dir.x;
|
nuclear@0
|
354 float tmax = (param[1 - sgn[0]].x - ray.origin.x) * inv_dir.x;
|
nuclear@0
|
355 float tymin = (param[sgn[1]].y - ray.origin.y) * inv_dir.y;
|
nuclear@0
|
356 float tymax = (param[1 - sgn[1]].y - ray.origin.y) * inv_dir.y;
|
nuclear@0
|
357
|
nuclear@0
|
358 pt.normal = vec3(ray.origin.x > 0.0 ? 1.0 : -1.0, 0.0, 0.0);
|
nuclear@0
|
359
|
nuclear@0
|
360 if(tmin > tymax || tymin > tmax) {
|
nuclear@0
|
361 return false;
|
nuclear@0
|
362 }
|
nuclear@0
|
363 if(tymin > tmin) {
|
nuclear@0
|
364 pt.normal = vec3(0.0, ray.origin.y > 0.0 ? 1.0 : -1.0, 0.0);
|
nuclear@0
|
365 tmin = tymin;
|
nuclear@0
|
366 }
|
nuclear@0
|
367 if(tymax < tmax) {
|
nuclear@0
|
368 tmax = tymax;
|
nuclear@0
|
369 }
|
nuclear@0
|
370
|
nuclear@0
|
371 float tzmin = (param[sgn[2]].z - ray.origin.z) * inv_dir.z;
|
nuclear@0
|
372 float tzmax = (param[1 - sgn[2]].z - ray.origin.z) * inv_dir.z;
|
nuclear@0
|
373
|
nuclear@0
|
374 if(tmin > tzmax || tzmin > tmax) {
|
nuclear@0
|
375 return false;
|
nuclear@0
|
376 }
|
nuclear@0
|
377 if(tzmin > tmin) {
|
nuclear@0
|
378 pt.normal = vec3(0.0, 0.0, ray.origin.z > 0.0 ? 1.0 : -1.0);
|
nuclear@0
|
379 tmin = tzmin;
|
nuclear@0
|
380 }
|
nuclear@0
|
381 if(tzmax < tmax) {
|
nuclear@0
|
382 tmax = tzmax;
|
nuclear@0
|
383 }
|
nuclear@0
|
384
|
nuclear@0
|
385 float t = tmin < EPSILON ? tmax : tmin;
|
nuclear@0
|
386 if(t >= 1e-4) {
|
nuclear@0
|
387 pt.dist = t;
|
nuclear@0
|
388 pt.pos = ray.origin + ray.dir * t;
|
nuclear@0
|
389 pt.mat = box.mat;
|
nuclear@0
|
390
|
nuclear@0
|
391 float min_dist = 10000.0;
|
nuclear@0
|
392
|
nuclear@0
|
393 vec3 offs = box.min + (box.max - box.min) / 2.0;
|
nuclear@0
|
394 vec3 local_pt = pt.pos - offs;
|
nuclear@0
|
395
|
nuclear@0
|
396 vec3 dist = abs((box.max - offs) - abs(local_pt));
|
nuclear@0
|
397 if(dist.x < min_dist) {
|
nuclear@0
|
398 min_dist = dist.x;
|
nuclear@0
|
399 pt.normal = sign(local_pt.x) * vec3(1.0, 0.0, 0.0);
|
nuclear@0
|
400 pt.texcoord = pt.pos.zy;
|
nuclear@0
|
401 }
|
nuclear@0
|
402 if(dist.y < min_dist) {
|
nuclear@0
|
403 min_dist = dist.y;
|
nuclear@0
|
404 pt.normal = sign(local_pt.y) * vec3(0.0, 1.0, 0.0);
|
nuclear@0
|
405 pt.texcoord = pt.pos.xz;
|
nuclear@0
|
406 }
|
nuclear@0
|
407 if(dist.z < min_dist) {
|
nuclear@0
|
408 pt.normal = sign(local_pt.y) * vec3(0.0, 0.0, 1.0);
|
nuclear@0
|
409 pt.texcoord = pt.pos.xy;
|
nuclear@0
|
410 }
|
nuclear@0
|
411
|
nuclear@0
|
412
|
nuclear@0
|
413 #ifdef USE_XFORM
|
nuclear@0
|
414 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
|
nuclear@0
|
415 pt.normal = normalize(transform(pt.normal, xform));
|
nuclear@0
|
416 #endif
|
nuclear@0
|
417 return true;
|
nuclear@0
|
418 }
|
nuclear@0
|
419 return false;
|
nuclear@0
|
420 }
|
nuclear@0
|
421
|
nuclear@0
|
422 vec3 transform(in vec3 v, in mat4 xform)
|
nuclear@0
|
423 {
|
nuclear@0
|
424 return mat3(xform) * v;
|
nuclear@0
|
425 }
|
nuclear@0
|
426
|
nuclear@0
|
427 Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform)
|
nuclear@0
|
428 {
|
nuclear@0
|
429 Ray res;
|
nuclear@0
|
430 res.origin = (xform * vec4(ray.origin, 1.0)).xyz;
|
nuclear@0
|
431 res.dir = transform(ray.dir, xform);
|
nuclear@0
|
432 return res;
|
nuclear@0
|
433 }
|
nuclear@0
|
434
|
nuclear@0
|
435 Ray get_primary_ray()
|
nuclear@0
|
436 {
|
nuclear@0
|
437 Ray ray;
|
nuclear@0
|
438 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
nuclear@0
|
439 vec3 dir = texture2D(tex_raydir, gl_TexCoord[0].st).xyz;
|
nuclear@0
|
440 ray.dir = normalize(gl_NormalMatrix * dir);
|
nuclear@0
|
441 return ray;
|
nuclear@0
|
442 }
|
nuclear@0
|
443
|
nuclear@0
|
444 #define ITEM(x) ((float(x) + 0.5) / OBJ_LINE_WIDTH)
|
nuclear@0
|
445
|
nuclear@0
|
446 Sphere read_sphere(in float idx)
|
nuclear@0
|
447 {
|
nuclear@0
|
448 Sphere sph;
|
nuclear@0
|
449 // +1 because the first scanline is the descriptor
|
nuclear@0
|
450 float ty = (idx + 1.0) / sph_tex_sz;
|
nuclear@0
|
451
|
nuclear@0
|
452 sph.index = texture2D(tex_spheres, vec2(ITEM(0), ty)).x;
|
nuclear@0
|
453
|
nuclear@0
|
454 vec4 texel = texture2D(tex_spheres, vec2(ITEM(1), ty));
|
nuclear@0
|
455 sph.pos = texel.xyz;
|
nuclear@0
|
456 sph.radius = texel.w;
|
nuclear@0
|
457
|
nuclear@0
|
458 sph.mat = read_material(tex_spheres, ty);
|
nuclear@0
|
459 return sph;
|
nuclear@0
|
460 }
|
nuclear@0
|
461
|
nuclear@0
|
462 Plane read_plane(in float idx)
|
nuclear@0
|
463 {
|
nuclear@0
|
464 Plane plane;
|
nuclear@0
|
465 // +1 (see above)
|
nuclear@0
|
466 float ty = (idx + 1.0) / plane_tex_sz;
|
nuclear@0
|
467
|
nuclear@0
|
468 plane.index = texture2D(tex_planes, vec2(ITEM(0), ty)).x;
|
nuclear@0
|
469
|
nuclear@0
|
470 vec4 texel = texture2D(tex_planes, vec2(ITEM(1), ty));
|
nuclear@0
|
471 plane.normal = texel.xyz;
|
nuclear@0
|
472 plane.dist = texel.w;
|
nuclear@0
|
473
|
nuclear@0
|
474 plane.mat = read_material(tex_planes, ty);
|
nuclear@0
|
475 return plane;
|
nuclear@0
|
476 }
|
nuclear@0
|
477
|
nuclear@0
|
478 Box read_box(in float idx)
|
nuclear@0
|
479 {
|
nuclear@0
|
480 Box box;
|
nuclear@0
|
481 float ty = (idx + 1.0) / box_tex_sz;
|
nuclear@0
|
482
|
nuclear@0
|
483 box.index = texture2D(tex_boxes, vec2(ITEM(0), ty)).x;
|
nuclear@0
|
484
|
nuclear@0
|
485 box.min = texture2D(tex_boxes, vec2(ITEM(1), ty)).xyz;
|
nuclear@0
|
486 box.max = texture2D(tex_boxes, vec2(ITEM(2), ty)).xyz;
|
nuclear@0
|
487
|
nuclear@0
|
488 box.mat = read_material(tex_boxes, ty);
|
nuclear@0
|
489 return box;
|
nuclear@0
|
490 }
|
nuclear@0
|
491
|
nuclear@0
|
492 void read_xform(in float idx, out mat4 xform, out mat4 inv_xform)
|
nuclear@0
|
493 {
|
nuclear@0
|
494 float ty = (idx + 1.0) / xform_tex_sz;
|
nuclear@0
|
495
|
nuclear@0
|
496 for(int i=0; i<4; i++) {
|
nuclear@0
|
497 xform[i] = texture2D(tex_xforms, vec2(ITEM(i), ty));
|
nuclear@0
|
498 }
|
nuclear@0
|
499 inv_xform = inverse(xform);
|
nuclear@0
|
500 /*for(int i=0; i<4; i++) {
|
nuclear@0
|
501 inv_xform[i] = texture2D(tex_xforms, vec2(ITEM(float(i) + 4.0), ty));
|
nuclear@0
|
502 }*/
|
nuclear@0
|
503 }
|
nuclear@0
|
504
|
nuclear@0
|
505 #define MAT_START 4
|
nuclear@0
|
506 Material read_material(in sampler2D tex, in float ty)
|
nuclear@0
|
507 {
|
nuclear@0
|
508 Material mat;
|
nuclear@0
|
509
|
nuclear@0
|
510 vec4 texel = texture2D(tex, vec2(ITEM(MAT_START), ty));
|
nuclear@0
|
511 mat.diffuse = texel.xyz;
|
nuclear@0
|
512
|
nuclear@0
|
513 texel = texture2D(tex, vec2(ITEM(MAT_START + 1), ty));
|
nuclear@0
|
514 mat.specular = texel.xyz;
|
nuclear@0
|
515 mat.shininess = texel.w;
|
nuclear@0
|
516
|
nuclear@0
|
517 texel = texture2D(tex, vec2(ITEM(MAT_START + 2), ty));
|
nuclear@0
|
518 mat.reflectivity = texel.x;
|
nuclear@0
|
519
|
nuclear@0
|
520 mat.megatex_rect = texture2D(tex, vec2(ITEM(MAT_START + 3), ty));
|
nuclear@0
|
521
|
nuclear@0
|
522 return mat;
|
nuclear@0
|
523 }
|