繪制虛線(xiàn)其實(shí)簡(jiǎn)單究驴。繪制線(xiàn)段弦疮,然后通過(guò)線(xiàn)段的uv坐標(biāo)剧辐,設(shè)置虛線(xiàn)貼圖就行寒亥。
或者用shader判斷uv坐標(biāo)決定好不要繪制線(xiàn)段的某一部分。
但是這樣還是免不了要在CPU中計(jì)算好頂點(diǎn)和UV荧关。如果線(xiàn)條數(shù)量很多(曲線(xiàn))溉奕,要經(jīng)常更新線(xiàn)條。而且要修改條線(xiàn)的粗細(xì)忍啤,虛線(xiàn)的密度加勤。那么為什么不把要顯示的東西交給GPU呢?
CPU端直接用兩個(gè)點(diǎn)就好了同波,也減少了CPU的計(jì)算量和額外的數(shù)據(jù)存儲(chǔ)鳄梅。
繪制線(xiàn)條的抗鋸齒效果比繪制三角形抗鋸齒效果要差一些
Shader "Unlit/geoline"
{
? ? Properties
? ? {
? ? ? ? _MainTex ("Texture", 2D) = "white" {}
????????_LineColor("LineColor", color) = (0,1,0,1)//顏色
????????_LineWidth("LineWidth",float) = 10//線(xiàn)寬
????????_SingleSegmentLength("SingleSegmentLength",float) = 500//線(xiàn)段單元長(zhǎng)度
????????_SolidRatio("SolidRatio",float) = 0.5//繪制實(shí)線(xiàn)部分比率
? ? }
? ? 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)]//產(chǎn)生最大的頂點(diǎn)數(shù),append到triStream的次數(shù)應(yīng)該小于此参萄。最大好像是64
????????????void geo(line appdata l[2], inout TriangleStream<v2f> triStream)
????????????{
????????????????v2f pIn;
????????????????v2f v[4];//先生成四個(gè)點(diǎn)卫枝,構(gòu)造兩個(gè)三角形
????????????????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));
????????????????//使用的原來(lái)的世界坐標(biāo)空間計(jì)算,完了后再映射為視圖空間讹挎。如果是在頂點(diǎn)著色進(jìn)行UnityObjectToClipPos后校赤,坐標(biāo)空間就是屏幕坐標(biāo)了。
????????????????//屏幕坐標(biāo)經(jīng)過(guò)投影變換筒溃。如果在vertex shader 計(jì)算UnityObjectToClipPos马篮。a, b點(diǎn)的坐標(biāo)x,y,z就不是均勻。垂直于線(xiàn)段的向量dir2就不對(duì)怜奖。
????????????????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();//重置三角形計(jì)數(shù)浑测,提交三角形
????????????????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
? ? ? ? }
? ? }
}