public override Color3 colorNormal(Color3 existing, Ray r, Hit h, Shape s, Light bulb) { switch (shader) { case ProcShading.Circle: return mapCircle(h); case ProcShading.Texture: return mapTexture(h); default: return mapSquare(h); } }
public override Color3 colorShadow(Color3 existing, Hit h, double factor) { switch (shader) { case ProcShading.Circle: return Color3.shade(mapCircle(h), factor); case ProcShading.Texture: return Color3.shade(mapTexture(h), factor); default: return Color3.shade(mapSquare(h), factor); } }
public override Vector3 calcNormal(Hit h) { Vector3 v; if (normals.TryGetValue(h.intersect, out v)) { return(v); } else { v.X = (h.intersect.x - center.x) / radius; v.Y = (h.intersect.y - center.y) / radius; v.Z = (h.intersect.z - center.z) / radius; v.Normalize(); normals.Add(h.intersect, v); return(v); } }
// spawn a shadow ray from the intersection point to the light source. private static bool spawnShadow(Light bulb, Hit finalHit, Shape hitShape, Shape fromShape) { Ray shadowRay = new Ray(); shadowRay.start = finalHit.intersect; shadowRay.direction = Point3.vectorize(shadowRay.start, bulb.Location); double shadowDist = Point3.distance(shadowRay.start, bulb.Location); foreach (Shape s in layout.Shapes) { // If this is the object we're checking from, ignore. Duh. if (s.Equals(hitShape) || s.Equals(fromShape) || s.Material.Kt > 0) { continue; } Hit shadowHit = s.intersect(shadowRay); if (shadowHit.intersect.z == Constants.FAR_AWAY) { continue; } // We need to check if hitShape object is in FRONT OF the current one. if it is, we need to ignore this current shape. Vector3 frontTest = Point3.vectorize(shadowHit.intersect, finalHit.intersect); if (frontTest.X > 0 && frontTest.Y > 0 && frontTest.Z > 0) { continue; } // something has to come between the light and the current shape. double shapeDist = Point3.distance(shadowRay.start, shadowHit.intersect); if (shapeDist < shadowDist) { return(true); } } return(false); }
public override Hit intersect(Ray r) { Hit h = new Hit(); double denominator = Vector3.DotProduct(normal, r.direction); if (denominator == 0.0) { h.intersect.z = Constants.FAR_AWAY; } else { double numerator = normal.X * r.start.x + normal.Y * r.start.y + normal.Z * r.start.z + distance; h.omega = -numerator / denominator; if (h.omega < 0) { h.intersect.z = Constants.FAR_AWAY; } else { h.intersect.x = r.start.x + r.direction.X * h.omega; h.intersect.y = r.start.y + r.direction.Y * h.omega; h.intersect.z = r.start.z + r.direction.Z * h.omega; // Boundary hit testing. if (h.intersect.x > Constants.RIGHT_PLANE_BOUNDARY || h.intersect.x < Constants.LEFT_PLANE_BOUNDARY) { h.intersect.x = h.intersect.y = h.intersect.z = Constants.FAR_AWAY; } } } return h; }
public override Hit intersect(Ray r) { Hit h = new Hit(); double denominator = Vector3.DotProduct(normal, r.direction); if (denominator == 0.0) { h.intersect.z = Constants.FAR_AWAY; } else { double numerator = normal.X * r.start.x + normal.Y * r.start.y + normal.Z * r.start.z + distance; h.omega = -numerator / denominator; if (h.omega < 0) { h.intersect.z = Constants.FAR_AWAY; } else { h.intersect.x = r.start.x + r.direction.X * h.omega; h.intersect.y = r.start.y + r.direction.Y * h.omega; h.intersect.z = r.start.z + r.direction.Z * h.omega; // Boundary hit testing. if (h.intersect.x > Constants.RIGHT_PLANE_BOUNDARY || h.intersect.x < Constants.LEFT_PLANE_BOUNDARY) { h.intersect.x = h.intersect.y = h.intersect.z = Constants.FAR_AWAY; } } } return(h); }
public abstract Color3 colorNormal(Color3 existing, Ray r, Hit h, Shape s, Light bulb);
// spawn a shadow ray from the intersection point to the light source. private static bool spawnShadow(Light bulb, Hit finalHit, Shape hitShape, Shape fromShape) { Ray shadowRay = new Ray(); shadowRay.start = finalHit.intersect; shadowRay.direction = Point3.vectorize(shadowRay.start, bulb.Location); double shadowDist = Point3.distance(shadowRay.start, bulb.Location); foreach (Shape s in layout.Shapes) { // If this is the object we're checking from, ignore. Duh. if (s.Equals(hitShape) || s.Equals(fromShape) || s.Material.Kt > 0) continue; Hit shadowHit = s.intersect(shadowRay); if (shadowHit.intersect.z == Constants.FAR_AWAY) continue; // We need to check if hitShape object is in FRONT OF the current one. if it is, we need to ignore this current shape. Vector3 frontTest = Point3.vectorize(shadowHit.intersect, finalHit.intersect); if (frontTest.X > 0 && frontTest.Y > 0 && frontTest.Z > 0) continue; // something has to come between the light and the current shape. double shapeDist = Point3.distance(shadowRay.start, shadowHit.intersect); if (shapeDist < shadowDist) { return true; } } return false; }
public override Hit intersect(Ray r) { Hit h = new Hit(); double b = 2 * (r.direction.X * (r.start.x - center.x) + r.direction.Y * (r.start.y - center.y) + r.direction.Z * (r.start.z - center.z)); double c = Math.Pow(r.start.x - center.x, 2) + Math.Pow(r.start.y - center.y, 2) + Math.Pow(r.start.z - center.z, 2) - Math.Pow(radius, radius); double disc = Math.Pow(b, 2) - 4 * c; if (disc < 0) { h.intersect.z = Constants.FAR_AWAY; } else { h.omega = (-b + Math.Sqrt(disc)) / 2; h.intersect.x = r.start.x + r.direction.X * h.omega; h.intersect.y = r.start.y + r.direction.Y * h.omega; h.intersect.z = r.start.z + r.direction.Z * h.omega; } return h; }
public override Color3 colorNormal(Color3 existing, Ray r, Hit h, Shape s, Light bulb) { return Color3.Black; }
public static Color3 diffuse(Hit h, Shape s, Light bulb) { Color3 diffuse = Black; Vector3 normal = s.calcNormal(h); Vector3 lightDir = Point3.vectorize(bulb.Location, h.intersect); double diffuseDot = Vector3.DotProduct(lightDir, normal); if (diffuseDot >= 0) diffuse = (bulb.Color * s.Material.Diffuse) * diffuseDot; return diffuse; }
public override Color3 colorShadow(Color3 existing, Hit h, double factor) { return(Color3.shade(existing, factor)); }
public override Color3 colorNormal(Color3 existing, Ray r, Hit h, Shape s, Light bulb) { return(Color3.Black); }
public override Vector3 calcNormal(Hit h) { return(normal); }
public abstract Color3 colorShadow(Color3 existing, Hit h, double factor);
public override Vector3 calcNormal(Hit h) { Vector3 v; if (normals.TryGetValue(h.intersect, out v)) { return v; } else { v.X = (h.intersect.x - center.x) / radius; v.Y = (h.intersect.y - center.y) / radius; v.Z = (h.intersect.z - center.z) / radius; v.Normalize(); normals.Add(h.intersect, v); return v; } }
public static Color3 floor(Color3 existing, Hit h, Plane p) { return Color3.Green; }
public override Color3 colorShadow(Color3 existing, Hit h, double factor) { return Color3.shade(existing, factor); }
public static Color3 specular(Ray r, Hit h, Shape s, Light bulb) { Color3 specular = Black; Vector3 normal = s.calcNormal(h); Vector3 lightDir = Point3.vectorize(bulb.Location, h.intersect); Vector3 refDir = lightDir - (2 * (Vector3.DotProduct(lightDir, normal) / Math.Pow(normal.Abs(), 2)) * normal); double specularDot = Vector3.DotProduct(r.direction, refDir); if (specularDot >= 0) specular = (bulb.Color * s.Material.Specular) * Math.Pow(specularDot, s.Material.Ke); return specular; }
public override Vector3 calcNormal(Hit h) { return normal; }
private Color3 mapCircle(Hit h) { Color3 shadeColor; const double SPHERESIZE = Constants.SPHERESIZE; int row = (int)Math.Round(h.intersect.x / SPHERESIZE); int col = (int)Math.Round(h.intersect.z / SPHERESIZE); double centerX = row * SPHERESIZE + SPHERESIZE / 4; double centerY = col * SPHERESIZE + SPHERESIZE / 4; double r = SPHERESIZE / 4; if (h.intersect.x <= centerX + r && h.intersect.x >= centerX - r && h.intersect.z <= centerY + r && h.intersect.z >= centerY - r) { double circle = Math.Pow(h.intersect.x - centerX, 2) + Math.Pow(h.intersect.z - centerY, 2); if (circle <= Math.Pow(r, 2)) shadeColor = Color3.Yellow; else shadeColor = Color3.Red; } else { shadeColor = Color3.Red; } return shadeColor; }
private Color3 mapSquare(Hit h) { Color3 shadeColor; int row = (int)Math.Round(h.intersect.x / Constants.CHECKSIZE); int col = (int)Math.Round(h.intersect.z / Constants.CHECKSIZE); if (row % 2 == 0 && col % 2 == 0) shadeColor = Color3.Red; else if (row % 2 == 0) shadeColor = Color3.Yellow; else if (col % 2 == 0) shadeColor = Color3.Yellow; else shadeColor = Color3.Red; return shadeColor; }
private Color3 mapTexture(Hit h) { Color3 shadeColor = Color3.Black; int texWidth = TextureLoader.Texture.Width; int texHeight = TextureLoader.Texture.Height; int row = (int)Math.Round(h.intersect.x / texWidth); int col = (int)Math.Round(h.intersect.z / texHeight); int startX = row * texWidth; int startY = col * texHeight; int texX = (int) Math.Round(Math.Abs(h.intersect.x - startX)); int texY = (int) Math.Round(Math.Abs(h.intersect.z - startY)); if (texX < TextureLoader.Texture.Width && texY < TextureLoader.Texture.Height) { System.Drawing.Color texColor = TextureLoader.Texture.GetPixel(texX, texY); shadeColor = new Color3(texColor.R, texColor.G, texColor.B); } return shadeColor; }
public static Color3 floor(Color3 existing, Hit h, Plane p) { return(Color3.Green); }
public abstract Vector3 calcNormal(Hit h);
private static Color3 fireRay(Ray incomingRay, int depth, Shape fromShape) { double closest = Constants.FAR_AWAY; Color3 retColor = Constants.BGCOLOR; int whichObject = 0, hitObject = 0; Hit finalHit = new Hit(); foreach (Shape s in layout.Shapes) { Hit rayHit = s.intersect(incomingRay); whichObject++; if (rayHit.intersect.z == Constants.FAR_AWAY) continue; double dist = Point3.distance(layout.Cam.Eye, rayHit.intersect); if (dist < closest && !s.Equals(fromShape)) { closest = dist; hitObject = whichObject; finalHit = rayHit; } } if (hitObject <= 0) return Constants.BGCOLOR; Shape hitShape = layout.Shapes[hitObject - 1]; retColor = Color3.ambient(hitShape); // phongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphong Color3 diffuseColor = Color3.Black, specularColor = Color3.Black; foreach (Light bulb in layout.Lights) { if (spawnShadow(bulb, finalHit, hitShape, fromShape)) { retColor = hitShape.colorShadow(retColor, finalHit, layout.Lights.Count * 3); } else { if (hitShape is Plane) { retColor = hitShape.colorNormal(retColor, incomingRay, finalHit, hitShape, bulb); } else { diffuseColor += Color3.diffuse(finalHit, hitShape, bulb); specularColor += Color3.specular(incomingRay, finalHit, hitShape, bulb); } } } if (hitShape is Sphere) { retColor += diffuseColor * hitShape.Material.Kd; retColor += specularColor * hitShape.Material.Ks; } if (depth < Constants.MAX_DEPTH) { Color3 reflectColor = Color3.Black; if (hitShape.Material.Kr > 0) { Ray reflectRay = new Ray(); reflectRay.start = finalHit.intersect; Vector3 normalVec = hitShape.calcNormal(finalHit); double c = -Vector3.DotProduct(normalVec, incomingRay.direction); reflectRay.direction = -(incomingRay.direction + (2 * normalVec * c)); reflectRay.direction.Normalize(); reflectColor = fireRay(reflectRay, depth + 1, hitShape); retColor += reflectColor * hitShape.Material.Kr; } if (hitShape.Material.Kt > 0) { Ray transRay = new Ray(); double indexRefract; Vector3 normalVec = Vector3.FaceForward(hitShape.calcNormal(finalHit), -incomingRay.direction); if (Vector3.DotProduct(-incomingRay.direction, hitShape.calcNormal(finalHit)) < 0) indexRefract = Constants.REFRACTION_INDEX_SPHERE / Constants.REFRACTION_INDEX_AIR; else indexRefract = Constants.REFRACTION_INDEX_AIR / Constants.REFRACTION_INDEX_SPHERE; double discrim = 1 + (Math.Pow(indexRefract, 2) * (Math.Pow(Vector3.DotProduct(-incomingRay.direction, normalVec), 2) - 1)); // Total internal reflection! if (discrim < 0) { retColor += reflectColor * hitShape.Material.Kt; } else { discrim = indexRefract * Vector3.DotProduct(-incomingRay.direction, normalVec) - Math.Sqrt(discrim); transRay.direction = (indexRefract * incomingRay.direction) + (discrim * normalVec); transRay.start = finalHit.intersect; Color3 transColor = fireRay(transRay, depth + 1, hitShape); retColor += transColor * hitShape.Material.Kt; } } } return retColor; }
private static Color3 fireRay(Ray incomingRay, int depth, Shape fromShape) { double closest = Constants.FAR_AWAY; Color3 retColor = Constants.BGCOLOR; int whichObject = 0, hitObject = 0; Hit finalHit = new Hit(); foreach (Shape s in layout.Shapes) { Hit rayHit = s.intersect(incomingRay); whichObject++; if (rayHit.intersect.z == Constants.FAR_AWAY) { continue; } double dist = Point3.distance(layout.Cam.Eye, rayHit.intersect); if (dist < closest && !s.Equals(fromShape)) { closest = dist; hitObject = whichObject; finalHit = rayHit; } } if (hitObject <= 0) { return(Constants.BGCOLOR); } Shape hitShape = layout.Shapes[hitObject - 1]; retColor = Color3.ambient(hitShape); // phongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphongphong Color3 diffuseColor = Color3.Black, specularColor = Color3.Black; foreach (Light bulb in layout.Lights) { if (spawnShadow(bulb, finalHit, hitShape, fromShape)) { retColor = hitShape.colorShadow(retColor, finalHit, layout.Lights.Count * 3); } else { if (hitShape is Plane) { retColor = hitShape.colorNormal(retColor, incomingRay, finalHit, hitShape, bulb); } else { diffuseColor += Color3.diffuse(finalHit, hitShape, bulb); specularColor += Color3.specular(incomingRay, finalHit, hitShape, bulb); } } } if (hitShape is Sphere) { retColor += diffuseColor * hitShape.Material.Kd; retColor += specularColor * hitShape.Material.Ks; } if (depth < Constants.MAX_DEPTH) { Color3 reflectColor = Color3.Black; if (hitShape.Material.Kr > 0) { Ray reflectRay = new Ray(); reflectRay.start = finalHit.intersect; Vector3 normalVec = hitShape.calcNormal(finalHit); double c = -Vector3.DotProduct(normalVec, incomingRay.direction); reflectRay.direction = -(incomingRay.direction + (2 * normalVec * c)); reflectRay.direction.Normalize(); reflectColor = fireRay(reflectRay, depth + 1, hitShape); retColor += reflectColor * hitShape.Material.Kr; } if (hitShape.Material.Kt > 0) { Ray transRay = new Ray(); double indexRefract; Vector3 normalVec = Vector3.FaceForward(hitShape.calcNormal(finalHit), -incomingRay.direction); if (Vector3.DotProduct(-incomingRay.direction, hitShape.calcNormal(finalHit)) < 0) { indexRefract = Constants.REFRACTION_INDEX_SPHERE / Constants.REFRACTION_INDEX_AIR; } else { indexRefract = Constants.REFRACTION_INDEX_AIR / Constants.REFRACTION_INDEX_SPHERE; } double discrim = 1 + (Math.Pow(indexRefract, 2) * (Math.Pow(Vector3.DotProduct(-incomingRay.direction, normalVec), 2) - 1)); // Total internal reflection! if (discrim < 0) { retColor += reflectColor * hitShape.Material.Kt; } else { discrim = indexRefract * Vector3.DotProduct(-incomingRay.direction, normalVec) - Math.Sqrt(discrim); transRay.direction = (indexRefract * incomingRay.direction) + (discrim * normalVec); transRay.start = finalHit.intersect; Color3 transColor = fireRay(transRay, depth + 1, hitShape); retColor += transColor * hitShape.Material.Kt; } } } return(retColor); }