Exemple #1
0
    // 在p1处开始画, p2p3是水平线, yStep为-1表示往下
    void DrawTriangleInner(MyShaderBase obj, ShaderParameters shaderParams, ShaderSemantic p1, ShaderSemantic p2, ShaderSemantic p3, int yStep)
    {
        float x1 = p1.SV_POSITION.x;
        int   y1 = (int)p1.SV_POSITION.y;
        float x2 = p2.SV_POSITION.x;
        int   y2 = (int)p2.SV_POSITION.y;
        float x3 = p3.SV_POSITION.x;
        float y3 = p3.SV_POSITION.y;

        float m1 = (y1 - y2) / (x1 - x2); // 直线p1p2: y - y1 = m1*(x - x1), m1 = (y1-y2)/(x1-x2)
        float m2 = (y1 - y3) / (x1 - x3); // 直线p1p3: y - y1 = m2*(x - x1), m2 = (y1-y3)/(x1-x3)

        var type = p1.GetType();

        for (int y = y1; y != y2;)
        {
            // scan line
            float          xl         = (y - y1) / m1 + x1;
            float          leftWeight = (xl - x1) / (x2 - x1);
            ShaderSemantic left       = ShaderSemantic.CreateInstance(type);
            left.Lerp(p1, p2, leftWeight);

            float          xr          = (y - y1) / m2 + x1;
            float          rightWeight = (xr - x1) / (x3 - x1);
            ShaderSemantic right       = ShaderSemantic.CreateInstance(type);
            right.Lerp(p1, p3, Mathf.Abs(rightWeight));

            DrawLine(obj, shaderParams, left, right);
            y += yStep;
        }
    }
Exemple #2
0
    void DrawLine(MyShaderBase obj, ShaderParameters shaderParams, ShaderSemantic p1, ShaderSemantic p2)
    {
        int x1 = (int)p1.SV_POSITION.x;
        int y1 = (int)p1.SV_POSITION.y;
        int x2 = (int)p2.SV_POSITION.x;
        int y2 = (int)p2.SV_POSITION.y;

        // 令x1 < x2 && 0 < abs(dy) < dx
        bool isSteep = Mathf.Abs(y2 - y1) > Mathf.Abs(x2 - x1);

        if (isSteep)
        {
            MyUtility.Swap(ref x1, ref y1);
            MyUtility.Swap(ref x2, ref y2);
        }
        if (x1 > x2)
        {
            MyUtility.Swap(ref x1, ref x2);
            MyUtility.Swap(ref y1, ref y2);
        }

        int dy = System.Math.Abs(y2 - y1);
        int dx = x2 - x1;

        if (dy == 0 && dx == 0)
        {
            return;
        }
        int slope_err = dy - dx;
        int ystep     = (y1 < y2) ? 1 : -1;
        var type      = p1.GetType();

        for (int x = x1, y = y1; x <= x2; x++)
        {
            int _x = isSteep ? y : x;
            int _y = isSteep ? x : y;
            if (_x > 0 && _x < tex.width && _y > 0 && _y < tex.height)
            {
                ShaderSemantic v2f = ShaderSemantic.CreateInstance(type);
                float          w   = ((float)x - x1) / (x1 - x2);
                v2f.Lerp(p1, p2, Mathf.Abs(w));
                var color = obj.PixelShader(v2f, shaderParams);
                renderBuffer.Update(obj, _x, _y, v2f, color);
            }
            slope_err += dy;
            if (slope_err >= 0)
            {
                slope_err -= dx;
                y         += ystep;
            }
        }
    }
Exemple #3
0
    void DrawCall(MyShaderBase obj, Mesh mesh)
    {
        var   vertices     = mesh.vertices;
        var   triangles    = mesh.triangles;
        float screenWidth  = MyCamera.pixelWidth;
        float screenHeight = MyCamera.pixelHeight;
        var   far          = MyCamera.farClipPlane;
        var   near         = MyCamera.nearClipPlane;
        float w            = screenWidth / 2;
        float h            = screenHeight / 2;
        var   shaderParams = new ShaderParameters(obj.transform, MyCamera);

        ShaderSemantic[] appFullData = new ShaderSemantic[vertices.Length];
        for (int i = 0; i < vertices.Length; i++)
        {
            var appdata = (ShaderSemantic)System.Activator.CreateInstance(obj.CastType);
            var p       = vertices[i];
            appdata.POSITION  = new Vector4(p.x, p.y, p.z, 1);
            appdata.NORMAL    = mesh.normals[i];
            appdata.TANGENT   = mesh.tangents[i];
            appdata.TEXCOORD0 = mesh.uv[i];
            appFullData[i]    = appdata;
        }

        // vertex shader
        for (int i = 0; i < vertices.Length; i++)
        {
            var appdata = appFullData[i];
            // vertex shader: local space -> world space -> view space -> clip space
            ShaderSemantic v2f = obj.VertexShader(appdata, shaderParams);
            var            p   = v2f.SV_POSITION;

            // homogeneous divide: clip space -> NDC[-1, 1]
            p            = new Vector4(p.x / p.w, p.y / p.w, p.z / p.w, 1);
            v2f.POSITION = p;

            // NDC -> screen space (window space) https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN#direct3d-9-vpos-and-direct3d-10-sv_position
            v2f.SV_POSITION = new Vector3(p.x * w + w, p.y * h + h, (far - near) * p.z / 2 + (far + near) / 2);
            appFullData[i]  = v2f;
        }

        // pixel shader
        if (shadingMode == ShadingMode.Wireframe)
        {
            Wireframe(obj, shaderParams, mesh, appFullData); // Wireframe
        }
        else
        {
            Shaded(obj, shaderParams, mesh, appFullData);    // Shaded
        }
    }
Exemple #4
0
    void DrawTriangle(MyShaderBase obj, ShaderParameters shaderParams, ShaderSemantic p1, ShaderSemantic p2, ShaderSemantic p3)
    {
        // 令 y1 ≥ y2 ≥ y3
        if (p2.SV_POSITION.y <= p3.SV_POSITION.y)
        {
            MyUtility.Swap(ref p2, ref p3);
        }
        if (p1.SV_POSITION.y <= p2.SV_POSITION.y)
        {
            MyUtility.Swap(ref p2, ref p1);
        }
        if (p2.SV_POSITION.y < p3.SV_POSITION.y)
        {
            MyUtility.Swap(ref p2, ref p3);
        }

        float y1 = p1.SV_POSITION.y; // A.y
        float y3 = p3.SV_POSITION.y; // C.y

        /*  将三角形在B点水平x轴切开上下两部分分开画:
         *  BM为水平直线, M在AC线上
         *  直线AC: y - y1 = m * (x - x1), 其中m = (y1-y3) / (x1-x3)
         *  将xy互换: x - x1 = m * (y - y1), 其中m = (x1-x3) / (y1-y3)
         *  已知: B.y == M.y(M_y), 求M.x 即(M_x)
         *      得: x = m * (y - y1) + x1
         */
        float          M_y = p2.SV_POSITION.y;
        ShaderSemantic M   = ShaderSemantic.CreateInstance(p1.GetType());
        float          w   = (M_y - y1) / (y3 - y1);

        M.Lerp(p1, p3, Mathf.Abs(w));

        // B和M的顺序 由x坐标确定
        ShaderSemantic Left  = p2.SV_POSITION.x < M.SV_POSITION.x ? p2 : M;
        ShaderSemantic Right = p2.SV_POSITION.x < M.SV_POSITION.x ? M : p2;

        DrawTriangleInner(obj, shaderParams, p1, Left, Right, -1); // draw 🔺ABM
        DrawTriangleInner(obj, shaderParams, p3, Left, Right, +1); // draw 🔺CBM
        DrawLine(obj, shaderParams, Left, Right);                  // draw line BM

        // debug

        /*
         * DrawPoint((int)p1.SV_POSITION.x, (int)p1.SV_POSITION.y, p1.COLOR);
         * DrawPoint((int)p3.SV_POSITION.x, (int)p3.SV_POSITION.y, p3.COLOR);
         * DrawPoint((int)M.SV_POSITION.x, (int)M.SV_POSITION.y, M.COLOR);
         * DrawPoint((int)p2.SV_POSITION.x, (int)p2.SV_POSITION.y, p2.COLOR);
         */
    }
Exemple #5
0
    void Wireframe(MyShaderBase obj, ShaderParameters shaderParams, Mesh mesh, ShaderSemantic[] appFullData)
    {
        var            triangles = mesh.triangles;
        ShaderSemantic last      = null;

        for (int i = 0; i < triangles.Length; i++)
        {
            var v2f = appFullData[triangles[i]];
            v2f.COLOR = Color.white;
            if (i > 0 && i % 3 != 0)
            {
                DrawLine(obj, shaderParams, last, v2f);
            }
            last = v2f;
        }
    }
Exemple #6
0
    void Shaded(MyShaderBase obj, ShaderParameters shaderParams, Mesh mesh, ShaderSemantic[] appFullData)
    {
        var triangles = mesh.triangles;

        for (int i = 0; i < triangles.Length; i += 3)
        {
            ShaderSemantic p1 = appFullData[triangles[i]];
            ShaderSemantic p2 = appFullData[triangles[i + 1]];
            ShaderSemantic p3 = appFullData[triangles[i + 2]];

            //outline debug
            //DrawLine(obj, shaderParams, p1, p2);
            //DrawLine(obj, shaderParams, p2, p3);
            //DrawLine(obj, shaderParams, p3, p1);

            // debug color
            p1.COLOR = Color.red;
            p2.COLOR = Color.green;
            p3.COLOR = Color.blue;

            DrawTriangle(obj, shaderParams, p1, p2, p3);
            //break; // debug
        }
    }
Exemple #7
0
    public void Update(MyShaderBase obj, int x, int y, ShaderSemantic v2f, Color outputColor)
    {
        if (!DepthTest(x, y, v2f))
        {
            return;
        }

        var newDepth = v2f.POSITION.z;
        var oldDepth = GetDepth(x, y);

        switch (obj.Commands.ZWrite)
        {
        case ZWrite.On:
            switch (obj.Commands.ZTest)
            {
            case ZTest.Less:
                if (newDepth < oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.LEqual:

                if (newDepth <= oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.Equal:
                if (newDepth == oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.GEqual:
                if (newDepth >= oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.Greater:
                if (newDepth > oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.NotEqual:
                if (newDepth != oldDepth)
                {
                    SetDepth(x, y, newDepth);
                    SetColor(x, y, outputColor);
                }
                break;

            case ZTest.Always:
                SetDepth(x, y, newDepth);
                SetColor(x, y, outputColor);
                break;
            }
            break;

        case ZWrite.Off:
            break;

        default:
            break;
        }
    }