问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

unity绘制虚线 geometry shader

发布网友 发布时间:2022-10-16 22:10

我来回答

1个回答

热心网友 时间:2023-10-24 16:36

绘制虚线其实简单。绘制线段,然后通过线段的uv坐标,设置虚线贴图就行。

或者用shader判断uv坐标决定好不要绘制线段的某一部分。

但是这样还是免不了要在CPU中计算好顶点和UV。如果线条数量很多(曲线),要经常更新线条。而且要修改条线的粗细,虚线的密度。那么为什么不把要显示的东西交给GPU呢?

CPU端直接用两个点就好了,也减少了CPU的计算量和额外的数据存储。

绘制线条的抗锯齿效果比绘制三角形抗锯齿效果要差一些

Shader "Unlit/geoline"

{

    Properties

    {

        _MainTex ("Texture", 2D) = "white" {}

        _LineColor("LineColor", color) = (0,1,0,1)//颜色

        _LineWidth("LineWidth",float) = 10//线宽

        _SingleSegmentLength("SingleSegmentLength",float) = 500//线段单元长度

        _SolidRatio("SolidRatio",float) = 0.5//绘制实线部分比率

    }

    SubShader

    {

        Cull Off

        Blend SrcAlpha OneMinusSrcAlpha

        Tags {"Queue"="Transparent"}

        LOD 100

        Pass

        {

            CGPROGRAM

            #pragma vertex vert

            #pragma geometry geo//几何着色器入口

            #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;

            float _LineWidth;

            float _SingleSegmentLength;

            float _SolidRatio;

            float4 _LineColor;

            [maxvertexcount(30)]//产生最大的顶点数,append到triStream的次数应该小于此。最大好像是64

            void geo(line appdata l[2], inout TriangleStream<v2f> triStream)

            {

                v2f pIn;

                v2f v[4];//先生成四个点,构造两个三角形

                float4 a = l[0].vertex;

                float4 b = l[1].vertex;

                float len = distance(b, a);

                float3 dir0 = normalize(b - a);

                float3 dir2 = normalize(cross(dir0, float3(0, 0, 1)));//加宽的方向

                float2 dir3 = dir2.xy * 0.5 * _LineWidth;

                v[0].vertex = UnityObjectToClipPos(a + float4(dir3, 0, 0));

                //使用的原来的世界坐标空间计算,完了后再映射为视图空间。如果是在顶点着色进行UnityObjectToClipPos后,坐标空间就是屏幕坐标了。

                //屏幕坐标经过投影变换。如果在vertex shader 计算UnityObjectToClipPos。a, b点的坐标x,y,z就不是均匀。垂直于线段的向量dir2就不对。

                v[0].uv = float2(0.0f, 1.0f) * float2(len / _SingleSegmentLength, 1.0f);

                v[1].vertex = UnityObjectToClipPos(b + float4(dir3, 0, 0));

                v[1].uv = float2(1.0f, 1.0f) * float2(len / _SingleSegmentLength, 1.0f);

                v[2].vertex = UnityObjectToClipPos(b + float4(-dir3, 0, 0));

                v[2].uv = float2(1.0f, 0.0f) * float2(len / _SingleSegmentLength, 1.0f);

                v[3].vertex = UnityObjectToClipPos(a + float4(-dir3, 0, 0));

                v[3].uv = float2(0.0f, 0.0f) * float2(len / _SingleSegmentLength, 1.0f);

                triStream.Append(v[0]);

                triStream.Append(v[1]);

                triStream.Append(v[2]);

                triStream.RestartStrip();//重置三角形计数,提交三角形

                triStream.Append(v[2]);

                triStream.Append(v[3]);

                triStream.Append(v[0]);

                triStream.RestartStrip();

                //最后倒下角,美化一下。这里可选。

                v2f va[3];

                v2f vb[3];

                float pi = 3.1415926;

                float points = 3;

                float segs = points + 1;

                for (int i = 1;i <= points;i++)

                {

                    float2 rot = normalize(-dir0 * sin(i / segs * pi) + dir2 * cos(i / segs * pi));

                    va[i - 1].vertex = UnityObjectToClipPos(a + float4(rot * 0.5 * _LineWidth, 0, 0));

                    va[i - 1].uv = float2(0, dot(rot, dir2)) * float2(len / _SingleSegmentLength, 1.0f);

                }

                for (int i = 1;i <= points;i++)

                {

                    float2 rot = normalize(dir0 * sin(i / segs * pi) + -dir2 * cos(i / segs * pi));

                    vb[i - 1].vertex = UnityObjectToClipPos(b + float4(rot * 0.5 * _LineWidth, 0, 0));

                    vb[i - 1].uv = float2(1, dot(rot, dir2)) * float2(len / _SingleSegmentLength, 1.0f);

                }

                for (int i = 0;i < points;i++)

                {

                    triStream.Append(v[3]);

                    triStream.Append(va[i]);

                    if (i - 1 < 0)

                        triStream.Append(v[0]);

                    else

                        triStream.Append(va[i - 1]);

                    triStream.RestartStrip();

                    triStream.Append(v[1]);

                    triStream.Append(vb[i]);

                    if (i - 1 < 0)

                        triStream.Append(v[2]);

                    else

                        triStream.Append(vb[i - 1]);

                    triStream.RestartStrip();

                }

            }

            v2f vert (appdata v)

            {

                v2f o;

                o.vertex = v.vertex;

                //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);

                fixed4 col = float4(0, 1, 0, 0);

                float m = fmod(i.uv.x, 1);

                if (m < _SolidRatio)

                {

                    col = _LineColor;

                }

                // apply fog

                //UNITY_APPLY_FOG(i.fogCoord, col);

                return col;

            }

            ENDCG

        }

    }

}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
找专业防水队做完还漏水怎么维权 法院会受理房屋漏水造成的纠纷吗? 巴西龟最长活多久,家养!!! 养胃的药最好的是什么啊 婴儿积食发烧不愿吃药怎么办 板门穴位在哪个部位 手机设置放偷看的方法? 凝结水回收器生产厂家? 个人账户养老金预测公式:现有5万元,缴费20年,能领多少钱? 临沂比较有名的男装品牌 腿和身体的完美比例是 建设银行信用卡刷钱显示持卡人验证失败是怎么回事? 古老的名人故事有哪些给我说说听吧 以前4s设置的360来电秀,现在换5s了,没有360,怎么关闭来电秀? 涡轮增压发动机寿命有多长 涡轮增压器可以用多久 女孩子练瑜伽什么发型最适合? 练瑜伽短发的要不要扎起来? 我的长发啊,每次练瑜伽的时候都要捣乱怎么办 练瑜伽时头发怎么扎 瑜伽的时候头发怎么弄才好看 她们的发型实在太美了 为什么有的人可以那样自私,贪婪。而从不顾忌身边人的感受? 谁来推荐网球拍 帮忙取个好听的女英文名!!! 女生英文名可以直接叫YC吗? 与杨畅谐音的英文名,不要普通的那种英文名,最好有YC字母的,类似日本香港人给自己起的英文名~谢谢! 「考试重点」古代文学-魏晋南北朝文学 拼音大写英文名 肖天顺英文名怎么写啊 我要不是拼音是英文名 知道的麻烦你告诉我 谢谢了 结婚封利是要写名字的话应该写在利是封的哪个位置 shader几何运算效果 gt440显卡 支持 geometry shader 吗? DX9/10是什么 Direct3D的Pipeline 听说ZBOM志邦是一线大品牌,是真的吗? 猜生肖 大嘴裂牙最灵活 配:妙机多保 配:古今藏胸 大嘴裂牙最灵活指什么生肖 字母m是什么星座 大嘴裂牙最灵活气吐如虹忠心耿耿是什么生肖? 大嘴裂牙最灵活妙机多保古今藏胸猜一生肖 破壳而出不犹豫,生性能巧,大嘴裂牙是什么生肖 大嘴裂牙最灵活~妙机多保~古今藏胸是指什么生肖 腹泻的人炖什么汤喝好一点 拉肚子炖什么汤比较好 小孩拉肚子喝什么汤 拉肚子喝什么汤 拉肚子喝什么汤比较好 小孩拉肚子可以喝什么汤 林培炜的草书怎么写 网络的创始人是谁