美文网首页
使用GL实现屏幕画线

使用GL实现屏幕画线

作者: 虫小白 | 来源:发表于2019-11-30 15:24 被阅读0次

    使用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();
        }
    

    效果:


    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();
        }
    

    效果图:


    01.PNG

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

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


    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();
        }
    
    效果图: 02.PNG

    相关文章

      网友评论

          本文标题:使用GL实现屏幕画线

          本文链接:https://www.haomeiwen.com/subject/fhcowctx.html