使用声明
#pragma geometry GS_Main
(2) 函数
【设置输出最大顶点数量】
函数前添加[maxvertexcount(4)]
【输入】的图元
必须添加以下前缀之一,例如添加Point就是指这个三角形被当作一个point读取第一个点。(注意如果处理一个quad,2个三角形,所以实际上只有2个点,而不是全部4个顶点)
point line triangle lineadj triangleadj
【输出】必须加inout前缀, triStream.Append(pIn);
PointStream
LineStream
TriangleStream
- [maxvertexcount(11)]
- void GS_Main(triangle GS_INPUT p[3], inout TriangleStream triStream)
- {
- for(int i=0;i<<font face="Consolas"> 3;i++)
- {
- FS_INPUT f;
- f.pos = p[i].pos;
- f.tex0 = p[i].tex0;
- triStream.Append(f);
- }
- triStream.RestartStrip();
- }
[例:不处理]
本例实现的效果和普通的Vertex/Fragment Shader效果一样。
- Shader "Custom/0same"
- {
- Properties
- {
- _MainTex ("Particle Texture", 2D) = "white" {}
- }
- SubShader
- {
- Pass
- {
- Tags { "RenderType"="Opaque" }
-
- CGPROGRAM
- #pragma target 5.0
- #pragma vertex VS_Main
- #pragma fragment FS_Main
- #pragma geometry GS_Main
- #include "UnityCG.cginc"
- sampler2D _MainTex;
- float4 _MainTex_ST;
- struct GS_INPUT
- {
- float4 pos : POSITION;
- float3 normal : NORMAL;
- float2 tex0 : TEXCOORD0;
- };
- struct FS_INPUT
- {
- float4 pos : SV_POSITION;
- float2 tex0 : TEXCOORD0;
- };
- //step1
- GS_INPUT VS_Main(appdata_base v)
- {
- GS_INPUT output = (GS_INPUT)0;
- output.pos = mul(UNITY_MATRIX_MVP,v.vertex);
- output.tex0 = TRANSFORM_TEX(v.texcoord,_MainTex);
- output.normal = v.normal;
- return output;
- }
- //step2
- [maxvertexcount(11)]
- void GS_Main(triangle GS_INPUT p[3], inout TriangleStream triStream)
- {
- for(int i=0;i <<font face="Consolas"> 3;i++)
- {
- FS_INPUT f;
- f.pos = p[i].pos;
- f.tex0 = p[i].tex0;
- triStream.Append(f);
- }
- triStream.RestartStrip();
- }
- //step3
- float4 FS_Main(FS_INPUT i) : COLOR
- {
- fixed4 col = tex2D(_MainTex, i.tex0);
- return col;
- }
- ENDCG
- }
- }
- }
[例一:显示模型顶点]
- Shader "Custom/ShowDots"
- {
- Properties
- {
- }
- SubShader
- {
- Pass
- {
- Tags { "RenderType"="Opaque" }
- LOD 200
-
- CGPROGRAM
- #pragma target 5.0
- #pragma vertex VS_Main
- #pragma fragment FS_Main
- #pragma geometry GS_Main
- #include "UnityCG.cginc"
- struct GS_INPUT
- {
- float4 pos : POSITION;
- float3 normal : NORMAL;
- float2 tex0 : TEXCOORD0;
- };
- struct FS_INPUT
- {
- float4 pos : POSITION;
- float2 tex0 : TEXCOORD0;
- };
- //step1
- GS_INPUT VS_Main(appdata_base v)
- {
- GS_INPUT output = (GS_INPUT)0;
- output.pos = mul(_Object2World, v.vertex);
- output.normal = v.normal;
- output.tex0 = float2(0, 0);
- return output;
- }
- //step2
- [maxvertexcount(4)]
- void GS_Main(point GS_INPUT p[1], inout PointStream triStream)
- {
- float4 v = float4(p[0].pos.x,p[0].pos.y,p[0].pos.z,1.0f);
- //can move up a little bit
- // v = v + float4(0,1,0,0);
- float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
- FS_INPUT pIn;
- pIn.pos = mul(vp, v);
- pIn.tex0 = float2(0.0f, 0.0f);
- triStream.Append(pIn);
- }
- //step3
- float4 FS_Main(FS_INPUT input) : COLOR
- {
- return float4(1,1,1,1);
- }
- ENDCG
- }
- }
- }
因为每个三角形只读一个点,如果改成如下,就每个点都显示了。
Shader "Custom/1ShowPoints2"
{
Properties
{
}
SubShader
{
Pass
{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#pragma target 5.0
#pragma vertex VS_Main
#pragma fragment FS_Main
#pragma geometry GS_Main
#include "UnityCG.cginc"
struct GS_INPUT
{
float4 pos : POSITION;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
};
struct FS_INPUT
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
};
//step1
GS_INPUT VS_Main(appdata_base v)
{
GS_INPUT output = (GS_INPUT)0;
output.pos = v.vertex;
output.normal = v.normal;
output.tex0 = float2(0, 0);
return output;
}
//step2
[maxvertexcount(11)]
void GS_Main(triangle GS_INPUT p[3], inout PointStream triStream)
{
for(int i=0;i<<fontface="Consolas"> 3;i++)
{
float4 v = float4(p[i].pos.x,p[i].pos.y,p[i].pos.z,1.0f);
float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
FS_INPUT pIn;
pIn.pos = mul(UNITY_MATRIX_MVP, v);
pIn.tex0 = float2(0.0f, 0.0f);
triStream.Append(pIn);
}
}
//step3
float4 FS_Main(FS_INPUT input) : COLOR
{
return float4(1,1,1,1);
}
ENDCG
}
}
}
[例二:模型每个顶点显示一个公告板]
Shader "Custom/2Billboard"
{
Properties
{
_SpriteTex ("Base (RGB)", 2D) = "white" {}
_Size ("Size", Range(0, 3)) = 0.5
}
SubShader
{
Pass
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma target 5.0
#pragma vertex VS_Main
#pragma fragment FS_Main
#pragma geometry GS_Main
#include "UnityCG.cginc"
struct GS_INPUT
{
float4 pos : POSITION;
float3 normal : NORMAL;
float2 tex0 : TEXCOORD0;
};
struct FS_INPUT
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
};
float _Size;
float4x4 _VP;
Texture2D _SpriteTex;
SamplerState sampler_SpriteTex;
GS_INPUT VS_Main(appdata_base v)
{
GS_INPUT output = (GS_INPUT)0;
output.pos = mul(_Object2World, v.vertex);
output.normal = v.normal;
output.tex0 = float2(0, 0);
return output;
}
[maxvertexcount(4)]
void GS_Main(point GS_INPUT p[1], inout TriangleStream triStream)
{
float3 up = float3(0, 1, 0);
float3 look = _WorldSpaceCameraPos - p[0].pos;
look.y = 0;
look = normalize(look);
float3 right = cross(up, look);
float halfS = 0.5f * _Size;
float4 v[4];
v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
FS_INPUT pIn;
pIn.pos = mul(vp, v[0]);
pIn.tex0 = float2(1.0f, 0.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[1]);
pIn.tex0 = float2(1.0f, 1.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[2]);
pIn.tex0 = float2(0.0f, 0.0f);
triStream.Append(pIn);
pIn.pos = mul(vp, v[3]);
pIn.tex0 = float2(0.0f, 1.0f);
triStream.Append(pIn);
}
float4 FS_Main(FS_INPUT input) : COLOR
{
return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
}
ENDCG
}
}
}
[例三:输出金字塔]
- Shader "Custom/3Pyramid"
- {
- Properties
- {
- _MainTex ("Particle Texture", 2D) = "white" {}
- _Explode ("Explode factor", Range(0.0, 4.0)) = 1.0
- }
-
- SubShader
- {
- Pass
- {
- CGPROGRAM
- #pragma target 5.0
-
- #pragma vertex vert
- #pragma geometry geom
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float _Explode;
- float4x4 _ViewMatrix;
-
- struct VS_INPUT
- {
- float4 Pos : POSITION;
- float3 Norm : NORMAL;
- float2 Tex : TEXCOORD0;
- };
-
- // GEOMETRY
- struct GSPS_INPUT
- {
- float4 Pos : SV_POSITION;
- float3 Norm : TEXCOORD0;
- float2 Tex : TEXCOORD1;
- };
-
- // Vertex Shader
- GSPS_INPUT vert( VS_INPUT input )
- {
- GSPS_INPUT output = (GSPS_INPUT)0;
-
- output.Pos = input.Pos; // mul( float4(input.Pos,1), _Object2World); // mul( float4(input.Pos,1), World );
- output.Norm = input.Norm; // mul(input.Norm, (float3x3)_Object2World ); // mul( input.Norm, (float3x3)World );
- output.Tex = TRANSFORM_TEX(input.Tex, _MainTex); // input.Tex;
-
- return output;
- }
-
- // Geometry Shader
- [maxvertexcount(12)]
- void geom( triangle GSPS_INPUT input[3], inout TriangleStream outStream )
- {
- GSPS_INPUT output;
-
- // Calculate the face normal
- float3 faceEdgeA = input[1].Pos - input[0].Pos;
- float3 faceEdgeB = input[2].Pos - input[0].Pos;
- float3 faceNormal = normalize( cross(faceEdgeA, faceEdgeB) );
- float3 ExplodeAmt = faceNormal*_Explode;
-
- // Calculate the face center
- float3 centerPos = (input[0].Pos.xyz + input[1].Pos.xyz + input[2].Pos.xyz)/3.0;
- float2 centerTex = (input[0].Tex + input[1].Tex + input[2].Tex)/3.0;
- centerPos += faceNormal*_Explode;
-
- // Output the pyramid
- for( int i=0; i<<fontface="Consolas"> 3; i++ )
- {
- output.Pos = input[i].Pos + float4(ExplodeAmt,0);
- output.Pos = mul(UNITY_MATRIX_MVP, output.Pos);
- output.Norm = input[i].Norm;
- output.Tex = input[i].Tex;
- outStream.Append( output );
-
- int iNext = (i+1)%3;
- output.Pos = input[iNext].Pos + float4(ExplodeAmt,0);
- output.Pos = mul(UNITY_MATRIX_MVP, output.Pos);
- output.Norm = input[iNext].Norm;
- output.Tex = input[iNext].Tex;
- outStream.Append( output );
-
- output.Pos = float4(centerPos,1) + float4(ExplodeAmt,0);
- output.Pos = mul(UNITY_MATRIX_MVP, output.Pos);
- output.Norm = faceNormal;
- output.Tex = centerTex;
- outStream.Append( output );
-
- outStream.RestartStrip();
- }
-
- for( int i=2; i>=0; i-- )
- {
- output.Pos = input[i].Pos + float4(ExplodeAmt,0);
- output.Pos = mul(UNITY_MATRIX_MVP, output.Pos);
- output.Norm = -input[i].Norm;
- output.Tex = input[i].Tex;
- outStream.Append( output );
- }
- outStream.RestartStrip();
- }
-
-
- // FRAG
- fixed4 frag (GSPS_INPUT i ) : COLOR0
- {
- fixed4 col = tex2D(_MainTex, i.Tex);
- return col;
- }
- ENDCG
- }
- }
- Fallback Off
- }
参考:
http://forum.unity3d.com/threads/geometry-shaders.156553/
http://forum.unity3d.com/threads/is-it-possible-to-use-geometry-shader-with-surface-shaders.164905/
http://msdn.microsoft.com/en-us/library/windows/desktop/bb205122(v=vs.85).aspx
http://blog.csdn.net/pizi0475/article/details/7795429