Shader 入门精要笔记
Posted 任葳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shader 入门精要笔记相关的知识,希望对你有一定的参考价值。
Unity Shader 并不等同真正的Shader,Unity Shader 可以在同一个文件里同时包含需要的顶点/片元着色器代码,通过自定义指令设置开启混合,深度测试,不需要开发者自行编码传给着色器,Unity Shader 提供了直接访问的方法,对于模型自带的数据(顶点位置,纹理坐标,法线),Unity Shader提供了直接访问的方法,不需要开发者自行编码;来传给着色器。由于Unity Shader的高度封装,我们可以编写的Shader类型和语法都被限制了,对于曲面细分着色器和几何着色器Unity 的支持较差,Unity 提供了一种让开发者同时控制渲染流水线中多阶段的一种方式,不仅仅是提供 Shader 代码,我们不需要关心渲染引擎底层的实现细节。由于Unity Shader是用Shaderlab编写的,对于顶点/片元着色器和表面着色器我们可以在Shaderlab内部嵌套CG/HLSL语言来编写这些着色器代码,这些CG/HLSL是嵌套在CGPROGRAM和ENDCG之间的由于CG和DX9风格的HLSL写法几乎一样,所有在Unity中CG和HLSL是等价的,CG代码拍那段是位于Pass语义块你内部的:
Pass{
//Pass 的标签和渲染状态
CGPROGRAM
// 编译指令,例如
#pragma vertex vert
#pragma fragment frag
//CG代码
ENDCG
//其他一些设置
}
由于表面着色器的本质是Unity在顶点/片元着色器上层为开发者提供的一层抽象封装,在背后Unity还是会将其转化成一个包含多Pass的顶点/片元着色器,从本质上讲,Unity中只存在顶点/片元着色器
再次我对所学Shader进行复习,先从简单光照模型lambert开始:
shader "MyShader/lambert"
Properties{
}
SubShader{
Tags{
"RenderType" = "Opaque"
}
Pass{
Name "FORWARD"
Tags{
"LightMode" = "ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
//输入结构
struct VertexInput {
float4 vertex : POSITION;
float4 normal : NORMAL;
};
//输出结构
struct Outout{
float4 pos ; SV_POSITION;
float3 nDirWs : TEXCOOD0;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput) 0;
o.pos = UnityObjectToCliPos(v.vertex);
o.nDirWs = UnityObjectToWorldNormal (v.normal);
return o;
}
float4 frag(VertexOutput i) :COLOR{
float3 nDir = i.nDirWs;
float3 lDir = _WorldSpaceLightPos0.xyz;
float nDotl = dot(i.nDirWs,lDir);
float lambert = max(0.0,nDotl);
return float4(lambert,lambert,lambert,1.0);
}
ENGCG
}
}
FallBack "Diffuse"
}
以上是关于Shader 入门精要笔记的主要内容,如果未能解决你的问题,请参考以下文章
Unity Shader入门精要学习笔记 - 第17章 Unity的表面着色器探秘
Unity Shader入门精要学习笔记 - 第9章 更复杂的光照