okpalan

raytracer-worker.js

Nov 9th, 2023 (edited)
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 4.13 KB | Source Code | 0 0
  1. self.addEventListener('message', function (e) {
  2.  
  3.     var canvas = e.data[0];
  4.     var ctx = canvas.getContext('2d');
  5.     var imgData = ctx.createImageData(canvas.width, canvas.height);
  6.     var maxdepth = e.data[2];
  7.     var lights = e.data[3];
  8. function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
  9.     var a1, a2, b1, b2, c1, c2;
  10.     var r1, r2, r3, r4;
  11.     var denom, offset, num;
  12.  
  13.     a1 = y2 - y1;
  14.     b1 = x1 - x2;
  15.     c1 = (x2 * y1) - (x1 * y2);
  16.     r3 = ((a1 * x3) + (b1 * y3) + c1);
  17.     r4 = ((a1 * x4) + (b1 * y4) + c1);
  18.  
  19.  
  20.     a2 = y4 - y3;
  21.     b2 = x3 - x4;
  22.     c2 = (x4 * y3) - (x3 * y4);
  23.     r1 = (a2 * x1) + (b2 * y1) + c2;
  24.     r2 = (a2 * x2) + (b2 * y2) + c2;
  25.  
  26.     denom = (r1 * r2) - (r3 * r4);
  27.     if (denom == 0) {
  28.         return false;
  29.     }
  30.  
  31.     offset = Math.abs(denom / 2);
  32.  
  33.     num = (r1 * r4) - (r2 * r3);
  34.     var x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
  35.  
  36.     num = (a1 * r4) - (a2 * r3);
  37.     var y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom);
  38.  
  39.     var point = new Point(x, y);
  40.  
  41.     if (r1 == 0 || r2 == 0 || r3 == 0 || r4 == 0) {
  42.         return true;
  43.     } else {
  44.         return (r1 > 0 && r2 > 0 && r3 > 0 && r4 > 0) ||
  45.             (r1 < 0 && r2 < 0 && r3 < 0 && r4 < 0);
  46.     }
  47. }
  48. function typedArrayToURL(typedArray, mimeType) {
  49.     return URL.createObjectURL(new Blob([typedArray.buffer], {type: mimeType}))
  50.   }
  51.  
  52.  
  53. function trace(scene, ray, lights, depth) {
  54.     // check if the ray hits an object
  55.     // if so, calculate the color
  56.     // if not, return the background color
  57.     // check if the ray hits an object
  58.  
  59.     var closest = findIntersection(scene.objects, ray);
  60.     if (closest) {
  61.         var point = ray.origin.add(ray.direction.multiply(closest.distance));
  62.         var normal = closest.object.normalAt(point);
  63.         var lambertAmount = 0;
  64.  
  65.         for (var i = 0; i < lights.length; i++) {
  66.             var lightDirection = lights[i].position.subtract(point).normalize();
  67.             var shadowOrigin = lightDirection.dot(normal) < 0 ? point.subtract(normal.multiply(1e-3)) : point.add(normal.multiply(1e-3));
  68.             var shadowRay = new Ray(shadowOrigin, lightDirection);
  69.             var inShadow = findIntersection(scene.objects, shadowRay);
  70.             if (inShadow && inShadow.distance < lights[i].position.subtract(shadowOrigin).magnitude()) {
  71.                 lambertAmount = 0;
  72.             }
  73.             else {
  74.                 lambertAmount += lights[i].intensity * Math.max(0, lightDirection.dot(normal));
  75.             }
  76.         }
  77.         var color = closest.object.color;
  78.         var finalColor = color.multiply(scene.ambientLight).add(color.multiply(lambertAmount));
  79.         var specularAmount = 0;
  80.         var reflectDirection = ray.direction.subtract(normal.multiply(2 * ray.direction.dot(normal))).normalize();
  81.         var reflectRay = new Ray(point.add(reflectDirection.multiply(1e-3)), reflectDirection);
  82.         var reflectColor = trace(scene, reflectRay, lights, depth + 1);
  83.         if (reflectColor && depth <= maxDepth) {
  84.             specularAmount = Math.pow(Math.max(0, -reflectDirection.dot(ray.direction)), closest.object.specularExponent);
  85.         }
  86.         finalColor = finalColor.add(reflectColor.multiply(closest.object.reflectivity).multiply(specularAmount));
  87.         return finalColor;
  88.     }
  89.     else {
  90.         return null;
  91.     }
  92. }
  93.  
  94. function findIntersection(objects, ray) {
  95.     var closest = Infinity;
  96.     var closestInter = null;
  97.     for (var i = 0; i < objects.length; i++) {
  98.         var inter = objects[i].intersect(ray);
  99.         if (inter != null && inter.distance < closest) {
  100.             closestInter = inter;
  101.             closest = inter.distance;
  102.         }
  103.     }
  104.     return closestInter;
  105. }
  106.     for (var i = 0; i < e.data[4].length; i++) {
  107.         var ray = e.data[4][i];
  108.         var color = trace(e.data[1], ray, lights, maxdepth);
  109.         if (color) {
  110.             imgData.data[i * 4] = color[0];
  111.             imgData.data[i * 4 + 1] = color[1];
  112.             imgData.data[i * 4 + 2] = color[2];
  113.         }
  114.     }
  115.     ctx.putImageData(imgData, 0, 0);
  116.     postMessage("Finished");
  117. }, false);
Advertisement
Add Comment
Please, Sign In to add comment