1. 程式人生 > >Unity3D-程式碼中動態設定Material引數

Unity3D-程式碼中動態設定Material引數

我們知道在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

法線對映