shader的个人小结
Pass
pass{
//渲染语义块
cg代码块
//1.顶点代码段 2.片元代码段
#program vertex vert
#program fragment frag
}
一个shader文件里pass是可以有一个或多个的,这个需要根据实际需求来写.
当Unity选择用于渲染的子着色器时,它为每一个被定义的通道渲染一次对象(可能会更多,这取决于光线的交互作用)。当对象的每一次渲染都是很费资源之时,我们便使用尽量少的通道来定义一个着色器。
在每个pass中也可以用UsePass "Pass1" 和 Name "Pass1"来通道复用,减少代码量
https://qianmo.blog.csdn.net/article/details/41175585
https://www.codinblack.com/shader-pass-and-multi-pass-shader/
Properties{}
properties里面写外部可以调的变量,如果这个变量在后面的函数里面要使用,要再声明一次的
#program vertex vert
#program fragment frag
这两行是相当于声明函数的
顶点函数名字是vert 着色器函数名字是frag ,可以自己命名
struct a2v{
顶点着色器的输入,使用模型空间的数据填充变量
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f{
顶点着色器的输出,用于在顶点和片元着色器之间传递信息
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv =TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
}
v2f不是fixed float那种变量,是返回的结构体,很多时候要返回的变量太多,就都写进一个结构体里面了,结构体名字也可以自己改成好记的
坐标变换
坐标变换基础就是线性矩阵,UNITY把MVP矩阵进行过封装,有方法可以调用,可以在cgnic里查找到
inline float4 UnityWorldToClipPos( in float3 pos )
{
return mul(UNITY_MATRIX_VP, float4(pos, 1.0));
}
// Tranforms position from view to homogenous space
inline float4 UnityViewToClipPos( in float3 pos )
{
return mul(UNITY_MATRIX_P, float4(pos, 1.0));
}
// Tranforms position from object to camera space
inline float3 UnityObjectToViewPos( in float3 pos )
{
return mul(UNITY_MATRIX_V, mul(unity_ObjectToWorld, float4(pos, 1.0))).xyz;
}
inline float3 UnityObjectToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
{
return UnityObjectToViewPos(pos.xyz);
}
// Tranforms position from world to camera space
inline float3 UnityWorldToViewPos( in float3 pos )
{
return mul(UNITY_MATRIX_V, float4(pos, 1.0)).xyz;
}
// Transforms direction from object to world space
inline float3 UnityObjectToWorldDir( in float3 dir )
{
return normalize(mul((float3x3)unity_ObjectToWorld, dir));
}
https://www.codinblack.com/coordinate-spaces-and-transformations-between-them/
其他
rgba和xyzw
初学shader有个比较绕的地方一会用.r,一会用.w其实这些都差不多一个意思
vec4 vector;
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;
vector.rgb就是vector[1,2,3]
hlsl,cg
此外,也可以用HLSL代码,URP和HDRP都支持HLSL,但不支持cg
以 HLSL 或 CG 为前缀的块之间的区别是:
以 CG 为前缀的着色器代码块较旧。默认情况下,它们包含几个 Unity 的内置着色器 include 文件,如果您需要此功能,这会很方便。内置 include 文件仅与内置渲染管线兼容。
以 HLSL 为前缀的着色器代码块较新。默认情况下,它们不包含 Unity 的内置着色器 include 文件,因此您必须手动包含要使用的任何库代码。它们适用于任何渲染管线。
HLSL和CG大部分语法相似,但写法上有区别
Shader "Examples/ExampleShader"
{
HLSLINCLUDE
// 在此编写要共享的 HLSL 代码
ENDHLSL
SubShader
{
Pass
{
Name "ExamplePassName"
Tags { "LightMode" = "ExampleLightModeTagValue" }
// 在此编写设置渲染状态的 ShaderLab 命令
HLSLPROGRAM
// 在此编写 HLSL 着色器代码
ENDHLSL
}
}
}