您的位置:首页 > 移动开发 > Unity3D

Unity烘焙材质到贴图脚本

2011-05-06 16:26 471 查看
这个脚本可以将复杂的材质,比如有法线贴图的材质进行"烘焙",转变为单一的贴图,可用来将Unity的游戏移植到移动平台时候使用.





讲脚本放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
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: