地址:
https://en.wikibooks.org/wiki/Cg_Programming/Unity/Minimal_Shader
重点
认识shader关键代码:
Shader "Cg basic shader" { // defines the name of the shader
SubShader { // Unity chooses the subshader that fits the GPU best
Pass { // some shaders require multiple passes
CGPROGRAM // here begins the part in Unity's Cg
#pragma vertex vert
// this specifies the vert function as the vertex shader
#pragma fragment frag
// this specifies the frag function as the fragment shader
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
// vertex shader
{
return mul(UNITY_MATRIX_MVP, vertexPos);
// this line transforms the vertex input parameter
// vertexPos with the built-in matrix UNITY_MATRIX_MVP
// and returns it as a nameless vertex output parameter
}
float4 frag(void) : COLOR // fragment shader
{
return float4(1.0, 0.0, 0.0, 1.0);
// this fragment shader returns a nameless fragment
// output parameter (with semantic COLOR) that is set to
// opaque red (red = 1, green = 0, blue = 0, alpha = 1)
}
ENDCG // here ends the part in Cg
}
}
}
在网页的最后有相关阅读,英文好的可以自己查阅,我再下面写出我自己的理解
解读
1.SubShader
http://docs.unity3d.com/Manual/SL-SubShader.html 官方解读
每个在Unity3D的shader都是由一系列的的subshaders组成的。当Unity3D显示一个网格的时候,它会使用第一个被用户显卡支持的subshader。
为什么要写多个呢?这就和硬件有关了,你以当前的硬件水平来编程的话可能实现了某个效果,但是早起的硬件不支持怎么办?你就得写多个,让硬件可以找到相关的,不然就会按最低标准实现。
2.Pass
这个标签没有找到太多资料只有:http://docs.unity3d.com/Manual/SL-Pass.html
3.
CGPROGRAM
ENDCG
是一组标签,程序在这部分编写
4.预处理指令
#pragma vertex vert #pragma fragment frag
指明顶点和片段的函数名
表明一个以vert为名字的函数的顶点程序
表明一个以frag为名字的函数的片段程序
5.函数
float4 vert(float4 vertexPos : POSITION) : SV_POSITION { return mul(UNITY_MATRIX_MVP, vertexPos); }
5.1.函数定义
返回值类型 函数名(参数类型 参数名:输入语义):输出语义
这里做一下语义的解释:
POSITION 绑定语义,表明该参数为位置信息,从程序中读取图片的位置信息,也就是找到相应的寄存器,从中拿到数据
SV_POSITION 绑定语义,表明返回值得存放位置
V_POSITION 这里的SV_POSITION叫做输出语义,语义是GPU编程里提出的一个概念
#pragma vertex vert是一个预处理指令,表明一个以vert为名字的函数的顶点程序
网络资料:
SV_前缀的变量代表system value,在DX10以后的语义绑定中被使用代表特殊的意义,和POSITION用法并无不同。唯一区别是 SV_POSTION一旦被作为vertex shader的输出语义,那么这个最终的顶点位置就被固定了(不能tensellate,不能再被后续改变它的空间位置?),直接进入光栅化处理,如果作为fragment shader的输入语义那么和POSITION是一样的,代表着每个像素点在屏幕上的位置(这个说法其实并不准确,事实是fragment 在 view space空间中的位置,但直观的感受是如括号之前所述一般)
最后这个回答者说了,在DX10版本之前没有引入SV_的预定义语义,POSITION被用作vertex shader的输入,输出,fragment shader的输入参数。但DX10之后就推荐使用SV_POSITION作为vertex shader的输出和fragment shader的输入了,注意vertex shader的输入还是使用POSITION!切记。但是DX10以后的代码依旧兼容POSITION作为全程表达,估计编译器会自动判断并替换的吧。好了SV_POSITION的疑惑就此解开。
#pragma vertex vert是一个预处理指令,表明一个以vert为名字的函数的顶点程序
网络资料:
SV_前缀的变量代表system value,在DX10以后的语义绑定中被使用代表特殊的意义,和POSITION用法并无不同。唯一区别是 SV_POSTION一旦被作为vertex shader的输出语义,那么这个最终的顶点位置就被固定了(不能tensellate,不能再被后续改变它的空间位置?),直接进入光栅化处理,如果作为fragment shader的输入语义那么和POSITION是一样的,代表着每个像素点在屏幕上的位置(这个说法其实并不准确,事实是fragment 在 view space空间中的位置,但直观的感受是如括号之前所述一般)
最后这个回答者说了,在DX10版本之前没有引入SV_的预定义语义,POSITION被用作vertex shader的输入,输出,fragment shader的输入参数。但DX10之后就推荐使用SV_POSITION作为vertex shader的输出和fragment shader的输入了,注意vertex shader的输入还是使用POSITION!切记。但是DX10以后的代码依旧兼容POSITION作为全程表达,估计编译器会自动判断并替换的吧。好了SV_POSITION的疑惑就此解开。
具体详见:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx msdn语义
GPU 编程与CG 语言之阳春白雪下里巴人 第七章
5.2.函数体
mul(UNITY_MATRIX_MVP, vertexPos)
mul是cg的标准函数库用于顶点变换函数,UNITY_MATRIX_MVP是unity的内建矩阵,vertexPos是这个函数的形参
作用为将形参vertexPos按照unity的内建矩阵进行顶点变换
cg的标准函数库,资料:
GPU 编程与CG 语言之阳春白雪下里巴人 第八章
Cg教程_可编程实时图形权威指南
unity的内建矩阵
支持的矩阵(float4x4):
UNITY_MATRIX_MVP 当前模型视图投影矩阵
UNITY_MATRIX_MV 当前模型视图矩阵
UNITY_MATRIX_V 当前视图矩阵。
UNITY_MATRIX_P 目前的投影矩阵
UNITY_MATRIX_VP 当前视图*投影矩阵
UNITY_MATRIX_T_MV 移调模型视图矩阵
UNITY_MATRIX_IT_MV 模型视图矩阵的逆转
UNITY_MATRIX_TEXTURE0 UNITY_MATRIX_TEXTURE3 纹理变换矩阵
UNITY_MATRIX_MVP 当前模型视图投影矩阵
UNITY_MATRIX_MV 当前模型视图矩阵
UNITY_MATRIX_V 当前视图矩阵。
UNITY_MATRIX_P 目前的投影矩阵
UNITY_MATRIX_VP 当前视图*投影矩阵
UNITY_MATRIX_T_MV 移调模型视图矩阵
UNITY_MATRIX_IT_MV 模型视图矩阵的逆转
UNITY_MATRIX_TEXTURE0 UNITY_MATRIX_TEXTURE3 纹理变换矩阵