Exemple #1
0
        bool FrontEndCullingByArea(VSOutput v0, VSOutput v1, VSOutput v2)
        {
            if (context.frontEndCull == FrontEndCull.Off)
            {
                return(true);
            }
            if (context.cullMode == CullMode.None)
            {
                return(true);
            }
            //cull back
            Vector2 p0 = new Vector2(v0.position.X, v0.position.Y);
            Vector2 p1 = new Vector2(v1.position.X, v1.position.Y);
            Vector2 p2 = new Vector2(v2.position.X, v2.position.Y);

            //做了透射除法,Culling准确点
            p0 *= 1 / v0.position.W;
            p1 *= 1 / v1.position.W;
            p2 *= 1 / v2.position.W;

            float area = Rasterizer.EdgeFunction(p0, p1, p2);

            //在Clip Space, area >= 0表示顺时针
            if (context.winding == Winding.Clockwise)
            {
                return(area > 0);
            }
            return(area < 0);
        }
Exemple #2
0
        //裁剪前
        public void DrawTriangle(VSOutput vClip0, VSOutput vClip1, VSOutput vClip2)
        {
            //Backface Culling
            if (!FrontEndCulling(vClip0, vClip1, vClip2))
            {
                return;
            }
            context.statics.triangleCount += 1;
            //Clipping
            List <VSOutput> inputs = new List <VSOutput> {
                vClip0, vClip1, vClip2
            };
            List <VSOutput> outputs = Clipping.Clip(inputs, context);

            //输出结果是trianglefan
            if (outputs.Count < 3)
            {
                //全裁剪掉了
                return;
            }

            //画Triangle Fan
            VSOutput v0    = outputs[0];
            VSOutput vNDC0 = Rasterizer.PerspectiveDivide(v0);

            if (vNDC0 == null)
            {
                return;
            }
            VSOutput vScreen0 = rasterizer.ViewportTransform(vNDC0);

            for (int i = 1; i + 1 < outputs.Count; i += 1)
            {
                VSOutput v1    = outputs[i];
                VSOutput v2    = outputs[i + 1];
                VSOutput vNDC1 = Rasterizer.PerspectiveDivide(v1);
                VSOutput vNDC2 = Rasterizer.PerspectiveDivide(v2);
                if (vNDC1 == null || vNDC2 == null)
                {
                    continue;
                }
                VSOutput vScreen1 = rasterizer.ViewportTransform(vNDC1);
                VSOutput vScreen2 = rasterizer.ViewportTransform(vNDC2);
                //检查Backface
                if (i == 1)
                {
                    //由于裁剪前后的三角形都在同一个平面上,所以只要检查第一个就够了
                    if (!BackfaceCulling(vScreen0, vScreen1, vScreen2))
                    {
                        return;
                    }
                }

                context.statics.rasterTriCount += 1;
                rasterizer.RasterizeTriangle(vScreen0, vScreen1, vScreen2);
            }
        }
Exemple #3
0
        //初始化
        void Init(Graphics g)
        {
            InitByGraphics(g);
            //初始化Frame Buffer
            RectangleF rect      = graphics.VisibleClipBounds;
            Size       frameSize = new Size((int)rect.Width, (int)rect.Height);

            context    = new Context(frameSize);
            rasterizer = new Rasterizer(context);
            camera     = new Camera();
        }
Exemple #4
0
        public void Test_BarycentricRasterizeTriangle()
        {
            context.clearColor = Color.White;
            Clear();
            //假设n = 1, far = 2
            //测试光栅化和插值
            //第一个三角形,v0红色在中上,v1绿和v2蓝在中间的左右,v0在far plane, v1,v2在near plane
            VSOutput v0 = new VSOutput();

            v0.position = new Vector4(0f, 1f, 1f, 2f);
            v0.color    = new Vector4(1f, 0f, 0f, 1f);
            VSOutput v1 = new VSOutput();

            v1.position = new Vector4(-0.5f, -0.5f, -1f, 1f);
            v1.color    = new Vector4(0f, 1f, 0f, 1f);
            VSOutput v2 = new VSOutput();

            v2.position = new Vector4(0.5f, -0.5f, -1f, 1f);
            v2.color    = new Vector4(0f, 0f, 1f, 1f);

            v0 = Rasterizer.PerspectiveDivide(v0);
            v0 = rasterizer.ViewportTransform(v0);
            v1 = Rasterizer.PerspectiveDivide(v1);
            v1 = rasterizer.ViewportTransform(v1);
            v2 = Rasterizer.PerspectiveDivide(v2);
            v2 = rasterizer.ViewportTransform(v2);

            rasterizer.BarycentricRasterizeTriangle(v0, v1, v2);

            //测试depth test
            //第二个三角形,v0红在近平面,v1,v2在远
            v0.position = new Vector4(-0.5f, 0.5f, -1f, 1f);
            v1.position = new Vector4(-2f, -1f, 1f, 2f);
            v2.position = new Vector4(0f, -2f, 1f, 2f);
            v0          = Rasterizer.PerspectiveDivide(v0);
            v0          = rasterizer.ViewportTransform(v0);
            v1          = Rasterizer.PerspectiveDivide(v1);
            v1          = rasterizer.ViewportTransform(v1);
            v2          = Rasterizer.PerspectiveDivide(v2);
            v2          = rasterizer.ViewportTransform(v2);
            rasterizer.BarycentricRasterizeTriangle(v0, v1, v2);

            //第三个三角形,v1绿在近,其他在远平面
            v0.position = new Vector4(-2f, 0f, 1f, 2f);
            v1.position = new Vector4(-0.5f, -1f, -1f, 1f);
            v2.position = new Vector4(0f, -1f, 1f, 2f);
            v0          = Rasterizer.PerspectiveDivide(v0);
            v0          = rasterizer.ViewportTransform(v0);
            v1          = Rasterizer.PerspectiveDivide(v1);
            v1          = rasterizer.ViewportTransform(v1);
            v2          = Rasterizer.PerspectiveDivide(v2);
            v2          = rasterizer.ViewportTransform(v2);
            rasterizer.BarycentricRasterizeTriangle(v0, v1, v2);
        }
Exemple #5
0
        bool BackfaceCulling(VSOutput vScreen0, VSOutput vScreen1, VSOutput vScreen2)
        {
            if (context.cullMode == CullMode.None)
            {
                return(true);
            }
            if (context.frontEndCull == FrontEndCull.On)
            {
                return(true);
            }

            Vector2 p0 = new Vector2(vScreen0.posScreen.X, vScreen0.posScreen.Y);
            Vector2 p1 = new Vector2(vScreen1.posScreen.X, vScreen1.posScreen.Y);
            Vector2 p2 = new Vector2(vScreen2.posScreen.X, vScreen2.posScreen.Y);

            float area = Rasterizer.EdgeFunction(p0, p1, p2);

            if (context.winding == Winding.Clockwise)
            {
                return(area < 0);
            }
            //在Viewport Space, 由于Y轴向下, area > 0表示逆时针
            return(area > 0);
        }