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

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

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 烘焙材质到单一贴图的脚本的更多相关文章

  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. 云计算之路-阿里云上:2014年6月12日14:40出现CPU 100%

    这是今天遇到的第2次故障,主站1台云服务器在14:40:33-14:41:09期间出现CPU突然跑满的状况,而CPU跑满之前,请求量并没有明显增长. 向阿里云提交之后,说晚上会对这台云服务器的虚拟机进 ...

  2. [USACO2005][POJ3045]Cow Acrobats(贪心)

    题目:http://poj.org/problem?id=3045 题意:每个牛都有一个wi和si,试将他们排序,每头牛的风险值等于前面所有牛的wj(j<i)之和-si,求风险值最大的牛的最小风 ...

  3. 第十一课:js操作选择器的通用函数

    1.判断文档是否是XML文档 var isXML = function(elem){ var documentElement = elem && (elem.ownerDocument ...

  4. Moqui学习之数据与资源

    资源位置: 资源门面位置的字符串类似于URL的构成方式:协议,主机,可选端口和文件名.它支持标准的java URL协议(http https ftp jar file).同样也支持一些扩展的协议: c ...

  5. 每天一个linux命令(20):linux chmod命令

    chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设定法:另一种是包含数字的数字设定法. Linux系统中的每 ...

  6. 拦路虎:jQuery

    1.   color设置无效的问题! $("#subscribe").hover(function(){ var $this = $("#subscribe .subsc ...

  7. Java中唯一数的生成

    唯一数的生成很简单,基本上以时间为基础进行生成.在JDK里面已经有java.util.UUID类可以生成唯一的随机数.如果希望生成的唯一数为特定的格式,那么就需要自己来生成唯一数了.生成唯一数时有两个 ...

  8. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  9. NOI2005维修数列 splay

    好题,错了不知道多少遍.这题其他几个操作都是比较经典的,多了一个最大子序列的.这时候对于当前的区间,最大子序列,可能使左区间的最值,可能是右区间的最值,也可能是整个区间的.所以维护lx[],rx[], ...

  10. Html-Css-设置DIV边框圆滑

    border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px; -o-border-radius: 10px; ...