zoukankan      html  css  js  c++  java
  • 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 }



  • 相关阅读:
    android 75 新闻列表页面
    android 74 下载文本
    android 73 下载图片
    android 72 确定取消对话框,单选对话框,多选对话框
    android 71 ArrayAdapter和SimpleAdapter
    android 70 使用ListView把数据显示至屏幕
    maven如何将本地jar安装到本地仓库
    Centos6.7搭建ISCSI存储服务器
    解决maven打包编译出现File encoding has not been set问题
    MySQL 解决 emoji表情 的方法,使用utf8mb4 字符集(4字节 UTF-8 Unicode 编码)
  • 原文地址:https://www.cnblogs.com/answer-yj/p/12752019.html
Copyright © 2011-2022 走看看