Unity之Geometry Shader

       在DirectX 9的渲染管线中,可编程的Shader只有顶点着色器和片段着色器两类。但是在DirectX 10开始,渲染管线增加了一个【可选】的几何体着色器。

优点:可以修改网格(增删改模型的顶点及三角面等)

缺点:几何体着色器并行调用硬件困难,并行程度低,效率和顶点着色器有很大的差距

实现流程:(以一个简单的实例为准)

Shader "Custom/GeometryLearn"
{
	Properties
	{
	Height("SingleH",float)=0.5
	}
	SubShader
	{
		Pass
		{
			Tags
			{
				"RenderType"="Opaque"
			}
			
			CGPROGRAM
			#pragma target 5.0
			#pragma vertex VS_Main
			#pragma geometry GS_Main
			#pragma fragment FS_Main			
			#include "UnityCG.cginc"			
			float Height;		
			struct GS_INPUT
			{
				float4 pos:POSITION;
			};			
			struct FS_INPUT
			{
				float4 pos:SV_POSITION;
			};			
			
			GS_INPUT VS_Main(appdata_base v)
			{
				GS_INPUT output;
				output.pos=v.vertex;
				return output;
			};
			//vs的输出作为gs的输入
			[maxvertexcount(3)]
			//输入 point line triangle lineadj triangleadj----输出: PointStream只显示点,LineStream只显示线,TriangleStream全显
			void GS_Main(triangle GS_INPUT p[3],inout LineStream<FS_INPUT> triStream)
			{
				for(int i=0;i<3;i++)
				{
					FS_INPUT output;
					//读取原来的点,这里不做改变
					float4 pos=float4(p[i].pos.x,p[i].pos.y,p[i].pos.z,p[i].pos.w);								
					output.pos=UnityObjectToClipPos(pos);
					if(pos.y<Height)
					{
					  triStream.Append(output);
					}					
				}
				triStream.RestartStrip();
			}
			//gs的输出作为fs的输入
			float4 FS_Main(FS_INPUT i):COLOR
			{
				return fixed4(1,1,1,1);
			}			
			ENDCG
		}
	}
	
}

更复杂一点的例子:从球体表面挤出锥体

Shader "MyShader/GSTest"
{
	Properties
	{
	    _Color("MianColor",color)=(1,1,1,1)
		_Length("Length", Range(0.01, 10)) = 0.02
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100 
		Pass
		{
		Cull Off
			CGPROGRAM
			#pragma target 4.0
			#pragma vertex vert
			#pragma fragment frag
			#pragma geometry geom			
			#include "UnityCG.cginc" 
			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			}; 
			struct v2g
			{
				float4 vertex : POSITION;
				float3 nor:NORMAL;
			};
			struct g2f
			{
				float4 vertex : SV_POSITION;
				float3 norg:NORMAL;
			};
			float _Length;
			fixed4 _LightColor0;
			fixed4 _Color;
			v2g vert(appdata_base v)
			{
				v2g o;
				o.vertex = v.vertex;
				o.nor=v.normal;
				return o;
			}
 
		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();
		}
      			
		[maxvertexcount(9)]
		void geom(triangle v2g IN[3], inout TriangleStream<g2f> tristream)
		{
			g2f o; 
			//--------计算原模型三角面的法线
			float3 edgeA = IN[1].vertex - IN[0].vertex;
			float3 edgeB = IN[2].vertex - IN[0].vertex;
			float3 normalFace = normalize(cross(edgeA, edgeB));
			//-------
            o.norg=-normalFace;
			//根据模型三角面信息额外生成一个向外突出的锥体
			float3 v0 = IN[0].vertex;
			float3 v1 = IN[1].vertex;
			float3 v2 = IN[2].vertex;
			float3 v3 = (IN[0].vertex+IN[1].vertex+IN[2].vertex)/3 + normalFace * _Length;				
			ADD_TRI(v0,v3,v2,o,tristream);
			ADD_TRI(v0,v1,v3,o,tristream);
			ADD_TRI(v2,v3,v1,o,tristream);
		} 
			fixed4 frag (g2f i) : SV_Target
			{
			//实现简单的Lambert光照
			   float3 LightDir = normalize(_WorldSpaceLightPos0.xyz);
			   float3 diffuseColor =_LightColor0*max(dot(i.norg, LightDir), 0);			 
			   return _Color*float4(diffuseColor,1);
			}
			ENDCG
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值