Unity之烘焙曲率图
曲率图一般可用在预积分次表面散射渲染上,那么如何在Unity中烘焙曲率图?
工具思路如下:
1. 使用shader,把曲率渲染出来。注意,要把顶点位置沿UV重新排列,也就是把曲率图平铺开来,关键代码:
float2 uv = input.texcoord;
float3 positionWS = float3(uv * 10 - 5, 0);
output.positionCS = TransformWorldToHClip(positionWS);
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