Unity之烘焙曲率图

发布时间 2023-07-15 18:00:56作者: 孤独の巡礼

曲率图一般可用在预积分次表面散射渲染上,那么如何在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