public void Tick() { // start timer timer.Restart(); // run the simulation, 1 step inBuffer.CopyToDevice(); kernel.Execute(workSize); outBuffer.CopyFromDevice(); for (int i = 0; i < pw * ph; i++) { _in[i] = 0; } // visualize current state, DRAW FUNCTION -> GPU BONUS. screen.Clear(0); for (uint y = 0; y < screen.height / scale; y++) { for (uint x = 0; x < screen.width / scale; x++) { if (GetBit(x + xoffset, y + yoffset) == 1) { if (scale > 1) { for (uint j = 0; ((j + 1) % scale) != 0; j++) { for (uint i = 0; ((i + 1) % scale) != 0; i++) { screen.Plot((x * scale + i), (y * scale + j), 0xffffff); } } } else { screen.Plot(x, y, 0xffffff); } } } } for (uint y = 0; y < ph; y++) { for (uint x = 0; x < pw * 32; x++) { if (GetBit(x, y) == 1) { BitSet(x, y); } } } string text = "Scale: " + scale + "x"; screen.Print(text, 5, 5, 0xffffff); // report performance Console.WriteLine("generation " + generation++ + ": " + timer.ElapsedMilliseconds + "ms"); }
public void Debug() { for (int i = 0; i < raytracer.eindpunten.Length; i++) { screen.Line(((int)Xtrans(raytracer.cameraPosition.X)), ((int)Ytrans(raytracer.cameraPosition.Z)), ((int)Xtrans(raytracer.eindpunten[i].X)), ((int)Ytrans((raytracer.eindpunten[i].Y))), 0xff00ff);// tekent de ray van de camera naar een intersectie //screen.Line(((int)Xtrans(raytracer.eindpunten[i].X)), ((int)Ytrans(raytracer.eindpunten[i].Y)), ((int)Xtrans(scene.lightPositie.X)), ((int)Ytrans(scene.lightPositie.Z)),0x00ffff);// tekent de rays van een intersectie naar de lichtbron } r = scene.radius * (screen.height / 10); for (double i = 0.0; i < 360.0; i += 0.1) { hoek = i * Math.PI / 180; xpositieDebug = (int)(Xtrans((int)scene.sphere1Positie.X) + r * Math.Cos(hoek)); ypositieDebug = (int)(Ytrans((int)scene.sphere1Positie.Z) + r * Math.Sin(hoek)); screen.Plot(xpositieDebug, ypositieDebug, CreateColorf(scene.kleur1.X, scene.kleur1.Y, scene.kleur1.Z)); } for (double i = 0.0; i < 360.0; i += 0.1) { hoek = i * Math.PI / 180; xpositieDebug = (int)(Xtrans((int)scene.sphere2Positie.X) + r * Math.Cos(hoek)); ypositieDebug = (int)(Ytrans((int)scene.sphere2Positie.Z) + r * Math.Sin(hoek)); screen.Plot(xpositieDebug, ypositieDebug, CreateColorf(scene.kleur2.X, scene.kleur2.Y, scene.kleur2.Z)); } for (double i = 0.0; i < 360.0; i += 0.1) { hoek = i * Math.PI / 180; xpositieDebug = (int)(Xtrans((int)scene.sphere3Positie.X) + r * Math.Cos(hoek)); ypositieDebug = (int)(Ytrans((int)scene.sphere3Positie.Z) + r * Math.Sin(hoek)); screen.Plot(xpositieDebug, ypositieDebug, CreateColorf(scene.kleur3.X, scene.kleur3.Y, scene.kleur3.Z)); } screen.Plot(((int)Xtrans(raytracer.cameraPosition.X)), ((int)Ytrans(raytracer.cameraPosition.Z)), 0xffffff); // geeft de camera positie screen.Plot(((int)Xtrans(scene.lightPositie.X)), ((int)Ytrans(scene.lightPositie.Z)), 0x0fffff); // geeft de licht positie }
private void RenderRaycastScene() { int viewportWidth = screen.width / 2; int viewportHeight = screen.height; Vector3 origin = camera.GetPosition(); Vector3 direction; for (int x = 0; x < viewportWidth; x++) { for (int y = 0; y < viewportHeight; y++) { direction = camera.GetRayDirection(x / (float)viewportWidth, y / (float)viewportHeight); Ray r = new Ray(origin, direction); Intersect intersect = new Intersect(); intersect.OriginalRay = r; scene.IntersectWithScene(intersect); screen.Plot(x, y, intersect.Col); if (y == viewportHeight / 2 && x % 32 == 0) { screen.Line(TX(camera.GetPosition().X), TY(camera.GetPosition().Y), TX(intersect.OriginalRay.distance * direction.X + camera.GetPosition().X), TY(intersect.OriginalRay.distance * direction.Y + camera.GetPosition().Y), 255 << 8); } } } }
public void Render() { // Een tijdelijk array wordt gemaakt om de kleuren van het scherm in te stoppen. // Dit zorgt ervoor dat de debug niet over het scherm wordt geprint. Vector3[] colors = new Vector3[512 * 512]; // De i houdt bij welke positie van de array er wordt gebruikt. int i = 0; for (int y = 0; y < 512; y++) { for (int x = 0; x < 512; x++) { // De camera heeft de richtingen per pixel opgeslagen in een array, en maakt hier nu een ray van. Ray ray = camera.SendRay(i); // Elke zoveel rays op y = 256 worden getekent. if (y == 256 && x % 20 == 0) { // De uiteindelijke kleur van de ray wordt hier opgeslagen. colors[i] = Trace(ray, true, maxRecursion); // De primary rays beginnen met een rood cirkelsegment van lengte 1, zoals in de opdracht vermeld wordt. DrawDebugRay(new Ray(ray.O, ray.D, 1), new Vector3(255, 0, 0)); } else { // Als het nit in de debug getekent moet worden wordt er false meegegeven. colors[i] = Trace(ray, false, maxRecursion); } i++; } } // Vervolgens worden de camera, screen en primitives (alleen spheres) getekent. DrawDebug(); // Tenslotte wordt de scene echt geplot. i = 0; for (int y = 0; y < 512; y++) { for (int x = 0; x < 512; x++) { screen.Plot(x, y, FixColor(colors[i])); i++; } } }
public void Raytracing() { // prepare for generic OpenGL rendering GL.Enable(EnableCap.DepthTest); GL.Disable(EnableCap.Texture2D); GL.Clear(ClearBufferMask.DepthBufferBit); float FOV = 400; // creating a scene Scene Scene1 = new Scene(); // Adding axis in the Debug view Scene1.toggleaxis(true); if (Scene1.Axis == true) { GL.Color4(1f, 1f, 1f, 1f); GL.Begin(PrimitiveType.Lines); GL.Vertex2(0.5f, 1); GL.Vertex2(0.5f, -1f); GL.Vertex2(0, 0); GL.Vertex2(1, 0); GL.End(); } // Adding main objects to the scene Sphere Sphere1 = new Sphere(new Vector3(200, 0, 200), 100f, new Vector3(255,0,0), aspectratio); Sphere Sphere2 = new Sphere(new Vector3(-200, 0, 200), 100f, new Vector3(0, 0, 255), aspectratio); Sphere Sphere3 = new Sphere(new Vector3(-100, 0, 200), 100f, new Vector3(0, 255,0), aspectratio); Camera mainCamera = new Camera(new Vector3(0,0,-400), new Vector3(0,0,1), FOV); Light LightSource1 = new Light(new Vector3(0, 200, 200), 255, 255, 0); // adding light source(s) to the list Scene1.LightList.Add(LightSource1); //adding primitives to te primitive list Scene1.PrimitivesList.Add(Sphere1); Scene1.PrimitivesList.Add(Sphere3); Scene1.PrimitivesList.Add(Sphere2); // draw every primitive in the list foreach (Sphere item in Scene1.PrimitivesList) { Scene1.DrawCircle(DebugConverter(item.Position), item.Color, item.Radius, screen); } // start raytracing Raytracer raytracer = new Raytracer(); raytracer.Render(mainCamera, Scene1, screen); for (int renderx = 0; renderx < 512; renderx++) { for (int rendery = 0; rendery < 512; rendery++) { int pixel = renderx + rendery * 512; screen.Plot(renderx, rendery, (int)raytracer.Image[pixel]); } } Raytr = raytracer; }
// tick: renders one frame public void Tick() { //clear screen.Clear(0); raytracer.rays.Clear(); int DEFAULT_COLOR = convertColor(new Vector3(255)); for (int i = 0; i < SCREEN_SIZE; i++) { for (int j = 0; j < SCREEN_SIZE; j++) { //Render Screen int location = i + j * SCREEN_SIZE * 2; Vector3 Color = raytracer.Render(i / (SCREEN_SIZE * 1.0f), j / (SCREEN_SIZE * 1.0f)); screen.pixels[location] = convertColor(Color); //Debug Screen Default screen.pixels[i + SCREEN_SIZE + j * SCREEN_SIZE * 2] = 0; } } //Debug View //Draw Sphere foreach(Primitive primitive in raytracer.scene.primitives) { if(primitive is Sphere) { Sphere sphere = (Sphere)primitive; for (int degree = 0; degree < 360; degree++) { int coordX = (int)(CUBE_SIZE * (sphere.radius * Math.Cos(degree) + sphere.pos.X)); int coordY = (int)(CUBE_SIZE * (sphere.radius * Math.Sin(degree) - sphere.pos.Z)); screen.Plot(coordX+ 768, coordY + 350, convertColor(sphere.Color)); } } } //Draw Camera point screen.Box((int)raytracer.camera.pos.X + 767, (int)raytracer.camera.pos.Z * -1 + 349, (int)raytracer.camera.pos.X + 769, (int)raytracer.camera.pos.Z * -1 + 351, DEFAULT_COLOR); //Draw Rays foreach(Ray ray in raytracer.rays) { float coordX = CUBE_SIZE * (ray.O.X + 40 * ray.D.X); float coordY = CUBE_SIZE * (ray.O.Z + 40 * ray.D.Z); screen.Line((int)ray.O.X + 768, (int)ray.O.Z * -1 + 350, (int)coordX + 768, (int)coordY * -1 + 350, DEFAULT_COLOR); } //Dividing Line screen.Line(SCREEN_SIZE, 0, SCREEN_SIZE, SCREEN_SIZE, DEFAULT_COLOR); //User Input application.UpdateCam(raytracer.camera); }
// Draws pixel on the screen with ability to zoom public void DrawScreenZoom() { // clear the screen screen.Clear(0); // you essentially draw a smaller segment of the field for (uint y = 0; y < screen.height / zoom; y++) { for (uint x = 0; x < screen.width / zoom; x++) { if (GetBit(x + xoffset, y + yoffset) == 1) { // draw a white square per white bit for (uint i = 0; i < zoom; i++) { for (uint j = 0; j < zoom; j++) { screen.Plot(x * zoom + i, y * zoom + j, 0xffffff); } } } } } }
public void RenderGL() { for (int x = 0; x < screen.width - 1; x++) { for (int y = 0; y < screen.height - 1; y++) { float rx = -1 + x * 2 / ((float)screen.width - 1); float ry = -1 + y * 2 / ((float)screen.height - 1); ray.O = new Vector2(rx, ry); pixelColor = 0; foreach (Light l in light_array) { float a = l.light_pos.X - ray.O.X, b = l.light_pos.Y - ray.O.Y, distanceToLight = (float)Math.Sqrt(a * a + b * b); ray.D = Vector2.Normalize(l.light_pos - ray.O); ray.t = distanceToLight; bool occluded = false; foreach (Primitive p in primitives) { if (p.Intersect(ray)) { occluded = true; break; } } if (!occluded) { int red_int = (int)(l.R * l.attentuation(distanceToLight) * 255), green_int = (int)(l.G * l.attentuation(distanceToLight) * 255), blue_int = (int)(l.B * l.attentuation(distanceToLight) * 255); pixelColor += (red_int << 16) + (green_int << 8) + blue_int; } } screen.Plot(x, y, MathHelper.Clamp(pixelColor, 0, 16777215)); //Clamp the light so it is always between 0,0,0 (Black) and 255,255,255 (White) } } }
// TICK // Main application entry point: the template calls this function once per frame. public void Tick() { // start timer timer.Restart(); // run the simulation, 1 step Simulate(); // visualize current state screen.Clear(0); for (uint y = 0; y < screen.height; y++) { for (uint x = 0; x < screen.width; x++) { if (GetBit(x + xoffset, y + yoffset) == 1) { screen.Plot(x, y, 0xffffff); } } } // report performance Console.WriteLine("generation " + generation++ + ": " + timer.ElapsedMilliseconds + "ms"); }
// tick: renders one frame public void Tick() { screen.Clear(0); //Parallel.For is used for Multi- threading //Loop over all pixels in the screen Parallel.For(0, screen.height, (y) => { Parallel.For(0, screen.width, (x) => { var color = new Vector3(); //Black to begin with Vector2 ray_position = new Vector2(TransX(x), TransY(y)); //position on the screen //for each pixel loop over the light sources foreach (Light light in LightList) { //shoot a ray from each pixel to each existing light source var ray = new Ray(ray_position, light.position - ray_position); bool occluded = false; //loop over all primitives that are in the world foreach (IPrimitive p in PrimitiveList) { if (p.Intersect(ray)) { occluded = true; } } if (!occluded) { color += light.color * lightAttenuation(ray.t) * light.brightness; } } screen.Plot(x, y, ToRGB32(color)); }); }); }
public void Tick() { for (int i = 0; i < 512; i++) { for (int j = 0; j < 512; j++) { int location = j + i * 1024; float u = j / 512f; float v = i / 512f; Vector3 floatcolor = tracer.Render(u, v); int intcolor = getIntColor(floatcolor); screen.pixels[location] = intcolor; } } //Debug Screen for (int k = 512; k < 1024; k++) { for (int l = 0; l < 512; l++) { int location = k + l * 1024; screen.pixels[location] = 0; } } //Draws every sphere, including its own offset and a bonus offset, so that the spheres don't cling to the edges. //Color offset is a cheap solution to give the spheres a different color each time. foreach (Sphere sphere in tracer.scene.sphereList) { int intcolor = getIntColor(sphere.material.color); for (int theta = 0; theta < 360; theta++) { double xcord = sphere.rad * 5 * Math.Cos(theta); double ycord = sphere.rad * 5 * Math.Sin(theta); int offsetX = 5 * (int)sphere.spherePos.X; int offsetZ = 5 * (int)sphere.spherePos.Z * -1; screen.Plot((int)xcord + offsetX + 750, (int)ycord + offsetZ + 400, intcolor); } } //Draws the camera in the debug view screen.Plot((int)tracer.camera.cameraPos.X + 750, (int)tracer.camera.cameraPos.Z * -1 + 400, 0xff0000); foreach (Light light in tracer.scene.lightList) { screen.Plot((int)light.lightPos.X + 750, (int)light.lightPos.Z * -1 + 400, 0xcc66ff); } //Draws the primary rays in the debug view for (int i = 0; i < tracer.raylist.Count; i++) { float t = 50; foreach (Primitive prim in tracer.scene.sphereList) { Intersection intersect = prim.Intersect(tracer.raylist[i]); if (intersect != null) { if (intersect.distance < t) { t = intersect.distance; } } } float primOx = tracer.raylist[i].Origin.X; float primOz = tracer.raylist[i].Origin.Z; float primTx = (primOx + t * tracer.raylist[i].Direction.X) * 5; float primTz = (primOz + t * tracer.raylist[i].Direction.Z) * 5; screen.Line((int)primOx + 750, (int)primOz * -1 + 400, (int)primTx + 750, (int)primTz * -1 + 400, 0xffff00); } tracer.raylist.Clear(); //Draws a seperation line. screen.Line(512, 0, 512, 512, 0xff0000); app.MoveCam(tracer.camera); }
// TICK // Main application entry point: the template calls this function once per frame. public void Tick() { GL.Finish(); // start timer timer.Restart(); //Initiate work sizes long[] workSize = { pw, ph }; long[] workSize2 = { pw *ph }; //Set kernel arguments kernel.SetArgument(5, xoffset); kernel.SetArgument(6, yoffset); resolution = (int)(zoom * 512); long[] workSize3 = { resolution / 32, resolution }; kernel.SetArgument(7, resolution); // run the simulation, 1 step screen.Clear(0); if (GLinterop) { if (resolution != oldResolution) { image = new OpenCLImage <int>(ocl, resolution, resolution); oldResolution = resolution; } //set image as argument imageClearKernel.SetArgument(0, image); imageClearKernel.LockOpenGLObject(image.texBuffer); imageClearKernel.Execute(workSize3); imageClearKernel.UnlockOpenGLObject(image.texBuffer); //lock image object kernel.SetArgument(0, image); kernel.LockOpenGLObject(image.texBuffer); //run kernel kernel.Execute(workSize); //unlock image object kernel.UnlockOpenGLObject(image.texBuffer); secondKernel.Execute(workSize2); } else { kernel.SetArgument(0, buffer); for (int i = 0; i < buffer.Length; i++) { buffer[i] = 0; } buffer.CopyToDevice(); kernel.Execute(workSize); secondKernel.Execute(workSize2); buffer.CopyFromDevice(); for (uint y = 0; y < screen.height; y++) { for (uint x = 0; x < screen.width; x++) { screen.Plot(x, y, buffer[x + y * 512]); } } } // visualize current state // report performance Console.WriteLine("generation " + generation++ + ": " + timer.ElapsedMilliseconds + "ms"); //Console.ReadLine(); }
// Render: renders one frame public void Render() { screen.Clear(0); Vector3 Color; //render screens for (int y = 0; y < screen.height; y++) { for (int x = 0; x < screen.width; x++) { //Create primary ray Ray ray; ray.t = 30; ray.O = camera.CamPos; ray.D = screen.pos0 + (x * ((screen.pos1 - screen.pos0) / 512.0f)) + (y * ((screen.pos2 - screen.pos0) / 512.0f)); //ray normalized direction ray.D = (ray.D - camera.CamPos).Normalized(); Intersection nearest = null; Intersection nearestref = null; foreach (Primitive p in prims) { Intersection overr = p.Intersection(ref ray); if (overr != null) { nearest = overr; } } // if there is an intersection, create a shadow ray if (nearest != null) { //Check if the material is reflective if (nearest.isMirror == false) { Color = CastShadowRay(nearest); } else { Color = CastShadowRay(nearest) * (1 - recursive / 100); //Create reflection ray Ray reflectionRay; reflectionRay.D = ray.D - 2 * nearest.N * (Vector3.Dot(ray.D, nearest.N)); reflectionRay.O = nearest.I + reflectionRay.D * 0.0001f; reflectionRay.t = 300; foreach (Primitive p in prims) { Intersection overr = p.Intersection(ref reflectionRay); if (overr != null) { nearestref = overr; } } Vector3 Color2 = Vector3.Zero; if (nearestref != null) { //check if the nearest reflected object is reflective to if (nearestref.isMirror) { if (recursive != 100) { Color2 = CastShadowRay(nearestref) * (recursive / 100.0f); } } else { Color2 = CastShadowRay(nearestref) * (recursive / 100.0f); } } else { Color2 = Vector3.Zero; } Color = Color + Color2; //draw reflectionrays on debug screen. if (x % 20 == 0 && y == screen.height / 2) { screenDebug.Line(CordxTrans(reflectionRay.O.X), CordzTrans(reflectionRay.O.Z), CordxTrans(reflectionRay.D.X * ray.t), CordzTrans(reflectionRay.D.Z * ray.t), 0xff00ff); } } } else { Color = Vector3.Zero; } //plot the correct color on the correct pixel screen.Plot(x, y, Color); //Draw 1 in 10 rays on the debugscreen if (x % 20 == 0 && y == screen.height / 2) { screenDebug.Line(CordxTrans(camera.CamPos.X), CordzTrans(camera.CamPos.Z), CordxTrans(ray.D.X * ray.t + camera.CamPos.X), CordzTrans(ray.D.Z * ray.t + camera.CamPos.Z), 0xffff00); } } } //Draw Debug screen //Draw line between screen and debug screen screenDebug.Line(0, 0, 0, 1024, 0xffffff); //Draw camera as 2 orange lines screenDebug.Line(CordxTrans(camera.CamPos.X) - 5, CordzTrans(camera.CamPos.Y) - 1, CordxTrans(camera.CamPos.X) + 5, CordzTrans(camera.CamPos.Y) - 1, 0xffa500); screenDebug.Line(CordxTrans(camera.CamPos.X) - 5, CordzTrans(camera.CamPos.Y) + 1, CordxTrans(camera.CamPos.X) + 5, CordzTrans(camera.CamPos.Y) + 1, 0xffa500); //Draw screen as a blue line screenDebug.Line(CordxTrans(screen.pos1.X), CordzTrans(screen.pos1.Z), CordxTrans(screen.pos2.X), CordzTrans(screen.pos2.Z), 0x00ffff); //Draw spheres var sphere1 = GetSphere1; screenDebug.DrawSphere(sphere1); var sphere2 = GetSphere2; screenDebug.DrawSphere(sphere2); var sphere3 = GetSphere3; screenDebug.DrawSphere(sphere3); }
// tick: renders one frame public void Tick() { screen.Clear(0); //move the lights if (dir % 2 == 0) { lightbuffer[0] += TW(0.1f); lightbuffer[5] -= TW(0.1f); lightbuffer[11] += TW(0.1f); lightbuffer[16] -= TW(0.1f); } else { lightbuffer[0] -= TW(0.1f); lightbuffer[5] += TW(0.1f); lightbuffer[11] -= TW(0.1f); lightbuffer[16] += TW(0.1f); } if (TW(worldsize) < lightbuffer[0] || lightbuffer[0] < TX(-worldsize)) { dir++; } Thread t1 = new Thread(() => { plot(TX((-worldsize + (0f / 8f * worldsize * 2))), TX((-worldsize + (1f / 8f * worldsize * 2)))); }); Thread t2 = new Thread(() => { plot(TX((-worldsize + (1f / 8f * worldsize * 2))), TX((-worldsize + (2f / 8f * worldsize * 2)))); }); Thread t3 = new Thread(() => { plot(TX((-worldsize + (2f / 8f * worldsize * 2))), TX((-worldsize + (3f / 8f * worldsize * 2)))); }); Thread t4 = new Thread(() => { plot(TX((-worldsize + (3f / 8f * worldsize * 2))), TX((-worldsize + (4f / 8f * worldsize * 2)))); }); Thread t5 = new Thread(() => { plot(TX((-worldsize + (4f / 8f * worldsize * 2))), TX((-worldsize + (5f / 8f * worldsize * 2)))); }); Thread t6 = new Thread(() => { plot(TX((-worldsize + (5f / 8f * worldsize * 2))), TX((-worldsize + (6f / 8f * worldsize * 2)))); }); Thread t7 = new Thread(() => { plot(TX((-worldsize + (6f / 8f * worldsize * 2))), TX((-worldsize + (7f / 8f * worldsize * 2)))); }); Thread t8 = new Thread(() => { plot(TX((-worldsize + (7f / 8f * worldsize * 2))), (TX((-worldsize + (8f / 8f * worldsize * 2)))) - 1); }); tarr[0] = t1; tarr[1] = t2; tarr[2] = t3; tarr[3] = t4; tarr[4] = t5; tarr[5] = t6; tarr[6] = t7; tarr[7] = t8; for (int td = 0; td < tarr.Length; td++) { tarr[td].Start(); } for (int td = 0; td < tarr.Length; td++) { tarr[td].Join(); } for (int i = 0; i < (screen.width - 1); i++) { for (int j = 0; j < (screen.height - 1); j++) { screen.Plot(i, j, MixColor(MathHelper.Clamp(floatbuffer[i, j][0], 0, 1), MathHelper.Clamp(floatbuffer[i, j][1], 0, 1), MathHelper.Clamp(floatbuffer[i, j][2], 0, 1))); } } primitivesDraw(); }
// initialize public void Init() { float[] aax = { 0, 0.5f, 0, 0.5f }; float[] aay = { 0, 0, 0.5f, 0.5f }; light = new List <Circle>(); circles = new List <Circle>(); squares = new List <Square>(); circles.Add(new Circle(0.3f, 0.1f, 0.1f, false, new floatColour(0, 0, 0))); circles.Add(new Circle(-0.3f, 0.5f, 0.1f, false, new floatColour(0, 0, 0))); squares.Add(new Square(-0.3f, -0.3f, 0.2f, new floatColour(0, 0, 0))); light.Add(new Circle(0f, 0.5f, 0.25f, true, new floatColour(1, 0, 1))); light.Add(new Circle(-0.2f, 0.2f, 0.25f, true, new floatColour(0, 1, 0))); light.Add(new Circle(0.2f, -0.4f, 0.25f, true, new floatColour(0, 0, 1))); ray = new Ray(); for (int x = 0; x < screen.width; x++) { for (int y = 0; y < screen.height; y++) { floatColour[] pixelColour = { new floatColour(0, 0, 0), new floatColour(0, 0, 0), new floatColour(0, 0, 0), new floatColour(0, 0, 0) }; foreach (Circle c in light) { for (int k = 0; k < 4; k++) { ray.O = pixelPosition(x + aax[k], y + aay[k]); ray.D = (new Vector2(ray.O.X - c.x, ray.O.Y - c.y)).Normalized(); ray.t = (float)Math.Sqrt(Math.Pow(ray.O.X - c.x, 2) + Math.Pow(ray.O.Y - c.y, 2)); bool occluded = false; foreach (Circle p in circles) { if ((Math.Pow(ray.O.X - p.x, 2) + Math.Pow(ray.O.Y - p.y, 2)) > (p.r * p.r)) { if (ray.intersection(p)) { occluded = true; float tmp = (float)Math.Sqrt((Math.Pow(c.x - p.x, 2) + Math.Pow(c.y - p.y, 2))); if (ray.t < tmp && (ray.t > 0 && tmp > 0)) { occluded = false; } tmp = (float)Math.Sqrt((Math.Pow(ray.O.X - p.x, 2) + Math.Pow(ray.O.Y - p.y, 2))); if (ray.t < tmp) { occluded = false; } } } else { occluded = true; pixelColour[k] = new floatColour(0, 0, 0); } } foreach (Square p in squares) { if (ray.intersection2(p)) { occluded = true; float tmp = (float)Math.Sqrt((Math.Pow(ray.O.X - (p.x + p.s), 2) + Math.Pow(ray.O.Y - (p.y + p.s), 2))); if (ray.t < tmp) { occluded = false; } } } if (!occluded) { pixelColour[k] += c.colour * lightAttenuation(Vector2.Distance(ray.O, new Vector2(c.x, c.y)), c.r); } } } screen.Plot(x, y, ((pixelColour[0] + pixelColour[1] + pixelColour[2] + pixelColour[3]) / 4.0f).ToRGB32()); } } }
// tick: renders one frame public void Tick() { for (int i = 0; i < _lights.Length; i++) { _lights[i].Location = Tools.MoveUp(0.05f, _lights[i].Location); } Parallel.For(0, (screen.width + 1) * (screen.height + 1), k => { int x = k % (screen.width + 1); int y = k / (screen.width + 1); float tx = (float)2 * x / (screen.width + 1) - 1; float ty = -((float)2 * y / (screen.height + 1) - 1); Vector2 location = new Vector2(tx, ty); Vector3 pixelColor = new Vector3(0, 0, 0); if (location.LengthSquared() < 1) { for (int i = 0, im = _lights.Length; i < im; i++) { Light light = _lights[i]; Ray ray = new Ray(location, Tools.Project(light.Location)); bool occluded = false; float shade = 0; for (int j = 0, jm = _primitives.Length; !occluded && j < jm; j++) { if (_primitives[j].Intersects(ray, out bool locked)) { occluded = true; shade *= locked ? 0 : 0.5f; } } if (!occluded) { shade = LightAttenuation(ray.Distance); } pixelColor += light.Color * shade; } } preBlend[x, y] = pixelColor; }); // blend! Parallel.For(0, screen.height * screen.width, k => { int x = k % screen.width; int y = k / screen.width; Vector3 pixelColor = new Vector3(0, 0, 0); pixelColor += preBlend[x, y]; pixelColor += preBlend[x + 1, y]; pixelColor += preBlend[x, y + 1]; pixelColor += preBlend[x + 1, y + 1]; pixelColor /= 4; screen.Plot(x, y, MixColor(pixelColor)); }); /* * Ray ray2 = new Ray(new Vector2(0, 0.25f), new Vector2(0.25f, 0)); * screen.Box(500 - 2, 400 - 2, 500 + 2, 400 + 2, MixColor(new Vector3(0, 0, 255))); * screen.Box(400 - 2, 300 - 2, 400 + 2, 300 + 2, MixColor(new Vector3(0, 0, 255))); * ray2.Draw(screen); * Console.WriteLine(_primitives[0].Intersects(ray2, out bool temp)); */ }