使用GL实现屏幕画线

使用GL画线非常简单,原理就是给定画线的起始位置。代码如下:

    public Material _mat;
    private void OnGUI()
    {
        DrawLine(new Vector2(0, 0), new Vector2(Screen.width, Screen.height));
    }

  //屏幕画线(宽度为1像素,无法修改)
    void DrawLine(Vector2 startPos, Vector2 endPos)
    {
        GL.PushMatrix();

        if (!_mat)
        {
            _mat = new Material(Shader.Find("Unlit/Color"));
        }

        _mat.SetPass(0);
        GL.LoadPixelMatrix();//按照像素画线

        GL.Begin(GL.LINES);
        GL.Vertex(startPos);
        GL.Vertex(endPos);

        GL.End();
        GL.PopMatrix();
    }

效果:


使用GL实现屏幕画线_第1张图片
03.PNG

进阶1:画有宽度的线,实际上是画矩形块,需给定矩形的四角的坐标值,代码如下:

//进阶1:屏幕画有宽度的线(实际为画矩形块)
void DrawLineWidth(Vector2 startPos, Vector2 endPos, float width)
    {
        GL.PushMatrix();

        if (!_mat)
        {
            _mat = new Material(Shader.Find("Unlit/Color"));
        }

        _mat.SetPass(0);

        Vector2 dir = endPos - startPos;
        Vector3 dir3 = new Vector3(dir.x, dir.y, 0);
        Vector3 dir_v = Vector3.Cross(Vector3.forward, dir3);
        Vector2 dir_v2 = new Vector2(dir_v.x, dir_v.y).normalized;

        GL.Begin(GL.QUADS);
        GL.LoadPixelMatrix();

        GL.Vertex(startPos + dir_v2 * 0.5f*width);
        GL.Vertex(endPos + dir_v2 * 0.5f*width);
        GL.Vertex(endPos - dir_v2 * 0.5f*width);
        GL.Vertex(startPos - dir_v2 * 0.5f*width);       

        GL.End();
        GL.PopMatrix();
    }

效果图:


使用GL实现屏幕画线_第2张图片
01.PNG

使用上面的方式画出来的线在边缘处很锐利、锯齿感很严重,分辨率越低越明显,可以通过为线条添加一张在边缘处渐变透明的贴图改善锯齿效果。

进阶2:为线条添加贴图和颜色
先准备一张贴图:


使用GL实现屏幕画线_第3张图片
Line.png

写一个支持透明贴图和可修改颜色的shader(该shader只会使用贴图的透明通道),如下:

Shader "Unlit/Line"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor("MainColor",color)=(1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent"}
        LOD 100

        zwrite off
        blend srcalpha oneminussrcalpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _MainColor;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return fixed4(_MainColor.rgb,col.a);
            }
            ENDCG
        }
    }
}

画线代码如下:

//进阶2:画有宽度的线并为其赋予颜色和贴图

void DrawLineWidthTex(Vector2 startPos, Vector2 endPos, float width, Color color)
    {
        GL.PushMatrix();

        if (!_mat)
        {
            _mat = new Material(Shader.Find("Unlit/Line"));
        }

        _mat.SetPass(0);
        _mat.SetColor("_MainColor", color);

        Vector2 dir = endPos - startPos;
        Vector3 dir3 = new Vector3(dir.x, dir.y, 0);
        Vector3 dir_v = Vector3.Cross(Vector3.forward, dir3);
        Vector2 dir_v2 = new Vector2(dir_v.x, dir_v.y).normalized;

        GL.Begin(GL.QUADS);
        GL.LoadPixelMatrix();

        GL.TexCoord(new Vector2(0, 1));//矩形左上角对应的uv坐标
        GL.Vertex(startPos + dir_v2 * 0.5f * width);
        GL.TexCoord(new Vector2(1, 1));//矩形右上角对应的uv坐标
        GL.Vertex(endPos + dir_v2 * 0.5f * width);
        GL.TexCoord(new Vector2(1, 0));//矩形右下角对应的uv坐标
        GL.Vertex(endPos - dir_v2 * 0.5f * width);
        GL.TexCoord(new Vector2(0, 0));//矩形左下角对应的uv坐标
        GL.Vertex(startPos - dir_v2 * 0.5f * width);

        GL.End();
        GL.PopMatrix();
    }

效果图:
使用GL实现屏幕画线_第4张图片
02.PNG

你可能感兴趣的:(使用GL实现屏幕画线)