您的位置:首页 > 移动开发 > Unity3D

unity shader 可编程管线(二) 顶点和片段着色器(Vertex Shader and Fragmet Shader)

2016-02-18 11:39 676 查看
顶点着色器和片段着色器。

可编程Shader的特点为:

功能最强大、最自由的形态。
特征是在Pass里出现CGPROGRAM和ENDCG块
编译指令#pragma。详见官网Cg snippets。其中重要的包括:

编译指令
示例/含义
#pragma vertex name

#pragma fragment name
替换name,来指定Vertex Shader函数、Fragment Shader函数。
#pragma target name
替换name(为2.0、3.0等)。设置编译目标shader model的版本。
#pragma only_renderers name name ...

#pragma exclude_renderers name name...
#pragma only_renderers gles gles3,

#pragma exclude_renderers d3d9 d3d11 opengl,

只为指定渲染平台(render platform)编译
关于引用库。通过形如#include "UnityCG.cginc"引入指定的库。常用的就是UnityCG.cginc了。其他库详见官网Built-in
shader include files。
ShaderLab内置值。Unity给Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了这个时刻的MVP矩阵。详见官网ShaderLab
built-in values。
Shader输入输出参数语义(Semantics)。在管线流程中每个阶段之间(比如Vertex Shader阶段和FragmentShader阶段之间)的输入输出参数,通过语义字符串,来指定参数的含义。常用的语义包括:COLOR、SV_Position、TEXCOORD
。完整的参数语义可见HLSL
Semantic(由于是HLSL的连接,所以可能不完全在Unity里可以使用)。
特别地,因为Vertex Shader的的输入往往是管线的最开始,Unity为此内置了常用的数据结构:

数据结构
含义
appdata_base
顶点着色器输入位置、法线以及一个纹理坐标。
appdata_tan
顶点着色器输入位置、法线、切线以及一个纹理坐标。
appdata_full
顶点着色器输入位置、法线、切线、顶点颜色以及两个纹理坐标。
appdata_img
顶点着色器输入位置以及一个纹理坐标。
例子如下:

Shader "基础/简单的顶点和片段着色器"
{
//-------------------------------【属性】--------------------------------------
Properties
{
_Color ("Color", Color) = (1.0,1.0,1.0,1.0)
_SpecColor ("Specular Color", Color) = (1.0,1.0,1.0,1.0)
_Shininess ("Shininess", Float) = 10
}

//--------------------------------【子着色器】--------------------------------
SubShader
{
//-----------子着色器标签----------
Tags { "LightMode" = "ForwardBase"
4000
}

//----------------通道---------------
Pass
{
//-------------------开始CG着色器编程语言段-----------------
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

//---------------声明变量--------------
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;

//--------------定义变量--------------
uniform float4 _LightColor0;

//--------------顶点输入结构体-------------
struct vertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};

//--------------顶点输出结构体-------------
struct vertexOutput
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};

//--------------顶点函数--------------
vertexOutput vert(vertexInput v)
{
vertexOutput o;

//一些方向
float3 normalDirection = normalize( mul( float4(v.normal, 0.0), _World2Object ).xyz );
float3 viewDirection = normalize( float3( float4( _WorldSpaceCameraPos.xyz, 1.0) - mul(_Object2World, v.vertex).xyz ) );
float3 lightDirection;
float atten = 1.0;

//光照
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuseReflection = atten * _LightColor0.xyz * max( 0.0, dot( normalDirection, lightDirection ) );
float3 specularReflection = atten * _LightColor0.xyz * _SpecColor.rgb * max( 0.0, dot( normalDirection, lightDirection ) ) * pow( max( 0.0, dot( reflect( -lightDirection, normalDirection ), viewDirection ) ), _Shininess );
float3 lightFinal = diffuseReflection + specularReflection + UNITY_LIGHTMODEL_AMBIENT;

//计算结果
o.col = float4(lightFinal * _Color.rgb, 1.0);//颜色
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//位置
return o;
}

//--------------片段函数---------------
float4 frag(vertexOutput i) : COLOR
{
return i.col;
}

//-------------------结束CG着色器编程语言段------------------
ENDCG
}
}
//备胎
Fallback "Diffuse"

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: