Unity 烘焙材质到单一贴图的脚本
原地址:http://www.cocoachina.com/gamedev/gameengine/2011/0406/2756.html
这个脚本由 CocoaChina 版主 “四角钱” 分享,可以将复杂的材质(比如有法线贴图的材质)进行"烘焙",转变为单一的贴图。可用来将 Unity 的游戏移植到移动平台时候使用。请将脚本放 Editor 文件夹里,使用时选择一个 Material 材质,然后在菜单种"Custom/Bake Material"打开并调整照明和其他参数,点击Bake按钮就会生成一个单一的贴图。
![](http://www.cocoachina.com/cms/uploads/allimg/110406/8_110406130701_1.jpg)
- class BakeMaterialSettings
- {
- private static var kEditorPrefsName = "BakeMaterialSettings";
- static var kBakingLayerShouldBeUnusedInScene = 30;
- static var kStandardTexNames = new Array ("_MainTex", "_BumpMap", "_Detail", "_ParallaxMap", "_Parallax");
- var bakeAlpha = false;
- var bakeMainTexAsWhite = false;
- var minTextureResolution = 8;
- var maxTextureResolution = 2048;
- var emptyScene = false;
- var useCustomLights = false;
- var ambient = Color.black;
- static var kLights = 3;
- var enableLight = new boolean[kLights];
- var colorLight = new Color[kLights];
- var dirLight = new Vector2[kLights];
- function BakeMaterialSettings ()
- {
- Load ();
- }
- function Load ()
- {
- bakeAlpha = EditorPrefs.GetBool(kEditorPrefsName + ".bakeAlpha");
- bakeMainTexAsWhite = EditorPrefs.GetBool(kEditorPrefsName + ".bakeMainTexAsWhite");
- minTextureResolution = EditorPrefs.GetInt(kEditorPrefsName + ".minTextureResolution", 8);
- maxTextureResolution = EditorPrefs.GetInt(kEditorPrefsName + ".maxTextureResolution", 2048);
- emptyScene = EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene");
- useCustomLights = EditorPrefs.GetBool(kEditorPrefsName + ".useCustomLights");
- ambient.r = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.r");
- ambient.g = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.g");
- ambient.b = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.b");
- ambient.a = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.a", 1.0f);
- for (var q = 0; q < kLights; ++q)
- {
- enableLight[q] = EditorPrefs.GetBool(kEditorPrefsName + ".enableLight" + q);
- colorLight[q].r = EditorPrefs.GetFloat(kEditorPrefsName + ".color.r" + q, 0.5f);
- colorLight[q].g = EditorPrefs.GetFloat(kEditorPrefsName + ".color.g" + q, 0.5f);
- colorLight[q].b = EditorPrefs.GetFloat(kEditorPrefsName + ".color.b" + q, 0.5f);
- colorLight[q].a = EditorPrefs.GetFloat(kEditorPrefsName + ".color.a" + q, 1.0f);
- dirLight[q].x = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.x" + q);
- dirLight[q].y = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.y" + q);
- }
- }
- function Save ()
- {
- EditorPrefs.SetBool(kEditorPrefsName + ".bakeAlpha", bakeAlpha);
- EditorPrefs.SetBool(kEditorPrefsName + ".bakeMainTexAsWhite", bakeMainTexAsWhite);
- EditorPrefs.SetInt(kEditorPrefsName + ".minTextureResolution", minTextureResolution);
- EditorPrefs.SetInt(kEditorPrefsName + ".maxTextureResolution", maxTextureResolution);
- EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene", emptyScene);
- EditorPrefs.SetBool(kEditorPrefsName + ".useCustomLights", useCustomLights);
- EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.r", ambient.r);
- EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.g", ambient.g);
- EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.b", ambient.b);
- EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.a", ambient.a);
- for (var q = 0; q < kLights; ++q)
- {
- EditorPrefs.SetBool(kEditorPrefsName + ".enableLight" + q, enableLight[q]);
- EditorPrefs.SetFloat(kEditorPrefsName + ".color.r" + q, colorLight[q].r);
- EditorPrefs.SetFloat(kEditorPrefsName + ".color.g" + q, colorLight[q].g);
- EditorPrefs.SetFloat(kEditorPrefsName + ".color.b" + q, colorLight[q].b);
- EditorPrefs.SetFloat(kEditorPrefsName + ".color.a" + q, colorLight[q].a);
- EditorPrefs.SetFloat(kEditorPrefsName + ".dir.x" + q, dirLight[q].x);
- EditorPrefs.SetFloat(kEditorPrefsName + ".dir.y" + q, dirLight[q].y);
- }
- }
- }
- class BakeMaterial extends EditorWindow
- {
- private static var kMateriBakeNodeName = "__MateriaBakeSetup";
- private static var kWindowMinSize = Vector2 (300, 386);
- private static var settings : BakeMaterialSettings;
- private static var visible : boolean = false;
- private var camera : GameObject;
- private var plane : GameObject;
- private var previewTexture : Texture;
- private var lights : GameObject[] = new GameObject[BakeMaterialSettings.kLights];
- private var stateChanged = false;
- private var texViewScrollPosition = Vector2.zero;
- private var lastMaterial : Material;
- private var originalScene = "";
- private var scheduleBakeOnNextUpdate = false;
- private function SetupScene ()
- {
- DestroyScene ();
- var oldGo = GameObject.Find(kMateriBakeNodeName);
- if (oldGo)
- DestroyImmediate (oldGo);
- camera = new GameObject (kMateriBakeNodeName, Camera);
- plane = GameObject.CreatePrimitive (PrimitiveType.Plane);
- var cam = camera;
- cam.camera.backgroundColor = Color.black;
- cam.camera.clearFlags = CameraClearFlags.SolidColor;
- cam.camera.orthographic = true;
- cam.camera.orthographicSize = 5.0;
- cam.camera.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene;
- plane.transform.parent = cam.transform;
- plane.transform.position = Vector3.forward * 10.0;
- plane.transform.rotation = Quaternion.Euler (0, 0, 180) * Quaternion.Euler (-90, 0, 0);
- plane.layer = settings.kBakingLayerShouldBeUnusedInScene;
- for (var l in lights)
- {
- l = new GameObject ("Light", Light);
- l.light.type = LightType.Directional;
- l.light.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene;
- l.transform.parent = cam.transform;
- l.active = false;
- }
- }
- private function UpdateScene (m : Material)
- {
- for (q = 0; q < settings.kLights; ++q)
- {
- lights[q].active = settings.useCustomLights & settings.enableLight[q];
- lights[q].light.color = settings.colorLight[q];
- lights[q].transform.rotation =
- Quaternion.AngleAxis(settings.dirLight[q].x, Vector3.up) *
- Quaternion.AngleAxis(settings.dirLight[q].y, Vector3.right);
- }
- if (settings.useCustomLights)
- RenderSettings.ambientLight = settings.ambient;
- else if (settings.emptyScene)
- RenderSettings.ambientLight = Color.white;
- plane.renderer.material = m;
- }
- private function DestroyScene ()
- {
- GameObject.DestroyImmediate (camera);
- GameObject.DestroyImmediate (plane);
- GameObject.DestroyImmediate (previewTexture);
- }
- function UpdateMaterialPreview (m : Material) : RenderTexture
- {
- if (!m)
- return;
- var saveAmbientLight = RenderSettings.ambientLight;
- var saveMainTexture = m.mainTexture;
- if (settings.bakeMainTexAsWhite)
- m.mainTexture = null;
- // setup
- if (!camera)
- SetupScene ();
- camera.SetActiveRecursively(true);
- UpdateScene (m);
- var res = FindLargestTextureResolution (plane.renderer.sharedMaterial, settings.minTextureResolution, settings.maxTextureResolution);
- var rt = RenderCameraToRenderTexture (camera.camera, res.x, res.y);
- // restore
- camera.SetActiveRecursively(false);
- RenderSettings.ambientLight = saveAmbientLight;
- m.mainTexture = saveMainTexture;
- previewTexture = rt;
- return rt;
- }
- function CaptureMaterial(m : Material)
- {
- var matAssetPath = AssetDatabase.GetAssetPath (m);
- var assetPath = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (matAssetPath), System.IO.Path.GetFileNameWithoutExtension (matAssetPath));
- var rt = UpdateMaterialPreview (m);
- RenderTextureToPNG (rt, settings.bakeAlpha, assetPath + ".png");
- }
- function OnEnable ()
- {
- if (!settings)
- settings = new BakeMaterialSettings ();
- SetupScene ();
- visible = true;
- }
- function OnDisable ()
- {
- DestroyScene ();
- settings.Save ();
- visible = false;
- }
- static function GetTargetMaterial () : Material
- {
- return EditorUtility.InstanceIDToObject (Selection.activeInstanceID) as Material;
- }
- function OnSelectionChange ()
- {
- Repaint ();
- }
- function Update ()
- {
- var rebuildScene = false;
- if (scheduleBakeOnNextUpdate)
- {
- Bake ();
- scheduleBakeOnNextUpdate = false;
- rebuildScene = true;
- }
- if (originalScene == "" && EditorApplication.currentScene == "")
- settings.emptyScene = true;
- if (settings.emptyScene && originalScene == "" && EditorApplication.currentScene != "")
- {
- DestroyScene ();
- if (EditorApplication.SaveCurrentSceneIfUserWantsTo ())
- {
- originalScene = EditorApplication.currentScene;
- EditorApplication.NewScene ();
- }
- else
- settings.emptyScene = false;
- rebuildScene = true;
- }
- else if (!settings.emptyScene && originalScene != "")
- {
- EditorApplication.OpenScene (originalScene);
- rebuildScene = true;
- originalScene = "";
- }
- if (rebuildScene)
- {
- SetupScene ();
- }
- if (rebuildScene || stateChanged || !settings.emptyScene)
- {
- UpdateMaterialPreview (lastMaterial);
- Repaint ();
- stateChanged = false;
- }
- }
- function OnGUI ()
- {
- var material = GetTargetMaterial ();
- if (lastMaterial != material)
- UpdateMaterialPreview (material);
- if (material)
- lastMaterial = material;
- EditorGUILayout.BeginHorizontal();
- EditorGUILayout.BeginVertical(GUILayout.MaxWidth(200));
- if (!(originalScene == "" && EditorApplication.currentScene == ""))
- {
- settings.emptyScene = !EditorGUILayout.BeginToggleGroup("Scene ligthing", !settings.emptyScene);
- EditorGUILayout.EndToggleGroup();
- }
- settings.useCustomLights = EditorGUILayout.BeginToggleGroup("Custom lighting", settings.useCustomLights);
- if (settings.useCustomLights)
- {
- EditorGUI.indentLevel = 1;
- settings.ambient = EditorGUILayout.ColorField("Ambient", settings.ambient);
- for (var q = 0; q < settings.kLights; ++q)
- {
- settings.enableLight[q] = EditorGUILayout.BeginToggleGroup("Light", settings.enableLight[q]);
- EditorGUI.indentLevel = 2;
- settings.colorLight[q] = EditorGUILayout.ColorField("Color", settings.colorLight[q]);
- settings.dirLight[q] = EditorGUILayout.Vector2Field("Direction", settings.dirLight[q]);
- EditorGUILayout.EndToggleGroup();
- }
- }
- EditorGUI.indentLevel = 0;
- EditorGUILayout.EndToggleGroup();
- settings.bakeAlpha = EditorGUILayout.Toggle("Bake Alpha", settings.bakeAlpha);
- settings.bakeMainTexAsWhite = !EditorGUILayout.Toggle("MainTex", !settings.bakeMainTexAsWhite);
- settings.minTextureResolution = EditorGUILayout.IntField("Min Resolution", settings.minTextureResolution);
- settings.maxTextureResolution = EditorGUILayout.IntField("Max Resolution", settings.maxTextureResolution);
- settings.minTextureResolution = Mathf.Max(2, settings.minTextureResolution);
- settings.maxTextureResolution = Mathf.Max(settings.minTextureResolution, settings.maxTextureResolution);
- EditorGUILayout.BeginHorizontal();
- if (GUILayout.Button("Bake"))
- {
- CaptureMaterial (lastMaterial);
- }
- if (GUILayout.Button("Bake Selected"))
- {
- scheduleBakeOnNextUpdate = true;
- }
- EditorGUILayout.EndHorizontal();
- EditorGUILayout.EndVertical();
- texViewScrollPosition = EditorGUILayout.BeginScrollView (texViewScrollPosition);
- var r = GUILayoutUtility.GetAspectRect(1.0f);
- if (previewTexture)
- EditorGUI.DrawPreviewTexture(r, previewTexture);
- EditorGUILayout.EndScrollView();
- EditorGUILayout.EndHorizontal();
- if (GUI.changed)
- {
- stateChanged = true;
- }
- }
- @MenuItem("Custom/Bake Material ...", false, 5)
- static function CreateBakeEditor()
- {
- var window = EditorWindow.GetWindow(BakeMaterial);
- window.title = "Bake Material";
- window.minSize = kWindowMinSize;
- window.Show();
- }
- @MenuItem("Custom/Bake Selected Materials", false, 4)
- static function Bake()
- {
- var instanceIDs = Selection.instanceIDs;
- var currentScene = EditorApplication.currentScene;
- var wasAlreadyVisible = BakeMaterial.visible;
- var window = EditorWindow.GetWindow(BakeMaterial);
- if (window.settings.emptyScene)
- {
- if (!EditorApplication.SaveCurrentSceneIfUserWantsTo ())
- return;
- EditorApplication.NewScene ();
- }
- window.SetupScene ();
- for (var i in instanceIDs)
- {
- var m : Material = EditorUtility.InstanceIDToObject (i) as Material;
- if (m)
- window.CaptureMaterial (m);
- }
- window.DestroyScene ();
- if (window.settings.emptyScene && currentScene)
- {
- EditorApplication.OpenScene (currentScene);
- }
- if (!wasAlreadyVisible)
- window.Close ();
- }
- static function FindLargestTextureResolution (m : Material, minTexRes : int, maxTexRes : int) : Vector2
- {
- var res = Vector2 (minTexRes, minTexRes);
- for (var n in BakeMaterialSettings.kStandardTexNames)
- {
- if (!m.HasProperty (n))
- continue;
- var t : Texture = m.GetTexture (n);
- if (!t)
- continue;
- res.x = Mathf.Max (res.x, t.width);
- res.y = Mathf.Max (res.y, t.height);
- }
- res.x = Mathf.Min (res.x, maxTexRes);
- res.y = Mathf.Min (res.y, maxTexRes);
- return res;
- }
- static function RenderCameraToRenderTexture (cam : Camera, width : int, height : int) : RenderTexture
- {
- var rt = cam.camera.targetTexture;
- if (rt && rt.width != width && rt.height != height)
- DestroyImmediate(rt);
- if (!rt)
- rt = new RenderTexture (width, height, 24);
- cam.camera.targetTexture = rt;
- cam.camera.Render ();
- return rt;
- }
- static function RenderTextureToPNG (rt : RenderTexture, bakeAlpha : boolean, assetPath : String)
- {
- RenderTexture.active = rt;
- var screenShot = new Texture2D (rt.width, rt.height, bakeAlpha? TextureFormat.ARGB32 : TextureFormat.RGB24, false);
- screenShot.ReadPixels (Rect (0, 0, rt.width, rt.height), 0, 0);
- RenderTexture.active = null;
- var bytes = screenShot.EncodeToPNG ();
- System.IO.File.WriteAllBytes (assetPath, bytes);
- AssetDatabase.ImportAsset (assetPath, ImportAssetOptions.ForceUpdate);
- }
- }
Unity 烘焙材质到单一贴图的脚本的更多相关文章
- 一键批量添加材质的法线贴图-unity插件
有时候材质做完后需要更改贴图,或者增加贴图,数量少的时候可以一张张添加和修改,数量多的时候就只能代码生成了.原理是通过名字的关联:主贴图和法线贴图大多数只是后缀的不同上,如果不是那是美术规范没做好啊, ...
- 解决Unity烘焙阴影锯齿精度不足的问题
烘焙阴影锯齿问题 烘焙后阴影锯齿明显,如下图: 烘焙的光照贴图质量主要受LightmapParameters 的Blur Radius和抗锯齿级别影响, 默认最高级别如下: 如果最高级别不能达到好的 ...
- Three.js基础探寻八——法向材质与材质的纹理贴图
4.法向材质 法向材质可以将材质的颜色设置为其法向量的方向,有时候对于调试很有帮助. 法向材质的设定很简单,甚至不用设置任何参数: new THREE.MeshNormalMaterial() 材质的 ...
- unity 模型 材质 贴图 关系;着色器属性
模型包含 材质(Material),包括 [核心]着色器(Shader) 贴图和其他参数,贴图也算是一种参数 其他,如网格渲染器(Mesh Renderer).动画.坐标 一个材质可以看做为一个Sha ...
- Unity透明材质Batch
NO Batch ? 游戏场景中存在大量例子的时候,DrallCall的压力很大,但是遍历一遍之后发现,为啥一样的粒子特效竟然没有合并,why?经过很多测试后发现,如果把透明材质的修改为非半透明的, ...
- Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.
这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用. 在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blin ...
- unity烘焙记录
1.Unity Android 阴影不显示.阴影显示不正确 解决 http://blog.csdn.net/xuetao0605/article/details/50626181 2.阴影强度问题 不 ...
- Unity 烘焙的2种方式
游戏场景通常有许多光源,使用实时渲染会非常消耗性能,解决办法是烘焙,烘焙有2种方式. 1, 在3dmax等模型制作软件中对场景进行烘焙.将烘焙好的模型以及贴图导入到unity3d. 相对复杂但效果好 ...
- OpenGL光照2:材质和光照贴图
本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 的内容为插入注释,可以先跳过 ...
随机推荐
- El Capitan 中 SIP 介绍
http://havee.me/mac/2015-10/system-integrity-protection-on-el-capitan.html 这两天大家纷纷将 OS X 系统升级到了 El C ...
- Javascript 里的 in
写js的时候需要遍历一个对象的属性,把属性名和属性值都提出来,之前没遇到这种需求,查了一下可以用for in的方式. var obj = { "key1":"value1 ...
- jquery扩展函数详解(我的人生颠覆)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上次分析了jquery的源码 ...
- ssh 返回错误 Too many authentic authentication failures for root 的时候检查 ssh 配置
路径 cd /etc/ssh ls -ltr sudo vi sshd_config 改为以下内容(yes): PermitRootLogin yes
- 在C#中使用官方驱动操作MongoDB ---转载
http://blog.csdn.net/dannywj1371/article/details/7440916
- nginx自学
需要了解的linux的命令: linux的命令:netstat -antnetstat -antp(天假了参数P)ps aux | grep 80kill -9 2985 号进程pkill -9 ht ...
- [BZOJ 1052][HAOI2007]覆盖问题(二分答案)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1052 分析: 挺有想法的一道题,先二分答案ans,主要是判断的问题. 首先可以弄出把所 ...
- CsharpThinking---代码契约CodeContract(八)
代码契约(Code Contract):它并不是语言本身的新功能,而是一些额外的工具,帮助人们控制代码边界. 代码契约之于C#,就相当于诗词歌赋之于语言. --- C# in Depth 一,概述 1 ...
- DOM(十)使用DOM设置单选按钮、复选框、下拉菜单
1.设置单选按钮 单选按钮在表单中即<input type="radio" />它是一组供用户选择的对象,但每次只能选一个.每一个都有checked属性,当一项选择为t ...
- Eclipse字体大小设置
打开Eclipse,在主界面下Window->Preferences->General->Appearance->Colors and Fonts, 然后在右边展开框Basic ...