曲率圖一般可用在預積分次表面散射渲染上,那麼如何在Unity中烘焙曲率圖?
工具思路如下:
1. 使用shader,把曲率渲染出來。注意,要把頂點位置沿UV重新排列,也就是把曲率圖平鋪開來,關鍵代碼:
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