public override IntersectionInfo intersect(Ray ray) { IntersectionInfo info = new IntersectionInfo(); info.shape = this; Vector3D dst = Vector3D.subtract(ray.position, this.position); double B = dst.dot(ray.direction); double C = dst.dot(dst) - (this.radius * this.radius); double D = (B * B) - C; if (D > 0) { // intersection! info.isHit = true; info.distance = (-B) - Math.Sqrt(D); info.position = Vector3D.add(ray.position, Vector3D.multiplyScalar(ray.direction, info.distance)); info.normal = Vector3D.subtract(info.position, this.position).normalize(); info.color = this.material.getColor(0, 0); } else { info.isHit = false; } return(info); }
public Color getPixelColor(Ray ray, Scene scene) { IntersectionInfo info = this.testIntersection(ray, scene, null); if (info.isHit) { Color color = this.rayTrace(info, ray, scene, 0); return(color); } return(scene.background.color); }
public override IntersectionInfo intersect(Ray ray) { IntersectionInfo info = new IntersectionInfo(); double Vd = this.position.dot(ray.direction); if (Vd == 0) { return(info); // no intersection } double t = -(this.position.dot(ray.position) + this.d) / Vd; if (t <= 0) { return(info); } info.shape = this; info.isHit = true; info.position = Vector3D.add(ray.position, Vector3D.multiplyScalar(ray.direction, t)); info.normal = this.position; info.distance = t; if (this.material.hasTexture) { Vector3D vU = new Vector3D(this.position.y, this.position.z, -this.position.x); Vector3D vV = vU.cross(this.position); double u = info.position.dot(vU); double v = info.position.dot(vV); info.color = this.material.getColor(u, v); } else { info.color = this.material.getColor(0, 0); } return(info); }
public IntersectionInfo testIntersection(Ray ray, Scene scene, BaseShape exclude) { int hits = 0; IntersectionInfo best = new IntersectionInfo(); best.distance = 2000; for (int i = 0; i < scene.shapes.Count; i++) { BaseShape shape = scene.shapes[i]; if (shape != exclude) { IntersectionInfo info = shape.intersect(ray); if (info.isHit && info.distance >= 0 && info.distance < best.distance) { best = info; hits++; } } } best.hitCount = hits; return(best); }
public Color rayTrace(IntersectionInfo info, Ray ray, Scene scene, int depth) { // Calc ambient Color color = Color.multiplyScalar(info.color, scene.background.ambience); Color oldColor = color; double shininess = Math.Pow(10, info.shape.material.gloss + 1); for (int i = 0; i < scene.lights.Count; i++) { Light light = scene.lights[i]; // Calc diffuse lighting Vector3D v = Vector3D.subtract(light.position, info.position).normalize(); if (this.options.renderDiffuse) { double L = v.dot(info.normal); if (L > 0.0) { color = Color.add(color, Color.multiply(info.color, Color.multiplyScalar(light.color, L))); } } // The greater the depth the more accurate the colours, but // this is exponentially (!) expensive if (depth <= this.options.rayDepth) { // calculate reflection ray if (this.options.renderReflections && info.shape.material.reflection > 0) { Ray reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction); IntersectionInfo refl = this.testIntersection(reflectionRay, scene, info.shape); if (refl.isHit && refl.distance > 0) { refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1); } else { refl.color = scene.background.color; } color = Color.blend(color, refl.color, info.shape.material.reflection); } // Refraction /* TODO */ } /* Render shadows and highlights */ IntersectionInfo shadowInfo = new IntersectionInfo(); if (this.options.renderShadows) { Ray shadowRay = new Ray(info.position, v); shadowInfo = this.testIntersection(shadowRay, scene, info.shape); if (shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/) { Color vA = Color.multiplyScalar(color, 0.5); double dB = (0.5 * Math.Pow(shadowInfo.shape.material.transparency, 0.5)); color = Color.addScalar(vA, dB); } } // Phong specular highlights if (this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0) { Vector3D Lv = Vector3D.subtract(info.shape.position, light.position).normalize(); Vector3D E = Vector3D.subtract(scene.camera.position, info.shape.position).normalize(); Vector3D H = Vector3D.subtract(E, Lv).normalize(); double glossWeight = Math.Pow(Math.Max(info.normal.dot(H), 0), shininess); color = Color.add(Color.multiplyScalar(light.color, glossWeight), color); } } color.limit(); return(color); }