Unity 几何着色器

摘要:
几何着色器将表示为单个基本图形(即实体)的一个或多个顶点作为输入,例如点或三角形。在将这些顶点发送到下一个着色阶段之前,几何着色器可以将它们转换为它认为合适的值。输入几何体着色器阶段将整个实体作为输入,并可以在输出上生成顶点。几何着色器在每次调用时可以输出的顶点数是可变的,但不能超过定义的最大值。流的拓扑由固定声明决定,TriangleStream、LineStream和PointStream被选为GS阶段的输出。
Unity 几何着色器
shaderGeometry Shader几何着色器
Unity 几何着色器

如果学习不能带来价值,那将毫无意义

简介

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

输入

    几何着色器阶段可将整个图元作为输入,并能够在输出上生成顶点。
    必须首先指定单次调用几何着色器输出的顶点的最大数量(每个图元调用几何着色器)。这可以通过使用以下属性语法在着色器定义之前设置最大顶点数:
[maxvertexcount(N)]
    其中N是几何着色器为单个调用输出的顶点的最大数量。几何着色器可以在每次调用时输出的顶点数量是可变的,但不能超过定义的最大值。出于性能考虑,最大顶点数应尽可能小; [NVIDIA08]指出,当GS输出在1到20个标量之间时,可以实现GS的性能峰值,如果GS输出在27-40个标量之间,则性能下降50%。每次调用的标量输出数是最大顶点输出数和输出顶点类型结构中的标量数的乘积。

基本图形描述
point 绘制GL_POINTS基本图形的时候(1)
line 当绘制GL_LINES或GL_LINE_STRIP(2)时
lineadj输入图元具有邻接线段(4)
triangle GL_TRIANGLES, GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN(3)
triangleadj输入图元具有邻接三角形(6)

输出

几何着色器通过将顶点附加到输出流对象来一次输出一个顶点。 流的拓扑由固定声明确定,选择 TriangleStream、LineStream 和 PointStream 作为 GS 阶段的输出。

声明

  1.  
  2. [maxvertexcount(3)] 
  3. void geometry_shader(point VS_OUTPUT IN[1], inout TriangleStream<GS_ 
  4. OUTPUT> triStream) { /*shader body*/

示例

不做处理

    几何着色器位于顶点着色器和片元着色器之间,下面示例中几何着色器没做多余的效果,仅仅相当于默认的数据传递。

  1. Shader "ShaderCookbook/几何着色器/SimplePoint" 

  2. Properties 

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

  4. SubShader 

  5. Tags { "RenderType"="Opaque" } 
  6. LOD 100 
  7.  
  8. Pass 

  9. CGPROGRAM 
  10. #pragma vertex vert 
  11. //-------声明几何着色器 
  12. #pragma geometry geom 
  13. #pragma fragment frag 
  14.  
  15. #include "UnityCG.cginc" 
  16.  
  17. struct appdata 

  18. float4 vertex : POSITION; 
  19. float2 uv : TEXCOORD0; 
  20. }; 
  21.  
  22. //-------顶点向几何阶段传递数据 
  23. struct v2g{ 
  24. float4 vertex:SV_POSITION; 
  25. float2 uv:TEXCOORD0; 
  26. }; 
  27.  
  28. //-------几何阶段向片元阶段传递数据 
  29. struct g2f 

  30. float2 uv : TEXCOORD0; 
  31. float4 vertex : SV_POSITION; 
  32. }; 
  33.  
  34. sampler2D _MainTex; 
  35. float4 _MainTex_ST; 
  36.  
  37. v2g vert (appdata v) 

  38. v2g o; 
  39. o.vertex = UnityObjectToClipPos(v.vertex); 
  40. o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
  41. return o; 

  42.  
  43. //-------静态制定单个调用的最大顶点个数 
  44. [maxvertexcount(3)] 
  45. void geom(triangle v2g input[3],inout TriangleStream<g2f> outStream){ 
  46. for(int i=0;i<3;i++){ 
  47. g2f o=(g2f)0
  48. o.vertex=input[i].vertex; 
  49. o.uv=input[i].uv; 
  50.  
  51. //-----将一个顶点添加到输出流列表 
  52. outStream.Append(o); 

  53.  
  54. //-------restart strip可以模拟一个primitives list 
  55. outStream.RestartStrip(); 

  56.  
  57. fixed4 frag (g2f i) : SV_Target 

  58. // sample the texture 
  59. fixed4 col = tex2D(_MainTex, i.uv); 
  60. return col; 

  61. ENDCG 



  62.  

示例一:单纯的点

 

点

 

  1. Shader "ShaderCookbook/几何着色器/OnlyPoint" 

  2. Properties 

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

  4. SubShader 

  5. Tags { "RenderType"="Opaque" } 
  6. LOD 100 
  7.  
  8. Pass 

  9. CGPROGRAM 
  10. #pragma vertex vert 
  11. //-------声明几何着色器 
  12. #pragma geometry geom 
  13. #pragma fragment frag 
  14.  
  15. #include "UnityCG.cginc" 
  16.  
  17. struct appdata 

  18. float4 vertex : POSITION; 
  19. float2 uv : TEXCOORD0; 
  20. }; 
  21.  
  22. //-------顶点向几何阶段传递数据 
  23. struct v2g{ 
  24. float4 vertex:SV_POSITION; 
  25. float2 uv:TEXCOORD0; 
  26. }; 
  27.  
  28. //-------几何阶段向片元阶段传递数据 
  29. struct g2f 

  30. float2 uv : TEXCOORD0; 
  31. float4 vertex : SV_POSITION; 
  32. }; 
  33.  
  34. sampler2D _MainTex; 
  35. float4 _MainTex_ST; 
  36.  
  37. v2g vert (appdata v) 

  38. v2g o; 
  39. o.vertex = UnityObjectToClipPos(v.vertex); 
  40. o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
  41. return o; 

  42.  
  43. //-------静态制定单个调用的最大顶点个数 
  44. [maxvertexcount(4)] 
  45. void geom(point v2g input[1],inout PointStream<g2f> outStream){ 
  46. g2f o=(g2f)0
  47. o.vertex=input[0].vertex; 
  48. o.uv=input[0].uv; 
  49.  
  50. outStream.Append(o); 

  51.  
  52. fixed4 frag (g2f i) : SV_Target 

  53. // sample the texture 
  54. fixed4 col = tex2D(_MainTex, i.uv); 
  55. return col; 

  56. ENDCG 



  57.  

示例二:散裂

    这里需要注意的是我们通过以v[0]为原点构建两个向量,通过这两个向量我们可以自定义点。

 

由s,t构成的仿射坐标系
由s,t构成的仿射坐标系

 

 

炸裂
炸裂

 

  1. Shader "ShaderCookbook/GeometryShader/分解" { 
  2. Properties { 
  3. _MainTex("Texture", 2 D) = "white" {} 
  4. _Height("Length", float) = 0.5 
  5. _Offset("Offset", float) = 0.1 
  6.  
  7. _StripColor("StripColor", Color) = (1, 1, 1, 1
  8. _OutColor("OutColor", Color) = (1, 1, 1, 1
  9. _InColor("InColor", Color) = (1, 1, 1, 1

  10. SubShader { 
  11. Cull off 
  12. Pass { 
  13. Tags { 
  14. "RenderType" = "Opaque" 

  15.  
  16. CGPROGRAM# pragma vertex vert# pragma fragment frag#include "UnityCG.cginc" 
  17.  
  18. struct appdata { 
  19. float4 vertex: POSITION; 
  20. float2 uv: TEXCOORD0; 
  21. }; 
  22.  
  23. struct v2f { 
  24. float4 vertex: SV_POSITION; 
  25. float4 objPos: TEXCOORD1; 
  26. float2 uv: TEXCOORD0; 
  27. }; 
  28.  
  29. sampler2D _MainTex; 
  30. float4 _MainTex_ST; 
  31. float _Height; 
  32. float _Offset; 
  33. fixed4 _StripColor; 
  34.  
  35. v2f vert(appdata v) { 
  36. v2f o; 
  37. o.vertex = UnityObjectToClipPos(v.vertex); 
  38. o.objPos = v.vertex; 
  39. o.uv = v.uv; 
  40. return o; 

  41.  
  42. fixed4 frag(v2f i): SV_Target { 
  43. fixed4 col = tex2D(_MainTex, i.uv); 
  44.  
  45. clip(_Height + _Offset - i.objPos.y); 
  46.  
  47. if (i.objPos.y > _Height) 
  48. col = _StripColor; 
  49.  
  50. return col; 

  51. ENDCG 

  52.  
  53. pass { 
  54. Tags { 
  55. "RenderType" = "Opaque" 

  56.  
  57. CGPROGRAM# pragma vertex vert# pragma geometry geome# pragma fragment frag#include "UnityCG.cginc" 
  58.  
  59. fixed4 _OutColor; 
  60. fixed4 _InColor; 
  61. float _Height; 
  62. float _Offset; 
  63.  
  64. struct appdata { 
  65. float4 vertex: POSITION; 
  66. float2 uv: TEXCOORD0; 
  67. float3 normal: NORMAL; 
  68. }; 
  69.  
  70. struct v2g { 
  71. float4 objPos: TEXCOORD0; 
  72. float3 normal: NORMAL; 
  73. }; 
  74.  
  75. struct g2f { 
  76. float4 vertex: SV_POSITION; 
  77. fixed4 col: TEXCOORD0; 
  78. }; 
  79.  
  80. void ADD_VERT(float4 v, g2f o, inout PointStream < g2f > outstream) { 
  81. o.vertex = v; 
  82. outstream.Append(o); 

  83.  
  84. v2g vert(appdata v) { 
  85. v2g o; 
  86. o.objPos = v.vertex; 
  87. o.normal = v.normal; 
  88. return o; 

  89.  
  90. [maxvertexcount(6)] 
  91. void geome(triangle v2g input[3], inout PointStream < g2f > outStream) { 
  92. g2f o; 
  93.  
  94. //--------将一个三角面三个顶点的平均位置作为均值 
  95. float4 vertex = (input[0].objPos + input[1].objPos + input[2].objPos) / 3.0
  96. float3 normal = (input[0].normal + input[1].normal + input[2].normal) / 3.0
  97.  
  98. if (vertex.y < _Height + _Offset) 
  99. return
  100.  
  101. //-------以v[0]为原点构建两个向量,用来在后续过程中通过这两个向量来构建三角面中自定义的点 
  102. float4 s = input[1].objPos - input[0].objPos; 
  103. float4 t = input[2].objPos - input[0].objPos; 
  104.  
  105. o.col = _OutColor * 2
  106. for (int i = 0; i < 3; i++) { 
  107. input[i].objPos.xyz += input[i].normal * (vertex.y - _Height); 
  108. input[i].objPos = UnityObjectToClipPos(input[i].objPos); 
  109. ADD_VERT(input[i].objPos, o, outStream); 

  110.  
  111. o.col = _InColor * 2
  112.  
  113. //-------通过s,t两个向量构建自定义点 
  114. float4 v[3]; 
  115.  
  116. v[0] = 0.2 * s + 0.2 * t; 
  117. v[1] = 0.4 * s + 0.6 * t; 
  118. v[2] = 0.6 * s + 0.4 * t; 
  119.  
  120. for (int i = 0; i < 3; i++) { 
  121. v[i].xyz += normal * (vertex.y - _Height); 
  122. v[i] = UnityObjectToClipPos(v[i]); 
  123. ADD_VERT(v[i], o, outStream); 


  124.  
  125. fixed4 frag(g2f i): SV_Target { 
  126. fixed4 col = i.col; 
  127. return col; 

  128. ENDCG 
  129.  



线

 

线
线

 

示例:wire frame

  1. Shader "ShaderCookbook/几何着色器/TriangleLine" 

  2. Properties 

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

  4. SubShader 

  5. Tags { "RenderType"="Opaque" } 
  6. LOD 100 
  7.  
  8. Pass 

  9. CGPROGRAM 
  10. #pragma vertex vert 
  11. //-------声明几何着色器 
  12. #pragma geometry geom 
  13. #pragma fragment frag 
  14.  
  15. #include "UnityCG.cginc" 
  16.  
  17. struct appdata 

  18. float4 vertex : POSITION; 
  19. float2 uv : TEXCOORD0; 
  20. }; 
  21.  
  22. //-------顶点向几何阶段传递数据 
  23. struct v2g{ 
  24. float4 vertex:SV_POSITION; 
  25. float2 uv:TEXCOORD0; 
  26. }; 
  27.  
  28. //-------几何阶段向片元阶段传递数据 
  29. struct g2f 

  30. float2 uv : TEXCOORD0; 
  31. float4 vertex : SV_POSITION; 
  32. }; 
  33.  
  34. sampler2D _MainTex; 
  35. float4 _MainTex_ST; 
  36.  
  37. v2g vert (appdata v) 

  38. v2g o; 
  39. o.vertex = UnityObjectToClipPos(v.vertex); 
  40. o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
  41. return o; 

  42.  
  43. //-------静态制定单个调用的最大顶点个数 
  44. [maxvertexcount(3)] 
  45. //使用三角面作为输入,线段作为输出我们得到完整的线框 
  46. void geom(triangle v2g input[3],inout LineStream<g2f> outStream){ 
  47. g2f o=(g2f)0
  48. o.vertex=input[0].vertex; 
  49. o.uv=input[0].uv; 
  50.  
  51. outStream.Append(o); 
  52.  
  53.  
  54. o.vertex=input[1].vertex; 
  55. o.uv=input[1].uv; 
  56.  
  57. outStream.Append(o); 
  58.  
  59. o.vertex=input[2].vertex; 
  60. o.uv=input[2].uv; 
  61. outStream.Append(o); 
  62.  

  63.  
  64. fixed4 frag (g2f i) : SV_Target 

  65. // sample the texture 
  66. fixed4 col = tex2D(_MainTex, i.uv); 
  67. return col; 

  68. ENDCG 



  69.  

 

enter description here
enter description here

 

示例:尖刺

  1. Shader "ShaderCookbook/GeometryShader/尖刺" { 
  2. Properties { 
  3. _MainTex("Texture", 2D) = "white" {} 
  4. _Length("Length", float) = 0.5 

  5. SubShader { 
  6. Tags { 
  7. "RenderType" = "Opaque" 

  8. LOD 100 
  9.  
  10. Pass { 
  11. CGPROGRAM 
  12. #pragma vertex vert 
  13. #pragma geometry geom 
  14. #pragma fragment frag 
  15. // make fog work 
  16. #pragma multi_compile_fog 
  17. #include "UnityCG.cginc" 
  18.  
  19. struct appdata { 
  20. float4 vertex: POSITION; 
  21. float2 uv: TEXCOORD0; 
  22. }; 
  23.  
  24. struct v2g { 
  25. float4 pos: SV_POSITION; 
  26. float2 uv: TEXCOORD0; 
  27. }; 
  28.  
  29. struct g2f { 
  30. float2 uv: TEXCOORD0; 
  31. float4 vertex: SV_POSITION; 
  32. }; 
  33.  
  34. sampler2D _MainTex; 
  35. float4 _MainTex_ST; 
  36. float _Length; 
  37.  
  38.  
  39. void ADD_VERT(float3 v, g2f o, inout TriangleStream < g2f > tristream) { 
  40. o.vertex = UnityObjectToClipPos(v); 
  41. tristream.Append(o); 

  42.  
  43.  
  44. void ADD_TRI(float3 p0, float3 p1, float3 p2, g2f o, inout TriangleStream < g2f > tristream) { 
  45. ADD_VERT(p0, o, tristream); 
  46. ADD_VERT(p1, o, tristream); 
  47. ADD_VERT(p2, o, tristream); 
  48. tristream.RestartStrip(); 

  49.  
  50.  
  51. v2g vert(appdata v) { 
  52. v2g o = (v2g) 0
  53. o.pos = v.vertex; 
  54. o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
  55. return o; 

  56.  
  57. [maxvertexcount(9)] 
  58. void geom(triangle v2g input[3], inout TriangleStream < g2f > outStream) { 
  59. g2f o; 
  60.  
  61. //-----------这里通过三角面的两个边叉乘来获得垂直于三角面的法线方向 
  62. float3 s = (input[1].pos - input[0].pos).xyz; 
  63. float3 t = (input[2].pos - input[0].pos).xyz; 
  64.  
  65. float3 normal = normalize(cross(s, t)); 
  66.  
  67. float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz) / 3.0
  68. float2 centerUv = (input[0].uv + input[1].uv + input[2].uv) / 3.0
  69.  
  70. o.uv = centerUv; 
  71.  
  72. centerPos += normal * _Length * abs(sin(_Time.y * 5)); 
  73.  
  74. ADD_TRI(input[0].pos, centerPos, input[2].pos, o, outStream); 
  75. ADD_TRI(input[2].pos, centerPos, input[1].pos, o, outStream); 
  76. ADD_TRI(input[1].pos, centerPos, input[0].pos, o, outStream); 
  77.  
  78.  

  79. fixed4 frag(g2f i): SV_Target { 
  80. fixed4 col = tex2D(_MainTex, i.uv); 
  81. return col; 

  82. ENDCG 



 

eqm2Bj23236

参考一
参考二
参考三
可视化shader编程工具

这里推荐一款可视化shader编程工具,对美术同学非常友好,就像建模工具中的材质编辑器一样

免责声明:文章转载自《Unity 几何着色器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇几篇关于MySQL数据同步到Elasticsearch的文章---第二篇:canal 实现Mysql到Elasticsearch实时增量同步windowForm学习资料总结下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity3D–Texture图片空间和内存占用分析

Texture图片空间和内存占用分析。由于U3D并没有很好的诠释对于图片的处理方式,所以很多人一直对于图集的大小和内存的占用情况都不了解。在此对于U3D的图片问题做一个实际数据的分析。此前的项目都会存在这样或者那样的打包后包大小与内存占用情况的问题,所以这次所以彻彻底底得分析下U3D对于Texture的处理方式。程序里的内存优化请参考《Unity3d优化之...

Unity NavMesh 格式 解析 分析 对比 Recast Navigation

工具软件 Excel Nodepad++ Sublime Unity 5.4 / 5.6 VS RecastDemo CodeBlocks 分析过程以Unity项目-Demo13为例 一. 创建测试模型 在Unity里搭建一个简单的寻路模型,并导出模型obj到Recastnavigation. 首先, 寻路模型要尽可能简单,(在Unity里,只包含2个N...

Unity3D 解决用Unity导出的Android工程在6.0及以上设备会弹出一串权限对话框的问题

解决用Unity导出的Android工程在6.0及以上设备会弹出一串权限对话框的问题 <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />...

Android全局桌面宠物 Unity方案实现

转载:https://blog.csdn.net/xssdmx/article/details/107315493 Android全局桌面宠物 Unity方案实现 最近接到一个任务是Android设备上实现一个全局的指引动画,开始想着就用普通动画控件或者svga、lottie控件实现,最近正好在学习Unity,所以试着用unity实现。经过三天努力,居...

在Unity中使用Lua脚本

前言:为什么要用Lua首先要说,所有编程语言里面,我最喜欢的还是C#,VisualStudio+C#,只能说太舒服了。所以说,为什么非要在unity里面用Lua呢?可能主要是闲的蛋疼。。。。。另外还有一些次要原因:方便做功能的热更新;Lua语言的深度和广度都不大,易学易用,可以降低项目成本。C#与Lua互相调用的方案坦白来将,我并没有对现在C#与Lua互相...

Unity3D获取系统当前时间,并格式化显示

Unity 获取系统当前时间,并格式化显示。通过“System.DateTime”获取系统当前的时间,然后通过格式化把获得的时间格式化显示出来,具体如下: 1、打开Unity,新建一个空工程,Unity界面如下图 2、在工程中新建一个脚本,可以命名为“CurrrentTimeTest”,选中“CurrrentTimeTest”,双击打开脚本。 3、在打...