0
点赞
收藏
分享

微信扫一扫

读UnityShader入门精要第五章-开始Unity Shader之旅

1.一个最简单的顶点/片元着色器

1.1  顶点/片元着色器的基本结构

//定义Shader的位置和名称
Shader " Unity Shaders Book/Chapter 5/ Simple Shader"
{
//可以不定义Properties,但是必须有至少一个SubShader
SubShader
{
Pass
{
//使用CGPROGRAM和ENDCG包裹CG代码片段
CGPROGRAM

//编译指令,指明顶点着色器代码是vert函数
#pragma vertex vert
//编译指令,指明片元着色器代码是frag函数
#pragma fragment frag

//顶点着色器函数,v为形参名称,POSITION为CG/HLSL的语义,代表将模型的顶点坐标输入,SV_POSITION也是CG/HLSL的语义,代表输出为裁剪空间中的顶点坐标
float4 vert(float4 v : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(v);
}

//片元着色器函数,SV_Target语义代表将输出颜色存储到一个渲染目标中
fixed4 frag() : SV_Target
{
return fixed4(1.0, 0.0, 0.0, 1.0);
}

ENDCG
}
}
}

1.2  模型数据从哪里来

  在着色器中使用语义(semantics)定义数据的来源,想得到更多的数据,我们可以定义一个结构体参数获取这些数据:

Shader " Unity Shaders Book/Chapter 5/ Simple Shader"
{
SubShader
{
Pass
{
CGPROGRAM

#pragma vertex vert
#pragma fragment frag

//使用结构体定义参数
struct a2v
{
//POSITION语义,代表使用模型空间的顶点坐标填充这个变量
float4 vertex : POSITION;
//NORMAL语义,代表使用模型空间的法线方向填充这个变量
float3 normal : NORMAL;
//TEXCOORD0语义,代表使用模型的第一套纹理坐标填充这个变量
float4 texcoord : TEXCOORD0;
};

//顶点着色器函数
float4 vert(a2v v) : SV_POSITION
{
return UnityObjectToClipPos(v.vertex);
}

fixed4 frag() : SV_Target
{
return fixed4(1.0, 0.0, 0.0, 1.0);
}

ENDCG
}
}
}

1.3  顶点着色器和片元着色器之间的通信

Shader " Unity Shaders Book/Chapter 5/ Simple Shader"
{
SubShader
{
Pass
{
CGPROGRAM

#pragma vertex vert
#pragma fragment frag

struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};

//在结构体中存储顶点着色器的输出
struct v2f
{
//SV_POSITION语义代表这里存储了裁剪空间的位置信息
float4 pos : SV_POSITION;
//COLOR0语义用于存储颜色信息
fixed3 color : COLOR0;
};

v2f vert(a2v v)
{
//声明一个结构体
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//根据发现方向计算一个颜色并存储
o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}

fixed4 frag(v2f i) : SV_Target
{
//将插值后的颜色显示到屏幕上
return fixed4(i.color, 1.0);
}

ENDCG
}
}
}

  注意:

    1)在结构体v2f中,必须包含语义为SV_POSITION的float4类型变量,否则片元着色器无法得到片元的位置信息;

    2)顶点着色器输出的v2f结构体中存储的信息和片元着色器中输入的v2f结构体中的信息并不一致,片元着色器得到的点可能是三角片元内的点,它的信息是经过三角形顶点的插值得到的.

1.4  如何使用属性

Shader " Unity Shaders Book/Chapter 5/ Simple Shader"
{
Properties
{
//声明一个color类型的属性
//属性名_Color, 在Shader属性面板中显示名称Color Tint,属性类型Color, 属性默认值(1.0, 1.0, 1.0, 1.0)
_Color("Color Tint", Color) = (1.0, 1.0, 1.0, 1.0)
}

SubShader
{
Pass
{
CGPROGRAM

#pragma vertex vert
#pragma fragment frag

//在CG代码中,需要定义一个与属性名称相同,类型匹配的变量,才能使用这个变量
fixed4 _Color;

struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};

struct v2f
{
float4 pos : SV_POSITION;
fixed3 color : COLOR0;
};

v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}

fixed4 frag(v2f i) : SV_Target
{
fixed3 c = i.color;
//使用_Color属性控制颜色输出
c *= _Color.rgb;
return fixed4(c, 1.0);
}

ENDCG
}
}
}

  ShaderLab的属性类型和Cg的变量类型匹配关系如下:

读UnityShader入门精要第五章-开始Unity Shader之旅_Unity

2.Unity提供的内置文件

  在Unity中,包含文件的后缀是.cginc.在编写Shader是,可以使用#include指令将这些文件包含进来,类似于C#包含其他命名空间.#include指令在CGPROGRAM和ENDCG中间的代码块中定义.

3.Unity提供的Cg/HLSL语义

3.1  语义的概念

  语义(semantics)是一个赋给Shader输入和输出的字符串,这个字符串表达了这个参数的含义.通常情况下,语义可以让我们指定Shader从哪里读取数据,或者指定Shader将数据输出到哪里.

  一些语义有特殊的含义规定,如TEXCOORD0,但是其他语义则没有这样的含义,如COLOR0,这些语义修饰的变量Shader并不关心它是用来做什么的,我们可以自己决定这些变量的用途.

  在DirecX 10以后,出现了一种新的语义类型:系统数值语义(system-value semantics).系统数值语义都是以SV(system value)开头的,如SV_POSITION.在Unity中有时系统数值语义和普通语义是可以替换的,但是最好使用系统数值语义,因为某些平台上必须使用系统数值语义.

3.2  Unity支持的语义

读UnityShader入门精要第五章-开始Unity Shader之旅_学习笔记_02

读UnityShader入门精要第五章-开始Unity Shader之旅_图形学_03

读UnityShader入门精要第五章-开始Unity Shader之旅_Shader_04

3.3  CG的数据类型

  Cg支持7种基础数据类型:

  1)float, 32位浮点数据

  2)half, 16位浮点数据

  3)fixed, 12位定点数据

  4)int, 32位整形数据

  5)bool, 布尔数据

  6)sampler*, 纹理对象的句柄,分为6类:sampler, sampler1D, sampler2D, sampler3D, samplerCUBE, samplerRECT

  7)string, 字符类型(几乎不会用到)



举报

相关推荐

0 条评论