I’m trying to automatically create textures on import, to merge seperate specular maps into the diffuse texture and because I need to reverse the green channel on the normal maps.
I’ve managed to get it to work so that it generates the textures correctly and all, but for reasons I don’t understand it doesn’t assign them to the material. If I run the same script again (i.e. click “reimport” once more), everything works just fine.
Which is crazy, given that on the 2nd run, when I skip the generation, I do the very same things (load asset and return it).
// FbxMeshPostProcessor utility script
// Written by Roger Clark 20/04/2009
//
// I wrote this script as the fbx models I was importing into Unity had the wrong "Scale factor"
// I also wanted all models to have a collider
// Note. When I did not set a value for generateMaterials, it appeared to default to not generating materials,
// so I set generateMaterials to true.
class FbxMeshPostprocessor extends AssetPostprocessor {
public var AnisoLevel = 4;
function OnPreprocessModel () {
var modelImporter : ModelImporter = assetImporter;
var fname:String = modelImporter.assetPath.ToLower();
modelImporter.generateMaterials = 1;// Enable material creation
modelImporter.addCollider = false; // This tells it to not add a collider to the object
modelImporter.globalScale= 1; // This changes the "Scale Factor" to 1.0
modelImporter.generateAnimations = ModelImporterGenerateAnimations.None;
}
function OnAssignMaterialModel(material : Material, renderer : Renderer) : Material {
var materialPath = "Assets/_generated materials/" + material.name + ".mat";
// Find if there is a material at the material path
// Turn this off to always regeneration materials
// if (AssetDatabase.LoadAssetAtPath(materialPath, Material)) return AssetDatabase.LoadAssetAtPath(materialPath, Material);
// set the names of the normal and specular maps we are looking for
// this is the setting that DEXSOFT textures use - N and S suffixes
var main = AssetDatabase.GetAssetPath(material.mainTexture);
var bump = System.IO.Path.GetFileNameWithoutExtension(main) + "N" + System.IO.Path.GetExtension(main);
bump = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(main), bump);
var specular = System.IO.Path.GetFileNameWithoutExtension(main) + "S" + System.IO.Path.GetExtension(main);
specular = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(main), specular);
Debug.Log("doing "+material.name);
if (AssetDatabase.LoadAssetAtPath(specular, Texture2D)) {
// specular map exists
if (AssetDatabase.LoadAssetAtPath(bump, Texture2D)) {
// bump and specular exist
material.shader = Shader.Find("Bumped Specular");
material.SetTexture("_BumpMap", ReverseNormals(bump));
material.mainTexture = AddSpecular(material.mainTexture, main, specular);
} else {
// only specular exists
material.mainTexture = AddSpecular(material.mainTexture, main, specular);
}
} else if (AssetDatabase.LoadAssetAtPath(bump, Texture2D)) {
// only bump map exists
material.shader = Shader.Find("Bumped Diffuse");
material.SetTexture("_BumpMap", ReverseNormals(bump));
material.mainTexture.anisoLevel = AnisoLevel;
} else {
// only diffuse map exists
material.mainTexture.anisoLevel = AnisoLevel;
}
AssetDatabase.CreateAsset(material, materialPath);
return material;
}
function ReverseNormals(input : String) : Texture2D {
// check if we already have one
var destpath = System.IO.Path.Combine("Assets/_generated textures/", System.IO.Path.GetFileNameWithoutExtension(input))+".png";
var test = AssetDatabase.LoadAssetAtPath(destpath, Texture2D);
if (test) {
Debug.Log("skipping already existing "+destpath);
return test;
}
// there are two kinds of normal maps, for my purposes, I need to flip the green channel
var textureImporter = AssetImporter.GetAtPath(input) as TextureImporter;
if (!textureImporter.isReadable) {
textureImporter.isReadable = true;
AssetDatabase.ImportAsset(input, ImportAssetOptions.ForceUpdate);
}
var source = AssetDatabase.LoadAssetAtPath(input, Texture2D) as Texture2D;
var w = source.width; var h = source.height;
var dest = new Texture2D(w, h);
dest.anisoLevel = AnisoLevel;
var Pixels = source.GetPixels();
for (var x=0;x<w;x++) for (var y=0;y<h;y++) {
var i = x*w+y;
Pixels[i].g = 1 - Pixels[i].g;
}
dest.SetPixels(Pixels);
dest.Apply();
// write texture to a .png
AssetDatabase.CreateAsset(dest, destpath);
var myBytes : byte[] = dest.EncodeToPNG();
System.IO.File.WriteAllBytes(destpath, myBytes);
// reimport the asset so it is properly assigned
AssetDatabase.ImportAsset(destpath, ImportAssetOptions.ForceUpdate);
dest = AssetDatabase.LoadAssetAtPath(destpath, Texture2D) as Texture2D;
return dest;
}
function AddSpecular(maintex, mainpath, specular) : Texture2D {
// check if we already have one
var destpath = System.IO.Path.Combine("Assets/_generated textures/", System.IO.Path.GetFileNameWithoutExtension(mainpath))+"DS.png";
var test = AssetDatabase.LoadAssetAtPath(destpath, Texture2D);
if (test) {
Debug.Log("skipping already existing "+destpath);
return test;
}
var textureImporter = AssetImporter.GetAtPath(mainpath) as TextureImporter;
if (!textureImporter.isReadable) {
textureImporter.isReadable = true;
AssetDatabase.ImportAsset(mainpath, ImportAssetOptions.ForceUpdate);
}
textureImporter = AssetImporter.GetAtPath(specular) as TextureImporter;
if (!textureImporter.isReadable) {
textureImporter.isReadable = true;
AssetDatabase.ImportAsset(specular, ImportAssetOptions.ForceUpdate);
}
var w = maintex.width; var h = maintex.height;
var dest = new Texture2D(w, h, TextureFormat.ARGB32, true);
dest.anisoLevel = AnisoLevel;
var MainPixels = maintex.GetPixels();
var speculartex = AssetDatabase.LoadAssetAtPath(specular, Texture2D) as Texture2D;
var SpecularPixels = speculartex.GetPixels();
for (var x=0;x<w;x++) for (var y=0;y<h;y++) {
var i = x*w+y;
var col = new Color(MainPixels[i].r, MainPixels[i].g, MainPixels[i].b, SpecularPixels[i].grayscale);
MainPixels[i] = col;
}
dest.SetPixels(MainPixels);
dest.Apply();
// write texture to a .png
AssetDatabase.CreateAsset(dest, destpath);
var myBytes : byte[] = dest.EncodeToPNG();
System.IO.File.WriteAllBytes(destpath, myBytes);
// reimport the asset so it is properly assigned
textureImporter = AssetImporter.GetAtPath(destpath) as TextureImporter;
textureImporter.textureFormat = TextureImporterFormat.DXT5;
AssetDatabase.ImportAsset(destpath, ImportAssetOptions.ForceUpdate);
dest = AssetDatabase.LoadAssetAtPath(destpath, Texture2D) as Texture2D;
return dest;
}
}