顶点片段着色器运行于具有可编程渲染管线的硬件上,它包括顶点程序(Vertex Programs)和片段程序(Fragment Programs)。
当使用顶点程序和片段程序进行渲染时,图形硬件的固定功能管线将会馆关闭,具体来说就是用户编写的顶点程序将会替换掉固定管线标准中的3D变换、光照、纹理坐标生成等功能,而片段程序会替换掉SetTexture命令中的纹理混合模式,因此编写顶点片段着色器需要对3D变换、光照计算等有非常透彻的了解。
用户需要自行编写代码来替代D3D或则OpenGL原先在固定管线中要做的工作。
与表面着色器一枪,顶点片段着色器也需要用Cg/HLSL来编写实现代码,代码用CGPROGRAM ENDCG语句包围起来,放在ShaderLab的Pass命令中:
Pass {
// 通道设置
CGPROGRAM
// 本段Cg代码的编译指令
#pragma vertex vert
#pragma fragment frag
// Cg代码
ENDCG
// 其他通道设置
}
下面是顶点片段着色器中编译命令的一些说明:
编译命令(Compilation Directive)
命令 | 说明 |
---|---|
pragma vertex name | 将函数name的代码编译成顶点程序 |
pragma fragment name | 将函数name的代码编译成片段程序 |
pragma geometry name | 将函数name的代码编译成DX10的几何着色器(Geometry Shader) |
pragma hull name | 将函数name的代码编译成DX11的hull着色器 |
pragma domain name | 将函数name的代码编译成DX11的domain着色器 |
pragma fragmentoption option | 添加选项到编译的OpenGL片段程序。对于顶点程序或编译目标不是OpenGL的程序无效 |
pragma target name | 设置着色器的编译目标 |
pragma only_renderers space separated names | 仅编译到指定的渲染平台 |
pragma exclude_renderers space separated names | 不编译到指定的渲染平台 |
pragma glsl | 为桌面系统的OpenGL进行编译时,将Gl、HLSL代码转换成GLSL代码 |
pragma glsl_no_auto_normalizationi | 编译到移动平台GLSL(iOS/Android),关闭在顶点着色器中对法线向量和切线向量自动进行规范化 |
编译目标(Shader Targets)
编译目标可以设置为#pragma target 2.0
、#pragma target 3.0
、#pragma target 4.0
、#pragma target 5.0
。
他们分别对应不同版本的着色器模型(Shader Modal)
渲染平台(Rendering Platforms)
Unity支持多重图形API:
- d3d9 即Direct3D 9
- d3d11 即Direct3D 11
- opengl 即OpenGL
- gles 即OpenGL ES 2.0
- gles3 即OpenGL ES 3.0
- metal 即 iOSMetal
- d3d11_9x 即Direct3D 11 9.x feature level
- xbox360 即Xbox360
- xbox one 即Xbox One
- ps3 即PlayStation3
- ps4 即PlayStation4
- psp2 即PlayStation Vita。
沿着法线方向移动顶点。
Shader "Example/Normal Extrusion" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Amount ("Extrusion Amount", Range(-1,1)) = 0.5
}
SubShader {
// 渲染类型为不透明
Tags { "RenderType" = "Opaque" }
CGPROGRAM
// 定义表面和顶点函数
#pragma surface surf Lambert vertex:vert
struct Input {
// MainTex的UV坐标
float2 uv_MainTex;
};
float _Amount;
// 输入结构作为参数
void vert (inout appdata_full v) {
// 修改顶点位置
v.vertex.xyz += v.normal * _Amount;
}
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
// 输出漫反射颜色
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
根据法线方向设置模型表面颜色
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Example/Display Normals" {
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos (v.vertex);
o.color = v.normal * 0.5 + 0.5;
return o;
}
// 片段程序代码,直接把输入的颜色返回,并把透明度设置为1
half4 frag (v2f i) : COLOR
{
return half4 (i.color, 1);
}
ENDCG
}
}
Fallback "VertexLit"
}
根据切向方向设置模型表面颜色
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Example/Tangents" {
SubShader {
Pass {
Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// vertex input: position, tangent
// 输入位置和切线数据
struct appdata {
float4 vertex : POSITION;
float4 tangent : TANGENT;
};
// 定义顶点位置结构体
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
// 顶点函数程序
v2f vert (appdata v) {
v2f o;
// 计算顶点位置
o.pos = UnityObjectToClipPos( v.vertex );
// 计算顶点颜色
o.color = v.tangent * 0.5 + 0.5;
return o;
}
// 片段程序,直接返回顶点颜色
fixed4 frag (v2f i) : COLOR0 { return i.color; }
ENDCG
}
}
}
作者:biezhihua 发表于2017/9/6 0:23:44 原文链接
阅读:23 评论:0 查看评论