/// <summary> /// Computes the premultiplied value of specified color /// </summary> /// <param name="color">Color value</param> /// <returns></returns> public static Color Premultiply(Color color) { return(new Color(Color4.Premultiply(color.RawColor))); }
private void RasterizeTriangle(Triangle <TPixelShaderInput> tri, MemoryResources resources, IPixelShader <TPixelShaderInput> pixelShader, OutputMerger outputMerger, int outputWidth, int outputHeight, Color4[,] colorBuffer, float[,] wBuffer) { var posA = tri.A.TransformedPosition; var posB = tri.B.TransformedPosition; var posC = tri.C.TransformedPosition; var bitmapCoordA = MapNdcToScreen(posA.X, posA.Y, outputWidth, outputHeight); var bitmapCoordB = MapNdcToScreen(posB.X, posB.Y, outputWidth, outputHeight); var bitmapCoordC = MapNdcToScreen(posC.X, posC.Y, outputWidth, outputHeight); // Triangle bounds (in [-1, 1] space) var boundsLeft = Math.Min(bitmapCoordA.X, Math.Min(bitmapCoordB.X, bitmapCoordC.X)); var boundsTop = Math.Min(bitmapCoordA.Y, Math.Min(bitmapCoordB.Y, bitmapCoordC.Y)); var boundsRight = Math.Max(bitmapCoordA.X, Math.Max(bitmapCoordB.X, bitmapCoordC.X)); var boundsBottom = Math.Max(bitmapCoordA.Y, Math.Max(bitmapCoordB.Y, bitmapCoordC.Y)); if (boundsLeft == boundsRight || boundsTop == boundsBottom) { return; } for (var j = boundsTop; j <= boundsBottom; ++j) { if (j < 0 || outputHeight <= j) { continue; } for (var i = boundsLeft; i <= boundsRight; ++i) { if (i < 0 || outputWidth <= i) { continue; } if (!Helper.PointInTriangle(new Point(i, j), bitmapCoordA, bitmapCoordB, bitmapCoordC)) { continue; } var pixCoord = MapScreenToNdc(i, j, outputWidth, outputHeight); var interpolated = InterpolatePoint(tri.A, tri.B, tri.C, pixCoord, out var outOfRange); //if (outOfRange) { // continue; //} var pos = interpolated.TransformedPosition; if (pos.Z < -1 || 1 < pos.Z || pos.Y < -1 || 1 < pos.Y || pos.X < -1 || 1 < pos.X) { continue; } var depthTestPassed = outputMerger.IsDepthTestPassed(pos.W, wBuffer[i, j]); if (!depthTestPassed && colorBuffer[i, j].Alpha.Equals(1)) { continue; } var pixel = pixelShader.Transform(resources, interpolated, out var discarded); if (discarded) { continue; } pixel = Color4.Premultiply(pixel); if (depthTestPassed) { wBuffer[i, j] = pos.W; colorBuffer[i, j] = outputMerger.Blend(colorBuffer[i, j], pixel); } else if (colorBuffer[i, j].Alpha < 1) { colorBuffer[i, j] = outputMerger.Blend(pixel, colorBuffer[i, j]); } } } }