Unity之烘焙曲率圖

曲率圖一般可用在預積分次表面散射渲染上,那麼如何在Unity中烘焙曲率圖?

工具思路如下:

1. 使用shader,把曲率渲染出來。注意,要把頂點位置沿UV重新排列,也就是把曲率圖平鋪開來,關鍵代碼:

float2 uv = input.texcoord;
float3 positionWS = float3(uv * 10 - 5, 0);
output.positionCS = TransformWorldToHClip(positionWS);

效果如下:

2. 然後通過攝像機截屏保存曲率圖圖片即可。

 

工具代碼如下:

shader:

Shader "TA/Role/BakeCurvature"
{
    Properties
    {
        

    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
        }
        LOD 500

        Pass
        {
            Tags{"LightMode" = "UniversalForward"}

            Cull Off
            
            HLSLPROGRAM
            #pragma target 3.0

            // ======================== GPU Instancing =====================================
            #pragma multi_compile_instancing
            #pragma instancing_options renderinglayer
            #pragma multi_compile _ DOTS_INSTANCING_ON

            #pragma vertex Vertex
            #pragma fragment Fragment

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

         
            // ======================== 通用結構體 =====================================
            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 texcoord : TEXCOORD0;
                float4 tangentOS : TANGENT;
                float3 normalOS : NORMAL;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 tangentWS : TEXCOORD1;
                float4 bitangentWS : TEXCOORD3;
                float4 normalWS : TEXCOORD2;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };


            // ======================== 通用頂點shader =====================================
            Varyings Vertex(Attributes input)
            {
                Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);

                float2 uv = input.texcoord;
                float3 positionWS = float3(uv * 10 - 5, 0);
                output.positionCS = TransformWorldToHClip(positionWS);

                output.uv = uv;
                
                VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
                output.tangentWS = float4(normalInput.tangentWS, positionWS.x);
                output.bitangentWS = float4(normalInput.bitangentWS, positionWS.y);
                output.normalWS = float4(normalInput.normalWS, positionWS.z);

                return output;
            }

            // ======================== 片元shader =====================================
            half4 Fragment(Varyings input) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(input);

                // ------------------------ TBN --------------------------------
                //float3 tangentWS = input.tangentWS.xyz;
                //float3 bitangentWS = input.bitangentWS.xyz;
                float3 N_Mesh = input.normalWS.xyz;
                float3 positionWS = float3(input.tangentWS.w, input.bitangentWS.w, input.normalWS.w);
                //float3x3 TBN = float3x3(tangentWS, bitangentWS, N_Mesh);
              
                // 計算曲率
                half curvature = 0.05 * length(fwidth(N_Mesh)) / length(fwidth(positionWS));
                //curvature = saturate(curvature);
                return half4(curvature.xxx, 1);
            }
            
            ENDHLSL
        }

      
    }

    FallBack "Hidden/Universal Render Pipeline/FallbackError"
    CustomEditor "TATools.SimpleShaderGUI"
}

工具代碼:

using UnityEngine;
using UnityEditor;
using System.IO;

public static class BakeCurvatureTool
{
    [MenuItem("TA/烘焙/烘焙曲率圖")]
    public static void BakeCurvature()
    {
        string savePath = EditorUtility.SaveFilePanel("", "Assets", "curvature", "png");
        Camera cam = GameObject.Find("Camera").GetComponent<Camera>();
        Texture2D img = CaptureCamera(cam);
        SaveImage(img, savePath);
        AssetDatabase.Refresh();
        Debug.Log("曲率圖烘焙成功,路徑:" + savePath, AssetDatabase.LoadAssetAtPath<Texture2D>(savePath));
    }

    static Texture2D CaptureCamera(Camera camera)
    {
        Rect rect = new Rect(0, 0, camera.targetTexture.width, camera.targetTexture.height);
        camera.RenderDontRestore(); // 手動渲染
        RenderTexture.active = camera.targetTexture;
        Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height);
        screenShot.ReadPixels(rect, 0, 0); // 讀取的是 RenderTexture.active 中的像素
        screenShot.Apply();
        RenderTexture.active = null;

        return screenShot;
    }

    static void SaveImage(Texture2D image, string path)
    {
        byte[] buffer = image.EncodeToPNG();
        File.WriteAllBytes(path, buffer);
    }
}

烘焙的曲率圖如下:

轉載請註明出處:https://www.cnblogs.com/jietian331/p/17556543.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章