最近学习shader的一些总结
旨在总结最近学习shader过程中一些关键要素,强化下记忆,如果有错误也烦请指出。
1.Properties
可调节变量,用于定义从外部传入到内部的变量, 以及外部通过访问这些变量名, 可以获取这些变量的值
其中定义时指定的类型, 在后文中类型不一定相同(基本不相同)
大致如下
2D -- sampler2D
Color -- half4(fixed4,float4皆可)
Cube -- samlperCUBE
Vector -- half4(fixed4等)
2.Tags
SubShader 的 Tags 主要影响渲染的整体行为, 决定整个 SubShader 如何在渲染管线中工作
Pass 的 Tags 主要影响该 Pass 的细节,用来细化单个渲染阶段的行为
RenderType: 定义Shader的渲染类型, 用于控制该材质的渲染行为
1.Qpaque(不透明): 表示该材质是完全不透明的物体, 通常, 这些物体没有透明度, 渲染时不会涉及任何透明或混合的计算
2.Transparent(透明): 表示该材质是透明物体, 透明物体在渲染时通常会涉及到深度测试和混合, 通常用于玻璃, 水面, 某些特殊效果
3.Background(背景): 表示该材质用于场景的背景渲染, 例如天空盒, 通常他们的渲染顺序比较特殊,因为通常是在对底层绘制的
4.Overlay(叠加): 表示该材质应当在其他所有物体上面渲染, 通常用于HUD 或 其他叠加在场景上的效果
5.ShadowCaster(阴影投射器): 表示该材质会投射阴影; 这个类型的物体通常会被渲染用于阴影生成, 但是不会出现在最终的场景中(例如在阴影贴图中);这些物体通常不直接参与最终图像的绘制, 只在阴影计算中使用
6.Wireframe(线框): 表示该材质应当使用线框模式进行渲染;通常用于调试或者特殊设计, 因为他显示物体的边界结构
7.TreeOpaque(树不透明): 表示树木等植物类物体的渲染类型, 这些物体在渲染时会有特殊的处理, 如透明度或反向面渲染等
8.TreeTransparentCutout(树透明裁剪): 表示透明裁剪的树木材质; 这类材质常见于植被或者树木, 通常使用透明度测试或裁剪来实现树叶的效果
9.TreeTransparent(树透明): 表示树木等透明物体, 通常不涉及透明裁剪, 而是完全透明处理; 这类材质可能用于树木的透明区域, 如树叶的透明部分
Queue: 定义该SubSahder在渲染时应该排在什么位置;
1.Background 队列通常用于背景物体
2.Geometry 用于常规物体
3.Overlay 用于 UI 元素
LightMode: 定义Shader的光照模式, 控制如何计算应用光照
1.ForwardBase和ForwadAdd: 前向渲染中的基础 和 额外光照 计算
2.Deferred 和 DeferredReflections: 延迟渲染中的光照计算
3.ShadowCaster: 阴影投射
4.Always 和 Meta: 用于特殊渲染效果 和 场景元数据
5.DepthOnly: 深度计算, 用于阴影, 深度测试
3.Pragma
#pragma 用于指令的预处理命令, 它告诉编辑器如何处理某个特定的编译指令; 启用或禁用某些功能, 设置特定的渲染行为, 或者优化性能;
1.#pragma vertex
指定顶点着色器函数, 此指令后面需要紧接一个函数名, 表示该函数作为顶点着色器入口
2.#pragma fragment
指定片元着色器函数, 此指令后面需要紧接一个函数名, 表示该函数作为片元着色器的入口
3.#pragma multi_compile
编译多个不同的着色器变体; 允许在同一个 Shader 中定义多个条件编译的分支, 编译器会为每个条件组合生成一个着色器变体
4.#pragma multi_feature
与上一条类似, 但只会在编译时启用实际使用的变体, 而不会生成所有可能的组合; 这通常用于优化, 因为减少了不必要的着色器变体
5.#pragma target
指定目标渲染平台的 Shader 模型; 它决定着色器将被编译为哪个版本的HLSL(#pragma target 3.0)
6.#pragma surface
指定表面着色器及其渲染属性; #pragma surface 会告诉Unity给定的表面着色器的计算规则和使用的光照模型(#pragma surface surf Lamber)
7.#pragma geometry
指定几何着色器函数, 用法与 vertex/fragment 类似
8.#pragma tessellatoin
指定曲面细分着色器函数, 用法与 vertex/fragment 类似
9.#pragma enable_d3d11_debug_symbols
启用Direct3D的调试符号, 通常用于调试和开发过程中
10.#pramga exclude_renderers
排除特定平台的渲染器(例如排除OpenGL和DirectX)
11.#pragma strict
开启严格模式, 在严格模式下, Shader 需要更明确的类型声明, 某些隐式类型转换将会引发编译器错误;
12.#pragma glsl
启用GLSL语言的兼容性; 如果编写一个需要在 OpenGL 平台运行的 Shader, 通常需要使用 GLSL 语法, 而不是 HLSL
4.Include
#include 指令用来引入外部的 .cginc 文件或其他编译单元(比如其他着色器代码文件); 这些文件通常包含了常用的函数, 宏, 预定义变量, 数据结构等, 可以在多个着色器中共享, 避免重复编写代码; Unity 提供了一些内置的 .cginc 文件, 这些文件包含了常用的渲染功能, 光照模型, 数学运算等;
1.UnityCG.cginc
包含了许多常用的函数, 宏和常量, 供顶点着色器和片元着色器使用
2.Lighting.cginc
包含光照计算相关的代码, 适用于在自定义着色器中实现不同的光照模型和阴影
3.UnityShaderVariables.cginc
包含一些全局的着色器变量和常量
4.UnityPBSLighting.cginc
用于物理基础渲染的着色器
5.AutoLight.cginc
自动计算光照的相关文件, 如点光源, 方向光源, 聚光灯的计算
5.结构定义
appdata 是 Unity 中顶点着色器输入的结构体, 它包含了顶点数据字段; 这些字段的定义会根据实际的渲染需求和顶点着色器的复杂性而变化; 可以根据需要自定义这些字段, 以便传递更多的顶点信息给顶点着色器处理
appdata
1.vertex: POSITION;
表示顶点的位置, 通常是局部空间中的位置(如物体坐标), 即float4(x, y, z, 1); 在渲染管线中, 它会被转换为世界空间, 视图空间或裁剪空间的坐标
2.normal:NORMAL;
表示顶点的法线, 通常表示该点的表面朝向, 用于光照计算
3.tangent:TANGENT
表示顶点的切线, 用于法线贴图和光照计算, 表示表面沿着纹理坐标方向的方向
4.color:COLOR
表示顶点的颜色, 通常用于顶点着色器的差值, 可以进行渐变和混合等效果
5.texcoord:TEXCOORD0
纹理坐标, 表示该顶点在纹理图像上的位置; 多个纹理坐标可以用于多重纹理映射
6.lightmap:TEXCOORD1
光照贴图坐标, 表示该顶点在光照贴图中的位置
7.worldPos:TEXCOORD2
顶点的世界坐标
v2f
v2f 是 Unity 中用于定义顶点着色器和片段着色器之间传递数据的结构体; v2f 是 Vertex-to-Fragment 的缩写, 即"顶点到片段"的意思; 它用来将定点着色器输出的计算结果传递到片元着色器进行后续处理; 也可以根据需求来自定义其中的字段
1.pos:POSITION;
裁剪空间坐标
2.worldPos:TEXCOORD0;
世界空间坐标
3.color:COLOR;
顶点颜色
4.texcoord:TEXCOORD1;
纹理坐标
5.normal:TEXCOORD2;
顶点法线
6.tangent:TEXCOORD3;
顶点切线
6.一些常见函数
UnityObjectToClipPos
将顶点坐标从对象空间转换到裁剪空间
UnityObjectToWorldNormal
将法线从对象空间转换到世界空间
mul
顶点位置转换到世界空间
tex2D
纹理采样函数
dot
点积函数, 通常用于计算光照和法线的关系, 如果光照方向与法线方向一致, 则值最大;
如果光照方向与法线方向成90°, 则值最小, 为0;
如果超过90°, 通常限制为0
length
求一个向量的长度(模)
后续再随着学习逐渐补充!