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工作流中设置高光贴图


以下为设置材质属性部分代码

///  
/// 设置材质中shader的相关属性 
/// 需要设置的Material  
/// 要传入shader的数据集合  
/// 模型的名字,在这里主要是为了得到材质贴图文件夹的位置 
/// 
void SetShader(Material mat, ShaderData data, string fbxName)
{  // 这里默认贴图资源中主贴图的名字就是材质名,其他贴图的名字是材质名+贴图类型
    string diffuseName = mat.name;
    // textureFiles用于记录贴图文件夹中所有的图片文件,记录它们的贴图名和路径
    Dictionary textureFiles = new Dictionary();
    // 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(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(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

法线映射

你可能感兴趣的:(Unity3D-代码中动态设置Material参数)