Unity 中使用Geomotry Shader(几何着色器)扩展点创建其他图形(并实现处理锯齿)

问题背景:

我们开发中需要有“点”对象,可以是像素的(不具备透视效果),始终等大,还有就是3D场景下的矢量点(随相机距离透视变化的)。

问题解决思路:

方案1:使用GS扩充顶点,并扩充三角面,通过GS直接绘制出想要图形点(我这里有几种图形的点)

方案2:使用GS扩充顶点,绘制出正方形面,到FS中去截取想要的形状

这两种方案基本思想都是一样的,我这里提供两种方案是因为我这个点的边框是有要求的,用GS扩线围一圈效果不好

知识扩展:

Geomotry Shader(几何着色器):几何着色器是可选的着色器,它位于顶点和片段着色器之间,它以一个或多个表示为一个单独基本图形(primitive)即图元的顶点作为输入,比如可以是一个点或者三角形,几何着色器在将这些顶点发送到下一个着色阶段之前,可以将这些顶点转变为它认为合适的内容。几何着色器有意思的地方在于它可以把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点。

 

上面是官方解释,通俗来讲:就是GeometryShader接收的实际上是VS输出的图元,对这些图元进行添加,修改,删除,然后输出新的图元信息。

 

图片说明:

这也就是人们常见的shader流程图。

具体实现代码:

方案一:

  1 Shader "Vector/Point"
  2 {
  3     Properties
  4     {
  5         _Color("MianColor",color)=(1,1,1,1)
  6     }
  7     SubShader
  8     {
  9         Pass
 10         {
 11             Tags { "RenderType"="Opaque" }
 12             LOD 100 
 13             Cull Off
 14             CGPROGRAM
 15             #pragma target 4.0
 16             #pragma vertex vert
 17             #pragma fragment frag
 18             #pragma geometry geom            
 19             #include "UnityCG.cginc" 
 20             struct appdata
 21             {
 22                 float4 vertex : POSITION;
 23                 float2 uv : TEXCOORD0;
 24                 float3 normal : NORMAL;
 25             }; 
 26             struct v2g
 27             {
 28                 float4 vertex : POSITION;
 29                 float3 nor:NORMAL;
 30             };
 31             struct g2f
 32             {
 33                 float4 vertex : SV_POSITION;
 34                 float3 norg:NORMAL;
 35             };
 36 
 37             fixed4 _LightColor0;
 38             fixed4 _Color;
 39             float radius;
 40             float initOffsetAngle=0;
 41             float verticesNumber=3;
 42             float IsEqualPixelPoint=0.0;
 43 
 44             v2g vert(appdata_base v)
 45             {
 46                 v2g o;
 47                 o.vertex = v.vertex;
 48                 o.nor=v.normal;
 49                 return o;
 50             }
 51  
 52         void ADD_VERTEX(float3 v,g2f o,inout TriangleStream<g2f> tristream)
 53         {
 54            o.vertex = UnityObjectToClipPos(v); 
 55            tristream.Append(o);
 56         }      
 57         void  ADD_INFO(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
 58         {
 59 
 60             ADD_VERTEX(p0,o,tristream);
 61             ADD_VERTEX(p1,o,tristream);
 62             ADD_VERTEX(p2,o,tristream);
 63             tristream.RestartStrip();
 64         }
 65                   
 66        // 根据模型坐标获得屏幕坐标
 67        float4 GetScreenPos(float4 vertex)
 68         {
 69           float4 pos = UnityObjectToClipPos(vertex);
 70           //return getScreenPosByClipPos(pos);
 71 
 72           pos = ComputeScreenPos(pos);
 73           pos.xy = pos.xy / pos.w;
 74           pos.xy = pos.xy * _ScreenParams.xy;
 75           return pos;
 76        }
 77 
 78         //将旋转完的坐标转回剪裁空间下
 79         void ADD_VERTEX_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
 80         {
 81             float4 pos=v;
 82             pos.xy=v.xy/_ScreenParams.xy;
 83             pos.xy=pos.xy * v.w;
 84 
 85             pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
 86             pos.x=(pos.x-(0.5*pos.w))/0.5;
 87 
 88             o.vertex = pos; 
 89             tristream.Append(o);
 90         }     
 91         
 92         void  ADD_INFO_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
 93         {
 94             ADD_VERTEX_Other(p0,o,tristream);
 95             ADD_VERTEX_Other(p1,o,tristream);
 96             ADD_VERTEX_Other(p2,o,tristream);
 97             tristream.RestartStrip();
 98         }
 99 
100         [maxvertexcount(60)]
101         void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
102         {
103            g2f o; 
104            if(IsEqualPixelPoint==0.0)
105            {
106             float3 p0=float3(0,0,0);
107             float3 dir=normalize( mul(unity_WorldToObject,_WorldSpaceCameraPos)-IN[0].vertex);
108             float3 cy=float3(0,1,0);
109             float3 right=normalize(cross(cy, dir));
110             float3 up=normalize(cross(dir,right));
111             float3 p=cy * radius;
112             //第一个点
113             float3 p1=float3((cos(radians(initOffsetAngle)) * (p).x)-(sin(radians(initOffsetAngle)) * (p).y),(sin(radians(initOffsetAngle)) * (p).x)+(cos(radians(initOffsetAngle)) * (p).y),(p).z);
114             float3 p2=float3(0,0,0);
115             float3 p3=float3(0,0,0);
116             float angle= radians(360/verticesNumber);
117             p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
118 
119             float3 p1p=(p1.x*right+p1.y*up+p1.z*dir);
120             p2=(p2.x*right+p2.y*up+p2.z*dir);
121 
122             float3 edgeA = p2 - p1p;
123             float3 edgeB = p3 - p1p;
124             float3 normalFace = normalize(cross(edgeA, edgeB));
125             o.norg=-normalFace;
126 
127             ADD_INFO(p0,p1p,p2,o,tristream);
128 
129             for (float i=1.0; i<verticesNumber;i+=1.0)
130             {
131                 p2=float3((cos(i*angle) * (p1).x)-(sin(i*angle) * (p1).y),(sin(i*angle) * (p1).x) + (cos(i*angle) * (p1).y),(p1).z);
132                 p3=float3((cos((i+1)*angle) * (p1).x)-(sin((i+1)*angle) * (p1).y),(sin((i+1) * angle) * (p1).x)+(cos((i+1) * angle) * (p1).y),(p1).z);
133     
134                 p2=(p2.x*right+p2.y*up+p2.z*dir);
135                 p3=(p3.x*right+p3.y*up+p3.z*dir);
136 
137                 float3 edgeA = p2 - p1;
138                 float3 edgeB = p3 - p1;
139                 float3 normalFace = normalize(cross(edgeA, edgeB));
140                 o.norg=-normalFace;
141 
142                 ADD_INFO(p0,p2,p3,o,tristream);
143             }
144           }
145           else
146           {
147             //等像素
148             float4 pp0=float4(0,0,0,1);
149             pp0= GetScreenPos(pp0);
150             float2 up=float2(0,1);
151             float2 pp=up * radius;
152             //第一个点
153             float4 pp1=pp0;
154             float4 pp2=pp0;
155             float4 pp3=pp0;
156             pp1.xy= float2((cos(radians(initOffsetAngle)) * (pp).x)-(sin(radians(initOffsetAngle)) * (pp).y),(sin(radians(initOffsetAngle)) * (pp).x)+(cos(radians(initOffsetAngle)) * (pp).y));
157             float angle= radians(360/verticesNumber);
158             pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
159             float3 edgeA = pp2 - pp1;
160             float3 edgeB = pp3 - pp1;
161             float3 normalFace = normalize(cross(edgeA, edgeB));
162             o.norg=-normalFace;
163 
164             ADD_INFO_Other(pp0,pp1+float4(pp0.xy,0,0),pp2+float4(pp0.xy,0,0),o,tristream);
165 
166            for (float i=1.0; i<verticesNumber;i+=1.0)
167             {
168                 pp2=pp0;
169                 pp3=pp0;
170                 pp2.xy=float2((cos(i*angle) * (pp1).x)-(sin(i*angle) * (pp1).y),(sin(i*angle) * (pp1).x) + (cos(i*angle) * (pp1).y));
171                 pp3.xy=float2((cos((i+1)*angle) * (pp1).x)-(sin((i+1)*angle) * (pp1).y),(sin((i+1) * angle) * (pp1).x)+(cos((i+1) * angle) * (pp1).y));
172 
173                 float3 edgeA = pp2 - pp1;
174                 float3 edgeB = pp3 - pp1;
175                 float3 normalFace = normalize(cross(edgeA, edgeB));
176                 o.norg=-normalFace;
177 
178                 ADD_INFO_Other(pp0,pp2+float4(pp0.xy,0,0),pp3+float4(pp0.xy,0,0),o,tristream);
179             }
180           }
181         } 
182             fixed4 frag (g2f i) : SV_Target
183             {
184               return _Color;
185             }
186             ENDCG
187         }
188     }
189 }

代码分析:

1.从模型坐标-剪裁空间坐标-屏幕空间坐标,如下:

        float4 GetScreenPos(float4 vertex)
          {
            float4 pos = UnityObjectToClipPos(vertex);
            //return getScreenPosByClipPos(pos);
 
           pos = ComputeScreenPos(pos);
          pos.xy = pos.xy / pos.w;
            pos.xy = pos.xy * _ScreenParams.xy;
            return pos;
        }

2.屏幕坐标扩展完坐标转回剪裁空间

       //将旋转完的坐标转回剪裁空间下
         void ADD_VERTEX_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
        {
             float4 pos=v;
              pos.xy=v.xy/_ScreenParams.xy;
              pos.xy=pos.xy * v.w;
  
             pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
             pos.x=(pos.x-(0.5*pos.w))/0.5;
  
             o.vertex = pos; 
              tristream.Append(o);
          }     

 这个地方就是转屏幕坐标的逆运算,主要注意的是定义位于UnityCG.cginc中的内置方法ComputeScreenPos,它的具体逻辑是这样:

inline float4 ComputeScreenPos (float4 pos)
{
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
    o.zw = pos.zw;
    
    return o;
}
即主要做的是就是这:

o.x = (pos.x * 0.5 + pos.w * 0.5)

o.y = (pos.y * 0.5 * _ProjectionParams.x + pos.w * 0.5)

这一步别忘了逆运算回去。

3.这里的算法逻辑是这样:给我一个中心点坐标,我求出正上方点坐标,根据你是几边形,去旋转(乘以旋转矩阵)得到扩展点。上面矢量点主要问题在于,我构建了本地坐标系,旋转就会有坑,因为我正上方点是通过构建坐标系去求得,然而旋转应该在自身坐标系下,
正上方点就是(0,1,0 )而不是自己构建坐标系下的up,记得转完返回去,所以这是一个坑。


方案二:

  1 Shader "MyShader/PointTwo"
  2 {
  3     Properties
  4     {
  5         _Color("MianColor",color)=(1,1,1,1)
  6     }
  7     SubShader
  8     {
  9 
 10         Tags { "RenderType"="Opaque" }
 11         LOD 100 
 12         Cull Off
 13 
 14         CGINCLUDE
 15     
 16         #include "UnityCG.cginc" 
 17 
 18         struct appdata
 19         {
 20             float4 vertex : POSITION;
 21             float2 uv : TEXCOORD0;
 22             float3 normal : NORMAL;
 23             fixed4 color : COLOR; //顶点自身的颜色
 24         }; 
 25 
 26         struct v2g
 27         {
 28             float4 vertex : POSITION;
 29             float3 nor:NORMAL;
 30             fixed4 color : COLOR; //顶点自身的颜色
 31         };
 32         
 33         struct g2f
 34         {
 35             float4 vertex : SV_POSITION;
 36             float3 pos: TEXCOORD0;
 37             float3 centerPos: TEXCOORD1;
 38             float3 norg:NORMAL;
 39             fixed4 color : COLOR; //顶点自身的颜色
 40         };
 41 
 42         //点的颜色
 43         fixed4 _Color;
 44         //边框的颜色
 45         fixed4 _LineColor;
 46         //点的半径大小(四边形内切圆)
 47         float _Radius;
 48         //点的线框宽度
 49         uniform float _LineWidth=5;
 50         //什么图形(-1圆/)
 51         float _PointType=-1;
 52         //是否是像素点
 53         float IsEqualPixelPoint=0.0;
 54         //交叉点宽度
 55         float _CrossPointWidth;
 56  
 57         //矢量点添加扩展点坐标转换      
 58         void ADD_VERTEX(float3 v,g2f o,inout TriangleStream<g2f> tristream)
 59         {
 60            o.vertex = UnityObjectToClipPos(v);
 61            o.pos = v;
 62            tristream.Append(o);
 63         }
 64 
 65         //矢量点添加扩展点面逻辑      
 66         void  ADD_INFO(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
 67         {
 68             ADD_VERTEX(p0,o,tristream);
 69             ADD_VERTEX(p1,o,tristream);
 70             ADD_VERTEX(p2,o,tristream);
 71             tristream.RestartStrip();
 72         }
 73                   
 74        // (像素点)根据模型坐标获得屏幕坐标
 75        float4 GetScreenPos(float4 vertex)
 76         {
 77           float4 pos = UnityObjectToClipPos(vertex);
 78 
 79           pos = ComputeScreenPos(pos);
 80           pos.xy = pos.xy / pos.w;
 81           pos.xy = pos.xy * _ScreenParams.xy;
 82           return pos;
 83        }
 84 
 85         //(像素点)将旋转完的坐标转回剪裁空间下
 86         void ADD_VERT_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
 87         {
 88             float4 pos=v;
 89             pos.xy=v.xy/_ScreenParams.xy;
 90             pos.xy=pos.xy * v.w;
 91 
 92             pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
 93             pos.x=(pos.x-(0.5*pos.w))/0.5;
 94 
 95             o.vertex = pos; 
 96             o.pos=v;
 97             tristream.Append(o);
 98         }     
 99         
100         //像素点添加点
101         void  ADD_INFO_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
102         {
103             ADD_VERTEX_Other(p0,o,tristream);
104             ADD_VERTEX_Other(p1,o,tristream);
105             ADD_VERTEX_Other(p2,o,tristream);
106             tristream.RestartStrip();
107         }
108 
109         // 判断点是否在三角形内
110         float PointinTriangle(float2 A, float2 B, float2 C, float2 P)
111         {
112             float2 ab=B-A;
113             float2 ac=C-A;
114             float2 ap=P-A;
115              
116             float u=(dot(ab,ab) *dot(ap,ac)-dot(ac,ab)* dot(ap,ab)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
117             float v=(dot(ac,ac) *dot(ap,ab)-dot(ac,ab)* dot(ap,ac)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
118 
119                if (u < 0 || u > 1) // if u out of range, return directly
120                {
121                   return 2 ;
122                }
123 
124                if (v < 0 || v > 1) // if v out of range, return directly
125                 {
126                     return 2 ;
127                 }
128                 return u+v;
129         }
130 
131         //截圆点
132         void DrawCirclePoint(g2f i,float type)
133         {
134 
135             //边框
136             _LineWidth=5;
137 
138             float _R = abs(type) < 0.05 ? _Radius :  (_Radius - _LineWidth);
139 
140             float dis=distance(i.centerPos,i.pos);
141               
142             //剔除圆
143             if(dis > _R)
144             {
145               discard;
146             }
147             
148         }  
149 
150         //截正方形点
151         void DrawSquarePoint(g2f i,float type)
152         {
153             //边框
154             _LineWidth=5;
155 
156             float _R = abs(type) < 0.05 ? 0.9 * _Radius :  (0.9 *_Radius - _LineWidth);
157 
158              //计算边缘点
159              float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
160              float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
161              float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
162              float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
163                
164              //正方形剔除
165              if(i.pos.x < leftTop.x | i.pos.x > rightTop.x | i.pos.y < leftButtom.y | i.pos.y > rightTop.y)
166              {
167                  discard;
168              }
176         }
177 
178         //截三角形点
179         void DrawTrianglePoint(g2f i,float type)
180         {
181             //边框
182             _LineWidth=5;
183 
184             float _R = abs(type) < 0.05 ? _Radius :  (_Radius - _LineWidth);
185              
186             //计算边缘点
187             float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
188             float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
189             float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
190             float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
191 
192             //三角形顶点
193             float2 topCenter=(leftTop+rightTop)/2;
194             float2 rightB=float2((i.centerPos.x + 0.707 * _R),i.centerPos.y - 0.5 *_R);
195             float2 leftB=float2((i.centerPos.x - 0.707 * _R),i.centerPos.y - 0.5 *_R);
196 
197             if(PointinTriangle(topCenter,rightB, leftB, i.pos.xy)>1)
198             {
199                 discard;
200             }
259         }
260         
261         //截交叉十字形点
262         void DrawCrossPoint(g2f i,float type)
263         {
264 
265              //边框
266             _LineWidth=5;
267 
268             _CrossPointWidth=16;
269 
270             float _R = abs(type) < 0.05 ? 0.9* _Radius :  (0.92 * _Radius - _LineWidth);
271 
272             float _InPoint = abs(type) < 0.05 ? _CrossPointWidth / 2 :  (_CrossPointWidth - _LineWidth) / 2;
273 
274             //计算边缘点
275             float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
276             float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
277             float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
278             float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
279 
280             //十字架内角点  
281             float2 inRightTop=float2(i.centerPos.x  + _InPoint , i.centerPos.y +  _InPoint);
282             float2 inLeftTop=float2(i.centerPos.x  - _InPoint , i.centerPos.y + _InPoint);
283             float2 inRightButtom=float2(i.centerPos.x  + _InPoint , i.centerPos.y -  _InPoint);
284             float2 inLeftButtom=float2(i.centerPos.x  - _InPoint , i.centerPos.y -  _InPoint);
285             
286             if(((i.pos.x) > (inRightTop.x) & (i.pos.y) > (inRightTop.y)) | ((i.pos.x) < (inLeftTop.x) & (i.pos.y) > (inLeftTop.y)) | ((i.pos.x) > (inRightButtom.x) & (i.pos.y) < (inRightButtom.y)) | ((i.pos.x) < (inLeftButtom.x) & (i.pos.y) < (inLeftButtom.y)) | ((i.pos.x) < (i.centerPos.x - _R) | (i.pos.x) > (i.centerPos.x+ _R)) | ((i.pos.y) < (i.centerPos.y- _R) | (i.pos.y) > (i.centerPos.y+ _R)))
287             { 
288                 discard;
289             }
298         }
299 
300         v2g vert(appdata_full  v)
301         {
302             v2g o;
303             o.vertex = v.vertex;
304             o.nor=v.normal;
305             o.color=v.color;
306             return o;
307         }
308 
309         [maxvertexcount(12)]
310         void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
311         {
312            g2f o; 
313            //固定只扩展4个点,且初始偏转为45
314            //矢量点
315            if(IsEqualPixelPoint==0.0)
316            {
317             //中心点   
318             float3 centerPos=float3(0,0,0);
319             o.centerPos=centerPos;
320             o.color=IN[0].color;
321 
322             //计算本地坐标系
323             float3 dir=normalize(mul(unity_WorldToObject,_WorldSpaceCameraPos)-IN[0].vertex);
324             float3 worldUp=float3(0,1,0);
325             float3 right=normalize(cross(worldUp, dir));
326             float3 up=normalize(cross(dir,right));
327 
328             //正上方点
329             float3 p=worldUp * _Radius * 1.414;
330             float3 p1=centerPos;
331             float3 p2=centerPos;
332             float3 p3=centerPos;
333             float3 p4=centerPos;
334 
335             //计算偏移角
336             float angle= radians(360/4);
337 
338             //求正方形四顶点
339             p1=float3((cos(radians(45)) * (p).x)-(sin(radians(45)) * (p).y),(sin(radians(45)) * (p).x)+(cos(radians(45)) * (p).y),(p).z);
340             p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
341             p3=float3((cos(angle * 2) * (p1).x)-(sin(angle * 2) * (p1).y),(sin(angle * 2) * (p1).x)+(cos(angle * 2) * (p1).y),(p1).z);
342             p4=float3((cos(angle * 3) * (p1).x)-(sin(angle * 3) * (p1).y),(sin(angle * 3) * (p1).x)+(cos(angle * 3) * (p1).y),(p1).z);
343             p1=(p1.x * right + p1.y * up + p1.z * dir);
344             p2=(p2.x * right + p2.y * up + p2.z * dir);
345             p3=(p3.x * right + p3.y * up + p3.z * dir);
346             p4=(p4.x * right + p4.y * up + p4.z * dir);
347 
348             //计算法线
349             float3 edgeA = p2 - p1;
350             float3 edgeB = p3 - p1;
351             float3 normalFace = normalize(cross(edgeA, edgeB));
352             o.norg=-normalFace;
353 
354             ADD_INFO(p1,p2,p3,o,tristream);
355             ADD_INFO(p3,p4,p1,o,tristream);
356           }
357           else
358           {
359             //等像素点
360             float4 centerPos1=float4(0,0,0,1);
361             centerPos1= GetScreenPos(centerPos1);
362             float2 up=float2(0,1);
363             float2 pp=up * _Radius * 1.414;
364             //第一个点
365             float4 pp1=centerPos1;
366             float4 pp2=centerPos1;
367             float4 pp3=centerPos1;
368             float4 pp4=centerPos1;
369 
370             //计算偏移角
371             float angle= radians(360/4);
372 
373             //求正方形四顶点
374             pp1.xy=float2((cos(radians(45)) * (pp).x)-(sin(radians(45)) * (pp).y),(sin(radians(45)) * (pp).x)+(cos(radians(45)) * (pp).y));
375             pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
376             pp3.xy=float2((cos(2 * angle) * (pp1).x)-(sin(2 * angle) * (pp1).y),(sin(2 * angle) * (pp1).x)+(cos(2 * angle) * (pp1).y));
377             pp4.xy=float2((cos(3 * angle) * (pp1).x)-(sin(3 * angle) * (pp1).y),(sin(3 * angle) * (pp1).x)+(cos(3 * angle) * (pp1).y));
378             
379             //计算偏移
380             pp1=pp1+float4(centerPos1.xy,0,0);
381             pp2=pp2+float4(centerPos1.xy,0,0);
382             pp3=pp3+float4(centerPos1.xy,0,0);
383             pp4=pp4+float4(centerPos1.xy,0,0);
384 
385             //计算法线
386             float3 edgeA = pp2 - pp1;
387             float3 edgeB = pp3 - pp1;
388             float3 normalFace = normalize(cross(edgeA, edgeB));
389             o.norg=-normalFace;
390             
391             o.centerPos=centerPos1;
392             o.color=IN[0].color;
393 
394             ADD_INFO_Other(pp1,pp2,pp3,o,tristream);
395             ADD_INFO_Other(pp3,pp4,pp1,o,tristream);
396 
397           }
398         } 
399             
400        fixed4 frag (g2f i) : SV_Target
401         {
402                  
403             //圆形点
404             if (abs(_PointType)<=0.05)
405             {    
406                DrawCirclePoint(i,0.0);       
407             }
408              
409             //正方形
410             if(abs(_PointType-2)<=0.05)
411             {
412                DrawSquarePoint(i,0.0);
413             }
414 
415             //三角形
416             if(abs(_PointType-1)<=0.05)
417             {
418                DrawTrianglePoint(i,0.0);
419             }
420 
421              //交叉十字
422             if(abs(_PointType-3)<=0.05)
423             {
424                 DrawCrossPoint(i,0.0);
425             }
426 
427              return _LineColor;
428         }
429 
430 
431         fixed4 fragOther (g2f i) : SV_Target
432         {
433             //圆形点
434             if (abs(_PointType)<=0.05)
435             {    
436                DrawCirclePoint(i,1.0);   
437             }
438              
439             //正方形
440             if(abs(_PointType-2)<=0.05)
441             {
442                DrawSquarePoint(i,1.0);
443             }
444 
445             //三角形
446             if(abs(_PointType-1)<=0.05)
447             {
448                DrawTrianglePoint(i,1.0);
449             }
450 
451              //交叉十字
452             if(abs(_PointType-3)<=0.05)
453             {
454                 DrawCrossPoint(i,1.0);
455             }
456 
457               return _Color;
458         }
459 
460         ENDCG
461 
462         Pass 
463         {
464               NAME "InitShader"
465 
466               Tags { "RenderType"="Opaque" }
467               LOD 100 
468               Cull Off
469 
470               CGPROGRAM
471               
472               #pragma target 4.0
473               #pragma vertex vert
474               #pragma geometry geom        
475               #pragma fragment frag
476 
477               ENDCG  
478         }
479 
480         Pass 
481         {
482               NAME "LineShader"
483             
484               Tags { "RenderType"="Opaque" }
485               LOD 100 
486               Cull Off
487 
488               CGPROGRAM
489               
490               #pragma target 4.0
491               #pragma vertex vert
492               #pragma geometry geom        
493               #pragma fragment fragOther
494               
495               ENDCG  
496         }
497     }
498 
499     FallBack "Diffuse"
500 }

代码分析:

这个方案主要是为了边框处理,我在这里画了两次,也可以处理一次,通过条件去改变Color,但是我这里不想过多处理过渡问题,所以采取了两个Pass渲两遍。。

这里附带一个判断点是否在三角形内算法:

 

对于三角形ABC和一点P,可以有如下的向量表示:

image

p点在三角形内部的充分必要条件是:1 >= u >= 0,   1 >= v >= 0,   u+v <= 1。

 

已知A,B,C,P四个点的坐标,可以求出u,v,把上面的式子分别点乘向量AC和向量AB

image

解方程得到:

image

解出u,v后只需要看他们是否满足“1 >= u >= 0, 1 >= v >= 0, u+v <= 1”,如满足,则,p 在三角形内。

(u = 0时,p在AB上, v = 0时,p在AC上,两者均为0时,p和A重合)

ps:是不是很熟悉,嘿嘿

 

 

 

 

关于GS:

1.属性语法在着色器定义之前设置最大顶点数:
[maxvertexcount(N)]
N是几何着色器为单个调用输出的顶点的最大数量
GS可以在每次调用时输出的顶点数量是可变的,但不能超过定义的最大值。出于性能考虑,最大顶点数应尽可能小; [NVIDIA08]指出,当GS输出在1到20个标量之间时,可以实现GS的性能峰值,如果GS输出在27-40个标量之间,则性能下降50%。

2.GS需要两个参数:输入参数和输出参数。 (实际上,它可能需要更多,但这是一个特殊的主题;请参见§11.2.4。)输入参数一般是一个定义了图元的顶点数组 — 一个顶点定义一个点,两个定义一条线,三个定义三角形,四个定义邻接线段,六个定义邻接三角形。 输入顶点的顶点类型是顶点着色器返回的顶点类型(例如,VertexOut)。 输入参数必须以原始类型为前缀,描述输入到几何着色器中的图元的类型。这可以是以下任何一种:

    1、point:输入图元是点。
    2、line:输入图元是线段(lists或strips)。
    3、triangle:输入图元是三角形(lists或strips)。
    4、lineadj:输入图元是具有邻接(lists或strips)的线段。
    5、triangleadj:输入图元是具有邻接(lists或strips)的三角形。

 

3.几何着色器输出的顶点形成基元; 输出原语的类型由流类型(PointStream,LineStream,TriangleStream)指示。 对于线和三角形,输出原语总是strips。 然而,线和三角形列表可以使用内在的RestartStrip方法进行

 

关于SubShader使用:

subShaderc 中 选择执行哪个?可根据LOG设置,(从上往下 &从大到小)写)<=LOD值就执行相应的子着色器,它会在子着色器列表中找《=LOD的,但是会找第一个满足条件的,所以从小到大,会只跑第一个最小的了,所以从大到小写(LOD)



最新:
解决问题:
1.面向相机问题(用的是世界下坐标)参考广告牌技术,任何物体的上方就是(0,1,0);无需先构建本地坐标系。
2.解决锯齿问题,使用颜色过渡。
最新代码:
  1 Shader "Vector/Point"
  2 {
  3     Properties
  4     {
  5         _Color("MianColor",color)=(1,1,1,1)
  6     }
  7     SubShader
  8     {
  9 
 10         Tags { "RenderType"="Transparent" "Queue"="Transparent+1"}
 11         LOD 100 
 12         Cull Off
 13 
 14         CGINCLUDE
 15     
 16         #include "UnityCG.cginc" 
 17 
 18         struct appdata
 19         {
 20             float4 vertex : POSITION;
 21             float2 uv : TEXCOORD0;
 22             float3 normal : NORMAL;
 23             fixed4 color : COLOR; //顶点自身的颜色
 24         }; 
 25 
 26         struct v2g
 27         {
 28             float4 vertex : POSITION;
 29             float3 nor:NORMAL;
 30             fixed4 color : COLOR; //顶点自身的颜色
 31         };
 32         
 33         struct g2f
 34         {
 35             float4 vertex : SV_POSITION;
 36             float3 pos: TEXCOORD0;
 37             float3 centerPos: TEXCOORD1;
 38             float3 norg:NORMAL;
 39             fixed4 color : COLOR; //顶点自身的颜色
 40         };
 41 
 42         //点的颜色
 43         fixed4 _Color;
 44         //边框的颜色
 45         fixed4 _LineColor;
 46         //点的半径大小(四边形内切圆)
 47         float _Radius;
 48         //点的线框宽度
 49         uniform float _LineWidth=5;
 50         //点类型
 51         float _PointType=-1;
 52         //是否是像素点
 53         float IsEqualPixelPoint=0.0;
 54         //交叉点宽度
 55         float _CrossPointWidth;
 56 
 57         //矢量点添加扩展点坐标转换      
 58         void ADD_VERT(float3 v,g2f o,inout TriangleStream<g2f> tristream)
 59         {
 60            o.vertex = UnityObjectToClipPos(v);
 61            o.pos = v;
 62            tristream.Append(o);
 63         }
 64 
 65         //矢量点添加扩展点面逻辑      
 66         void  ADD_TRI(float3 p0,float3 p1,float3 p2,g2f o,inout TriangleStream<g2f> tristream)
 67         {
 68             ADD_VERT(p0,o,tristream);
 69             ADD_VERT(p1,o,tristream);
 70             ADD_VERT(p2,o,tristream);
 71             tristream.RestartStrip();
 72         }
 73                   
 74        // (像素点)根据模型坐标获得屏幕坐标
 75        float4 GetScreenPos(float4 vertex)
 76         {
 77           float4 pos = UnityObjectToClipPos(vertex);
 78 
 79           pos = ComputeScreenPos(pos);
 80           pos.xy = pos.xy / pos.w;
 81           pos.xy = pos.xy * _ScreenParams.xy;
 82           return pos;
 83        }
 84 
 85         //(像素点)将旋转完的坐标转回剪裁空间下
 86         void ADD_VERT_Other(float4 v,g2f o,inout TriangleStream<g2f> tristream)
 87         {
 88             float4 pos=v;
 89             pos.xy=v.xy/_ScreenParams.xy;
 90             pos.xy=pos.xy * v.w;
 91 
 92             pos.y= (pos.y-(0.5*pos.w))/(_ProjectionParams.x * 0.5);
 93             pos.x=(pos.x-(0.5*pos.w))/0.5;
 94 
 95             o.vertex = pos; 
 96             o.pos=v;
 97             tristream.Append(o);
 98         }     
 99         
100         //像素点添加点
101         void  ADD_TRI_Other(float4 p0,float4 p1,float4 p2,g2f o,inout TriangleStream<g2f> tristream)
102         {
103             ADD_VERT_Other(p0,o,tristream);
104             ADD_VERT_Other(p1,o,tristream);
105             ADD_VERT_Other(p2,o,tristream);
106             tristream.RestartStrip();
107         }
108 
109         // 判断点是否在三角形内
110         float PointinTriangle(float2 A, float2 B, float2 C, float2 P)
111         {
112             float2 ab=B-A;
113             float2 ac=C-A;
114             float2 ap=P-A;
115              
116             float u=(dot(ab,ab) *dot(ap,ac)-dot(ac,ab)* dot(ap,ab)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
117             float v=(dot(ac,ac) *dot(ap,ab)-dot(ac,ab)* dot(ap,ac)) / (dot(ac,ac) * dot(ab,ab)-dot(ac,ab) * dot(ab,ac));
118 
119                if (u < 0 || u > 1) // if u out of range, return directly
120                {
121                   return 2 ;
122                }
123 
124                if (v < 0 || v > 1) // if v out of range, return directly
125                 {
126                     return 2 ;
127                 }
128                 return u+v;
129         }
130 
131         //截圆点
132         void DrawCirclePoint(g2f i,float type)
133         {
134 
135             float _R = abs(type) < 0.05 ? _Radius +0.5 :  (_Radius - _LineWidth +0.5);
136 
137             float dis=distance(i.centerPos,i.pos);
138               
139             if(abs(type) <= 1.05 ){
140                //剔除圆
141                if(dis > _R)
142                {
143                  discard;
144                }
145             }
146         }  
147 
148         //截正方形点
149         void DrawSquarePoint(g2f i,float type)
150         {
151 
152             float _R = abs(type) < 0.05 ? 0.92 * _Radius :  (0.92 *_Radius - _LineWidth);
153 
154              //计算边缘点
155              float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
156              float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
157              float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
158              float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
159                
160              //正方形剔除
161              if(i.pos.x < leftTop.x | i.pos.x > rightTop.x | i.pos.y < leftButtom.y | i.pos.y > rightTop.y)
162              {
163                  discard;
164              }
165         }
166 
167         //截三角形点
168         fixed4 DrawTrianglePoint(g2f i,float type)
169         {
170 
171             float _R = abs(type) < 0.05 ? _Radius * 0.92 :  (_Radius * 0.92 );
172              
173             //计算边缘点
174             float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
175             float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
176             float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
177             float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
178 
179             //三角形顶点
180             float2 topCenter=float2(i.centerPos.x , i.centerPos.y + (sin(radians(60))*2-1) * _R);
181             float2 rightB = rightButtom;
182             float2 leftB = leftButtom;
183             if(abs(type-1) < 0.05)
184             {  
185                 float2 center=float2(0,0);
186                 center=(topCenter+rightB+leftB) / 3;
187                 topCenter=topCenter + normalize(center-topCenter) * 2 * _LineWidth ;
188                 rightB = rightButtom + normalize(center-rightButtom) * 2 * _LineWidth ;
189                 leftB = leftButtom + normalize(center-leftButtom) * 2 * _LineWidth ;
190 
191             }
192 
193             if(PointinTriangle(topCenter,rightB, leftB, i.pos.xy)>1)
194             {
195                 discard;
196             }
197 
198             float2 right_center=(topCenter+rightB)/2;
199             float2 buttom_center=(leftB+rightB)/2;
200             float2 left_center=(topCenter+leftB)/2;
201 
202             //在右三角形内
203             if(PointinTriangle(topCenter,i.centerPos, rightB, i.pos.xy)<=1)
204             {
205                float2 right_center_o=(right_center-i.centerPos);
206                float2 P_o=(i.pos-i.centerPos);
207                float l1= length(right_center_o-i.centerPos);
208                float dis= dot(right_center_o,P_o)/l1;
209 
210                float delta =l1-0.5;
211                float edge = smoothstep(delta, delta+0.5, dis);
212                if(abs(type-1) < 0.05){
213                   fixed3 col = lerp( _Color,_LineColor,  edge);
214                   return fixed4(col, 1.0);
215                    
216                }
217                else
218                {
219                    fixed4 target=fixed4(_LineColor.rbg,0);
220                    fixed4 col = lerp(_LineColor, target ,edge);
221                    return col;
222                }
223             }
224             else if(PointinTriangle(topCenter,i.centerPos, leftB, i.pos.xy)<=1)
225             {
226                //左三角形内
227                float2 left_center_o=(left_center-i.centerPos);
228                float2 P_o=(i.pos-i.centerPos);
229                float l1= length(left_center_o-i.centerPos);
230                float dis= dot(left_center_o,P_o)/l1;
231 
232                float delta =l1-0.5;
233                float edge = smoothstep(delta, delta+0.5, dis);
234                 if(abs(type-1) < 0.05){
235                   fixed3 col = lerp( _Color,_LineColor,  edge);
236                   return fixed4(col, 1.0);
237                    
238                }
239                else
240                {
241                    fixed4 target=fixed4(_LineColor.rbg,0);
242                    fixed4 col = lerp(_LineColor, target ,edge);
243                    return col;
244                }
245             }
246             else
247             {
248                 //下三角型内
249                float2 buttom_center_o=(buttom_center-i.centerPos);
250                float2 P_o=(i.pos-i.centerPos);
251                float l1= length(buttom_center_o-i.centerPos);
252                float dis= dot(buttom_center_o,P_o)/l1;
253 
254                float delta =l1-0.5;
255                float edge = smoothstep(delta, delta+0.5, dis);
256                 if(abs(type-1) < 0.05){
257                   fixed3 col = lerp( _Color,_LineColor,  edge);
258                   return fixed4(col, 1.0);
259                }
260                else
261                {
262                    fixed4 target=fixed4(_LineColor.rbg,0);
263                    fixed4 col = lerp(_LineColor, target ,edge);
264                    return col;
265                }
266             }
267         }
268         
269         //截交叉十字形点
270         void DrawCrossPoint(g2f i,float type)
271         {
272 
273             float _R = abs(type) < 0.05 ? 0.92 * _Radius :  (0.92 * _Radius - _LineWidth);
274 
275            //宽度 
276            _CrossPointWidth=_R/3;
277 
278             float _InPoint = abs(type) < 0.05 ? _CrossPointWidth / 2 :  (_CrossPointWidth - _LineWidth) / 2;
279 
280             //计算边缘点
281             float2 leftTop=float2(i.centerPos.x  - _R , i.centerPos.y +  _R);
282             float2 leftButtom=float2(i.centerPos.x  - _R , i.centerPos.y -  _R);
283             float2 rightTop=float2(i.centerPos.x  + _R , i.centerPos.y +  _R);
284             float2 rightButtom=float2(i.centerPos.x  + _R , i.centerPos.y -  _R);
285 
286             //十字架内角点  
287             float2 inRightTop=float2(i.centerPos.x  + _InPoint , i.centerPos.y +  _InPoint);
288             float2 inLeftTop=float2(i.centerPos.x  - _InPoint , i.centerPos.y + _InPoint);
289             float2 inRightButtom=float2(i.centerPos.x  + _InPoint , i.centerPos.y -  _InPoint);
290             float2 inLeftButtom=float2(i.centerPos.x  - _InPoint , i.centerPos.y -  _InPoint);
291 
292             if(((i.pos.x) > (inRightTop.x) & (i.pos.y) > (inRightTop.y)) | ((i.pos.x) < (inLeftTop.x) & (i.pos.y) > (inLeftTop.y)) | ((i.pos.x) > (inRightButtom.x) & (i.pos.y) < (inRightButtom.y)) | ((i.pos.x) < (inLeftButtom.x) & (i.pos.y) < (inLeftButtom.y)) | ((i.pos.x) <= (i.centerPos.x - _R) | (i.pos.x) >= (i.centerPos.x+ _R)) | ((i.pos.y) <= (i.centerPos.y- _R) | (i.pos.y) >= (i.centerPos.y+ _R)))
293             { 
294                 discard;
295             }
296         }
297 
298         v2g vert(appdata_full  v)
299         {
300             v2g o;
301             o.vertex = v.vertex;
302             o.nor=v.normal;
303             o.color=v.color;
304             return o;
305         }
306 
307         float3 _CenterOffset=float3(0,0,0);
308         float3 GetTowardsCamera(float3 objectPos, float3 normal, float3 upDir, float3 rightDir)
309         {
310             objectPos -= _CenterOffset.xyz;
311 
312             float3 localPos = _CenterOffset.xyz + rightDir * objectPos.x + upDir * objectPos.y + normal * objectPos.z;
313 
314             return localPos;
315         } 
316 
317         [maxvertexcount(12)]
318         void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
319         {
320            g2f o; 
321            //固定只扩展4个点,且初始偏转为45
322            //矢量点
323            if(IsEqualPixelPoint==0.0)
324            {
325                 //中心点   
326                 //矢量点 
327                 float3 centerPos=float3(0,0,0);
328                 o.centerPos=centerPos;
329                 o.color=IN[0].color;
330 
331                 //正上方点
332                 float3 worldUp=float3(0,1,0);
333                 float3 p=worldUp * _Radius * 1.414;
334                 float3 p1=centerPos;
335                 float3 p2=centerPos;
336                 float3 p3=centerPos;
337                 float3 p4=centerPos;
338 
339                 //计算偏移角
340                 float angle= radians(360/4);
341 
342                 //求正方形四顶点
343                 p1=float3((cos(radians(45)) * (p).x)-(sin(radians(45)) * (p).y),(sin(radians(45)) * (p).x)+(cos(radians(45)) * (p).y),(p).z);
344                 p2=float3((cos(angle) * (p1).x)-(sin(angle) * (p1).y),(sin(angle) * (p1).x)+(cos(angle) * (p1).y),(p1).z);
345                 p3=float3((cos(angle * 2) * (p1).x)-(sin(angle * 2) * (p1).y),(sin(angle * 2) * (p1).x)+(cos(angle * 2) * (p1).y),(p1).z);
346                 p4=float3((cos(angle * 3) * (p1).x)-(sin(angle * 3) * (p1).y),(sin(angle * 3) * (p1).x)+(cos(angle * 3) * (p1).y),(p1).z);
347 
348                 float3 normal = mul((float3x3)UNITY_MATRIX_I_V, float3(0,0,-1));
349                 float3 upDir =  abs(normal.y) > 0.999 ? float3(0,0,1) : float3(0,1,0);
350                 float3 rightDir = normalize(cross(upDir, normal));
351                 upDir = normalize(cross(normal, rightDir));
352 
353                 p1=GetTowardsCamera(p1, normal, upDir, rightDir);
354                 p2=GetTowardsCamera(p2, normal, upDir, rightDir);
355                 p3=GetTowardsCamera(p3, normal, upDir, rightDir);
356                 p4=GetTowardsCamera(p4, normal, upDir, rightDir);
357 
358                 //计算法线
359                 float3 edgeA = p2 - p1;
360                 float3 edgeB = p3 - p1;
361                 float3 normalFace = normalize(cross(edgeA, edgeB));
362                 o.norg=-normalFace;
363 
364                 ADD_TRI(p1,p2,p3,o,tristream);
365 
366                 ADD_TRI(p3,p4,p1,o,tristream);
367 
368             }
369             else
370             {
371                 //等像素点
372                 float4 centerPos1=float4(0,0,0,1);
373                 centerPos1= GetScreenPos(centerPos1);
374                 float2 up=float2(0,1);
375                 float2 pp=up * _Radius * 1.414;
376                 //第一个点
377                 float4 pp1=centerPos1;
378                 float4 pp2=centerPos1;
379                 float4 pp3=centerPos1;
380                 float4 pp4=centerPos1;
381 
382                 //计算偏移角
383                 float angle= radians(360/4);
384 
385                 //求正方形四顶点
386                 pp1.xy=float2((cos(radians(45)) * (pp).x)-(sin(radians(45)) * (pp).y),(sin(radians(45)) * (pp).x)+(cos(radians(45)) * (pp).y));
387                 pp2.xy=float2((cos(angle) * (pp1).x)-(sin(angle) * (pp1).y),(sin(angle) * (pp1).x)+(cos(angle) * (pp1).y));
388                 pp3.xy=float2((cos(2 * angle) * (pp1).x)-(sin(2 * angle) * (pp1).y),(sin(2 * angle) * (pp1).x)+(cos(2 * angle) * (pp1).y));
389                 pp4.xy=float2((cos(3 * angle) * (pp1).x)-(sin(3 * angle) * (pp1).y),(sin(3 * angle) * (pp1).x)+(cos(3 * angle) * (pp1).y));
390                 
391                 //计算偏移
392                 pp1=pp1+float4(centerPos1.xy,0,0);
393                 pp2=pp2+float4(centerPos1.xy,0,0);
394                 pp3=pp3+float4(centerPos1.xy,0,0);
395                 pp4=pp4+float4(centerPos1.xy,0,0);
396 
397                 //计算法线
398                 float3 edgeA = pp2 - pp1;
399                 float3 edgeB = pp3 - pp1;
400                 float3 normalFace = normalize(cross(edgeA, edgeB));
401                 o.norg=-normalFace;
402                 
403                 o.centerPos=centerPos1;
404                 o.color=IN[0].color;
405 
406                 ADD_TRI_Other(pp1,pp2,pp3,o,tristream);
407                 ADD_TRI_Other(pp3,pp4,pp1,o,tristream);
408 
409           }
410         } 
411             
412        fixed4 frag (g2f i) : SV_Target
413         {
414                  
415             //圆形点
416             if (abs(_PointType)<=0.05)
417             {    
418                 DrawCirclePoint(i,0.0);       
419                 float dis= distance(i.pos,i.centerPos);
420                 float delta = _Radius-0.5;
421                 float edge = smoothstep(delta, delta + 0.5, dis );
422                 fixed4 target= fixed4(_LineColor.rbg,0);
423                 fixed4 col = lerp( _LineColor, target, edge);
424                 return col;
425             }
426              
427             //正方形
428             if(abs(_PointType-2)<=0.05)
429             {
430                 DrawSquarePoint(i,0.0);
431                 float _distance=0.9*_Radius;
432                 float2 centerTop_center=((float2(i.centerPos.x,i.centerPos.y+_distance))-i.centerPos);
433                 float2 pos_center=(i.pos-i.centerPos);
434                 float pos_center_dis= distance(i.pos,i.centerPos);
435                 float dis= dot(pos_center,centerTop_center)/_distance;
436 
437                 float delta = _distance-0.5;
438                 float edge = smoothstep(delta, delta + 0.5, dis );
439                 fixed4 target= fixed4(_LineColor.rbg,0);
440                 fixed4 col = lerp( _LineColor, target, edge);
441                 return col;
442 
443 
444             }
445 
446             //三角形
447             if(abs(_PointType-1)<=0.05)
448             {
449                DrawTrianglePoint(i,0.0);
450             }
451 
452              //交叉十字
453             if(abs(_PointType-3)<=0.05)
454             {
455                 DrawCrossPoint(i,0.0);
456             }
457 
458              return _LineColor;
459         }
460 
461 
462         fixed4 fragOther (g2f i) : SV_Target
463         {
464             //圆形点
465             if (abs(_PointType)<=0.05)
466             {    
467                 DrawCirclePoint(i,1.0);   
468                 float dis= distance(i.pos,i.centerPos);
469                 float delta = _Radius-_LineWidth;
470                 float edge = smoothstep(delta-0.5, delta + 0.5, dis );
471                 fixed3 col = lerp( _Color, _LineColor, edge);
472                 return fixed4(col, 1.0);
473             }
474              
475             //正方形
476             if(abs(_PointType-2)<=0.05)
477             {
478                 DrawSquarePoint(i,1.0);
479                 float _distance=0.9*_Radius-_LineWidth;
480                 float2 centerTop_center=((float2(i.centerPos.x,i.centerPos.y+_distance))-i.centerPos);
481                 float2 pos_center=(i.pos-i.centerPos);
482                 float pos_center_dis= distance(i.pos,i.centerPos);
483                 float dis= (dot(pos_center,centerTop_center)/_distance);
484 
485                 float delta = _distance-0.5;
486                 float edge = smoothstep(delta, delta + 0.5, dis );
487                 fixed3 col = lerp( _Color, _LineColor, edge);
488                 return fixed4(col, 1.0);
489             }
490 
491             //三角形
492             if(abs(_PointType-1)<=0.05)
493             {
494                DrawTrianglePoint(i,1.0);
495             }
496 
497              //交叉十字
498             if(abs(_PointType-3)<=0.05)
499             {
500                 DrawCrossPoint(i,1.0);
501             }
502 
503               return _Color;
504         }
505 
506         ENDCG
507 
508         Pass 
509         {
510               NAME "InitShader"
511 
512               Cull Off
513               ZTest Off 
514               Blend SrcAlpha OneMinusSrcAlpha
515 
516               CGPROGRAM
517               
518               #pragma target 4.0
519               #pragma vertex vert
520               #pragma geometry geom        
521               #pragma fragment frag
522 
523               ENDCG  
524         }
525 
526         Pass 
527         {
528               NAME "LineShader"
529               ZTest Off
530               Cull Off
531 
532               CGPROGRAM
533               
534               #pragma target 4.0
535               #pragma vertex vert
536               #pragma geometry geom        
537               #pragma fragment fragOther
538               
539               ENDCG  
540         }
541 
542     }
543 
544     FallBack "Diffuse"
545 }

 




posted @ 2020-04-22 14:47  望景思心  阅读(623)  评论(0编辑  收藏  举报