public override float Intersect(SLRay currentRay) { float normDotRay = pNormal.Dot(currentRay.Direction); if (normDotRay == 0) return -1; float d = -(pNormal.Dot(currentRay.Origin) - Offset) / normDotRay; if (d < 0) return -1; else return d; }
static void GetClosestIntersection(ref SLRay ray) { foreach(SLRayPrimitive primitive in RayObjects) { float d = primitive.Intersect(ray); if (d < ray.ClosestPointDistance && d > 0) { ray.ClosestPrimitive = primitive; ray.ClosestPointDistance = d; } } ray.ClosestPoint = ray.Origin + (ray.Direction * ray.ClosestPointDistance); }
public override float Intersect(SLRay currentRay) { SLVector3f e = currentRay.Origin; SLVector3f o = position; SLVector3f d = currentRay.Direction; SLVector3f rayToSphereOrigin = o - e; float b = rayToSphereOrigin.Dot(d); float h = radius * radius + b * b - rayToSphereOrigin.x * rayToSphereOrigin.x - rayToSphereOrigin.y * rayToSphereOrigin.y - rayToSphereOrigin.z * rayToSphereOrigin.z; // Early out if (h < 0) return -1; h = b - (float)Math.Sqrt(h); if (h < 0) return -1; else return h; }
public abstract float Intersect(SLRay currentRay);
static Color SetPixelColor(SLRay ray, int depth) { // Get closest intersection IF ANY GetClosestIntersection(ref ray); // Return if the ray didn't hit anything if (ray.ClosestPointDistance >= SLRay.Max_Distance || ray.ClosestPrimitive == null) return BG_COLOR; // Set ambient light float r = LaR * ray.ClosestPrimitive.PrimitiveColor.R; float g = LaG * ray.ClosestPrimitive.PrimitiveColor.G; float b = LaB * ray.ClosestPrimitive.PrimitiveColor.B; // Add contributions of each light SLVector3f normal = ray.ClosestPrimitive.PointNormal(ray.ClosestPoint); SLVector3f viewDir = -ray.Direction; foreach (SLLight light in Lights) { SLVector3f lightDir = new SLVector3f(); float lightDistance; // Find light direction and distance lightDir = light.position - ray.ClosestPoint; lightDistance = lightDir.Magnitude(); lightDir.Normalize(); SLRay pointToLight = new SLRay(ray.ClosestPoint + (lightDir * TINY), lightDir); pointToLight.ClosestPointDistance = lightDistance; GetClosestIntersection(ref pointToLight); if (pointToLight.ClosestPrimitive != null) continue; // DIFFUSE LIGHTING float lDotN = normal.Dot(lightDir); // Clamp if (lDotN <= 0) continue; float diffColorContrR = (light.color.R * lDotN)/255.0f; float diffColorContrG = (light.color.G * lDotN)/ 255.0f; float diffColorContrB = (light.color.B * lDotN)/ 255.0f; // Add this light's diffuse contribution to our running totals r += diffColorContrR * ray.ClosestPrimitive.PrimitiveColor.R; g += diffColorContrG * ray.ClosestPrimitive.PrimitiveColor.G; b += diffColorContrB * ray.ClosestPrimitive.PrimitiveColor.B; if (MATERIAL_SPECULAR_COEFFICIENT > TINY) { // Specular component - dot product of light's reflection vector and viewer direction // Direction to the viewer is simply negative of the ray direction SLVector3f lightReflectionDir = normal * (lDotN * 2) - lightDir; float specularFactor = viewDir.Dot(lightReflectionDir); if (specularFactor > 0) { // To get smaller, sharper highlights we raise it to a power and multiply it specularFactor = MATERIAL_SPECULAR_COEFFICIENT * (float)Math.Pow(specularFactor, MATERIAL_SPECULAR_POWER); // Add the specular contribution to our running totals r += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.R; g += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.G; b += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.B; } } if (depth < MAX_DEPTH && MATERIAL_REFLECTION_COEFFICIENT > TINY) { // Set up the reflected ray - notice we move the origin out a tiny bit again SLVector3f reflectedDir = ray.Direction.Reflection(normal); SLRay reflectionRay = new SLRay(ray.ClosestPoint + reflectedDir * TINY, reflectedDir); // And trace! Color reflectionCol = SetPixelColor(reflectionRay, depth + 1); // Add reflection results to running totals, scaling by reflect coeff. r += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.R; g += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.G; b += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.B; } } // Clamp if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; // Take care of NaN if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; return (Color.FromArgb(255, (int)r, (int)g, (int)b)); }
static Color Render(int x, int y) { float sx = (x / WIDTH_DIV_2 - 1.0f); float sy = (1.0f - y / HEIGHT_DIV_2); SLVector3f u = screenU * sx; SLVector3f v = screenV * sy; SLVector3f direction = u + v - dir; direction.Normalize(); SLRay posRay = new SLRay(EYE, direction); return SetPixelColor(posRay, 0); }