Unity5的ShaderVariants实验和总结
来源:互联网 发布:电脑喊麦用什么软件 编辑:程序博客网 时间:2024/06/06 08:44
http://www.manew.com/thread-101642-1-1.html
ShaderVariants(下文用shader变种描述)是unity中用来合并组织shader的一个方式之一,在shader中的使用类似宏定义。最近项目使用shader变种的时候发现了一些坑,所以做了如下实验和总结。其中前两节是基础部分,看官方文档也可以了解,只是通过实验来加强理解。第三节shader变种的打包是重点描述的,比较重要。
一、生成shader变种机制
为了做实验,制作shader如下:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Shader
"Custom/Color"
{
SubShader
{
Pass
{
Cull Off
ZWrite Off
Lighting Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma shader_feature RED GREEN BLUE
//#pragma shader_feature GREEN
//#pragma shader_feature BLUE
//#pragma multi_compile RED GREEN BLUE
//#pragma multi_compile __ GREEN
struct
v2f
{
fixed4 pos : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
return
o;
}
half4 frag(v2f i) : COLOR
{
fixed4 c = fixed4(0,0,0,1);
#ifdef RED
c += fixed4(1,0,0,1);
#endif
#ifdef GREEN
c += fixed4(0,1,0,1);
#endif
#ifdef BLUE
c += fixed4(0,0,1,1);
#endif
return
c;
}
ENDCG
}
}
CustomEditor
"ColorsGUI"
}
shader的变种数量可以通过shader面板上面查看到,点击Show按钮可以看到都有哪些变种
做如下实验对比shader_feature:
单一行命令
#pragma shader_feature RED
两个变种: __, RED
#pragma shader_feature RED GREEN
两个变种:RED,GREEN
#pragma shader_feature RED GREEN BLUE
三个变种:RED,GREEN,BLUE
#pragma multi_compile RED
一个变种:RED
#pragma multi_compile RED GREEN
两个变种:RED,GREEN
#pragma multi_compile RED GREEN BLUE
三个变种:RED,GREEN,BLUE
分析:shader_feature 和multi_compile 在Keyword 数量大于1时,生成变种的机制是一样的,都是一个keyword一个变种;当keyword只有1个时,shader_feature 会增加一个none变种。再来做个实验:
#pragma shader_feature __ RED
两个变种: none, RED
可见,当shader_feature 的keyword数量是1时不论是否有__符号,都会增加一个空keyword(__),除了这个在生成变种的机制上和multi_compile都是一致的。
多行命令
#pragma multi_compile __ RED
#pragma multi_compile __ GREEN
四个变种:__,RED,GREEN,RED GREEN
分析:多行命令就是单行命令的乘法组合,shader_feature和multi_compile除了单一keyword时是否补__之外,在多行命令中也是一致的。
二、匹配shader变种机制
为了实验shader变种的匹配,做一个方便定义keyword的shader界面,代码如下:
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public
class
ColorsGUI: ShaderGUI {
private
static
bool
bRed =
false
;
private
static
bool
bGreen =
false
;
private
static
bool
bBlue =
false
;
public
override
void
OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
// render the default gui
base.OnGUI(materialEditor, properties);
Material targetMat = materialEditor.target as Material;
bRed = Array.IndexOf(targetMat.shaderKeywords,
"RED"
) != -1;
bGreen = Array.IndexOf(targetMat.shaderKeywords,
"GREEN"
) != -1;
bBlue = Array.IndexOf(targetMat.shaderKeywords,
"BLUE"
) != -1;
EditorGUI.BeginChangeCheck();
bRed = EditorGUILayout.Toggle(
"红"
, bRed);
bGreen = EditorGUILayout.Toggle(
"绿"
, bGreen);
bBlue = EditorGUILayout.Toggle(
"蓝"
, bBlue);
if
(EditorGUI.EndChangeCheck())
{
if
(bRed)
targetMat.EnableKeyword(
"RED"
);
else
targetMat.DisableKeyword(
"RED"
);
if
(bGreen)
targetMat.EnableKeyword(
"GREEN"
);
else
targetMat.DisableKeyword(
"GREEN"
);
if
(bBlue)
targetMat.EnableKeyword(
"BLUE"
);
else
targetMat.DisableKeyword(
"BLUE"
);
}
}
}
shader界面如下:
这样,勾选一个颜色,就会enable一个keyword,通过查看结果颜色就能知道匹配到了哪个shader变种,实验如下:
#pragma multi_compile RED GREEN(两个变种:RED, GREEN)
材质keyword为RED : 显示红色(匹配RED)
材质keyword为GREEN : 显示绿色(匹配GREEN)
材质keyword为__ : 显示红色(匹配RED)
材质keyword为RED GREEN: 显示红色(匹配RED)
分析:当keyword存在正好匹配的变种时直接匹配、当keyword不存在匹配变种时取第一个变种
三、shader变种打包
打包的代码如下:
[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[MenuItem(
"Assets/Build AssetBundles"
)]
static
void
BuildAllAssetBundles()
{
List<AssetBundleBuild> maps =
new
List<AssetBundleBuild>();
maps.Clear();
//资源打包
string
[] files = {
"Assets/ShaderVariants/Resources/red.prefab"
,
};
AssetBundleBuild build =
new
AssetBundleBuild();
build.assetBundleName =
"ShaderVariantsPrefab"
;
build.assetNames = files;
maps.Add(build);
string
[] file2s = {
"Assets/ShaderVariants/Resources/Shader/Colors.shader"
,
};
AssetBundleBuild build2 =
new
AssetBundleBuild();
build2.assetBundleName =
"ShaderVariantsShader"
;
build2.assetNames = file2s;
maps.Add(build2);
BuildAssetBundleOptions options = BuildAssetBundleOptions.DeterministicAssetBundle;
BuildPipeline.BuildAssetBundles(
"Assets/StreamingAssets"
, maps.ToArray(), options, BuildTarget.StandaloneWindows);
AssetDatabase.Refresh();
}
读包并实例化的代码如下:
[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public
class
BundleLoader : MonoBehaviour
{
void
Start () {
load();
}
public
void
load()
{
StartCoroutine(LoadMainGameObject(
"file://"
+ Application.dataPath +
"/StreamingAssets/"
+
"ShaderVariantsShader"
));
StartCoroutine(LoadMainGameObject(
"file://"
+ Application.dataPath +
"/StreamingAssets/"
+
"ShaderVariantsPrefab"
));
}
private
IEnumerator LoadMainGameObject(
string
path)
{
WWW bundle =
new
WWW(path);
yield
return
bundle;
if
(bundle.url.Contains(
"ShaderVariantsShader"
))
{
//依赖shader包
bundle.assetBundle.LoadAllAssets();
}
else
{
UnityEngine.Object obj = bundle.assetBundle.LoadAsset(
"assets/ShaderVariants/resources/red.prefab"
);
Instantiate(obj);
bundle.assetBundle.Unload(
false
);
}
}
}
为了对比shader_feature 和multi_compile 以及shader依赖和非依赖打包,做如下实验:
#pragma shader_feature RED GREEN BLUE
将选中RED关键字的prefab打包,加载bundle和其中的prefab,显示了红色,此时改变此材质的keyword为GREEN或者BLUE,没有效果
#pragma multi_compile RED GREEN BLUE
将选中RED关键字的prefab打包,加载bundle和其中的prefab,显示了红色,此时改变此材质的keyword为GREEN或者BLUE,可以显示绿色和蓝色
分析:shader_feature声明变种时,打包只会打包被资源引用的keyword变种,multi_compile声明变种时,打包会把所有变种都打进去
#pragma shader_feature RED GREEN BLUE
将选中RED关键字的prefab和shader依赖打包,加载bundle和其中的prefab,显示了异常粉红,任何变种都没有生效
分析:shader_feature标记的shader单独依赖打包时,任何变种都不会打进去,分析原因估计是unity认为单包中shader没有被引用过
总结:unity5中新出的shader_feature可以只将引用过的shader变种打进包里面,听起来很有用,可是大部分项目中为了节省冗余shader的内存,shader都是作为依赖包单独成一包的,此时没有任何shader变种被打进包中;更何况即使shader没有依赖打包,如果计划代码中动态修改shader的变种而不是记录在材质里面,此时也不能用shader_feature。基本上我们的项目中shader_feature可以废弃了。。。
以上代码地址:https://github.com/liuxq/UnityForBlog
自己的开源游戏demo:https://github.com/liuxq/StriveGame
0 0
- Unity5的ShaderVariants实验和总结
- Unity5.0 AssetBundle 实验
- Drawcall总结-Unity5.X
- [Unity5.X]AssetBundle总结
- Unity5.0新特性------unity内部:内存 和 性能(以及Unity5的升级优化)
- Unity5.0新特性------unity内部:内存 和 性能(以及Unity5的升级优化)
- Unity5.0新特性------unity内部:内存 和 性能(以及Unity5的升级优化)
- Unity5.0新特性------unity内部:内存 和 性能(以及Unity5的升级优化)
- unity5 资源管理和打包
- unity4和unity5区别
- CME的实验总结
- unity5 和UGUI的小Demo贪吃蛇
- Unity5和unity4的AssetBundle打包策略对比分析
- unity5 测试导出场景和光照贴图丢失的问题
- unity5. Unet同步问题总结
- 关于强制转换操作符reinterpret_cast的实验和总结
- hadoop常用的压缩算法总结和实验验证
- 总结NFE板卡实验中遇到的问题和解决方法
- Java打印长方形
- Spring-2,helloworld
- 树莓派3-搭建文件下载服务器二
- shell编程 for in 循环 抓取index
- adb 截屏和录屏命令
- Unity5的ShaderVariants实验和总结
- Density of Power Network (题意杀,水题)
- (七)枚举 & 注解
- Phaser中文说明文档
- 算法基础篇(10)------匈牙利算法
- Dealing with the nonlinearly separable case using slack variables
- leetcodeOJ 16. 3Sum Closest
- python类型比较的3种方式
- JDBC 基础代码