예제 #1
0
        public static void DrawBlock(ref T shader, ref TriangleEquations eqn, int x, int y, bool TestEdges)
        {
            float xf = x + 0.5f;
            float yf = y + 0.5f;

            PixelData po = new PixelData();

            po.Init(ref eqn, xf, yf, shader.AVarCount, shader.PVarCount, shader.InterpolateZ, shader.InterpolateW);

            EdgeData eo = new EdgeData();

            if (TestEdges)
            {
                eo.init(ref eqn, xf, yf);
            }

            for (int yy = y; yy < y + Constants.BlockSize; yy++)
            {
                PixelData pi = CopyPixelData(ref shader, ref po);

                EdgeData ei = new EdgeData();
                if (TestEdges)
                {
                    ei = eo;
                }

                for (int xx = x; xx < x + Constants.BlockSize; xx++)
                {
                    if (!TestEdges || ei.test(ref eqn))
                    {
                        pi.x = xx;
                        pi.y = yy;
                        shader.DrawPixel(ref pi);
                    }

                    pi.StepX(ref eqn, shader.AVarCount, shader.PVarCount, shader.InterpolateZ, shader.InterpolateW);
                    if (TestEdges)
                    {
                        ei.stepX(ref eqn);
                    }
                }

                po.StepY(ref eqn, shader.AVarCount, shader.PVarCount, shader.InterpolateZ, shader.InterpolateW);
                if (TestEdges)
                {
                    eo.stepY(ref eqn);
                }
            }
        }
예제 #2
0
            public void DrawTriangleBlockTemplate(ref RasterizerVertex v0, ref RasterizerVertex v1, ref RasterizerVertex v2)
            {
                // Compute triangle equations.
                TriangleEquations eqn = new TriangleEquations(ref v0, ref v1, ref v2, shader.AVarCount, shader.PVarCount);

                // Check if triangle is backfacing.
                if (eqn.area2 <= 0)
                {
                    return;
                }

                // Compute triangle bounding box.
                int minX = (int)Math.Min(Math.Min(v0.x, v1.x), v2.x);
                int maxX = (int)Math.Max(Math.Max(v0.x, v1.x), v2.x);
                int minY = (int)Math.Min(Math.Min(v0.y, v1.y), v2.y);
                int maxY = (int)Math.Max(Math.Max(v0.y, v1.y), v2.y);

                // Clip to scissor rect.
                minX = Math.Max(minX, rasterizer.m_minX);
                maxX = Math.Min(maxX, rasterizer.m_maxX);
                minY = Math.Max(minY, rasterizer.m_minY);
                maxY = Math.Min(maxY, rasterizer.m_maxY);

                // Round to block grid.
                minX &= ~(Constants.BlockSize - 1);
                maxX &= ~(Constants.BlockSize - 1);
                minY &= ~(Constants.BlockSize - 1);
                maxY &= ~(Constants.BlockSize - 1);

                float s = Constants.BlockSize - 1;

                int stepsX = (maxX - minX) / Constants.BlockSize + 1;
                int stepsY = (maxY - minY) / Constants.BlockSize + 1;

                for (int i = 0; i < stepsX * stepsY; ++i)
                {
                    int sx = i % stepsX;
                    int sy = i / stepsX;

                    // Add 0.5 to sample at pixel centers.
                    int x = minX + sx * Constants.BlockSize;
                    int y = minY + sy * Constants.BlockSize;

                    float xf = x + 0.5f;
                    float yf = y + 0.5f;

                    // Test if block is inside or outside triangle or touches it.
                    EdgeData e00 = new EdgeData(); e00.init(ref eqn, xf, yf);
                    EdgeData e01 = e00; e01.stepY(ref eqn, s);
                    EdgeData e10 = e00; e10.stepX(ref eqn, s);
                    EdgeData e11 = e01; e11.stepX(ref eqn, s);

                    bool e00_0 = eqn.e0.test(e00.ev0), e00_1 = eqn.e1.test(e00.ev1), e00_2 = eqn.e2.test(e00.ev2), e00_all = e00_0 && e00_1 && e00_2;
                    bool e01_0 = eqn.e0.test(e01.ev0), e01_1 = eqn.e1.test(e01.ev1), e01_2 = eqn.e2.test(e01.ev2), e01_all = e01_0 && e01_1 && e01_2;
                    bool e10_0 = eqn.e0.test(e10.ev0), e10_1 = eqn.e1.test(e10.ev1), e10_2 = eqn.e2.test(e10.ev2), e10_all = e10_0 && e10_1 && e10_2;
                    bool e11_0 = eqn.e0.test(e11.ev0), e11_1 = eqn.e1.test(e11.ev1), e11_2 = eqn.e2.test(e11.ev2), e11_all = e11_0 && e11_1 && e11_2;

                    int result = (e00_all ? 1 : 0) + (e01_all ? 1 : 0) + (e10_all ? 1 : 0) + (e11_all ? 1 : 0);

                    // Potentially all out.
                    if (result == 0)
                    {
                        // Test for special case.
                        bool e00Same = e00_0 == e00_1 == e00_2;
                        bool e01Same = e01_0 == e01_1 == e01_2;
                        bool e10Same = e10_0 == e10_1 == e10_2;
                        bool e11Same = e11_0 == e11_1 == e11_2;

                        if (!e00Same || !e01Same || !e10Same || !e11Same)
                        {
                            shader.DrawBlock(ref eqn, x, y, true);
                        }
                    }
                    else if (result == 4)
                    {
                        // Fully Covered.
                        shader.DrawBlock(ref eqn, x, y, false);
                    }
                    else
                    {
                        // Partially Covered.
                        shader.DrawBlock(ref eqn, x, y, true);
                    }
                }
            }