Unity HDRP快速制作Mask Map

2023-11-07 材质Shader 0 939
安全检测亲测可用腾讯管家360卫士
¥ 0开通VIP尊享优惠特权
立即下载 升级会员
详情介绍

【操作界面】

将下面的代码直接复制粘贴后,可以在下图中找到打开操作界面的位置。注意要在unity当中将颜色空间改为线性空间。

在下方的操作界面中,可以拖进来对应的纹理,可以在Preview Output中预览当前的合成结果,点击下面的按钮会生成Mask Map贴图。

实现和注释看下文的代码。

【代码原理】

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
 
public class MaskMapEditor : EditorWindow//扩展编辑器要继承EditorWindow
{
    private Texture2D metallic, occlusion, detailmask, smoothness;//四个纹理字段
    private Texture2D _metallic, _occlusion, _detailmask, _smoothness;//这四个字段用于预览的实现
    private Material mat;//带有Shader的材质
    private bool changed;
 
    [MenuItem("HDRP/CreateMaskMap")]
    static void OpenMaskMapEditor()//实现点击菜单栏的按钮弹出窗口
    {
        MaskMapEditor maskMapEditor = GetWindow<MaskMapEditor>(false, "MaskMap Editor");//创建窗口
        maskMapEditor.titleContent.text = "MaskMap Editor";//给窗口命名
        maskMapEditor.Init();//初始化
    }
 
    private void Init()
    {
        if (mat == null)
        {
            mat = new Material(Shader.Find("Hidden/MaskMap"));//根据MaskMap这个Shader创建材质
            mat.hideFlags = HideFlags.HideAndDontSave;//材质不保存
        }
    }
 
    public void OnGUI()
    {
        GetInput();
        Preview();
        CreateMask();
    }
 
    private void CreateMask()
    {
        if (GUILayout.Button("Create Mask Map"))
        {
            GenPicture();
           
        }
    }
 
    private void GenPicture()
    {
        Texture2D output = GetTexture();
        
        string savePath = EditorUtility.SaveFilePanel("Save", Application.dataPath, "texture.png", "png");
        File.WriteAllBytes(savePath,output.EncodeToPNG());//将纹理保存为png格式,也可以是jpg、exr等格式
        AssetDatabase.Refresh();//更新,要不然在Unity当中不会看到生成的图片(在win的文件管理器中可以看到)
    }
 
    private Texture2D GetTexture()
    {
        if (metallic != null)
        {
            mat.SetTexture("_Metallic", metallic);//给Shader的属性赋值
        }
 
        if (occlusion != null)
        {
            mat.SetTexture("_Occlusion", occlusion);
        }
 
        if (detailmask != null)
        {
            mat.SetTexture("_DetailMask", detailmask);
        }
 
        if (smoothness != null)
        {
            mat.SetTexture("_Smoothness", smoothness);
        }
 
        RenderTexture tempRT = new RenderTexture(2048, 2048, 32, RenderTextureFormat.ARGB32);//生成纹理,分辨率可以自己改为1024的,也可以自己在编辑器上做出多个可供选择的分辨率,容易实现
        tempRT.Create();
        Texture2D temp2 = new Texture2D(tempRT.width, tempRT.height, TextureFormat.ARGB32, false);
        Graphics.Blit(temp2, tempRT, mat);//将temp2纹理的值通过mat赋值到tempRT,核心的代码,可以好好看看对这个方法的解释
        RenderTexture prev = RenderTexture.active;
        RenderTexture.active = tempRT;//设置当前active的纹理
 
        Texture2D output = new Texture2D(tempRT.width, tempRT.height, TextureFormat.ARGB32, false);//创建一个RGBA格式的纹理
        output.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0);//读取当前active的纹理            
        output.Apply();//apply将改变写入
        RenderTexture.active = prev;
 
        return output;
    }
 
 
    private void GetInput()
    {
        EditorGUILayout.BeginHorizontal("Box");
        GUILayout.Label("Input Textures");
        EditorGUILayout.EndHorizontal();
 
        EditorGUILayout.BeginHorizontal("Box");
        _metallic = TextureField("metallic", metallic);
        if (_metallic != metallic)
        {
            metallic = _metallic;
            changed = true;
        }
        _occlusion = TextureField("occlusion", occlusion);
        if (_occlusion != occlusion)
        {
            occlusion = _occlusion;
            changed = true;
        }
        _detailmask = TextureField("detailmask", detailmask);
        if (_detailmask != detailmask)
        {
            detailmask = _detailmask;
            changed = true;
        }
        _smoothness = TextureField("smoothness", smoothness);
        if (_smoothness != smoothness)
        {
            smoothness = _smoothness;
            changed = true;
        }
        EditorGUILayout.EndHorizontal();
 
    }
 
    private Texture2D preview = null;
    private void Preview()
    {
        EditorGUILayout.BeginHorizontal("Box");
        GUILayout.Label("Preview Output");
        EditorGUILayout.EndHorizontal();
 
        EditorGUILayout.BeginHorizontal("Box");
 
        Rect previewRect = new Rect(this.position.width / 2-75, 250, 150, 150);
        if (preview == null)
        {
            preview = Texture2D.blackTexture;
        }
 
        if (changed)
        {
            preview = GetTexture();
            changed = false;
        }
        EditorGUI.DrawPreviewTexture(previewRect, preview);
        EditorGUILayout.Space(160);
        EditorGUILayout.EndHorizontal();
    }
 
    private Texture2D TextureField(string name,Texture2D texture)
    {
        EditorGUILayout.BeginVertical();
        var style = new GUIStyle(GUI.skin.label);
        style.alignment = TextAnchor.MiddleCenter;
        style.fixedWidth = 150;
        GUILayout.Label(name,style);
        Texture2D result = EditorGUILayout.ObjectField(texture,typeof(Texture2D),false,GUILayout.Width(150),GUILayout.Height(150)) as Texture2D;
        EditorGUILayout.EndHorizontal();
        return result;
    }
}
Shader "Hidden/MaskMap"
{
    Properties
    {
        _MainTex("Texture",2D) = "white"{}
        _Metallic("Texture", 2D) = "black"{}
        _Occlusion("Texture", 2D) = "black"{}
        _DetailMask("Texture",2D) = "black"{}
        _Smoothness("Texture",2D) = "black"{}
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        LOD 100
 
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "UnityCG.cginc"
 
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
 
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
 
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _Metallic;
            sampler2D _Occlusion;
            sampler2D _DetailMask;
            sampler2D _Smoothness;
 
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
 
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                col.r = tex2D(_Metallic, i.uv).r;
                col.g = tex2D(_Occlusion, i.uv).g;
                col.b = tex2D(_DetailMask, i.uv).b;
                col.a = tex2D(_Smoothness, i.uv).g;                
                col.a = pow(col.a, 0.45);      //线性空间会对a通道做gamma校正,要自己校正         
                return col;
            }
            ENDCG
        }
    }
}
资源下载此资源仅限注册用户下载,请先
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

迪米特 材质Shader Unity HDRP快速制作Mask Map https://www.dimit.cn/u3d/shader/id-43594.html

上一篇:

已经没有上一篇了!

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务