Unity Shader 深度重建世界坐标

只用一张深度图就能还原每个像素对应的世界空间位置:用 NDC 坐标 + 逆 VP 矩阵反算。这是 SSAO、SSR、体积雾等所有屏幕空间效果的底层基础。

一、核心原理

当我们渲染一个 3D 场景时,GPU 会将顶点从世界空间变换到屏幕空间,这个过程涉及 View 矩阵和 Projection 矩阵。深度重建的本质就是反向这个过程。

Pworld = (VP)-1 × Pndc

世界坐标 = 逆 View-Projection 矩阵 × 标准化设备坐标

为什么不用线性深度? 透视投影的非线性深度分布使得直接反算不可行。NDC 深度值 [0,1] 对应的是经过透视除法的齐次坐标,只有逆 VP 矩阵才能正确还原原始的 3D 位置。

二、完整实现代码

下面是一个完整的 Shader 实现,使用 URP 的内置函数和属性来重建世界坐标。

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class DepthReconstructionFeature : ScriptableRendererFeature
    DepthReconstructionPass m_ScriptablePass;
    public override void Create()
    {
        m_ScriptablePass = new DepthReconstructionPass();
        m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    }
    public override void AddRenderPasses(ScriptableRenderer renderer,
        ref RenderingData renderingData)
    {
        m_ScriptablePass.Setup(renderer.cameraDepthTexture);
        renderer.EnqueuePass(m_ScriptablePass);
    }
}
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class DepthReconstructionFeature : ScriptableRendererFeature
    DepthReconstructionPass m_ScriptablePass;
    public override void Create()
    {
        m_ScriptablePass = new DepthReconstructionPass();
        m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    }
    public override void AddRenderPasses(ScriptableRenderer renderer,
        ref RenderingData renderingData)
    {
        m_ScriptablePass.Setup(renderer.cameraDepthTexture);
        renderer.EnqueuePass(m_ScriptablePass);
    }
}
DepthReconstructionPass.cs
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class DepthReconstructionPass : ScriptableRenderPass
    private Shader m_Shader;
    private Material m_Material;
    private RTHandle m_DepthTexture;
    public void Setup(RTHandle depthTexture)
    {
        m_DepthTexture = depthTexture;
        m_Shader = Shader.Find("Hidden/DepthReconstruction");
    }
    public override void Execute(ScriptableRenderContext context,
        ref RenderingData renderingData)
    {
        if (m_Shader == null) return;
        
        if (m_Material == null)
            m_Material = new Material(m_Shader);
        ref CameraData cameraData = ref renderingData.cameraData;
        Matrix4x4 invVP = cameraData.camera.projectionMatrix
                         * cameraData.camera.worldToCameraMatrix;
        invVP = invVP.inverse;
        
        m_Material.SetMatrix("_InvVP矩阵", invVP);
        m_Material.SetTexture("_CameraDepthTexture", m_DepthTexture);
        
        // 在此处绘制全屏Quad进行深度重建
    }
}
Shader "Hidden/DepthReconstruction"
    Properties
    {
        _MainTex ("Screen Texture", 2D) = "white" {}
    }
    CGINCLUDE
    #include "UnityCG.cginc"
    
    // ============================================
    // 核心方法:从深度图重建世界坐标
    // ============================================
    float3 ReconstructWorldPosition(float2 uv, float rawDepth)
    {
        // 步骤1:构建 NDC 坐标
        // 将屏幕UV转换为NDC空间 [-1, 1]
        float2 ndc = uv * 2.0 - 1.0;
        
        // 步骤2:构造齐次坐标
        // NDC_z 已经经过透视除法,需要恢复为 clip space
        float4 clipPos = float4(ndc.x, ndc.y, rawDepth * 2.0 - 1.0, 1.0);
        
        // 步骤3:逆变换到世界空间
        // 乘以逆 VP 矩阵
        float4 worldPos = mul(_InvVP, clipPos);
        
        // 步骤4:透视除法
        // w 分量保存原始深度信息,除以它得到真实坐标
        worldPos /= worldPos.w;
        
        return worldPos.xyz;
    }
    ENDCG

三、矩阵变换详解

理解 VP 矩阵及其逆矩阵是掌握深度重建的关键。下面的流程图展示了完整的变换链路:

1

世界矩阵 (M)

模型自身变换

2

视图矩阵 (V)

相机坐标系变换

3

投影矩阵 (P)

透视/正交投影

性能提示:逆 VP 矩阵可以在 C# 端预计算并传递给 Shader,避免在 GPU 上进行昂贵的矩阵求逆运算。

矩阵作用输入空间输出空间
View (V)将世界坐标转换到相机视角World SpaceView Space
Projection (P)将视图坐标投影到裁剪空间View SpaceClip Space
VP组合变换,一步到位World SpaceClip Space
(VP)⁻¹逆向重建世界坐标NDC SpaceWorld Space

四、应用场景

深度重建是众多屏幕空间技术的基石。掌握这项技术后,你可以实现以下效果:

SSAO

Screen Space Ambient Occlusion
屏幕空间环境光遮蔽

SSR

Screen Space Reflections
屏幕空间反射

体积雾

Volumetric Fog
基于深度的雾效计算

SSAO 实现要点


性能提示:逆 VP 矩阵可以在 C# 端预计算并传递给 Shader,避免在 GPU 上进行昂贵的矩阵求逆运算。

矩阵	作用	输入空间	输出空间
View (V)	将世界坐标转换到相机视角	World Space	View Space
Projection (P)	将视图坐标投影到裁剪空间	View Space	Clip Space
VP	组合变换,一步到位	World Space	Clip Space
(VP)⁻¹	逆向重建世界坐标	NDC Space	World Space
四、应用场景
深度重建是众多屏幕空间技术的基石。掌握这项技术后,你可以实现以下效果:

SSAO
Screen Space Ambient Occlusion
屏幕空间环境光遮蔽

SSR
Screen Space Reflections
屏幕空间反射

体积雾
Volumetric Fog
基于深度的雾效计算

SSAO 实现要点
SSAO.frag (片段着色器)
// 采样周围多个点进行深度比较
float CalculateAO(float2 uv, float3 normal)
{
    float ao = 0.0;
    
    // 获取当前像素的世界坐标
    float depth = SAMPLE_TEXTURE2D(_CameraDepthTexture, uv);
    float3 currentPos = ReconstructWorldPosition(uv, depth);
    
    // 在半球方向采样多个点
    for (int i = 0; i < 16; i++)
    {
        float3 sampleDir = GetHemisphereSample(i, normal);
        float3 samplePos = currentPos + sampleDir * radius;
        
        // 将采样点投影回屏幕空间
        float2 sampleUV = ProjectToScreen(samplePos);
        float sampleDepth = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampleUV);
        
        // 深度差异决定遮蔽程度
        float rangeCheck = smoothstep(0.0, 1.0, radius / abs(currentPos.z - samplePos.z));
        ao += (samplePos.z < currentPos.z ? 1.0 : 0.0) * rangeCheck;
    }
    
    return 1.0 - (ao / 16.0);
}

五、关键要点总结

NDC 坐标转换

uv * 2.0 - 1.0 是将 [0,1] 范围映射到 [-1,1] 的标准操作

透视除法不可省略

w 分量保存了原始深度信息,必须除以 w 才能得到正确的世界坐标

逆矩阵计算时机

建议在 C# 端计算逆矩阵并通过 SetMatrix 传递,避免 GPU 端的矩阵求逆开销

深度纹理格式

确保在 URP Asset 中开启 Depth Texture,否则 m_DepthTexture 将为 null

SRP Batcher 兼容性

使用常量缓冲区传递矩阵时,需确保格式兼容以获得最佳性能

六、URP 配置要点

要在 URP 中使用深度重建功能,需要正确配置渲染管线资产:

1

打开 URP Asset

选中你的 URP Renderer Asset

2

启用 Depth Texture

勾选 "Depth Texture" 选项

代码中启用深度纹理(备选方案):

// 在你的 Renderer 的 BeginCameraRendering 中
var cameraData = renderingData.cameraData;
if (cameraData.cameraType == CameraType.Game)
{
    cameraData.camera.depthTextureMode |= DepthTextureMode.Depth;
}

内容概要:本文围绕《【卫星信号】模拟卫星信号传播研究(Matlab代码实现)》这一技术资源展开,系统介绍了利用Matlab进行卫星信号传播过程建模与仿真的方法。该资源聚焦于构建卫星信号在复杂空间环境中的传播模型,综合考虑自由空间路径损耗、大气吸收、多径效应、多普勒频移、电离层闪烁及噪声干扰等多种物理因素,通过Matlab编程实现信号传输特性的动态仿真与可视化分析,帮助研究人员深入掌握卫星通信信道的关键特性与建模流程。; 适合人群:具备Matlab编程能力和通信原理基础知识的高校研究生、科研机构研究人员及从事卫星通信、导航定位、遥感遥测等领域的工程技术人员,特别适用于需要完成相关课题仿真、毕业设计或项目开发的初级与中级科研人员。; 使用场景及目标:①用于教学与课程设计中加深对卫星信号传播机制的理解;②支撑卫星通信系统链路预算、接收机灵敏度分析与抗干扰算法设计;③服务于学术论文撰写、科研项目申报中的仿真验证环节,提供可复用的代码框架与建模思路。; 阅读建议:建议读者结合经典通信理论教材同步学习,重点剖析代码中关于信号调制、信道建模、噪声叠加与接收端解调等模块的实现逻辑,动手运行并调整轨道参数、频率、环境条件等变量,观察信号质量变化,从而深化对卫星信道动态行为的认知。
内容概要:本文系统介绍了2024年最新提出的两种智能优化算法——青蒿素优化算法与霜冰优化算法(RIME),并通过Matlab代码实现对二者进行了深入对比研究。文档不仅阐述了两种算法的核心原理与数学模型,还全面展示了其在电力系统优化、新能源调度、路径规划、机器学习参数调优等复杂工程问题中的应用性能差异。文中涵盖了微电网调度、电动汽车充电优化、无人机三维路径规划、风光互补制氢系统调度等多个前沿科研方向的典型案例,并配套提供了完整的Matlab仿真代码与模型资源,便于读者复现高水平学术论文成果并开展创新性研究。; 适合人群:具备一定编程基础,熟练掌握Matlab/Simulink环境,正在从事智能优化算法相关研究的研究生、高校教师及工程技术人员,尤其适用于专注于能源系统优化、智能交通、智能制造、自动化控制等领域的科研工作者。; 使用场景及目标:①深入理解青蒿素算法与RIME算法的基本思想、迭代机制与收敛特性;②通过实际代码复现EI、顶刊级别论文中的优化模型;③在具体科研项目中对比两类算法的寻优能力、稳定性与计算效率,完成算法选型与改进;④拓展新型优化算法在多能互补系统、智能路径规划、分布式调度等交叉学科中的创新应用。; 阅读建议:建议读者结合网盘提供的完整代码资源,按照文档中给出的应用实例循序渐进地实践操作,重点关注不同场景下的参数设置策略、算法收敛曲线分析与鲁棒性表现,同时关注公众号“荔枝科研社”获取持续的技术支持与更新资料。
内容概要:本文档聚焦于“直流电机双闭环控制Matlab仿真”,系统阐述了基于Matlab/Simulink平台的直流电机双闭环控制系统的设计与仿真方法。重点围绕电流环与转速环的协同控制策略,详细介绍了控制器结构设计、PI参数整定、系统建模及动态响应分析过程,实现了对电机速度和电流的高精度调控。文档充分展示了双闭环控制在提升系统稳定性、加快响应速度和增强抗干扰能力方面的优越性能,并结合电力电子变换器(如Buck电路)的双闭环控制案例,拓展了该技术在实际工程中的应用范围。资源配套完整,适用于理论学习与实践操作相结合的研究需求。; 适合人群:具备自动控制原理基础知识和Matlab/Simulink软件操作能力的高校本科生、研究生,以及从事电机控制、电力电子系统开发等相关领域的工程技术人员。; 使用场景及目标:①深入理解直流电机双闭环控制的核心原理与工程实现方法;②掌握利用Matlab/Simulink进行控制系统建模、仿真与性能评估的关键技能;③为课程设计、毕业论文、科研项目或工业控制系统开发提供可复用的技术方案与仿真参考。; 阅读建议:建议读者结合文档中的Simulink模型文件,边学习边动手实践,重点关注PID控制器的参数调节过程与系统阶跃响应特性,通过对比不同参数下的仿真结果,深化对控制性能影响因素的理解,从而全面提升系统设计与分析能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值