예제 #1
0
 /// <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)));
 }
예제 #2
0
        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]);
                    }
                }
            }
        }