protected override void Draw() { if (_activeProfile > -1) { _profiles[_activeProfile].Draw(); } else { SoftwareRasterizer.ClearBitmap(CurrentSwapchainBuffer, System.Drawing.Color.CornflowerBlue); } base.Draw(); }
void initializeResources() { _swapchainBuffers = new Bitmap[SWAPCHAIN_BUFFER_COUNT]; _depthBuffers = new float[SWAPCHAIN_BUFFER_COUNT][, ]; for (int i = 0; i < SWAPCHAIN_BUFFER_COUNT; i++) { _swapchainBuffers[i] = new Bitmap(800, 600); _depthBuffers[i] = new float[800, 600]; SoftwareRasterizer.ClearBitmap(_swapchainBuffers[i], Color.CornflowerBlue); SoftwareRasterizer.ClearDepth(_depthBuffers[i]); } }
public void Run(VertexIn[] vertexBuffer, int[] indexBuffer, CBuffer constantBuffer, Bitmap outputBuffer, float[,] depthBuffer) { TextureSampler sampler = new TextureSampler() { _pipeline = this }; //initialize variables if (verts == null || verts.Length == vertexBuffer.Length) { verts = new VertexData[vertexBuffer.Length]; } if (depthBuffer != null) { if (depthLock == null || depthLock.GetLength(0) != outputBuffer.Width || depthLock.GetLength(1) != outputBuffer.Height) { depthLock = new object[depthBuffer.GetLength(0), depthBuffer.GetLength(0)]; } for (int x = 0; x < outputBuffer.Width; x++) { for (int y = 0; y < outputBuffer.Height; y++) { depthLock[x, y] = new object(); } } } //Create tasks and process vertices; Parallel.For(0, vertexBuffer.Length, (i) => { verts[i] = VertexShader.VertexMain(vertexBuffer[i], in constantBuffer); verts[i].Position.Y = -verts[i].Position.Y; }); int size = outputBuffer.Width * outputBuffer.Height; BitmapData dat = outputBuffer.LockBits(new Rectangle(0, 0, 800, 600), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); byte[] colDat = new byte[size * 4]; Marshal.Copy(dat.Scan0, colDat, 0, colDat.Length); int width = outputBuffer.Width; int height = outputBuffer.Height; //Create tasks and process data to output pixels Parallel.For(0, indexBuffer.Length / 3, (i) => { int i1 = i * 3; //Assemble geometry and rasterize triangles List <FragmentData> frags = SoftwareRasterizer.Rasterize(verts[indexBuffer[i1]], verts[indexBuffer[i1 + 1]], verts[indexBuffer[i1 + 2]], height, width); Parallel.For(0, frags.Count, (j) => { //get fragment FragmentData frag = frags[j]; //get pixel color Vector4 pixel = FragmentShader.FragmentMain(frag, in sampler, in constantBuffer); //store coord into ints for speed int x = (int)frag.Position.X, y = (int)frag.Position.Y; //don't do depth test if no buffer is given if (depthBuffer == null) { lock (depthLock[x, y]) { int index = (y * width) + x; index *= 4; colDat[index] = (byte)(pixel.Z * 255); colDat[index + 1] = (byte)(pixel.Y * 255); colDat[index + 2] = (byte)(pixel.X * 255); colDat[index + 3] = (byte)(pixel.W * 255); } } else { //check depth buffer and set output if necessary //lock for thread safety lock (depthLock[x, y]) { //check if our pixel is nearer than nearest pixel previously drawn float depth = depthBuffer[x, y]; if (frag.Position.Z <= depth) { //if our pixel is closest, set depthbuffer to our depth depthBuffer[x, y] = frag.Position.Z; //set outputBuffer color int index = (y * width) + x; index *= 4; colDat[index] = (byte)(pixel.Z * 255); colDat[index + 1] = (byte)(pixel.Y * 255); colDat[index + 2] = (byte)(pixel.X * 255); colDat[index + 3] = (byte)(pixel.W * 255); } } } }); }); Marshal.Copy(colDat, 0, dat.Scan0, colDat.Length); outputBuffer.UnlockBits(dat); }