Unity 3D 图形学 Shader之语义的定义(六)

通过前面介绍的渲染管线的大概流程:从应用程序阶段传递数值到顶点着色器,然后又经顶点着色器将数据传递给片断着色器并最终显示在屏幕上。

在应用阶段传入顶点着色器的数据我们看到有这样的语法:

 struct appdata
    {
        float4 vertex : POSITION;
    };

这里我们声明了一个float4类型的变量vertex,并给予了它顶点数据的语义(在变量后加冒号并跟一个语义),也就是说vertex变量将代表着模型的顶点数据被我们使用与传递。

那么都有哪些语义呢?如下:

struct appdata
{
	float4 vertex : POSITION;		//顶点
	float4 tangent : TANGENT;		//切线
	float3 normal : NORMAL;			//法线
	float4 texcoord : TEXCOORD0;	        //UV1
	float4 texcoord1 : TEXCOORD1;	        //UV2
	float4 texcoord2 : TEXCOORD2;	        //UV3
	float4 texcoord3 : TEXCOORD3;	        //UV4
	fixed4 color : COLOR;			//顶点色
};

仔细观察,这些正好也是模型在Unity中的所有数据信息。

在UnityCG.cginc中内置定义了三种常用的结构,我们也可以直接引用并调用,有关cginc的具体用法我们后面再讨论,这里为了熟悉学习,我们尽量自己定义结构。

顶点着色器到片断着色器的数据

顶点着色器在处理完应用阶段传过来的数据后,会需要输出并传入片断着色器,这个时候我们同样需要定义一个结构来承载其中的数据,同样的,输出给片断着色器的值也需要语义来标识。

struct v2f
{
	float4 pos:SV_POSITION;
};

这里声明了float4类型的变量pos,并指定为SV_POSITION语义,表示pos就是顶点着色器输出的屏幕裁剪空间下的顶点位置。这条语义是必须要有的,否则GPU无法进行接下来的光栅化处理。

其实在现代GPU上对这里的语义如何定义并不关心了(除了SV_POSITION以外),主要是部分OpenGL ES2.0上面才需要特别注意而已。
这里的语义除了SV_POSITION以外,我们还有另外两种选择:

TEXCOORD0~N系列
例如TEXCOORD0、TEXCOORD1、TEXCOORD2…等等,主要用于高精度数据。

COLOR0~N系列

例如COLOR0、COLOR1、COLOR2…等等,主要用于低精度数据。

虽然这两种语义我们可以根据需要自由定义,但是,它并不是可以无限定义的,不同的GPU硬件有不同的数量限制。

以下为手机平台的常见规则:

OpenGL ES2.0支持最多8个
OpenGL ES3.0支持最多16个
从性能优化角度来讲,数量越少性能越好。
另外,每个语义是4维向量,利用好这一点,可以大大节省总数量。

VFACE

在片断着色器中还有些特殊的语义的可以识别,比如VFACE
如果渲染表面朝向摄像机,则Face节点输出正值1,如果远离摄像机,则输出负值-1。

Shader "Unlit/Test2"
{
	Properties
	{
		_FrontTex("FrontTex", 2d) = "white"{}
		_BackTex("BackTex", 2d) = "white"{}
	}

	SubShader
	{
		cull off
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 3.0

			sampler2D _FrontTex;
			sampler2D _BackTex;

			struct appdata
			{
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};


			struct v2f
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			v2f vert(appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}

			fixed4 frag(v2f i,float face : VFACE) : SV_Target
			{
				fixed4 col = 1;
				col = face > 0 ? tex2D(_FrontTex,i.uv) : tex2D(_BackTex,i.uv);
				return col;
			}
			ENDCG
		}
	}
}

在这里插入图片描述

片断着色器输出相关语义

通常情况下,片断着色器最终只需返回一个颜色值即可,也是我们最常见到的编写方式,如下:

fixed4 frag (v2f i ) : SV_TARGET
这里的SV_TARGET就是指定输出颜色到RenderTarget的语义,其实我们也可以采用Struct的方式,就是像应用阶段到顶点与顶点到片断一样,只是由于平时我们只需返回一个颜色所以就无需再用一个Struct了(你非要用也是可以的)。

当我们利用Struct时,就可以通过下列语义来输出多个内容:

SV_Target0〜N
默认SV_TARGET0,也就是SV_TARGET,还有SV_TARGET1,SV_TARGET2…这个在需要输出多个RenderTarget时很有用。

SV_Depth
一般情况下,模型的像素深度值在光栅化时会自动插值计算得出,并不需要我们做额外的处理,但这并不代表不可以修改它,通过在片断着色器中输出SV_DEPTH语义可以更改像素的深度值。

注意此功能相对会消耗性能,在没有特别需求的情况下尽量不要用!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值