private void SetupScene1() { TextureMaterial woodMaterial = new TextureMaterial(woodTexture, 0.2, 0.0, 2, .5); TextureMaterial marbleMaterial = new TextureMaterial(marbleTexture, 0.0, 0.0, 2, .5); TextureMaterial wallMaterial = new TextureMaterial(wallTexture, 0.0, 0.0, 2, .4); scene = new Scene(); scene.Background = new Background(new RGBA_Doubles(.8, .8, .8), 0.8); Vector campos = new Vector(5, 1.8, -15); scene.Camera = new Camera(campos, campos / -3, new Vector(0, 1, 0).Normalize()); // marble scene.Shapes.Add(new SphereShape(new Vector(1, 1, -5), 1, marbleMaterial)); //floor scene.Shapes.Add(new PlaneShape(new Vector(0, 1, 0).Normalize(), 0, woodMaterial)); //wall scene.Shapes.Add(new PlaneShape(new Vector(0, 0, 1).Normalize(), 0, wallMaterial)); scene.Lights.Add(new Light(new Vector(25, 20, -20), new RGBA_Doubles(0.5, 0.5, 0.5))); scene.Lights.Add(new Light(new Vector(-3, 5, -15), new RGBA_Doubles(0.5, 0.5, 0.5))); }
// marble balls scene private void SetupScene0() { TextureMaterial texture = new TextureMaterial(marbleTexture, 0.0, 0.0, 2, .5); scene = new Scene(); scene.Camera = new Camera(new Vector3(0, 0, -15), new Vector3(-.2, 0, 5), new Vector3(0, 1, 0)); // setup a solid reflecting sphere scene.Shapes.Add(new SphereShape(new Vector(-1.5, 0.5, 0), .5, new SolidMaterial(new RGBA_Doubles(0, .5, .5), 0.2, 0.0, 2.0))); // setup sphere with a marble texture from an image scene.Shapes.Add(new SphereShape(new Vector(0, 0, 0), 1, texture)); scene.Shapes.Add(new BoxShape(new Vector(0, 0, -15), new Vector(.5, .5, .5), new SolidMaterial(new RGBA_Doubles(0, 0, 1), .1, 0, .2))); // setup the chessboard floor scene.Shapes.Add(new PlaneShape(new Vector(0.1, 0.9, -0.5).Normalize(), 1.2, new ChessboardMaterial(new RGBA_Doubles(1, 1, 1), new RGBA_Doubles(0, 0, 0), 0.2, 0, 1, 0.7))); //add two lights for better lighting effects scene.Lights.Add(new Light(new Vector(5, 10, -1), new RGBA_Doubles(0.8, 0.8, 0.8))); scene.Lights.Add(new Light(new Vector(-3, 5, -15), new RGBA_Doubles(0.8, 0.8, 0.8))); }
private void CreateScene() { scene = new Scene(); scene.camera = new TrackBallCamera(trackballTumbleWidget); //scene.background = new Background(new RGBA_Floats(0.5, .5, .5), 0.4); scene.background = new Background(new RGBA_Floats(1, 1, 1, 0), 0.6); AddTestMesh(loadedMeshGroups); allObjects = BoundingVolumeHierarchy.CreateNewHierachy(renderCollection); allObjectsHolder = new Transform(allObjects); //allObjects = root; scene.shapes.Add(allObjectsHolder); //AddAFloor(); //add two lights for better lighting effects //scene.lights.Add(new Light(new Vector3(5000, 5000, 5000), new RGBA_Floats(0.8, 0.8, 0.8))); scene.lights.Add(new PointLight(new Vector3(-5000, -5000, 3000), new RGBA_Floats(0.5, 0.5, 0.5))); }
private void CreateScene() { scene = new Scene(); scene.camera = new TrackBallCamera(trackballTumbleWidget); scene.background = new Background(new RGBA_Floats(0.5, .5, .5), 0.4); AddBoxAndSheresBooleanTest(); //AddBoxAndBoxBooleanTest(); #if false renderCollection.Add(new BoxShape(new Vector3(), new Vector3(1, 1, 1), new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0))); renderCollection.Add(new BoxShape(new Vector3(.5,.5,.5), new Vector3(1.5, 1.5, 1.5), new SolidMaterial(new RGBA_Floats(.9, .2, .1), .01, 0.0, 2.0))); #endif //renderCollection.Add(new CylinderShape(.25, 1, new SolidMaterial(RGBA_Floats.Cyan, 0, 0, 0))); //AddTestStl(); //AddPolygonTest(); //AddSphereAndBox(); //AddAxisMarker(); //AddCubeOfShperes(); //renderCollection.Add(MakerGearXCariage()); allObjects = BoundingVolumeHierarchy.CreateNewHierachy(renderCollection); allObjectsHolder = new Transform(allObjects); //allObjects = root; scene.shapes.Add(allObjectsHolder); //AddAFloor(); //add two lights for better lighting effects scene.lights.Add(new PointLight(new Vector3(5000, 5000, 5000), new RGBA_Floats(0.8, 0.8, 0.8))); scene.lights.Add(new PointLight(new Vector3(-5000, -5000, 3000), new RGBA_Floats(0.5, 0.5, 0.5))); }
public RGBA_Floats CreateAndTraceSecondaryRays(IntersectInfo info, Ray ray, Scene scene, int depth) { // calculate ambient light RGBA_Floats infoColorAtHit = info.closestHitObject.GetColor(info); RGBA_Floats color = infoColorAtHit * scene.background.Ambience; double shininess = Math.Pow(10, info.closestHitObject.Material.Gloss + 1); foreach (Light light in scene.lights) { // calculate diffuse lighting Vector3 directiorFromHitToLight = light.Transform.Position - info.hitPosition; double distanceToLight = directiorFromHitToLight.Length; Vector3 directiorFromHitToLightNormalized = directiorFromHitToLight.GetNormal(); if (RenderDiffuse) { double L = Vector3.Dot(directiorFromHitToLightNormalized, info.normalAtHit); if (L > 0.0f) { color += infoColorAtHit * light.Color * L; } } // this is the max depth of raytracing. // increasing depth will calculate more accurate color, however it will // also take longer (exponentially) if (depth < 3) { // calculate reflection ray if (RenderReflection && info.closestHitObject.Material.Reflection > 0) { Ray reflectionRay = GetReflectionRay(info.hitPosition, info.normalAtHit, ray.direction); IntersectInfo reflectionInfo = TracePrimaryRay(reflectionRay, scene); RGBA_Floats reflectionColorAtHit;// = reflectionInfo.closestHitObject.GetColor(reflectionInfo); if (reflectionInfo.hitType != IntersectionType.None && reflectionInfo.distanceToHit > 0) { // recursive call, this makes reflections expensive reflectionColorAtHit = CreateAndTraceSecondaryRays(reflectionInfo, reflectionRay, scene, depth + 1); } else // does not reflect an object, then reflect background color { reflectionColorAtHit = scene.background.Color; } color = color.Blend(reflectionColorAtHit, info.closestHitObject.Material.Reflection); } //calculate refraction ray if (RenderRefraction && info.closestHitObject.Material.Transparency > 0) { Ray refractionRay = new Ray(info.hitPosition, ray.direction, Ray.sameSurfaceOffset, double.MaxValue); // GetRefractionRay(info.hitPosition, info.normalAtHit, ray.direction, info.closestHit.Material.Refraction); IntersectInfo refractionInfo = TracePrimaryRay(refractionRay, scene); RGBA_Floats refractionColorAtHit = refractionInfo.closestHitObject.GetColor(refractionInfo); if (refractionInfo.hitType != IntersectionType.None && refractionInfo.distanceToHit > 0) { // recursive call, this makes refractions expensive refractionColorAtHit = CreateAndTraceSecondaryRays(refractionInfo, refractionRay, scene, depth + 1); } else { refractionColorAtHit = scene.background.Color; } color = refractionColorAtHit.Blend(color, info.closestHitObject.Material.Transparency); } } IntersectInfo shadow = new IntersectInfo(); if (RenderShadow) { // calculate shadow, create ray from intersection point to light Ray shadowRay = new Ray(info.hitPosition, directiorFromHitToLightNormalized, Ray.sameSurfaceOffset, double.MaxValue); // it may be usefull to limit the legth to te dist to the camera (but I doubt it LBB). shadowRay.isShadowRay = true; // if the normal at the closest hit is away from the shadow it is already it it's own shadow. if (Vector3.Dot(info.normalAtHit, directiorFromHitToLightNormalized) < 0) { shadow.hitType = IntersectionType.FrontFace; color *= 0.5;// +0.5 * Math.Pow(shadow.closestHit.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount); } else { // find any element in between intersection point and light shadow = TracePrimaryRay(shadowRay, scene); if (shadow.hitType != IntersectionType.None && shadow.closestHitObject != info.closestHitObject && shadow.distanceToHit < distanceToLight) { // only cast shadow if the found interesection is another // element than the current element color *= 0.5;// +0.5 * Math.Pow(shadow.closestHit.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount); } } } // only show highlights if it is not in the shadow of another object if (RenderHighlights && shadow.hitType == IntersectionType.None && info.closestHitObject.Material.Gloss > 0) { // only show Gloss light if it is not in a shadow of another element. // calculate Gloss lighting (Phong) Vector3 Lv = (info.hitPosition - light.Transform.Position).GetNormal(); Vector3 E = (scene.camera.Origin - info.hitPosition).GetNormal(); Vector3 H = (E - Lv).GetNormal(); double Glossweight = 0.0; Glossweight = Math.Pow(Math.Max(Vector3.Dot(info.normalAtHit, H), 0), shininess); color += light.Color * (Glossweight); } } color.Clamp0To1(); return color; }
public void TracePrimaryRayBundle(RayBundle rayBundle, IntersectInfo[] intersectionsForBundle, Scene scene) { if (scene.shapes.Count != 1) { throw new Exception("You can only trace a ray bundle into a sigle shape, usually a BoundingVolumeHierachy."); } scene.shapes[0].GetClosestIntersections(rayBundle, 0, intersectionsForBundle); }
public IntersectInfo TracePrimaryRay(Ray ray, Scene scene) { IntersectInfo primaryRayIntersection = new IntersectInfo(); foreach (IRayTraceable shapeToTest in scene.shapes) { IntersectInfo info = shapeToTest.GetClosestIntersection(ray); if (info != null && info.hitType != IntersectionType.None && info.distanceToHit < primaryRayIntersection.distanceToHit && info.distanceToHit >= 0) { primaryRayIntersection = info; } } return primaryRayIntersection; }
public void FullyTraceRayBundle(RayBundle rayBundle, IntersectInfo[] intersectionsForBundle, Scene scene) { TracePrimaryRayBundle(rayBundle, intersectionsForBundle, scene); for (int i = 0; i < rayBundle.rayArray.Length; i++) { IntersectInfo primaryInfo = TracePrimaryRay(rayBundle.rayArray[i], scene); if (intersectionsForBundle[i].hitType != IntersectionType.None) { intersectionsForBundle[i].totalColor = CreateAndTraceSecondaryRays(primaryInfo, rayBundle.rayArray[i], scene, 0); } intersectionsForBundle[i].totalColor = scene.background.Color; } }
public RGBA_Floats FullyTraceRay(Ray ray, Scene scene) { IntersectInfo primaryInfo = TracePrimaryRay(ray, scene); if (primaryInfo.hitType != IntersectionType.None) { RGBA_Floats totalColor = CreateAndTraceSecondaryRays(primaryInfo, ray, scene, 0); return totalColor; } return scene.background.Color; }
public void AntiAliasScene(Graphics2D graphics2D, RectangleInt viewport, Scene scene, RGBA_Floats[][] buffer, int maxSamples) { IImageByte destImage = (IImageByte)graphics2D.DestImage; if (destImage.BitDepth != 32) { throw new Exception("We can only render to 32 bit dest at the moment."); } Byte[] destBuffer = destImage.GetBuffer(); #if MULTI_THREAD System.Threading.Tasks.Parallel.For(1, viewport.Height - 1, y => // #else for (int y = 1; y < viewport.Height - 1; y++) #endif { int fillY = viewport.Top - (viewport.Bottom + y); int bufferOffset = 0; if (y > 0 && y < destImage.Height) { bufferOffset = destImage.GetBufferOffsetY(y); } for (int x = 1; x < viewport.Width - 1; x++) { RGBA_Floats avg = (buffer[x - 1][y - 1] + buffer[x][y - 1] + buffer[x + 1][y - 1] + buffer[x - 1][y] + buffer[x][y] + buffer[x + 1][y] + buffer[x - 1][y + 1] + buffer[x][y + 1] + buffer[x + 1][y + 1]) / 9; // use a more accurate antialasing method (MonteCarlo implementation) // this will fire multiple rays per pixel double sumOfDifferencesThreshold = .05; // TODO: figure out a good way to determin this. if (avg.SumOfDistances(buffer[x][y]) > sumOfDifferencesThreshold) { RGBA_Floats accumulatedColor = buffer[x][y]; for (int i = 0; i < maxSamples; i++) { // get some 'random' samples double rx = Math.Sign(i % 4 - 1.5) * (IntNoise(x + y * viewport.Width * maxSamples * 2 + i) + 1) / 4; double ry = Math.Sign(i % 2 - 0.5) * (IntNoise(x + y * viewport.Width * maxSamples * 2 + 1 + i) + 1) / 4; double xp = x + rx; double yp = y + ry; Ray ray = scene.camera.GetRay(xp, yp); accumulatedColor += FullyTraceRay(ray, scene); } buffer[x][y] = accumulatedColor / (maxSamples + 1); // this is the slow part of the painting algorithm, it can be greatly speed up // by directly accessing the bitmap data int fillX = viewport.Left + x; int totalOffset = bufferOffset + fillX * 4; destBuffer[totalOffset++] = (byte)buffer[x][y].Blue0To255; destBuffer[totalOffset++] = (byte)buffer[x][y].Green0To255; destBuffer[totalOffset++] = (byte)buffer[x][y].Red0To255; destBuffer[totalOffset] = 255; } } } #if MULTI_THREAD ); #endif }
public void RayTraceScene(Graphics2D graphics2D, RectangleInt viewport, Scene scene) { int maxsamples = (int)AntiAliasing; //graphics2D.FillRectangle(viewport, RGBA_Floats.Black); if (imageBufferAsDoubles == null || imageBufferAsDoubles.Length < viewport.Width || imageBufferAsDoubles[0].Length < viewport.Height) { imageBufferAsDoubles = new RGBA_Floats[viewport.Width][]; for (int i = 0; i < viewport.Width; i++) { imageBufferAsDoubles[i] = new RGBA_Floats[viewport.Height]; } } IImageByte destImage = (IImageByte)graphics2D.DestImage; if (destImage.BitDepth != 32) { throw new Exception("We can only render to 32 bit dest at the moment."); } Byte[] destBuffer = destImage.GetBuffer(); viewport.Bottom = Math.Max(0, Math.Min(destImage.Height, viewport.Bottom)); viewport.Top = Math.Max(0, Math.Min(destImage.Height, viewport.Top)); #if MULTI_THREAD System.Threading.Tasks.Parallel.For(viewport.Bottom, viewport.Height, y => // #else for (int y = viewport.Bottom; y < viewport.Height; y++) #endif { for (int x = viewport.Left; x < viewport.Right; x++) { if (traceWithRayBundles) { int width = Math.Min(8, viewport.Right - x); int height = Math.Min(8, viewport.Top - y); FrustumRayBundle rayBundle = new FrustumRayBundle(width * height); IntersectInfo[] intersectionsForBundle = new IntersectInfo[width * height]; for (int rayY = 0; rayY < height; rayY++) { for (int rayX = 0; rayX < width; rayX++) { rayBundle.rayArray[rayX + rayY * width] = scene.camera.GetRay(x + rayX, y + rayY); intersectionsForBundle[rayX + rayY * width] = new IntersectInfo(); } } rayBundle.CalculateFrustum(width, height, scene.camera.Origin); FullyTraceRayBundle(rayBundle, intersectionsForBundle, scene); for (int rayY = 0; rayY < height; rayY++) { int bufferOffset = destImage.GetBufferOffsetY(y + rayY); for (int rayX = 0; rayX < width; rayX++) { imageBufferAsDoubles[x + rayX][y + rayY] = intersectionsForBundle[rayX + rayY * width].totalColor; // we don't need to set this if we are anti-aliased int totalOffset = bufferOffset + (x + rayX) * 4; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Blue0To255; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Green0To255; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x + rayX][y + rayY].Red0To255; destBuffer[totalOffset] = 255; } } x += width - 1; // skip all the pixels we bundled y += height - 1; // skip all the pixels we bundled } else { int bufferOffset = destImage.GetBufferOffsetY(y); Ray ray = scene.camera.GetRay(x, y); imageBufferAsDoubles[x][y] = FullyTraceRay(ray, scene); // we don't need to set this if we are anti-aliased int totalOffset = bufferOffset + x * 4; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Blue0To255; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Green0To255; destBuffer[totalOffset++] = (byte)imageBufferAsDoubles[x][y].Red0To255; destBuffer[totalOffset] = 255; } } } #if MULTI_THREAD ); #endif if (AntiAliasing != AntiAliasing.None) { AntiAliasScene(graphics2D, viewport, scene, imageBufferAsDoubles, (int)AntiAliasing); } destImage.MarkImageChanged(); }
public void AntiAliasScene(RectangleInt viewport, Scene scene, RGBA_Floats[][] imageBufferAsDoubles, int maxSamples) { #if MULTI_THREAD System.Threading.Tasks.Parallel.For(1, viewport.Height - 1, y => // #else for (int y = 1; y < viewport.Height - 1; y++) #endif { int fillY = viewport.Top - (viewport.Bottom + y); for (int x = 1; x < viewport.Width - 1; x++) { RGBA_Floats avg = (imageBufferAsDoubles[x - 1][y - 1] + imageBufferAsDoubles[x][y - 1] + imageBufferAsDoubles[x + 1][y - 1] + imageBufferAsDoubles[x - 1][y] + imageBufferAsDoubles[x][y] + imageBufferAsDoubles[x + 1][y] + imageBufferAsDoubles[x - 1][y + 1] + imageBufferAsDoubles[x][y + 1] + imageBufferAsDoubles[x + 1][y + 1]) / 9; // use a more accurate antialasing method (MonteCarlo implementation) // this will fire multiple rays per pixel double sumOfDifferencesThreshold = .05; // TODO: figure out a good way to determin this. if (avg.SumOfDistances(imageBufferAsDoubles[x][y]) > sumOfDifferencesThreshold) { RGBA_Floats accumulatedColor = imageBufferAsDoubles[x][y]; for (int i = 0; i < maxSamples; i++) { // get some 'random' samples double rx = Math.Sign(i % 4 - 1.5) * (IntNoise(x + y * viewport.Width * maxSamples * 2 + i) + 1) / 4; double ry = Math.Sign(i % 2 - 0.5) * (IntNoise(x + y * viewport.Width * maxSamples * 2 + 1 + i) + 1) / 4; double xp = x + rx; double yp = y + ry; Ray ray = scene.camera.GetRay(xp, yp); IntersectInfo primaryInfo; accumulatedColor += FullyTraceRay(ray, scene, out primaryInfo); } imageBufferAsDoubles[x][y] = accumulatedColor / (maxSamples + 1); } } } #if MULTI_THREAD ); #endif }
public void RayTraceScene(RectangleInt viewport, Scene scene) { int maxsamples = (int)AntiAliasing; //graphics2D.FillRectangle(viewport, RGBA_Floats.Black); if (colorBuffer == null || colorBuffer.Length < viewport.Width || colorBuffer[0].Length < viewport.Height) { colorBuffer = new RGBA_Floats[viewport.Width][]; for (int i = 0; i < viewport.Width; i++) { colorBuffer[i] = new RGBA_Floats[viewport.Height]; } normalBuffer = new Vector3[viewport.Width][]; for (int i = 0; i < viewport.Width; i++) { normalBuffer[i] = new Vector3[viewport.Height]; } depthBuffer = new double[viewport.Width][]; for (int i = 0; i < viewport.Width; i++) { depthBuffer[i] = new double[viewport.Height]; } } #if MULTI_THREAD System.Threading.Tasks.Parallel.For(viewport.Bottom, viewport.Height, y => // #else for (int y = viewport.Bottom; y < viewport.Height; y++) #endif { for (int x = viewport.Left; x < viewport.Right; x++) { if (traceWithRayBundles) { int width = Math.Min(8, viewport.Right - x); int height = Math.Min(8, viewport.Top - y); FrustumRayBundle rayBundle = new FrustumRayBundle(width * height); IntersectInfo[] intersectionsForBundle = new IntersectInfo[width * height]; for (int rayY = 0; rayY < height; rayY++) { for (int rayX = 0; rayX < width; rayX++) { rayBundle.rayArray[rayX + rayY * width] = scene.camera.GetRay(x + rayX, y + rayY); intersectionsForBundle[rayX + rayY * width] = new IntersectInfo(); } } // get a ray to find the origin (every ray comes from the camera and should have the same origin) Ray screenRay = scene.camera.GetRay(0, 0); rayBundle.CalculateFrustum(width, height, screenRay.origin); FullyTraceRayBundle(rayBundle, intersectionsForBundle, scene); for (int rayY = 0; rayY < height; rayY++) { for (int rayX = 0; rayX < width; rayX++) { colorBuffer[x + rayX][y + rayY] = intersectionsForBundle[rayX + rayY * width].totalColor; } } x += width - 1; // skip all the pixels we bundled y += height - 1; // skip all the pixels we bundled } else { Ray ray = scene.camera.GetRay(x, y); IntersectInfo primaryInfo; colorBuffer[x][y] = FullyTraceRay(ray, scene, out primaryInfo); if (false) { if (primaryInfo != null) { normalBuffer[x][y] = primaryInfo.normalAtHit; depthBuffer[x][y] = primaryInfo.distanceToHit; } else { normalBuffer[x][y] = Vector3.UnitZ; depthBuffer[x][y] = double.PositiveInfinity; } } } } } #if MULTI_THREAD ); #endif if (AntiAliasing != AntiAliasing.None) { AntiAliasScene(viewport, scene, colorBuffer, (int)AntiAliasing); } }
private void SetupScene2() { scene = new Scene(); scene.Background = new Background(new RGBA_Doubles(.2, .3, .4), 0.5); Vector campos = new Vector(0, 0, -5); scene.Camera = new Camera(campos, campos / -2, new Vector(0, 1, 0).Normalize()); Random rnd = new Random(); for (int i = 0; i < 40; i++) { // setup a solid reflecting sphere scene.Shapes.Add(new SphereShape(new Vector(rnd.Next(-100, 100) / 50.0, rnd.Next(-100, 100) / 50.0, rnd.Next(0, 200) / 50.0), .2, new SolidMaterial(new RGBA_Doubles(rnd.Next(0, 100) / 100.0, rnd.Next(0, 100) / 100.0, rnd.Next(0, 100) / 100.0), 0.4, 0.0, 2.0))); } scene.Lights.Add(new Light(new Vector(5, 10, -1), new RGBA_Doubles(0.8, 0.8, 0.8))); scene.Lights.Add(new Light(new Vector(-3, 5, -15), new RGBA_Doubles(0.8, 0.8, 0.8))); }
// metallic box with marble on stone floor private void SetupScene4() { TextureMaterial woodMaterial = new TextureMaterial(woodTexture, 0.0, 0.0, 2, .5); TextureMaterial marbleMaterial = new TextureMaterial(marbleTexture, 0.3, 0.0, 2, .5); TextureMaterial wallMaterial = new TextureMaterial(wallTexture, 0.0, 0.0, 2, .4); scene = new Scene(); scene.Background = new Background(new RGBA_Doubles(.3, .8, .8), 0.8); Vector campos = new Vector(14, 2, -6); scene.Camera = new Camera(campos, campos / -2.5, new Vector(-0, 1, 0.1).Normalize()); // marble scene.Shapes.Add(new SphereShape(new Vector(-3, 1, 5), 2, marbleMaterial)); // box scene.Shapes.Add(new BoxShape(new Vector(0, 1, -1), new Vector(1, 0, 0), woodMaterial)); //floor scene.Shapes.Add(new PlaneShape(new Vector(0, 1, 0).Normalize(), 0, wallMaterial)); //wall //scene.Shapes.Add(new PlaneShape(new Vector(0, 0, 1).Normalize(), 0, wallMaterial)); scene.Lights.Add(new Light(new Vector(25, 20, -20), new RGBA_Doubles(0.5, 0.5, 0.5))); scene.Lights.Add(new Light(new Vector(-23, 25, -15), new RGBA_Doubles(0.5, 0.5, 0.5))); }
private void SetupScene3() { scene = new Scene(); scene.Camera = new Camera(new Vector(0, 0, -15), new Vector(-.2, 0, 5), new Vector(0, 1, 0)); scene.Background = new Background(new RGBA_Doubles(0.5, .5, .5), 0.4); // setup a solid reflecting sphere scene.Shapes.Add(new SphereShape(new Vector(-0.5, 0.5, -2), 1.5, new SolidMaterial(new RGBA_Doubles(0, .5, .5), 0.3, 0.0, 2.0))); // setup the chessboard floor scene.Shapes.Add(new PlaneShape(new Vector(0.1, 0.9, -0.5).Normalize(), 1.2, new ChessboardMaterial(new RGBA_Doubles(1, 1, 1), new RGBA_Doubles(0, 0, 0), 0.2, 0, 1, 0.7))); //add two lights for better lighting effects scene.Lights.Add(new Light(new Vector(5, 10, -1), new RGBA_Doubles(0.8, 0.8, 0.8))); scene.Lights.Add(new Light(new Vector(-3, 5, -15), new RGBA_Doubles(0.8, 0.8, 0.8))); }