Unity 几何着色器
Unity 几何着色器
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 阶段的输出。
声明
- [maxvertexcount(3)]
- void geometry_shader(point VS_OUTPUT IN[1], inout TriangleStream<GS_
- OUTPUT> triStream) { /*shader body*/ }
示例
不做处理
几何着色器位于顶点着色器和片元着色器之间,下面示例中几何着色器没做多余的效果,仅仅相当于默认的数据传递。
- Shader "ShaderCookbook/几何着色器/SimplePoint"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- //-------声明几何着色器
- #pragma geometry geom
- #pragma fragment frag
- #include "UnityCG.cginc"
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
- //-------顶点向几何阶段传递数据
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
- //-------几何阶段向片元阶段传递数据
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
- sampler2D _MainTex;
- float4 _MainTex_ST;
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
- //-------静态制定单个调用的最大顶点个数
- [maxvertexcount(3)]
- void geom(triangle v2g input[3],inout TriangleStream<g2f> outStream){
- for(int i=0;i<3;i++){
- g2f o=(g2f)0;
- o.vertex=input[i].vertex;
- o.uv=input[i].uv;
- //-----将一个顶点添加到输出流列表
- outStream.Append(o);
- }
- //-------restart strip可以模拟一个primitives list
- outStream.RestartStrip();
- }
- fixed4 frag (g2f i) : SV_Target
- {
- // sample the texture
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
点
示例一:单纯的点

- Shader "ShaderCookbook/几何着色器/OnlyPoint"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- //-------声明几何着色器
- #pragma geometry geom
- #pragma fragment frag
- #include "UnityCG.cginc"
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
- //-------顶点向几何阶段传递数据
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
- //-------几何阶段向片元阶段传递数据
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
- sampler2D _MainTex;
- float4 _MainTex_ST;
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
- //-------静态制定单个调用的最大顶点个数
- [maxvertexcount(4)]
- void geom(point v2g input[1],inout PointStream<g2f> outStream){
- g2f o=(g2f)0;
- o.vertex=input[0].vertex;
- o.uv=input[0].uv;
- outStream.Append(o);
- }
- fixed4 frag (g2f i) : SV_Target
- {
- // sample the texture
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
示例二:散裂
这里需要注意的是我们通过以v[0]为原点构建两个向量,通过这两个向量我们可以自定义点。


- Shader "ShaderCookbook/GeometryShader/分解" {
- Properties {
- _MainTex("Texture", 2 D) = "white" {}
- _Height("Length", float) = 0.5
- _Offset("Offset", float) = 0.1
- _StripColor("StripColor", Color) = (1, 1, 1, 1)
- _OutColor("OutColor", Color) = (1, 1, 1, 1)
- _InColor("InColor", Color) = (1, 1, 1, 1)
- }
- SubShader {
- Cull off
- Pass {
- Tags {
- "RenderType" = "Opaque"
- }
- CGPROGRAM# pragma vertex vert# pragma fragment frag#include "UnityCG.cginc"
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- };
- struct v2f {
- float4 vertex: SV_POSITION;
- float4 objPos: TEXCOORD1;
- float2 uv: TEXCOORD0;
- };
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _Height;
- float _Offset;
- fixed4 _StripColor;
- v2f vert(appdata v) {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.objPos = v.vertex;
- o.uv = v.uv;
- return o;
- }
- fixed4 frag(v2f i): SV_Target {
- fixed4 col = tex2D(_MainTex, i.uv);
- clip(_Height + _Offset - i.objPos.y);
- if (i.objPos.y > _Height)
- col = _StripColor;
- return col;
- }
- ENDCG
- }
- pass {
- Tags {
- "RenderType" = "Opaque"
- }
- CGPROGRAM# pragma vertex vert# pragma geometry geome# pragma fragment frag#include "UnityCG.cginc"
- fixed4 _OutColor;
- fixed4 _InColor;
- float _Height;
- float _Offset;
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- float3 normal: NORMAL;
- };
- struct v2g {
- float4 objPos: TEXCOORD0;
- float3 normal: NORMAL;
- };
- struct g2f {
- float4 vertex: SV_POSITION;
- fixed4 col: TEXCOORD0;
- };
- void ADD_VERT(float4 v, g2f o, inout PointStream < g2f > outstream) {
- o.vertex = v;
- outstream.Append(o);
- }
- v2g vert(appdata v) {
- v2g o;
- o.objPos = v.vertex;
- o.normal = v.normal;
- return o;
- }
- [maxvertexcount(6)]
- void geome(triangle v2g input[3], inout PointStream < g2f > outStream) {
- g2f o;
- //--------将一个三角面三个顶点的平均位置作为均值
- float4 vertex = (input[0].objPos + input[1].objPos + input[2].objPos) / 3.0;
- float3 normal = (input[0].normal + input[1].normal + input[2].normal) / 3.0;
- if (vertex.y < _Height + _Offset)
- return;
- //-------以v[0]为原点构建两个向量,用来在后续过程中通过这两个向量来构建三角面中自定义的点
- float4 s = input[1].objPos - input[0].objPos;
- float4 t = input[2].objPos - input[0].objPos;
- o.col = _OutColor * 2;
- for (int i = 0; i < 3; i++) {
- input[i].objPos.xyz += input[i].normal * (vertex.y - _Height);
- input[i].objPos = UnityObjectToClipPos(input[i].objPos);
- ADD_VERT(input[i].objPos, o, outStream);
- }
- o.col = _InColor * 2;
- //-------通过s,t两个向量构建自定义点
- float4 v[3];
- v[0] = 0.2 * s + 0.2 * t;
- v[1] = 0.4 * s + 0.6 * t;
- v[2] = 0.6 * s + 0.4 * t;
- for (int i = 0; i < 3; i++) {
- v[i].xyz += normal * (vertex.y - _Height);
- v[i] = UnityObjectToClipPos(v[i]);
- ADD_VERT(v[i], o, outStream);
- }
- }
- fixed4 frag(g2f i): SV_Target {
- fixed4 col = i.col;
- return col;
- }
- ENDCG
- }
- }
- }
线

示例:wire frame
- Shader "ShaderCookbook/几何着色器/TriangleLine"
- {
- Properties
- {
- _MainTex ("Texture", 2D) = "white" {}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" }
- LOD 100
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- //-------声明几何着色器
- #pragma geometry geom
- #pragma fragment frag
- #include "UnityCG.cginc"
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
- //-------顶点向几何阶段传递数据
- struct v2g{
- float4 vertex:SV_POSITION;
- float2 uv:TEXCOORD0;
- };
- //-------几何阶段向片元阶段传递数据
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
- sampler2D _MainTex;
- float4 _MainTex_ST;
- v2g vert (appdata v)
- {
- v2g o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
- //-------静态制定单个调用的最大顶点个数
- [maxvertexcount(3)]
- //使用三角面作为输入,线段作为输出我们得到完整的线框
- void geom(triangle v2g input[3],inout LineStream<g2f> outStream){
- g2f o=(g2f)0;
- o.vertex=input[0].vertex;
- o.uv=input[0].uv;
- outStream.Append(o);
- o.vertex=input[1].vertex;
- o.uv=input[1].uv;
- outStream.Append(o);
- o.vertex=input[2].vertex;
- o.uv=input[2].uv;
- outStream.Append(o);
- }
- fixed4 frag (g2f i) : SV_Target
- {
- // sample the texture
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
面

示例:尖刺
- Shader "ShaderCookbook/GeometryShader/尖刺" {
- Properties {
- _MainTex("Texture", 2D) = "white" {}
- _Length("Length", float) = 0.5
- }
- SubShader {
- Tags {
- "RenderType" = "Opaque"
- }
- LOD 100
- Pass {
- CGPROGRAM
- #pragma vertex vert
- #pragma geometry geom
- #pragma fragment frag
- // make fog work
- #pragma multi_compile_fog
- #include "UnityCG.cginc"
- struct appdata {
- float4 vertex: POSITION;
- float2 uv: TEXCOORD0;
- };
- struct v2g {
- float4 pos: SV_POSITION;
- float2 uv: TEXCOORD0;
- };
- struct g2f {
- float2 uv: TEXCOORD0;
- float4 vertex: SV_POSITION;
- };
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _Length;
- void ADD_VERT(float3 v, g2f o, inout TriangleStream < g2f > tristream) {
- o.vertex = UnityObjectToClipPos(v);
- tristream.Append(o);
- }
- void ADD_TRI(float3 p0, float3 p1, float3 p2, g2f o, inout TriangleStream < g2f > tristream) {
- ADD_VERT(p0, o, tristream);
- ADD_VERT(p1, o, tristream);
- ADD_VERT(p2, o, tristream);
- tristream.RestartStrip();
- }
- v2g vert(appdata v) {
- v2g o = (v2g) 0;
- o.pos = v.vertex;
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- return o;
- }
- [maxvertexcount(9)]
- void geom(triangle v2g input[3], inout TriangleStream < g2f > outStream) {
- g2f o;
- //-----------这里通过三角面的两个边叉乘来获得垂直于三角面的法线方向
- float3 s = (input[1].pos - input[0].pos).xyz;
- float3 t = (input[2].pos - input[0].pos).xyz;
- float3 normal = normalize(cross(s, t));
- float3 centerPos = (input[0].pos.xyz + input[1].pos.xyz + input[2].pos.xyz) / 3.0;
- float2 centerUv = (input[0].uv + input[1].uv + input[2].uv) / 3.0;
- o.uv = centerUv;
- centerPos += normal * _Length * abs(sin(_Time.y * 5));
- ADD_TRI(input[0].pos, centerPos, input[2].pos, o, outStream);
- ADD_TRI(input[2].pos, centerPos, input[1].pos, o, outStream);
- ADD_TRI(input[1].pos, centerPos, input[0].pos, o, outStream);
- }
- fixed4 frag(g2f i): SV_Target {
- fixed4 col = tex2D(_MainTex, i.uv);
- return col;
- }
- ENDCG
- }
- }
- }
Other
项目工程:链接: https://pan.baidu.com/s/1eGk6GHIfWzIFcAX6pxTGRA 提取码: fv75
解压密码:https://fgk.pw/i/eqm2Bj23236
这里推荐一款可视化shader编程工具,对美术同学非常友好,就像建模工具中的材质编辑器一样
Unity 几何着色器的更多相关文章
- DirectX11 With Windows SDK--15 几何着色器初探
前言 从这一部分开始,感觉就像是踏入了无人深空一样,在之前初学DX11的时候,这部分内容都是基本上跳过的,现在打算重新认真地把它给拾回来. DirectX11 With Windows SDK完整目录 ...
- DirectX11 With Windows SDK--17 利用几何着色器实现公告板效果
前言 上一章我们知道了如何使用几何着色器将顶点通过流输出阶段输出到绑定的顶点缓冲区.接下来我们继续利用它来实现一些新的效果,在这一章,你将了解: 实现公告板效果 Alpha-To-Coverage 对 ...
- 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化
翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...
- Unity Shader着色器优化
https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247493518&idx=1&sn=c51b92e9300bcf ...
- Unity 5着色器系统代码介绍(上)
http://forum.china.unity3d.com/thread-25724-1-10.html Unity 5着色器系统代码介绍(上) Unity在着色器开发方面提供了很大的灵活性.有些工 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十二章:几何着色器(The Geometry Shader)
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十二章:几何着色器(The Geometry Shader) 代码工 ...
- [Unity] Shader(着色器)输入输出和语义
在Unity5.x后, 已经支持了基于物理的光照模型,也就是常说的次时代引擎所必须具备的功能. 如果在Properties使用2D,CG里要用sampler2D,代表使用的是2维纹理 如果在Prope ...
- Unity 5着色器系统代码介绍(下)
http://forum.china.unity3d.com/thread-25738-1-10.html 上一篇对着色器系统的工作原理做了介绍,现在我们将继续深入,将目光聚焦在标准着色器的光照函数. ...
- [Unity] Shader(着色器)之纹理贴图
在Shader中,我们除了可以设定各种光线处理外,还可以增加纹理贴图. 使用 settexture 命令可以为着色器指定纹理. 示例代码: Shader "Sbin/ff2" { ...
随机推荐
- 以太坊系列之一: 以太坊RLP用法-以太坊源码学习
RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式.RLP的唯一目标就是解决结构体的编码问题:对原子数据类型(比如,字符串,整数型, ...
- 在.NET中操作数字证书(新手教程)
.NET为我们提供了操作数字证书的两个主要的类,分为为: System.Security.Cryptography.X509Certificates.X509Certificate2类, 每个这个类的 ...
- python第十八课——常用内置函数
常用内置函数:round(): print(round(3.14),round(3.99)) print(round(3145.926,-2),round(413.575,2)) abs(): pri ...
- 微软YY公开课[《微软中国云计算Azure平台体验与新企业架构设计》 周六晚9点
YY频道是 52545291//@_勤_: YY账号真的是一次一账号啊! 全然记不得之前注冊的//@老徐FrankXuLei: 最火爆的微软免费公开课.第一次顶峰126人.第二次96人.第三次我们又来 ...
- BZOJ1444:[JSOI2009]有趣的游戏(AC自动机,矩阵乘法)
Description Input 注意 是0<=P, n , l, m≤ 10. Output Sample Input input 1 3 2 2 1 2 1 2 AB BA AA inpu ...
- 配置网卡绑卡 --RHEL7
配置网卡绑卡 1)网卡绑定(team方式) # 创建组接口nmcli connection add type team ifname team0 con-name team0 config '{&qu ...
- Day10 MVC
经典三层 表述层(表示层): 前台交互,调用后台 web 业务逻辑层: 处理业务 service 数据持久层: 与数据库之间进行交互 dao 面向对象原则 面 ...
- docker 不同版本 添加--insecure-registry
docker 17.0.3 vim /lib/systemd/system/docker.service 然后重启 systemctl daemon-reload , systemctl rest ...
- DevOps 解读
本文为 转载文章, 非原创 DevOps DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化.运 ...
- SRcnn:神经网络重建图片的开山之作
% ========================================================================= % Test code for Super-Re ...