unity摄像机深度图使用[通俗易懂]

unity摄像机深度图使用[通俗易懂]https://www.jianshu.com/p/80a932d1f11ehttps://www.jianshu.com/p/178f3a065187https://www.cnblogs.com/czaoth/p/5830735.htmlhttps://www.cnblogs.com/jackmaxwell/p/7117909.htmlhttps://docs.unity3d.com/…

大家好,又见面了,我是你们的朋友全栈君。

https://www.jianshu.com/p/80a932d1f11e
https://www.jianshu.com/p/178f3a065187
https://www.cnblogs.com/czaoth/p/5830735.html
https://www.cnblogs.com/jackmaxwell/p/7117909.html
https://docs.unity3d.com/540/Documentation/Manual/SL-Pass.html
http://www.lsngo.net/2018/01/20/unity_depthtextureprojector/
https://blog.csdn.net/puppet_master/article/details/77489948

本篇博客主要是解决,深度图的原理与例子实现问题。
下面我们直接用unity的脚本和shader,介绍如何使用unity给我们提供的深度图。
C#脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class DepthTextureTest : MonoBehaviour
{ 
   
    private Material postEffectMat = null;
    private Camera currentCamera = null;

    void Awake()
    { 
   
        currentCamera = GetComponent<Camera>();
    }

    void OnEnable()
    { 
   
        if (postEffectMat == null)
            postEffectMat = new Material(Shader.Find("DepthTexture/DepthTextureTest"));
        currentCamera.depthTextureMode |= DepthTextureMode.Depth;
    }

    void OnDisable()
    { 
   
        currentCamera.depthTextureMode &= ~DepthTextureMode.Depth;
    }

    void OnRenderImage(RenderTexture source, RenderTexture destination)
    { 
   
        if (postEffectMat == null)
        { 
   
            Graphics.Blit(source, destination);
        }
        else
        { 
   
            Graphics.Blit(source, destination, postEffectMat);
        }
    }
}

shader代码:

Shader "DepthTexture/DepthTextureTest"
{ 
   
	CGINCLUDE
		#include "UnityCG.cginc"
		sampler2D _CameraDepthTexture;

		fixed4 frag_depth(v2f_img i) : SV_Target
		{ 
   
			float depthTextureValue = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
			//float linear01EyeDepth = LinearEyeDepth(depthTextureValue) * _ProjectionParams.w;
			float linear01EyeDepth = Linear01Depth(depthTextureValue);
			return fixed4(linear01EyeDepth, linear01EyeDepth, linear01EyeDepth, 1.0);
		}
	ENDCG

	SubShader
	{ 
   
		Pass
		{ 
   
			ZTest Off
			Cull Off
			ZWrite Off
			Fog{ 
    Mode Off }

			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag_depth
			ENDCG
		}
	}
}

最终结果:
在这里插入图片描述

上面用到了这个宏:SAMPLE_DEPTH_TEXTURE
原型如下:

#define SAMPLE_DEPTH_TEXTURE(sampler, uv) (tex2D(sampler, uv).r)

这句代码也可以写为:
tex2D(_CameraDepthTexture, i.uv).r;

从视空间深度转化到屏幕空间深度的公式如下:
a = F/(F – N)
b = NF/(N – F)
最终depth(屏幕空间)=(aZ + b)/Z (Z为视空间深度)

我们在屏幕空间使用屏幕空间的坐标进行插值,得到逐像素的坐标。
屏幕空间的深度是和1/z成正比的。
那么经过透视变换、透视投影之后,得到的是屏幕空间的深度值,而我们需要使用视空间下的z才好计算,所以需要反推得到视空间下的深度z。
在这里插入图片描述
在这里插入图片描述
Linear01Depth原型:

// Z buffer to linear 0..1 depth
inline float Linear01Depth( float z )
{ 
   
    return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y);
}

这地方的推导有点问题:

// Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
// x = 1-far/near
// y = far/near
// z = x/far
// w = y/far
// or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
// x = -1+far/near
// y = 1
// z = x/far
// w = 1/far
float4 _ZBufferParams;

LinearEyeDepth原型:

// Z buffer to linear depth
inline float LinearEyeDepth( float z )
{ 
   
    return 1.0 / (_ZBufferParams.z * z + _ZBufferParams.w);
}

z&1/z
通过上面的深度图具体的使用,我们发现,实际上真正使用的深度,是从顶点的视空间在,经过投影变成一个1/Z成正比的值(屏幕空间Depth),然后在使用时,再通过投影变换时的计算公式反推回对应视空间像素的位置Z。
https://developer.nvidia.com/content/depth-precision-visualized

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/129926.html原文链接:https://javaforall.net

(0)
上一篇 2022年4月25日 下午8:40
下一篇 2022年4月25日 下午11:20


相关推荐

  • 斯皮尔曼等级相关称名数据_斯皮尔曼和皮尔森区别

    斯皮尔曼等级相关称名数据_斯皮尔曼和皮尔森区别Spearman相关系数又称秩相关系数,是利用两变量的秩次大小作线性相关分析,对原始变量的分布不作要求,属于非参数统计方法,适用范围要广些。对于服从Pearson相关系数的数据亦可计算Spearman

    2022年8月5日
    6
  • 简单介绍一下spring bean的生命周期_java类的生命周期

    简单介绍一下spring bean的生命周期_java类的生命周期1.springbean生命周期2.Aware接口2.1.作用一个标记,标记在spring容器初始化时需要获取上下文中当前的一些运行环境;2.2.常用接口ApplicationContextAware:获取ApplicationContextspring上下文;ApplicationEventPublisherAware:获取ApplicationEventPublisher事件发布器;BeanClassLoaderAware:获取当前的ClassLoader类加载器;BeanFac

    2025年11月23日
    3
  • usb眼图测试方法_USB4.0

    usb眼图测试方法_USB4.01、现象HUB芯片电源噪声所引起;USBHUB芯片电压偏置电阻不合适所引起。2、参考电路3、原因分析在眼图测试时发现有一个USB口的眼图有抖动碰到眼图模板,当时经过千辛万苦,屡试不成,都未找到具体原因。只能确定眼图的抖动可能由于电源的噪声所引起,后续多次更换电源的滤波参数和割PCB后才找到由于一路电源1.8VPLL的布局所引起。真是众里寻她千百度,暮然回首,尽在一个HUBcore电源的滤波未做好。未通过模板时眼图如下图(未做任何调试):未通过模板时所对应的PCB布局..

    2025年6月19日
    5
  • Pandas中DataFrame数据合并、连接(concat、merge、join)

    Pandas中DataFrame数据合并、连接(concat、merge、join)最近在工作中 遇到了数据合并 连接的问题 故整理如下 供需要者参考 一 concat 沿着一条轴 将多个对象堆叠到一起 concat 方法相当于数据库中的全连接 unionall 它不仅可以指定连接的方式 outerjoin 或 innerjoin 还可以指定按照某个轴进行连接 与数据库不同的是 它不会去重 但是可以使用 drop duplicates 方法达到去重的效果 concat

    2026年3月18日
    2
  • java string转inputstream(substring截取字符串)

    Apachecommons是一个强大的Java辅助工具包。它提供的IOUtils可以让我们很便捷的实现InputStream转换为String。StringWriterwriter=newStringWriter();IOUtils.copy(inputStream,writer,encoding);StringtheString=writer.toString();首先把in…

    2022年4月16日
    126
  • 字与字节的关系_一个比特等于多少字节

    字与字节的关系_一个比特等于多少字节之前一直认为1个字等于2个字节,刚在书中发现有个说法说,4个字节作为一个字,与之前记忆的1个字等于2个字节相违背,这才“较真”好好查了下相关的概念。基本概念字:计算机进行数据处理时,一次存取、加工和

    2022年8月2日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号