gpuray_glsl

annotate sdr/rt.glsl @ 4:2ed3da7dc0bc

broken
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 10 Nov 2014 01:26:00 +0200
parents f234630e38ff
children
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@4 49 struct Cone {
nuclear@4 50 float index;
nuclear@4 51 float angle;
nuclear@4 52 float start, end;
nuclear@4 53 struct Material mat;
nuclear@4 54 };
nuclear@4 55
nuclear@0 56 struct Light {
nuclear@0 57 vec3 pos, color;
nuclear@0 58 };
nuclear@0 59
nuclear@0 60 vec3 shade(in Ray ray, in HitPoint hit);
nuclear@0 61 bool find_intersection(in Ray ray, out HitPoint hit);
nuclear@0 62 bool sphere_intersect(in Sphere sph, in Ray ray, out HitPoint pt);
nuclear@0 63 bool plane_intersect(in Plane plane, in Ray ray, out HitPoint pt);
nuclear@0 64 bool box_intersect(in Box box, in Ray ray, out HitPoint pt);
nuclear@4 65 bool cone_intersect(in Cone cone, in Ray ray, out HitPoint pt);
nuclear@0 66 vec3 transform(in vec3 v, in mat4 inv_xform);
nuclear@0 67 Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform);
nuclear@0 68 Ray get_primary_ray();
nuclear@0 69
nuclear@0 70 Sphere read_sphere(in float idx);
nuclear@0 71 Plane read_plane(in float idx);
nuclear@0 72 Box read_box(in float idx);
nuclear@4 73 Cone read_cone(in float idx);
nuclear@0 74 Material read_material(in sampler2D tex, in float ty);
nuclear@0 75 void read_xform(in float idx, out mat4 xform, out mat4 inv_xform);
nuclear@0 76
nuclear@0 77 uniform sampler2D tex_raydir;
nuclear@4 78 uniform sampler2D tex_spheres, tex_planes, tex_boxes, tex_cones;
nuclear@0 79 uniform sampler2D tex_megatex;
nuclear@0 80 uniform sampler2D tex_xforms;
nuclear@0 81 uniform samplerCube tex_env;
nuclear@0 82 uniform vec2 fog;
nuclear@0 83
nuclear@0 84 uniform Light lights[8];
nuclear@0 85 uniform int num_lights;
nuclear@0 86
nuclear@4 87 int num_spheres, num_planes, num_boxes, num_cones;
nuclear@4 88 float sph_tex_sz, plane_tex_sz, box_tex_sz, cone_tex_sz, xform_tex_sz;
nuclear@0 89
nuclear@0 90 #ifdef INIT_EVERYTHING
nuclear@0 91 Material default_material;
nuclear@0 92 #endif
nuclear@0 93
nuclear@0 94 void main()
nuclear@0 95 {
nuclear@0 96 #ifdef INIT_EVERYTHING
nuclear@0 97 default_material.diffuse = default_material.specular = vec3(0.0, 0.0, 0.0);
nuclear@0 98 default_material.shininess = 1.0;
nuclear@0 99 default_material.reflectivity = 0.0;
nuclear@0 100 default_material.megatex_rect = vec4(0.0, 0.0, 0.0, 0.0);
nuclear@0 101 #endif
nuclear@0 102
nuclear@0 103 Ray ray = get_primary_ray();
nuclear@0 104
nuclear@0 105 /* read the various descriptors specifying dimensions and counts for
nuclear@0 106 * all the relevant data textures
nuclear@0 107 */
nuclear@0 108 vec4 desc = texture2D(tex_spheres, vec2(0.0, 0.0));
nuclear@0 109 num_spheres = int(desc.x);
nuclear@0 110 sph_tex_sz = desc.y;
nuclear@0 111
nuclear@0 112 desc = texture2D(tex_planes, vec2(0.0, 0.0));
nuclear@0 113 num_planes = int(desc.x);
nuclear@0 114 plane_tex_sz = desc.y;
nuclear@0 115
nuclear@0 116 desc = texture2D(tex_boxes, vec2(0.0, 0.0));
nuclear@0 117 num_boxes = int(desc.x);
nuclear@0 118 box_tex_sz = desc.y;
nuclear@0 119
nuclear@4 120 desc = texture2D(tex_cones, vec2(0.0, 0.0));
nuclear@4 121 num_cones = int(desc.x);
nuclear@4 122 cone_tex_sz = desc.y;
nuclear@4 123
nuclear@0 124 xform_tex_sz = texture2D(tex_xforms, vec2(0.0, 0.0)).x;
nuclear@0 125
nuclear@0 126
nuclear@0 127 HitPoint hit;
nuclear@0 128 #ifdef INIT_EVERYTHING
nuclear@0 129 hit.dist = 0.0;
nuclear@0 130 hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
nuclear@0 131 #endif
nuclear@0 132
nuclear@0 133 vec3 color = vec3(0.0, 0.0, 0.0);
nuclear@0 134 float energy = 1.0;
nuclear@0 135
nuclear@0 136 int iter = 0;
nuclear@0 137 while(energy > 0.01 && iter++ < 4) {
nuclear@0 138 vec3 envcol = textureCube(tex_env, ray.dir).xyz;
nuclear@0 139
nuclear@0 140 if(find_intersection(ray, hit)) {
nuclear@0 141 float fog_t = clamp((hit.dist - fog.x) / (fog.y - fog.x), 0.0, 1.0);
nuclear@0 142 color += mix(shade(ray, hit), envcol, fog_t) * energy;
nuclear@0 143 energy *= hit.mat.reflectivity * (1.0 - fog_t);
nuclear@0 144 ray.origin = hit.pos;
nuclear@0 145 ray.dir = reflect(ray.dir, hit.normal);
nuclear@0 146 } else {
nuclear@0 147 color += envcol * energy;
nuclear@0 148 energy = 0.0;
nuclear@0 149 iter = 100;
nuclear@0 150 }
nuclear@0 151 }
nuclear@0 152
nuclear@0 153 gl_FragColor.xyz = color;
nuclear@0 154 gl_FragColor.w = 1.0;
nuclear@0 155 }
nuclear@0 156
nuclear@0 157 vec3 shade(in Ray ray, in HitPoint hit)
nuclear@0 158 {
nuclear@0 159 vec3 normal = faceforward(hit.normal, ray.dir, hit.normal);
nuclear@0 160
nuclear@0 161 vec3 vdir = normalize(ray.dir);
nuclear@0 162 vec3 vref = reflect(vdir, normal);
nuclear@0 163
nuclear@0 164 /* if there's no texture rect.zw will be (0, 0, 0, 0) so this will map onto
nuclear@0 165 * the top-left 1x1 null texture which is all white (having no effect)
nuclear@0 166 */
nuclear@0 167 vec2 tc = mod(hit.texcoord, vec2(1.0, 1.0)) * hit.mat.megatex_rect.zw + hit.mat.megatex_rect.xy;
nuclear@0 168
nuclear@0 169 vec3 diffuse_color = hit.mat.diffuse * texture2D(tex_megatex, tc).xyz;
nuclear@0 170
nuclear@0 171 vec3 color = vec3(0.0, 0.0, 0.0);
nuclear@0 172 for(int i=0; i<num_lights; i++) {
nuclear@0 173 Ray shadow_ray;
nuclear@0 174 shadow_ray.origin = hit.pos;
nuclear@0 175 shadow_ray.dir = lights[i].pos - hit.pos;
nuclear@0 176
nuclear@0 177 HitPoint shadow_hit;
nuclear@0 178 if(!find_intersection(shadow_ray, shadow_hit) || shadow_hit.dist > 1.0) {
nuclear@0 179 vec3 ldir = normalize(shadow_ray.dir);
nuclear@0 180
nuclear@0 181 float diffuse = max(dot(ldir, normal), 0.0);
nuclear@0 182 float specular = pow(max(dot(ldir, vref), 0.0), hit.mat.shininess);
nuclear@0 183
nuclear@0 184 color += (diffuse_color * diffuse + hit.mat.specular * specular) * lights[i].color;
nuclear@0 185 }
nuclear@0 186 }
nuclear@0 187
nuclear@0 188 return color;
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 bool find_intersection(in Ray ray, out HitPoint hit)
nuclear@0 192 {
nuclear@0 193 hit.dist = 100000.0;
nuclear@0 194 #ifdef INIT_EVERYTHING
nuclear@0 195 hit.pos = hit.normal = vec3(0.0, 0.0, 0.0);
nuclear@0 196 hit.mat = default_material;
nuclear@0 197 hit.texcoord = vec2(0.0, 0.0);
nuclear@0 198 #endif
nuclear@0 199 bool found = false;
nuclear@0 200
nuclear@0 201 for(int i=0; i<num_spheres; i++) {
nuclear@0 202 Sphere sph = read_sphere(i);
nuclear@0 203
nuclear@0 204 HitPoint tmphit;
nuclear@0 205 if(sphere_intersect(sph, ray, tmphit) && tmphit.dist < hit.dist) {
nuclear@0 206 hit = tmphit;
nuclear@0 207 found = true;
nuclear@0 208 }
nuclear@0 209 }
nuclear@0 210
nuclear@0 211 for(int i=0; i<num_planes; i++) {
nuclear@0 212 Plane plane = read_plane(i);
nuclear@0 213
nuclear@0 214 HitPoint tmphit;
nuclear@0 215 if(plane_intersect(plane, ray, tmphit) && tmphit.dist < hit.dist) {
nuclear@0 216 hit = tmphit;
nuclear@0 217 found = true;
nuclear@0 218 }
nuclear@0 219 }
nuclear@0 220
nuclear@0 221 for(int i=0; i<num_boxes; i++) {
nuclear@0 222 Box box = read_box(i);
nuclear@0 223
nuclear@0 224 HitPoint tmphit;
nuclear@0 225 if(box_intersect(box, ray, tmphit) && tmphit.dist < hit.dist) {
nuclear@0 226 hit = tmphit;
nuclear@0 227 found = true;
nuclear@0 228 }
nuclear@0 229 }
nuclear@0 230
nuclear@4 231 for(int i=0; i<num_cones; i++) {
nuclear@4 232 Cone cone = read_cone(i);
nuclear@4 233
nuclear@4 234 HitPoint tmphit;
nuclear@4 235 if(cone_intersect(cone, ray, tmphit) && tmphit.dist < hit.dist) {
nuclear@4 236 hit = tmphit;
nuclear@4 237 found = true;
nuclear@4 238 }
nuclear@4 239 }
nuclear@4 240
nuclear@0 241 return found;
nuclear@0 242 }
nuclear@0 243
nuclear@0 244 #define EPSILON 1e-4
nuclear@0 245 #define SQ(x) ((x) * (x))
nuclear@0 246
nuclear@0 247 bool sphere_intersect(in Sphere sph, in Ray inray, out HitPoint pt)
nuclear@0 248 {
nuclear@0 249 #ifdef USE_XFORM
nuclear@0 250 mat4 xform, inv_xform;
nuclear@0 251 read_xform(sph.index, xform, inv_xform);
nuclear@0 252
nuclear@0 253 Ray ray = transform(inray, inv_xform, xform);
nuclear@0 254 #else
nuclear@0 255 Ray ray = inray;
nuclear@0 256 #endif
nuclear@0 257
nuclear@0 258 #ifdef INIT_EVERYTHING
nuclear@0 259 pt.dist = 0.0;
nuclear@0 260 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
nuclear@0 261 pt.mat = default_material;
nuclear@0 262 pt.texcoord = vec2(0.0, 0.0);
nuclear@0 263 #endif
nuclear@0 264
nuclear@0 265 float a = dot(ray.dir, ray.dir);
nuclear@0 266 float b = dot(ray.dir, ray.origin - sph.pos) * 2.0;
nuclear@0 267 float c = dot(ray.origin, ray.origin) + dot(sph.pos, sph.pos) -
nuclear@0 268 2.0 * dot(ray.origin, sph.pos) - sph.radius * sph.radius;
nuclear@0 269
nuclear@0 270 float discr = b * b - 4.0 * a * c;
nuclear@0 271 if(discr < EPSILON)
nuclear@0 272 return false;
nuclear@0 273
nuclear@0 274 float sqrt_discr = sqrt(discr);
nuclear@0 275 float t0 = (-b + sqrt_discr) / (2.0 * a);
nuclear@0 276 float t1 = (-b - sqrt_discr) / (2.0 * a);
nuclear@0 277
nuclear@0 278 if(t0 < EPSILON)
nuclear@0 279 t0 = t1;
nuclear@0 280 if(t1 < EPSILON)
nuclear@0 281 t1 = t0;
nuclear@0 282
nuclear@0 283 float t = min(t0, t1);
nuclear@0 284 if(t < EPSILON)
nuclear@0 285 return false;
nuclear@0 286
nuclear@0 287 // fill the HitPoint structure
nuclear@0 288 pt.dist = t;
nuclear@0 289 pt.pos = ray.origin + ray.dir * t;
nuclear@0 290 pt.normal = (pt.pos - sph.pos) / sph.radius;
nuclear@0 291 pt.mat = sph.mat;
nuclear@0 292
nuclear@0 293 pt.texcoord.x = 0.5 * atan(pt.normal.z, pt.normal.x) / M_PI + 0.5;
nuclear@0 294 pt.texcoord.y = acos(pt.normal.y) / M_PI;
nuclear@0 295
nuclear@0 296 #ifdef USE_XFORM
nuclear@0 297 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
nuclear@0 298 pt.normal = normalize(transform(pt.normal, xform));
nuclear@0 299 #endif
nuclear@0 300 return true;
nuclear@0 301 }
nuclear@0 302
nuclear@0 303 bool plane_intersect(in Plane plane, in Ray inray, out HitPoint pt)
nuclear@0 304 {
nuclear@0 305 #ifdef USE_XFORM
nuclear@0 306 mat4 xform, inv_xform;
nuclear@0 307 read_xform(plane.index, xform, inv_xform);
nuclear@0 308
nuclear@0 309 Ray ray = transform(inray, inv_xform, xform);
nuclear@0 310 #else
nuclear@0 311 Ray ray = inray;
nuclear@0 312 #endif
nuclear@0 313
nuclear@0 314 #ifdef INIT_EVERYTHING
nuclear@0 315 pt.dist = 0.0;
nuclear@0 316 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
nuclear@0 317 pt.mat = default_material;
nuclear@0 318 pt.texcoord = vec2(0.0, 0.0);
nuclear@0 319 #endif
nuclear@0 320
nuclear@0 321 float ndotdir = dot(plane.normal, ray.dir);
nuclear@0 322 if(abs(ndotdir) < EPSILON) {
nuclear@0 323 return false;
nuclear@0 324 }
nuclear@0 325
nuclear@0 326 vec3 planept = plane.normal * plane.dist;
nuclear@0 327 vec3 pptdir = planept - ray.origin;
nuclear@0 328
nuclear@0 329 float t = dot(plane.normal, pptdir) / ndotdir;
nuclear@0 330 if(t < EPSILON) {
nuclear@0 331 return false;
nuclear@0 332 }
nuclear@0 333
nuclear@0 334 pt.dist = t;
nuclear@0 335 pt.pos = ray.origin + ray.dir * t;
nuclear@0 336 pt.normal = plane.normal;
nuclear@0 337 pt.mat = plane.mat;
nuclear@0 338 pt.texcoord.x = pt.pos.x;
nuclear@0 339 pt.texcoord.y = pt.pos.z;
nuclear@0 340
nuclear@0 341 #ifdef USE_XFORM
nuclear@0 342 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
nuclear@0 343 pt.normal = normalize(transform(pt.normal, xform));
nuclear@0 344 #endif
nuclear@0 345 return true;
nuclear@0 346 }
nuclear@0 347
nuclear@0 348 bool box_intersect(in Box box, in Ray inray, out HitPoint pt)
nuclear@0 349 {
nuclear@0 350 #ifdef USE_XFORM
nuclear@0 351 mat4 xform, inv_xform;
nuclear@0 352 read_xform(box.index, xform, inv_xform);
nuclear@0 353
nuclear@0 354 Ray ray = transform(inray, inv_xform, xform);
nuclear@0 355 #else
nuclear@0 356 Ray ray = inray;
nuclear@0 357 #endif
nuclear@0 358
nuclear@0 359 #ifdef INIT_EVERYTHING
nuclear@0 360 pt.dist = 0.0;
nuclear@0 361 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
nuclear@0 362 pt.mat = default_material;
nuclear@0 363 pt.texcoord = vec2(0.0, 0.0);
nuclear@0 364 #endif
nuclear@0 365
nuclear@0 366 vec3 param[2];
nuclear@0 367 param[0] = box.min;
nuclear@0 368 param[1] = box.max;
nuclear@0 369
nuclear@0 370 vec3 inv_dir = 1.0 / ray.dir;
nuclear@0 371 int sgn[3];
nuclear@0 372 sgn[0] = inv_dir.x < 0.0 ? 1 : 0;
nuclear@0 373 sgn[1] = inv_dir.y < 0.0 ? 1 : 0;
nuclear@0 374 sgn[2] = inv_dir.z < 0.0 ? 1 : 0;
nuclear@0 375
nuclear@0 376 float tmin = (param[sgn[0]].x - ray.origin.x) * inv_dir.x;
nuclear@0 377 float tmax = (param[1 - sgn[0]].x - ray.origin.x) * inv_dir.x;
nuclear@0 378 float tymin = (param[sgn[1]].y - ray.origin.y) * inv_dir.y;
nuclear@0 379 float tymax = (param[1 - sgn[1]].y - ray.origin.y) * inv_dir.y;
nuclear@0 380
nuclear@0 381 pt.normal = vec3(ray.origin.x > 0.0 ? 1.0 : -1.0, 0.0, 0.0);
nuclear@0 382
nuclear@0 383 if(tmin > tymax || tymin > tmax) {
nuclear@0 384 return false;
nuclear@0 385 }
nuclear@0 386 if(tymin > tmin) {
nuclear@0 387 pt.normal = vec3(0.0, ray.origin.y > 0.0 ? 1.0 : -1.0, 0.0);
nuclear@0 388 tmin = tymin;
nuclear@0 389 }
nuclear@0 390 if(tymax < tmax) {
nuclear@0 391 tmax = tymax;
nuclear@0 392 }
nuclear@0 393
nuclear@0 394 float tzmin = (param[sgn[2]].z - ray.origin.z) * inv_dir.z;
nuclear@0 395 float tzmax = (param[1 - sgn[2]].z - ray.origin.z) * inv_dir.z;
nuclear@0 396
nuclear@0 397 if(tmin > tzmax || tzmin > tmax) {
nuclear@0 398 return false;
nuclear@0 399 }
nuclear@0 400 if(tzmin > tmin) {
nuclear@0 401 pt.normal = vec3(0.0, 0.0, ray.origin.z > 0.0 ? 1.0 : -1.0);
nuclear@0 402 tmin = tzmin;
nuclear@0 403 }
nuclear@0 404 if(tzmax < tmax) {
nuclear@0 405 tmax = tzmax;
nuclear@0 406 }
nuclear@0 407
nuclear@0 408 float t = tmin < EPSILON ? tmax : tmin;
nuclear@0 409 if(t >= 1e-4) {
nuclear@0 410 pt.dist = t;
nuclear@0 411 pt.pos = ray.origin + ray.dir * t;
nuclear@0 412 pt.mat = box.mat;
nuclear@0 413
nuclear@0 414 float min_dist = 10000.0;
nuclear@0 415
nuclear@0 416 vec3 offs = box.min + (box.max - box.min) / 2.0;
nuclear@0 417 vec3 local_pt = pt.pos - offs;
nuclear@0 418
nuclear@0 419 vec3 dist = abs((box.max - offs) - abs(local_pt));
nuclear@0 420 if(dist.x < min_dist) {
nuclear@0 421 min_dist = dist.x;
nuclear@0 422 pt.normal = sign(local_pt.x) * vec3(1.0, 0.0, 0.0);
nuclear@0 423 pt.texcoord = pt.pos.zy;
nuclear@0 424 }
nuclear@0 425 if(dist.y < min_dist) {
nuclear@0 426 min_dist = dist.y;
nuclear@0 427 pt.normal = sign(local_pt.y) * vec3(0.0, 1.0, 0.0);
nuclear@0 428 pt.texcoord = pt.pos.xz;
nuclear@0 429 }
nuclear@0 430 if(dist.z < min_dist) {
nuclear@0 431 pt.normal = sign(local_pt.y) * vec3(0.0, 0.0, 1.0);
nuclear@0 432 pt.texcoord = pt.pos.xy;
nuclear@0 433 }
nuclear@0 434
nuclear@0 435
nuclear@0 436 #ifdef USE_XFORM
nuclear@0 437 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
nuclear@0 438 pt.normal = normalize(transform(pt.normal, xform));
nuclear@0 439 #endif
nuclear@0 440 return true;
nuclear@0 441 }
nuclear@0 442 return false;
nuclear@0 443 }
nuclear@0 444
nuclear@4 445 bool cone_intersect(in Cone cone, in Ray inray, out HitPoint pt)
nuclear@4 446 {
nuclear@4 447 #ifdef USE_XFORM
nuclear@4 448 mat4 xform, inv_xform;
nuclear@4 449 read_xform(cone.index, xform, inv_xform);
nuclear@4 450
nuclear@4 451 Ray ray = transform(inray, inv_xform, xform);
nuclear@4 452 #else
nuclear@4 453 Ray ray = inray;
nuclear@4 454 #endif
nuclear@4 455
nuclear@4 456 #ifdef INIT_EVERYTHING
nuclear@4 457 pt.dist = 0.0;
nuclear@4 458 pt.pos = pt.normal = vec3(0.0, 0.0, 0.0);
nuclear@4 459 pt.mat = default_material;
nuclear@4 460 pt.texcoord = vec2(0.0, 0.0);
nuclear@4 461 #endif
nuclear@4 462
nuclear@4 463 float slope = 2.0 * cone.angle / M_PI;
nuclear@4 464
nuclear@4 465 float a = SQ(ray.dir.x) - SQ(slope * ray.dir.y) + SQ(ray.dir.z);
nuclear@4 466 float b = 2.0 * ray.origin.x * ray.dir.x - 2.0 * SQ(slope) * ray.origin.y * ray.dir.y +
nuclear@4 467 2.0 * ray.origin.z * ray.dir.z;
nuclear@4 468 float c = SQ(ray.origin.x) - SQ(slope * ray.origin.y) + SQ(ray.origin.z);
nuclear@4 469
nuclear@4 470 float discr = b * b - 4.0 * a * c;
nuclear@4 471 if(discr < EPSILON)
nuclear@4 472 return false;
nuclear@4 473
nuclear@4 474 float sqrt_discr = sqrt(discr);
nuclear@4 475 float t0 = (-b + sqrt_discr) / (2.0 * a);
nuclear@4 476 float t1 = (-b - sqrt_discr) / (2.0 * a);
nuclear@4 477
nuclear@4 478 if(t0 < EPSILON)
nuclear@4 479 t0 = t1;
nuclear@4 480 if(t1 < EPSILON)
nuclear@4 481 t1 = t0;
nuclear@4 482
nuclear@4 483 float t = min(t0, t1);
nuclear@4 484 if(t < EPSILON)
nuclear@4 485 return false;
nuclear@4 486
nuclear@4 487 // fill the HitPoint structure
nuclear@4 488 pt.dist = t;
nuclear@4 489 pt.pos = ray.origin + ray.dir * t;
nuclear@4 490
nuclear@4 491 if(pt.pos.y < cone.start || pt.pos.y >= cone.end) {
nuclear@4 492 return false;
nuclear@4 493 }
nuclear@4 494
nuclear@4 495 float radius = pt.pos.y * slope;
nuclear@4 496 pt.normal = vec3(pt.pos.x, 0.0, pt.pos.z) / radius;
nuclear@4 497
nuclear@4 498 float ny = sin(cone.angle);
nuclear@4 499 float xzlen = sqrt(1.0 - ny * ny);
nuclear@4 500 pt.normal.x *= xzlen;
nuclear@4 501 pt.normal.y = ny;
nuclear@4 502 pt.normal.z *= xzlen;
nuclear@4 503
nuclear@4 504 pt.mat = cone.mat;
nuclear@4 505
nuclear@4 506 pt.texcoord.x = 0.5 * atan(pt.normal.z, pt.normal.x) / M_PI + 0.5;
nuclear@4 507 pt.texcoord.y = (pt.pos.y - cone.start) / (cone.end - cone.start);
nuclear@4 508
nuclear@4 509 #ifdef USE_XFORM
nuclear@4 510 pt.pos = (xform * vec4(pt.pos, 1.0)).xyz;
nuclear@4 511 pt.normal = normalize(transform(pt.normal, xform));
nuclear@4 512 #endif
nuclear@4 513 return true;
nuclear@4 514 }
nuclear@4 515
nuclear@0 516 vec3 transform(in vec3 v, in mat4 xform)
nuclear@0 517 {
nuclear@0 518 return mat3(xform) * v;
nuclear@0 519 }
nuclear@0 520
nuclear@0 521 Ray transform(in Ray ray, in mat4 xform, in mat4 inv_xform)
nuclear@0 522 {
nuclear@0 523 Ray res;
nuclear@0 524 res.origin = (xform * vec4(ray.origin, 1.0)).xyz;
nuclear@0 525 res.dir = transform(ray.dir, xform);
nuclear@0 526 return res;
nuclear@0 527 }
nuclear@0 528
nuclear@0 529 Ray get_primary_ray()
nuclear@0 530 {
nuclear@0 531 Ray ray;
nuclear@0 532 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
nuclear@0 533 vec3 dir = texture2D(tex_raydir, gl_TexCoord[0].st).xyz;
nuclear@0 534 ray.dir = normalize(gl_NormalMatrix * dir);
nuclear@0 535 return ray;
nuclear@0 536 }
nuclear@0 537
nuclear@0 538 #define ITEM(x) ((float(x) + 0.5) / OBJ_LINE_WIDTH)
nuclear@0 539
nuclear@0 540 Sphere read_sphere(in float idx)
nuclear@0 541 {
nuclear@0 542 Sphere sph;
nuclear@0 543 // +1 because the first scanline is the descriptor
nuclear@0 544 float ty = (idx + 1.0) / sph_tex_sz;
nuclear@0 545
nuclear@0 546 sph.index = texture2D(tex_spheres, vec2(ITEM(0), ty)).x;
nuclear@0 547
nuclear@0 548 vec4 texel = texture2D(tex_spheres, vec2(ITEM(1), ty));
nuclear@0 549 sph.pos = texel.xyz;
nuclear@0 550 sph.radius = texel.w;
nuclear@0 551
nuclear@0 552 sph.mat = read_material(tex_spheres, ty);
nuclear@0 553 return sph;
nuclear@0 554 }
nuclear@0 555
nuclear@0 556 Plane read_plane(in float idx)
nuclear@0 557 {
nuclear@0 558 Plane plane;
nuclear@0 559 // +1 (see above)
nuclear@0 560 float ty = (idx + 1.0) / plane_tex_sz;
nuclear@0 561
nuclear@0 562 plane.index = texture2D(tex_planes, vec2(ITEM(0), ty)).x;
nuclear@0 563
nuclear@0 564 vec4 texel = texture2D(tex_planes, vec2(ITEM(1), ty));
nuclear@0 565 plane.normal = texel.xyz;
nuclear@0 566 plane.dist = texel.w;
nuclear@0 567
nuclear@0 568 plane.mat = read_material(tex_planes, ty);
nuclear@0 569 return plane;
nuclear@0 570 }
nuclear@0 571
nuclear@0 572 Box read_box(in float idx)
nuclear@0 573 {
nuclear@0 574 Box box;
nuclear@0 575 float ty = (idx + 1.0) / box_tex_sz;
nuclear@0 576
nuclear@0 577 box.index = texture2D(tex_boxes, vec2(ITEM(0), ty)).x;
nuclear@0 578
nuclear@0 579 box.min = texture2D(tex_boxes, vec2(ITEM(1), ty)).xyz;
nuclear@0 580 box.max = texture2D(tex_boxes, vec2(ITEM(2), ty)).xyz;
nuclear@0 581
nuclear@0 582 box.mat = read_material(tex_boxes, ty);
nuclear@0 583 return box;
nuclear@0 584 }
nuclear@0 585
nuclear@4 586 Cone read_cone(in float idx)
nuclear@4 587 {
nuclear@4 588 Cone cone;
nuclear@4 589 float ty = (idx + 1.0) / cone_tex_sz;
nuclear@4 590
nuclear@4 591 cone.index = texture2D(tex_cones, vec2(ITEM(0), ty)).x;
nuclear@4 592
nuclear@4 593 vec4 texel = texture2D(tex_cones, vec2(ITEM(1), ty));
nuclear@4 594 cone.angle = texel.x;
nuclear@4 595 cone.start = texel.y;
nuclear@4 596 cone.end = texel.z;
nuclear@4 597
nuclear@4 598 cone.mat = read_material(tex_cones, ty);
nuclear@4 599 return cone;
nuclear@4 600 }
nuclear@4 601
nuclear@0 602 void read_xform(in float idx, out mat4 xform, out mat4 inv_xform)
nuclear@0 603 {
nuclear@0 604 float ty = (idx + 1.0) / xform_tex_sz;
nuclear@0 605
nuclear@0 606 for(int i=0; i<4; i++) {
nuclear@0 607 xform[i] = texture2D(tex_xforms, vec2(ITEM(i), ty));
nuclear@0 608 }
nuclear@0 609 inv_xform = inverse(xform);
nuclear@0 610 /*for(int i=0; i<4; i++) {
nuclear@0 611 inv_xform[i] = texture2D(tex_xforms, vec2(ITEM(float(i) + 4.0), ty));
nuclear@0 612 }*/
nuclear@0 613 }
nuclear@0 614
nuclear@0 615 #define MAT_START 4
nuclear@0 616 Material read_material(in sampler2D tex, in float ty)
nuclear@0 617 {
nuclear@0 618 Material mat;
nuclear@0 619
nuclear@0 620 vec4 texel = texture2D(tex, vec2(ITEM(MAT_START), ty));
nuclear@0 621 mat.diffuse = texel.xyz;
nuclear@0 622
nuclear@0 623 texel = texture2D(tex, vec2(ITEM(MAT_START + 1), ty));
nuclear@0 624 mat.specular = texel.xyz;
nuclear@0 625 mat.shininess = texel.w;
nuclear@0 626
nuclear@0 627 texel = texture2D(tex, vec2(ITEM(MAT_START + 2), ty));
nuclear@0 628 mat.reflectivity = texel.x;
nuclear@0 629
nuclear@0 630 mat.megatex_rect = texture2D(tex, vec2(ITEM(MAT_START + 3), ty));
nuclear@0 631
nuclear@0 632 return mat;
nuclear@0 633 }