原地址:http://www.cocoachina.com/gamedev/gameengine/2011/0406/2756.html

这个脚本由 CocoaChina 版主 “四角钱” 分享,可以将复杂的材质(比如有法线贴图的材质)进行"烘焙",转变为单一的贴图。可用来将 Unity 的游戏移植到移动平台时候使用。请将脚本放 Editor 文件夹里,使用时选择一个 Material 材质,然后在菜单种"Custom/Bake Material"打开并调整照明和其他参数,点击Bake按钮就会生成一个单一的贴图。

  1. class BakeMaterialSettings
  2. {
  3. private static var kEditorPrefsName = "BakeMaterialSettings";
  4.  
  5. static var kBakingLayerShouldBeUnusedInScene = 30;
  6. static var kStandardTexNames = new Array ("_MainTex", "_BumpMap", "_Detail", "_ParallaxMap", "_Parallax");
  7.  
  8. var bakeAlpha = false;
  9. var bakeMainTexAsWhite = false;
  10. var minTextureResolution = 8;
  11. var maxTextureResolution = 2048;
  12.  
  13. var emptyScene = false;
  14. var useCustomLights = false;
  15. var ambient = Color.black;
  16.  
  17. static var kLights = 3;
  18. var enableLight = new boolean[kLights];
  19. var colorLight = new Color[kLights];
  20. var dirLight = new Vector2[kLights];
  21.  
  22. function BakeMaterialSettings ()
  23. {
  24. Load ();
  25. }
  26.  
  27. function Load ()
  28. {
  29. bakeAlpha = EditorPrefs.GetBool(kEditorPrefsName + ".bakeAlpha");
  30. bakeMainTexAsWhite = EditorPrefs.GetBool(kEditorPrefsName + ".bakeMainTexAsWhite");
  31. minTextureResolution = EditorPrefs.GetInt(kEditorPrefsName + ".minTextureResolution", 8);
  32. maxTextureResolution = EditorPrefs.GetInt(kEditorPrefsName + ".maxTextureResolution", 2048);
  33.  
  34. emptyScene = EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene");
  35. useCustomLights = EditorPrefs.GetBool(kEditorPrefsName + ".useCustomLights");
  36. ambient.r = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.r");
  37. ambient.g = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.g");
  38. ambient.b = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.b");
  39. ambient.a = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.a", 1.0f);
  40.  
  41. for (var q = 0; q < kLights; ++q)
  42. {
  43. enableLight[q] = EditorPrefs.GetBool(kEditorPrefsName + ".enableLight" + q);
  44. colorLight[q].r = EditorPrefs.GetFloat(kEditorPrefsName + ".color.r" + q, 0.5f);
  45. colorLight[q].g = EditorPrefs.GetFloat(kEditorPrefsName + ".color.g" + q, 0.5f);
  46. colorLight[q].b = EditorPrefs.GetFloat(kEditorPrefsName + ".color.b" + q, 0.5f);
  47. colorLight[q].a = EditorPrefs.GetFloat(kEditorPrefsName + ".color.a" + q, 1.0f);
  48. dirLight[q].x = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.x" + q);
  49. dirLight[q].y = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.y" + q);
  50. }
  51. }
  52.  
  53. function Save ()
  54. {
  55. EditorPrefs.SetBool(kEditorPrefsName + ".bakeAlpha", bakeAlpha);
  56. EditorPrefs.SetBool(kEditorPrefsName + ".bakeMainTexAsWhite", bakeMainTexAsWhite);
  57. EditorPrefs.SetInt(kEditorPrefsName + ".minTextureResolution", minTextureResolution);
  58. EditorPrefs.SetInt(kEditorPrefsName + ".maxTextureResolution", maxTextureResolution);
  59.  
  60. EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene", emptyScene);
  61. EditorPrefs.SetBool(kEditorPrefsName + ".useCustomLights", useCustomLights);
  62. EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.r", ambient.r);
  63. EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.g", ambient.g);
  64. EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.b", ambient.b);
  65. EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.a", ambient.a);
  66.  
  67. for (var q = 0; q < kLights; ++q)
  68. {
  69. EditorPrefs.SetBool(kEditorPrefsName + ".enableLight" + q, enableLight[q]);
  70. EditorPrefs.SetFloat(kEditorPrefsName + ".color.r" + q, colorLight[q].r);
  71. EditorPrefs.SetFloat(kEditorPrefsName + ".color.g" + q, colorLight[q].g);
  72. EditorPrefs.SetFloat(kEditorPrefsName + ".color.b" + q, colorLight[q].b);
  73. EditorPrefs.SetFloat(kEditorPrefsName + ".color.a" + q, colorLight[q].a);
  74. EditorPrefs.SetFloat(kEditorPrefsName + ".dir.x" + q, dirLight[q].x);
  75. EditorPrefs.SetFloat(kEditorPrefsName + ".dir.y" + q, dirLight[q].y);
  76. }
  77. }
  78. }
  79.  
  80. class BakeMaterial extends EditorWindow
  81. {
  82. private static var kMateriBakeNodeName = "__MateriaBakeSetup";
  83. private static var kWindowMinSize = Vector2 (300, 386);
  84.  
  85. private static var settings : BakeMaterialSettings;
  86. private static var visible : boolean = false;
  87.  
  88. private var camera : GameObject;
  89. private var plane : GameObject;
  90. private var previewTexture : Texture;
  91. private var lights : GameObject[] = new GameObject[BakeMaterialSettings.kLights];
  92. private var stateChanged = false;
  93.  
  94. private var texViewScrollPosition = Vector2.zero;
  95. private var lastMaterial : Material;
  96.  
  97. private var originalScene = "";
  98.  
  99. private var scheduleBakeOnNextUpdate = false;
  100.  
  101. private function SetupScene ()
  102. {
  103. DestroyScene ();
  104. var oldGo = GameObject.Find(kMateriBakeNodeName);
  105. if (oldGo)
  106. DestroyImmediate (oldGo);
  107. camera = new GameObject (kMateriBakeNodeName, Camera);
  108. plane = GameObject.CreatePrimitive (PrimitiveType.Plane);
  109.  
  110. var cam = camera;
  111. cam.camera.backgroundColor = Color.black;
  112. cam.camera.clearFlags = CameraClearFlags.SolidColor;
  113. cam.camera.orthographic = true;
  114. cam.camera.orthographicSize = 5.0;
  115. cam.camera.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene;
  116.  
  117. plane.transform.parent = cam.transform;
  118. plane.transform.position = Vector3.forward * 10.0;
  119. plane.transform.rotation = Quaternion.Euler (0, 0, 180) * Quaternion.Euler (-90, 0, 0);
  120. plane.layer = settings.kBakingLayerShouldBeUnusedInScene;
  121.  
  122. for (var l in lights)
  123. {
  124. l = new GameObject ("Light", Light);
  125. l.light.type = LightType.Directional;
  126. l.light.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene;
  127. l.transform.parent = cam.transform;
  128. l.active = false;
  129. }
  130. }
  131.  
  132. private function UpdateScene (m : Material)
  133. {
  134. for (q = 0; q < settings.kLights; ++q)
  135. {
  136. lights[q].active = settings.useCustomLights & settings.enableLight[q];
  137. lights[q].light.color = settings.colorLight[q];
  138. lights[q].transform.rotation =
  139. Quaternion.AngleAxis(settings.dirLight[q].x, Vector3.up) *
  140. Quaternion.AngleAxis(settings.dirLight[q].y, Vector3.right);
  141. }
  142.  
  143. if (settings.useCustomLights)
  144. RenderSettings.ambientLight = settings.ambient;
  145. else if (settings.emptyScene)
  146. RenderSettings.ambientLight = Color.white;
  147.  
  148. plane.renderer.material = m;
  149. }
  150.  
  151. private function DestroyScene ()
  152. {
  153. GameObject.DestroyImmediate (camera);
  154. GameObject.DestroyImmediate (plane);
  155. GameObject.DestroyImmediate (previewTexture);
  156. }
  157.  
  158. function UpdateMaterialPreview (m : Material) : RenderTexture
  159. {
  160. if (!m)
  161. return;
  162.  
  163. var saveAmbientLight = RenderSettings.ambientLight;
  164. var saveMainTexture = m.mainTexture;
  165. if (settings.bakeMainTexAsWhite)
  166. m.mainTexture = null;
  167.  
  168. // setup
  169. if (!camera)
  170. SetupScene ();
  171. camera.SetActiveRecursively(true);
  172. UpdateScene (m);
  173.  
  174. var res = FindLargestTextureResolution (plane.renderer.sharedMaterial, settings.minTextureResolution, settings.maxTextureResolution);
  175. var rt = RenderCameraToRenderTexture (camera.camera, res.x, res.y);
  176.  
  177. // restore
  178. camera.SetActiveRecursively(false);
  179. RenderSettings.ambientLight = saveAmbientLight;
  180. m.mainTexture = saveMainTexture;
  181.  
  182. previewTexture = rt;
  183. return rt;
  184. }
  185.  
  186. function CaptureMaterial(m : Material)
  187. {
  188. var matAssetPath = AssetDatabase.GetAssetPath (m);
  189. var assetPath = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (matAssetPath), System.IO.Path.GetFileNameWithoutExtension (matAssetPath));
  190.  
  191. var rt = UpdateMaterialPreview (m);
  192. RenderTextureToPNG (rt, settings.bakeAlpha, assetPath + ".png");
  193. }
  194.  
  195. function OnEnable ()
  196. {
  197. if (!settings)
  198. settings = new BakeMaterialSettings ();
  199. SetupScene ();
  200. visible = true;
  201. }
  202.  
  203. function OnDisable ()
  204. {
  205. DestroyScene ();
  206. settings.Save ();
  207. visible = false;
  208. }
  209.  
  210. static function GetTargetMaterial () : Material
  211. {
  212. return EditorUtility.InstanceIDToObject (Selection.activeInstanceID) as Material;
  213. }
  214.  
  215. function OnSelectionChange ()
  216. {
  217. Repaint ();
  218. }
  219.  
  220. function Update ()
  221. {
  222. var rebuildScene = false;
  223. if (scheduleBakeOnNextUpdate)
  224. {
  225. Bake ();
  226. scheduleBakeOnNextUpdate = false;
  227. rebuildScene = true;
  228. }
  229.  
  230. if (originalScene == "" && EditorApplication.currentScene == "")
  231. settings.emptyScene = true;
  232.  
  233. if (settings.emptyScene && originalScene == "" && EditorApplication.currentScene != "")
  234. {
  235. DestroyScene ();
  236. if (EditorApplication.SaveCurrentSceneIfUserWantsTo ())
  237. {
  238. originalScene = EditorApplication.currentScene;
  239. EditorApplication.NewScene ();
  240. }
  241. else
  242. settings.emptyScene = false;
  243. rebuildScene = true;
  244. }
  245. else if (!settings.emptyScene && originalScene != "")
  246. {
  247. EditorApplication.OpenScene (originalScene);
  248. rebuildScene = true;
  249. originalScene = "";
  250. }
  251.  
  252. if (rebuildScene)
  253. {
  254. SetupScene ();
  255. }
  256.  
  257. if (rebuildScene || stateChanged || !settings.emptyScene)
  258. {
  259. UpdateMaterialPreview (lastMaterial);
  260. Repaint ();
  261. stateChanged = false;
  262. }
  263. }
  264.  
  265. function OnGUI ()
  266. {
  267. var material = GetTargetMaterial ();
  268. if (lastMaterial != material)
  269. UpdateMaterialPreview (material);
  270. if (material)
  271. lastMaterial = material;
  272.  
  273. EditorGUILayout.BeginHorizontal();
  274. EditorGUILayout.BeginVertical(GUILayout.MaxWidth(200));
  275. if (!(originalScene == "" && EditorApplication.currentScene == ""))
  276. {
  277. settings.emptyScene = !EditorGUILayout.BeginToggleGroup("Scene ligthing", !settings.emptyScene);
  278. EditorGUILayout.EndToggleGroup();
  279. }
  280. settings.useCustomLights = EditorGUILayout.BeginToggleGroup("Custom lighting", settings.useCustomLights);
  281. if (settings.useCustomLights)
  282. {
  283. EditorGUI.indentLevel = 1;
  284. settings.ambient = EditorGUILayout.ColorField("Ambient", settings.ambient);
  285. for (var q = 0; q < settings.kLights; ++q)
  286. {
  287. settings.enableLight[q] = EditorGUILayout.BeginToggleGroup("Light", settings.enableLight[q]);
  288. EditorGUI.indentLevel = 2;
  289. settings.colorLight[q] = EditorGUILayout.ColorField("Color", settings.colorLight[q]);
  290. settings.dirLight[q] = EditorGUILayout.Vector2Field("Direction", settings.dirLight[q]);
  291. EditorGUILayout.EndToggleGroup();
  292. }
  293. }
  294. EditorGUI.indentLevel = 0;
  295. EditorGUILayout.EndToggleGroup();
  296.  
  297. settings.bakeAlpha = EditorGUILayout.Toggle("Bake Alpha", settings.bakeAlpha);
  298. settings.bakeMainTexAsWhite = !EditorGUILayout.Toggle("MainTex", !settings.bakeMainTexAsWhite);
  299. settings.minTextureResolution = EditorGUILayout.IntField("Min Resolution", settings.minTextureResolution);
  300. settings.maxTextureResolution = EditorGUILayout.IntField("Max Resolution", settings.maxTextureResolution);
  301. settings.minTextureResolution = Mathf.Max(2, settings.minTextureResolution);
  302. settings.maxTextureResolution = Mathf.Max(settings.minTextureResolution, settings.maxTextureResolution);
  303.  
  304. EditorGUILayout.BeginHorizontal();
  305. if (GUILayout.Button("Bake"))
  306. {
  307. CaptureMaterial (lastMaterial);
  308. }
  309. if (GUILayout.Button("Bake Selected"))
  310. {
  311. scheduleBakeOnNextUpdate = true;
  312. }
  313. EditorGUILayout.EndHorizontal();
  314.  
  315. EditorGUILayout.EndVertical();
  316.  
  317. texViewScrollPosition = EditorGUILayout.BeginScrollView (texViewScrollPosition);
  318. var r = GUILayoutUtility.GetAspectRect(1.0f);
  319. if (previewTexture)
  320. EditorGUI.DrawPreviewTexture(r, previewTexture);
  321. EditorGUILayout.EndScrollView();
  322. EditorGUILayout.EndHorizontal();
  323.  
  324. if (GUI.changed)
  325. {
  326. stateChanged = true;
  327. }
  328. }
  329.  
  330. @MenuItem("Custom/Bake Material ...", false, 5)
  331. static function CreateBakeEditor()
  332. {
  333. var window = EditorWindow.GetWindow(BakeMaterial);
  334. window.title = "Bake Material";
  335. window.minSize = kWindowMinSize;
  336. window.Show();
  337. }
  338.  
  339. @MenuItem("Custom/Bake Selected Materials", false, 4)
  340. static function Bake()
  341. {
  342. var instanceIDs = Selection.instanceIDs;
  343. var currentScene = EditorApplication.currentScene;
  344.  
  345. var wasAlreadyVisible = BakeMaterial.visible;
  346. var window = EditorWindow.GetWindow(BakeMaterial);
  347.  
  348. if (window.settings.emptyScene)
  349. {
  350. if (!EditorApplication.SaveCurrentSceneIfUserWantsTo ())
  351. return;
  352. EditorApplication.NewScene ();
  353. }
  354.  
  355. window.SetupScene ();
  356. for (var i in instanceIDs)
  357. {
  358. var m : Material = EditorUtility.InstanceIDToObject (i) as Material;
  359. if (m)
  360. window.CaptureMaterial (m);
  361. }
  362. window.DestroyScene ();
  363.  
  364. if (window.settings.emptyScene && currentScene)
  365. {
  366. EditorApplication.OpenScene (currentScene);
  367. }
  368.  
  369. if (!wasAlreadyVisible)
  370. window.Close ();
  371. }
  372.  
  373. static function FindLargestTextureResolution (m : Material, minTexRes : int, maxTexRes : int) : Vector2
  374. {
  375. var res = Vector2 (minTexRes, minTexRes);
  376. for (var n in BakeMaterialSettings.kStandardTexNames)
  377. {
  378. if (!m.HasProperty (n))
  379. continue;
  380.  
  381. var t : Texture = m.GetTexture (n);
  382. if (!t)
  383. continue;
  384.  
  385. res.x = Mathf.Max (res.x, t.width);
  386. res.y = Mathf.Max (res.y, t.height);
  387. }
  388. res.x = Mathf.Min (res.x, maxTexRes);
  389. res.y = Mathf.Min (res.y, maxTexRes);
  390. return res;
  391. }
  392.  
  393. static function RenderCameraToRenderTexture (cam : Camera, width : int, height : int) : RenderTexture
  394. {
  395. var rt = cam.camera.targetTexture;
  396. if (rt && rt.width != width && rt.height != height)
  397. DestroyImmediate(rt);
  398. if (!rt)
  399. rt = new RenderTexture (width, height, 24);
  400. cam.camera.targetTexture = rt;
  401. cam.camera.Render ();
  402. return rt;
  403. }
  404.  
  405. static function RenderTextureToPNG (rt : RenderTexture, bakeAlpha : boolean, assetPath : String)
  406. {
  407. RenderTexture.active = rt;
  408.  
  409. var screenShot = new Texture2D (rt.width, rt.height, bakeAlpha? TextureFormat.ARGB32 : TextureFormat.RGB24, false);
  410. screenShot.ReadPixels (Rect (0, 0, rt.width, rt.height), 0, 0);
  411.  
  412. RenderTexture.active = null;
  413.  
  414. var bytes = screenShot.EncodeToPNG ();
  415. System.IO.File.WriteAllBytes (assetPath, bytes);
  416.  
  417. AssetDatabase.ImportAsset (assetPath, ImportAssetOptions.ForceUpdate);
  418. }
  419. }

  

Unity 烘焙材质到单一贴图的脚本的更多相关文章

  1. 一键批量添加材质的法线贴图-unity插件

    有时候材质做完后需要更改贴图,或者增加贴图,数量少的时候可以一张张添加和修改,数量多的时候就只能代码生成了.原理是通过名字的关联:主贴图和法线贴图大多数只是后缀的不同上,如果不是那是美术规范没做好啊, ...

  2. 解决Unity烘焙阴影锯齿精度不足的问题

    烘焙阴影锯齿问题  烘焙后阴影锯齿明显,如下图: 烘焙的光照贴图质量主要受LightmapParameters 的Blur Radius和抗锯齿级别影响, 默认最高级别如下: 如果最高级别不能达到好的 ...

  3. Three.js基础探寻八——法向材质与材质的纹理贴图

    4.法向材质 法向材质可以将材质的颜色设置为其法向量的方向,有时候对于调试很有帮助. 法向材质的设定很简单,甚至不用设置任何参数: new THREE.MeshNormalMaterial() 材质的 ...

  4. unity 模型 材质 贴图 关系;着色器属性

    模型包含 材质(Material),包括 [核心]着色器(Shader) 贴图和其他参数,贴图也算是一种参数 其他,如网格渲染器(Mesh Renderer).动画.坐标 一个材质可以看做为一个Sha ...

  5. Unity透明材质Batch

    NO Batch  ? 游戏场景中存在大量例子的时候,DrallCall的压力很大,但是遍历一遍之后发现,为啥一样的粒子特效竟然没有合并,why?经过很多测试后发现,如果把透明材质的修改为非半透明的, ...

  6. Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.

    这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用. 在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blin ...

  7. unity烘焙记录

    1.Unity Android 阴影不显示.阴影显示不正确 解决 http://blog.csdn.net/xuetao0605/article/details/50626181 2.阴影强度问题 不 ...

  8. Unity 烘焙的2种方式

    游戏场景通常有许多光源,使用实时渲染会非常消耗性能,解决办法是烘焙,烘焙有2种方式. 1, 在3dmax等模型制作软件中对场景进行烘焙.将烘焙好的模型以及贴图导入到unity3d. 相对复杂但效果好 ...

  9. OpenGL光照2:材质和光照贴图

    本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 的内容为插入注释,可以先跳过 ...

随机推荐

  1. El Capitan 中 SIP 介绍

    http://havee.me/mac/2015-10/system-integrity-protection-on-el-capitan.html 这两天大家纷纷将 OS X 系统升级到了 El C ...

  2. Javascript 里的 in

    写js的时候需要遍历一个对象的属性,把属性名和属性值都提出来,之前没遇到这种需求,查了一下可以用for in的方式. var obj = { "key1":"value1 ...

  3. jquery扩展函数详解(我的人生颠覆)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上次分析了jquery的源码 ...

  4. ssh 返回错误 Too many authentic authentication failures for root 的时候检查 ssh 配置

    路径 cd /etc/ssh ls -ltr sudo vi sshd_config 改为以下内容(yes): PermitRootLogin yes

  5. 在C#中使用官方驱动操作MongoDB ---转载

    http://blog.csdn.net/dannywj1371/article/details/7440916

  6. nginx自学

    需要了解的linux的命令: linux的命令:netstat -antnetstat -antp(天假了参数P)ps aux | grep 80kill -9 2985 号进程pkill -9 ht ...

  7. [BZOJ 1052][HAOI2007]覆盖问题(二分答案)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1052 分析: 挺有想法的一道题,先二分答案ans,主要是判断的问题. 首先可以弄出把所 ...

  8. CsharpThinking---代码契约CodeContract(八)

    代码契约(Code Contract):它并不是语言本身的新功能,而是一些额外的工具,帮助人们控制代码边界. 代码契约之于C#,就相当于诗词歌赋之于语言. --- C# in Depth 一,概述 1 ...

  9. DOM(十)使用DOM设置单选按钮、复选框、下拉菜单

    1.设置单选按钮 单选按钮在表单中即<input type="radio" />它是一组供用户选择的对象,但每次只能选一个.每一个都有checked属性,当一项选择为t ...

  10. Eclipse字体大小设置

    打开Eclipse,在主界面下Window->Preferences->General->Appearance->Colors and Fonts, 然后在右边展开框Basic ...