Sharder学习 1
在看shader入门精要。
第四章 数学基础
矩阵的运算。矩阵的乘法等,与坐标系变换。
一般顺序:先缩放,旋转,平衡。
Unity在模型空间和世界空间中用的是左手坐标系,观察空间是右手坐标系。这是符合OpenGL传统,摄像机的正前方是-z轴方向。
坐标空间:
- 模型
- 世界
- 观察,摄像机
- 裁剪,视锥体(view frustum)有两种类型,正交投影(orthographic projection)和透视投影(perspective projection)。
- 屏幕
4.8 unity shader的内置变量
UnityShaderVariables.cginc文件中有内置的变换矩阵。
还有关于内置摄像机和屏幕参数。
第五章 shader学习之旅
一个简单的shader
Shader "MyShaderName" {
Properties {
//属性
}
SubShader {
//针对显卡A的SubShader
Pass {
//设置渲染状态和标签
//开始CG代码片段
CGPROGRAM
//该代码片段的编译指令,
// #pragma vertex vertFunName
// #pragma fragment fragmentFunName
// 上面分别是哪个函数包含了顶点着色器的代码,哪个函数包含了片元着色器的代码
//如:
#pragma vertex vert
#pragma fragment frag
# CG代码写在这里
ENDCG
//其他设置
}
//其他需要的pass
}
SubShader {
// 针对显卡B的SubShader
}
//
Fallback "VertexLit"
}
cg代码
float4 vert(float4 v : POSITION) : SV_POSITION {
return mul (UNITY_MATRIX_MVP, V);
}
float4 frag() : SV_Target {
return fixed4(1.0,1.0,1.0,1.0);
}
MyShaderName可以是带目录格式的,如:”Unity Shaders Book/Chapter 5/Simple Shader”。
POSITION,SV_POSITION是CG/HLSL中的语义(semantics)。
vert的输入是float4类型的变量,POSITION告诉Unity,把模型的顶点坐标填充到输入参数v中。
返回值也是一个float4类型,SV_POSITION告诉Unity,顶点着色器的输出是裁剪空间中的顶点坐标。
UNITY_MATRIX_MVP矩阵是Unity内置的模型·观察·投影矩阵。
SV_Target告诉渲染器,把用户的输出颜色存储到一个渲染目标中。
多个输入数据的着色器。
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 mul ( UNITY_MATRIX_MVP, v.vertex );
}
float4 frag() : SV_Target {
return fixed4(1.0,1.0,1.0,1.0);
}
ENDCG
}
}
}
a2v表示application to vertex shader。
顶点着色器和片元着色器之间如何通信
修改前面的代码
...
struct a2v {
...
}
struct v2f {
// SV_POSITION语义告诉Unity,pos包含了顶点在裁剪空间中的位置信息
float4 pos : SV_POSITION;
// COLOR0语义可以用于存储颜色信息
fixed3 color : COLOR0;
}
v2f vert(a2v v) : SV_POSITION {
v2f o;
o.pos = mul ( UNITY_MATRIX_MVP, v.vertex );
// v.normal包含了顶点的法线方向,其分量范围在[-1.0,1.0]
// 下面的代码把分量范围映射到了[0.0, 1.0]
// 存储到o.color中传递给片元着色器
o.color = v.normal * 0.5 + fixed3(0.5,0.5,0.5);
return o;
}
fixed4 frag(v2f i) : SV_Target {
// 将插值后的i.color显示到屏幕上
return fixed4(i.color, 1.0);
}
...
需要注意的是,顶点着色器是逐顶点调用的,而片元着色器是逐片元调用的。片元着色器中的输入实际上是把顶点着色器的输出进行插值后得到的结果 。
如何使用属性
待学习。