Unity烘焙材质到贴图脚本
2011-05-06 16:26
471 查看
这个脚本可以将复杂的材质,比如有法线贴图的材质进行"烘焙",转变为单一的贴图,可用来将Unity的游戏移植到移动平台时候使用.
讲脚本放Editor文件夹里,使用时选择一个Material材质,然后在菜单种"Custom/Bake Material"打开并调整照明和其他参数,点击Bake按钮,就会生成一个单一的贴图.
脚本:BakeMaterial.js
js 代码
讲脚本放Editor文件夹里,使用时选择一个Material材质,然后在菜单种"Custom/Bake Material"打开并调整照明和其他参数,点击Bake按钮,就会生成一个单一的贴图.
脚本:BakeMaterial.js
js 代码
001 | class BakeMaterialSettings |
002 | { |
003 | privatestatic var kEditorPrefsName = "BakeMaterialSettings" ; |
004 |
005 | static var kBakingLayerShouldBeUnusedInScene = 30; |
006 | static var kStandardTexNames = new Array ( "_MainTex" , "_BumpMap" , "_Detail" , "_ParallaxMap" , "_Parallax" ); |
007 |
008 | var bakeAlpha = false ; |
009 | var bakeMainTexAsWhite = false ; |
010 | var minTextureResolution= 8; |
011 | var maxTextureResolution= 2048; |
012 |
013 | var emptyScene = false ; |
014 | var useCustomLights = false ; |
015 | var ambient = Color.black; |
016 |
017 | static var kLights = 3; |
018 | var enableLight = new boolean[kLights]; |
019 | var colorLight = new Color[kLights]; |
020 | var dirLight = new Vector2[kLights]; |
021 |
022 | function BakeMaterialSettings () |
023 | { |
024 | Load (); |
025 | } |
026 |
027 | function Load () |
028 | { |
029 | bakeAlpha =EditorPrefs.GetBool(kEditorPrefsName + ".bakeAlpha" ); |
030 | bakeMainTexAsWhite =EditorPrefs.GetBool(kEditorPrefsName + ".bakeMainTexAsWhite" ); |
031 | minTextureResolution= EditorPrefs.GetInt(kEditorPrefsName + ".minTextureResolution" ,8); |
032 | maxTextureResolution= EditorPrefs.GetInt(kEditorPrefsName + ".maxTextureResolution" ,2048); |
033 |
034 | emptyScene =EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene" ); |
035 | useCustomLights =EditorPrefs.GetBool(kEditorPrefsName + ".useCustomLights" ); |
036 | ambient.r = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.r" ); |
037 | ambient.g = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.g" ); |
038 | ambient.b = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.b" ); |
039 | ambient.a = EditorPrefs.GetFloat(kEditorPrefsName + ".ambient.a" ,1.0f); |
040 |
041 | for ( var q = 0; q < kLights; ++q) |
042 | { |
043 | enableLight[q] = EditorPrefs.GetBool(kEditorPrefsName + ".enableLight" + q); |
044 | colorLight[q].r = EditorPrefs.GetFloat(kEditorPrefsName + ".color.r" + q,0.5f); |
045 | colorLight[q].g = EditorPrefs.GetFloat(kEditorPrefsName + ".color.g" + q,0.5f); |
046 | colorLight[q].b = EditorPrefs.GetFloat(kEditorPrefsName + ".color.b" + q,0.5f); |
047 | colorLight[q].a = EditorPrefs.GetFloat(kEditorPrefsName + ".color.a" + q,1.0f); |
048 | dirLight[q].x = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.x" + q); |
049 | dirLight[q].y = EditorPrefs.GetFloat(kEditorPrefsName + ".dir.y" + q); |
050 | } |
051 | } |
052 |
053 | function Save () |
054 | { |
055 | EditorPrefs.SetBool(kEditorPrefsName + ".bakeAlpha" ,bakeAlpha); |
056 | EditorPrefs.SetBool(kEditorPrefsName + ".bakeMainTexAsWhite" ,bakeMainTexAsWhite); |
057 | EditorPrefs.SetInt(kEditorPrefsName + ".minTextureResolution" ,minTextureResolution); |
058 | EditorPrefs.SetInt(kEditorPrefsName + ".maxTextureResolution" ,maxTextureResolution); |
059 |
060 | EditorPrefs.GetBool(kEditorPrefsName + ".emptyScene" ,emptyScene); |
061 | EditorPrefs.SetBool(kEditorPrefsName + ".useCustomLights" ,useCustomLights); |
062 | EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.r" ,ambient.r); |
063 | EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.g" ,ambient.g); |
064 | EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.b" ,ambient.b); |
065 | EditorPrefs.SetFloat(kEditorPrefsName + ".ambient.a" ,ambient.a); |
066 |
067 | for ( var q = 0; q < kLights; ++q) |
068 | { |
069 | EditorPrefs.SetBool(kEditorPrefsName + ".enableLight" + q,enableLight[q]); |
070 | EditorPrefs.SetFloat(kEditorPrefsName + ".color.r" + q,colorLight[q].r); |
071 | EditorPrefs.SetFloat(kEditorPrefsName + ".color.g" + q,colorLight[q].g); |
072 | EditorPrefs.SetFloat(kEditorPrefsName + ".color.b" + q,colorLight[q].b); |
073 | EditorPrefs.SetFloat(kEditorPrefsName + ".color.a" + q,colorLight[q].a); |
074 | EditorPrefs.SetFloat(kEditorPrefsName + ".dir.x" + q,dirLight[q].x); |
075 | EditorPrefs.SetFloat(kEditorPrefsName + ".dir.y" + q,dirLight[q].y); |
076 | } |
077 | } |
078 | } |
079 |
080 | class BakeMaterialextends EditorWindow |
081 | { |
082 | privatestatic var kMateriBakeNodeName = "__MateriaBakeSetup" ; |
083 | privatestatic var kWindowMinSize = Vector2 (300,386); |
084 |
085 | privatestatic var settings : BakeMaterialSettings; |
086 | privatestatic var visible : boolean= false ; |
087 |
088 | private var camera : GameObject; |
089 | private var plane : GameObject; |
090 | private var previewTexture : Texture; |
091 | private var lights : GameObject[] = new GameObject[BakeMaterialSettings.kLights]; |
092 | private var stateChanged = false ; |
093 |
094 | private var texViewScrollPosition= Vector2.zero; |
095 | private var lastMaterial: Material; |
096 |
097 | private var originalScene = "" ; |
098 |
099 | private var scheduleBakeOnNextUpdate = false ; |
100 |
101 |
102 | private function SetupScene () |
103 | { |
104 | DestroyScene (); |
105 | var oldGo = GameObject.Find(kMateriBakeNodeName); |
106 | if (oldGo) |
107 | DestroyImmediate (oldGo); |
108 | camera = new GameObject (kMateriBakeNodeName,Camera); |
109 | plane = GameObject.CreatePrimitive (PrimitiveType.Plane); |
110 |
111 | var cam = camera; |
112 | cam.camera.backgroundColor = Color.black; |
113 | cam.camera.clearFlags = CameraClearFlags.SolidColor; |
114 | cam.camera.orthographic = true ; |
115 | cam.camera.orthographicSize = 5.0; |
116 | cam.camera.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene; |
117 |
118 | plane.transform.parent = cam.transform; |
119 | plane.transform.position= Vector3.forward * 10.0; |
120 | plane.transform.rotation= Quaternion.Euler (0,0,180) * Quaternion.Euler (-90,0,0); |
121 | plane.layer = settings.kBakingLayerShouldBeUnusedInScene; |
122 |
123 | for ( var l in lights) |
124 | { |
125 | l= new GameObject ( "Light" ,Light); |
126 | l.light.type = LightType.Directional; |
127 | l.light.cullingMask = 1 << settings.kBakingLayerShouldBeUnusedInScene; |
128 | l.transform.parent = cam.transform; |
129 | l.active = false ; |
130 | } |
131 | } |
132 |
133 | private function UpdateScene (m : Material) |
134 | { |
135 | for (q = 0; q < settings.kLights; ++q) |
136 | { |
137 | lights[q].active = settings.useCustomLights & settings.enableLight[q]; |
138 | lights[q].light.color = settings.colorLight[q]; |
139 | lights[q].transform.rotation= |
140 | Quaternion.AngleAxis(settings.dirLight[q].x,Vector3.up) * |
141 | Quaternion.AngleAxis(settings.dirLight[q].y,Vector3.right); |
142 | } |
143 |
144 | if (settings.useCustomLights) |
145 | RenderSettings.ambientLight = settings.ambient; |
146 | else if (settings.emptyScene) |
147 | RenderSettings.ambientLight = Color.white; |
148 |
149 | plane.renderer.material= m; |
150 | } |
151 |
152 | private function DestroyScene () |
153 | { |
154 | GameObject.DestroyImmediate (camera); |
155 | GameObject.DestroyImmediate (plane); |
156 | GameObject.DestroyImmediate (previewTexture); |
157 | } |
158 |
159 | function UpdateMaterialPreview (m : Material) : RenderTexture |
160 | { |
161 | if (!m) |
162 | return ; |
163 |
164 | var saveAmbientLight = RenderSettings.ambientLight; |
165 | var saveMainTexture = m.mainTexture; |
166 | if (settings.bakeMainTexAsWhite) |
167 | m.mainTexture = null ; |
168 |
169 |
170 | // setup |
171 | if (!camera) |
172 | SetupScene (); |
173 | camera.SetActiveRecursively( true ); |
174 | UpdateScene (m); |
175 |
176 | var res = FindLargestTextureResolution(plane.renderer.sharedMaterial,settings.minTextureResolution,settings.maxTextureResolution); |
177 | var rt =RenderCameraToRenderTexture (camera.camera,res.x,res.y); |
178 |
179 | // restore |
180 | camera.SetActiveRecursively( false ); |
181 | RenderSettings.ambientLight = saveAmbientLight; |
182 | m.mainTexture =saveMainTexture; |
183 |
184 | previewTexture = rt; |
185 | return rt; |
186 | } |
187 |
188 | function CaptureMaterial(m : Material) |
189 | { |
190 | var matAssetPath = AssetDatabase.GetAssetPath (m); |
191 | var assetPath = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (matAssetPath),System.IO.Path.GetFileNameWithoutExtension(matAssetPath)); |
192 |
193 | var rt =UpdateMaterialPreview (m); |
194 | RenderTextureToPNG (rt,settings.bakeAlpha,assetPath + ".png" ); |
195 | } |
196 |
197 | function OnEnable () |
198 | { |
199 | if (!settings) |
200 | settings = new BakeMaterialSettings (); |
201 | SetupScene (); |
202 | visible = true ; |
203 | } |
204 |
205 | function OnDisable () |
206 | { |
207 | DestroyScene (); |
208 | settings.Save (); |
209 | visible = false ; |
210 | } |
211 |
212 | static function GetTargetMaterial() : Material |
213 | { |
214 | return EditorUtility.InstanceIDToObject (Selection.activeInstanceID) as Material; |
215 | } |
216 |
217 | function OnSelectionChange () |
218 | { |
219 | Repaint (); |
220 | } |
221 |
222 | function Update () |
223 | { |
224 | var rebuildScene = false ; |
225 | if (scheduleBakeOnNextUpdate) |
226 | { |
227 | Bake (); |
228 | scheduleBakeOnNextUpdate = false ; |
229 | rebuildScene = true ; |
230 | } |
231 |
232 | if (originalScene == "" && EditorApplication.currentScene == "" ) |
233 | settings.emptyScene = true ; |
234 |
235 | if (settings.emptyScene && originalScene == "" && EditorApplication.currentScene != "" ) |
236 | { |
237 | DestroyScene (); |
238 | if (EditorApplication.SaveCurrentSceneIfUserWantsTo ()) |
239 | { |
240 | originalScene =EditorApplication.currentScene; |
241 | EditorApplication.NewScene (); |
242 | } |
243 | else |
244 | settings.emptyScene = false ; |
245 | rebuildScene = true ; |
246 | } |
247 | else if (!settings.emptyScene && originalScene != "" ) |
248 | { |
249 | EditorApplication.OpenScene (originalScene); |
250 | rebuildScene = true ; |
251 | originalScene = "" ; |
252 | } |
253 |
254 | if (rebuildScene) |
255 | { |
256 | SetupScene (); |
257 | } |
258 |
259 | if (rebuildScene || stateChanged || !settings.emptyScene) |
260 | { |
261 | UpdateMaterialPreview (lastMaterial); |
262 | Repaint (); |
263 | stateChanged = false ; |
264 | } |
265 | } |
266 |
267 | function OnGUI () |
268 | { |
269 | var material= GetTargetMaterial(); |
270 | if (lastMaterial!= material) |
271 | UpdateMaterialPreview (material); |
272 | if (material) |
273 | lastMaterial= material; |
274 |
275 | EditorGUILayout.BeginHorizontal(); |
276 | EditorGUILayout.BeginVertical(GUILayout.MaxWidth(200)); |
277 | if (!(originalScene == "" && EditorApplication.currentScene == "" )) |
278 | { |
279 | settings.emptyScene =!EditorGUILayout.BeginToggleGroup( "Scene ligthing" ,!settings.emptyScene); |
280 | EditorGUILayout.EndToggleGroup(); |
281 | } |
282 | settings.useCustomLights =EditorGUILayout.BeginToggleGroup( "Custom lighting" ,settings.useCustomLights); |
283 | if (settings.useCustomLights) |
284 | { |
285 | EditorGUI.indentLevel= 1; |
286 | settings.ambient = EditorGUILayout.ColorField( "Ambient" ,settings.ambient); |
287 | for ( var q = 0; q < settings.kLights; ++q) |
288 | { |
289 | settings.enableLight[q] = EditorGUILayout.BeginToggleGroup( "Light" ,settings.enableLight[q]); |
290 | EditorGUI.indentLevel= 2; |
291 | settings.colorLight[q] = EditorGUILayout.ColorField( "Color" ,settings.colorLight[q]); |
292 | settings.dirLight[q] = EditorGUILayout.Vector2Field( "Direction" ,settings.dirLight[q]); |
293 | EditorGUILayout.EndToggleGroup(); |
294 | } |
295 | } |
296 | EditorGUI.indentLevel= 0; |
297 | EditorGUILayout.EndToggleGroup(); |
298 |
299 | settings.bakeAlpha =EditorGUILayout.Toggle( "Bake Alpha" ,settings.bakeAlpha); |
300 | settings.bakeMainTexAsWhite =!EditorGUILayout.Toggle( "MainTex" ,!settings.bakeMainTexAsWhite); |
301 | settings.minTextureResolution= EditorGUILayout.IntField( "MinResolution" ,settings.minTextureResolution); |
302 | settings.maxTextureResolution= EditorGUILayout.IntField( "Max Resolution" ,settings.maxTextureResolution); |
303 | settings.minTextureResolution= Mathf.Max(2,settings.minTextureResolution); |
304 | settings.maxTextureResolution= Mathf.Max(settings.minTextureResolution,settings.maxTextureResolution); |
305 |
306 | EditorGUILayout.BeginHorizontal(); |
307 | if (GUILayout.Button( "Bake" )) |
308 | { |
309 | CaptureMaterial(lastMaterial); |
310 | } |
311 | if (GUILayout.Button( "Bake Selected" )) |
312 | { |
313 | scheduleBakeOnNextUpdate = true ; |
314 | } |
315 | EditorGUILayout.EndHorizontal(); |
316 |
317 | EditorGUILayout.EndVertical(); |
318 |
319 | texViewScrollPosition= EditorGUILayout.BeginScrollView (texViewScrollPosition); |
320 | var r = GUILayoutUtility.GetAspectRect(1.0f); |
321 | if (previewTexture) |
322 | EditorGUI.DrawPreviewTexture(r,previewTexture); |
323 | EditorGUILayout.EndScrollView(); |
324 | EditorGUILayout.EndHorizontal(); |
325 |
326 | if (GUI.changed) |
327 | { |
328 | stateChanged = true ; |
329 | } |
330 | } |
331 |
332 | @MenuItem( "Custom/Bake Material..." , false ,5) |
333 | static function CreateBakeEditor() |
334 | { |
335 | var window = EditorWindow.GetWindow(BakeMaterial); |
336 | window.title = "Bake Material" ; |
337 | window.minSize = kWindowMinSize; |
338 | window.Show(); |
339 | } |
340 |
341 | @MenuItem( "Custom/Bake Selected Materials" , false ,4) |
342 | static function Bake() |
343 | { |
344 | var instanceIDs = Selection.instanceIDs; |
345 | var currentScene = EditorApplication.currentScene; |
346 |
347 | var wasAlreadyVisible = BakeMaterial.visible; |
348 | var window = EditorWindow.GetWindow(BakeMaterial); |
349 |
350 | if (window.settings.emptyScene) |
351 | { |
352 | if (!EditorApplication.SaveCurrentSceneIfUserWantsTo ()) |
353 | return ; |
354 | EditorApplication.NewScene (); |
355 | } |
356 |
357 | window.SetupScene (); |
358 | for ( var i in instanceIDs) |
359 | { |
360 | var m : Material= EditorUtility.InstanceIDToObject (i) as Material; |
361 | if (m) |
362 | window.CaptureMaterial(m); |
363 | } |
364 | window.DestroyScene (); |
365 |
366 | if (window.settings.emptyScene && currentScene) |
367 | { |
368 | EditorApplication.OpenScene (currentScene); |
369 | } |
370 |
371 | if (!wasAlreadyVisible) |
372 | window.Close (); |
373 | } |
374 |
375 | static function FindLargestTextureResolution(m : Material,minTexRes : int,maxTexRes : int) : Vector2 |
376 | { |
377 | var res = Vector2 (minTexRes,minTexRes); |
378 | for ( var n in BakeMaterialSettings.kStandardTexNames) |
379 | { |
380 | if (!m.HasProperty (n)) |
381 | continue ; |
382 |
383 | var t : Texture = m.GetTexture (n); |
384 | if (!t) |
385 | continue ; |
386 |
387 | res.x = Mathf.Max (res.x,t.width); |
388 | res.y = Mathf.Max (res.y,t.height); |
389 | } |
390 | res.x = Mathf.Min(res.x,maxTexRes); |
391 | res.y = Mathf.Min(res.y,maxTexRes); |
392 | return res; |
393 | } |
394 |
395 | static function RenderCameraToRenderTexture (cam : Camera,width : int,height : int) : RenderTexture |
396 | { |
397 | var rt =cam.camera.targetTexture; |
398 | if (rt && rt.width != width && rt.height != height) |
399 | DestroyImmediate(rt); |
400 | if (!rt) |
401 | rt = new RenderTexture (width,height,24); |
402 | cam.camera.targetTexture = rt; |
403 | cam.camera.Render (); |
404 | return rt; |
405 | } |
406 |
407 | static function RenderTextureToPNG (rt : RenderTexture,bakeAlpha : boolean,assetPath : String) |
408 | { |
409 | RenderTexture.active =rt; |
410 |
411 | var screenShot = new Texture2D (rt.width,rt.height,bakeAlpha? TextureFormat.ARGB32 : TextureFormat.RGB24, false ); |
412 | screenShot.ReadPixels (Rect (0,0,rt.width,rt.height),0,0); |
413 |
414 | RenderTexture.active = null ; |
415 |
416 | var bytes = screenShot.EncodeToPNG (); |
417 | System.IO.File.WriteAllBytes (assetPath,bytes); |
418 |
419 | AssetDatabase.ImportAsset (assetPath,ImportAssetOptions.ForceUpdate); |
420 | } |
421 | } |
相关文章推荐
- Unity 烘焙材质到单一贴图的脚本
- Unity 烘焙材质到单一贴图的脚本
- unity自带LightMapping和3Ds Max烘焙贴图的小对比
- Unity 5光照贴图烘焙课程分享
- blender 带贴图与颜色材质的模型,导入到Unity中
- Unity 3D 动态创建对象,并渲染贴图,动态添加删除脚本
- unity开发经验之用材质贴图模拟流体特效
- 【Unity资源】(贴图和材质)
- Unity 3D 动态创建对象,并渲染贴图,动态添加删除脚本
- Unity_脚本和材质系统的结合使用_012
- Unity 5光照贴图烘焙
- unity场景烘焙贴图丢失问题
- 多维子材质脚本加入了对于贴图名称的查找,去除了 logo
- unity自带LightMapping和3Ds Max烘焙贴图的小对比
- unity自带LightMapping和3Ds Max烘焙贴图的小对比
- 3DMax脚本插件--改动材质&贴图名称
- 初识Unity 3D——认识材质球、贴图
- 【个人Unity笔记】烘焙光照贴图后保留法线和光探头
- unity 模型 材质 贴图 关系;着色器属性
- Unity 烘焙贴图后再拖成预设体后场景光照信息丢失