Unity3D-程式碼中動態設定Material引數
阿新 • • 發佈:2018-12-26
我們知道在Unity中可以在程式碼中動態地改變Material監視面板中的引數,如改變數值大小或替換貼圖。常用的API有:SetColor , SetFloat, SetInt, SetTexture.
然而今天在設定一個StandardShader的材質貼圖的時候,發現設定了法線貼圖但是場景中的物體並沒有法線凹凸的效果,需要啟用一下材質面板才行。經過反覆檢查以及查詢資料,主要有以下兩個問題
// 貼圖型別 string[] TEXTURE_TYPE = { "_MetallicGlossMap", "_BumpMap", "_ParallaxMap", "_OcclusionMap", "_DetailMask", "_DetailAlbedoMap", "_DetailNormalMap"}; // Material需要設定的關鍵字 string[] TEXTURE_KEYWORD = { "_METALLICGLOSSMAP", "_NORMALMAP", "_PARALLAXMAP", "", "_DETAIL_MULX2", "_DETAIL_MULX2", "_DETAIL_MULX2" };
1.法線貼圖匯入進來需要設定型別為NormalMap
// 設定法線貼圖的型別
if (fileName == diffuseName + TEXTURE_TYPE[1])
{
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(filePath);
importer.textureType = TextureImporterType.NormalMap;
importer.SaveAndReimport();
}
2.使用標準著色器(StandardShader)的Material要設定啟用相應的關鍵字
// 在Material.SetTexture之前 開啟相應的KeyWord
mat.EnableKeyword(TEXTURE_KEYWORD[i]);
以下是我查文件自己理解的,不一定準確。
一個Material所使用的標準著色器在Unity中其實是多個著色器的集合。因為一個材質的著色器不可能涵蓋所有的功能,比如GI、霧效、HDR等高耗能的效果,所以Unity把標準著色器分成了帶有不同特殊功能的著色器變體(Shader Variant)。當把NormalMap分配給材質,就是激活了支援法線貼圖的著色器變體;把視差貼圖分配給材質,就是激活了支援視差貼圖的著色器變體。所以,如果要把某個特殊的貼圖賦給材質,就要開啟材質相應的關鍵字,以啟用支援相應功能的著色器變體。
需要專門開啟的關鍵字有以下幾個:
關鍵字 | 特性 |
_NORMALMAP | 法線對映 |
_ALPHATEST_ON | 用於CutOut渲染模式 |
_ALPHABLEND_ON | 用於Fade渲染模式 |
_ALPHAPREMULTIPLY_ON | 用於Transparent渲染模式 |
_EMISSION | 設定自發光 |
_PARALLAXMAP | 設定視差貼圖 |
_DETAIL_MULX2 | 用於設定第二個貼圖通道 |
_METALLICGLOSSMAP | 在Metallic工作流中設定金屬度貼圖 |
_SPECGLOSSMAP | 在Specular工作流中設定高光貼圖 |
以下為設定材質屬性部分程式碼
/// <summary>
/// 設定材質中shader的相關屬性
///<para name = "mat"> 需要設定的Material </para>
///<para name = "meshMat"> 要傳入shader的資料集合 </para>
///<para name = "fbxName"> 模型的名字,在這裡主要是為了得到材質貼圖資料夾的位置 </para>
/// </summary>
void SetShader(Material mat, ShaderData data, string fbxName)
{ // 這裡預設貼圖資源中主貼圖的名字就是材質名,其他貼圖的名字是材質名+貼圖型別
string diffuseName = mat.name;
// textureFiles用於記錄貼圖資料夾中所有的圖片檔案,記錄它們的貼圖名和路徑
Dictionary<string, string> textureFiles = new Dictionary<string, string>();
// texturePath是之前記錄好的一個fbx模型對應的貼圖資料夾的路徑
string[] filesPath = Directory.GetFiles(texturePath[fbxName]);
foreach (string filePath in filesPath)
{ // TEXTURE_EXT是預設的圖片字尾名,用於標記圖片格式(如.jpg,.png,.tif等)
if (Array.IndexOf(TEXTURE_EXT, Path.GetExtension(filePath)) != -1)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
if (fileName.IndexOf(diffuseName) == 0)
{
textureFiles[fileName] = filePath;
Debug.Log(fileName + " , " + filePath);
// 設定法線貼圖的型別
if (fileName == diffuseName + TEXTURE_TYPE[1])
{
TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(filePath);
importer.textureType = TextureImporterType.NormalMap;
importer.SaveAndReimport();
}
}
}
}
// 設定材質的主貼圖,也就是Albedo貼圖
if (textureFiles.ContainsKey(diffuseName))
{
Debug.Log("MainTexture Exist");
mat.mainTexture = AssetDatabase.LoadAssetAtPath<Texture>(textureFiles[diffuseName]);
}
// 設定其他特殊型別的貼圖
for (int i = 0; i < TEXTURE_TYPE.Length; ++i)
{
if (textureFiles.ContainsKey(diffuseName + TEXTURE_TYPE[i]))
{
Debug.Log(TEXTURE_TYPE[i] + " Exist ");
if (TEXTURE_KEYWORD[i] != "")
mat.EnableKeyword(TEXTURE_KEYWORD[i]);
mat.SetTexture(TEXTURE_TYPE[i], AssetDatabase.LoadAssetAtPath<Texture>(textureFiles[diffuseName + TEXTURE_TYPE[i]]));
}
}
mat.color = data.color;
mat.SetFloat("_Metallic", data.metallic);
mat.SetFloat("_Glossiness", data.glossiness);
mat.SetColor("_EmissionColor", data.emissionColor);
原創連結http://blog.csdn.net/lilysara/article/details/77513123法線對映 |