2018-01-15 14:19:35 linian71 阅读数 4577

工作原因,又把Unity3D捡起来了,需要实现一个深度相机。网上查了查资料,整理如下。

参考:http://williamchyr.com/2013/11/unity-shaders-depth-and-normal-textures/

我的代码在:

https://github.com/NianLi71/Camera-Util-Unity3D/tree/master/DepthCamera

一、如下建立场景,做一排cube放入一个CubeRow中。放好MainCamera位置,然后复制出DepthCamera,这样两个相机的位置视角一致,方便后续调试。


新建一个shader,参考链接中的地址,输入代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/DepthGrayscale" {
SubShader {
Tags { "RenderType"="Opaque" }

Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

sampler2D _CameraDepthTexture;

struct v2f {
   float4 pos : SV_POSITION;
   float4 scrPos:TEXCOORD1;
};

//Vertex Shader
v2f vert (appdata_base v){
   v2f o;
   o.pos = UnityObjectToClipPos (v.vertex);
   o.scrPos=ComputeScreenPos(o.pos);
   //for some reason, the y position of the depth texture comes out inverted
   //o.scrPos.y = 1 - o.scrPos.y;
   return o;
}

//Fragment Shader
half4 frag (v2f i) : COLOR{
   float depthValue = Linear01Depth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.scrPos)).r);
   half4 depth;

   depth.r = depthValue;
   depth.g = depthValue;
   depth.b = depthValue;

   depth.a = 1;
   return depth;
}
ENDCG
}
}
FallBack "Diffuse"
}

新建一个Material,并选择刚刚建好的shader文件



给DepthCamera添加脚本文件,输入以下代码:

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

[ExecuteInEditMode]   // 可以在编辑界面看到深度绘制效果
public class MainCameraDepth : MonoBehaviour {

	public Material mat;
	public int width = 512;
	public int height= 512;

	private Camera cam;
	private RenderTexture rt;
	private int image_id = 0;

	void Start () {
		cam = GetComponent<Camera>();   //获取当前绑定到脚本的相机

		cam.depthTextureMode = DepthTextureMode.Depth;

		//		rt = new RenderTexture (width, height, 24);  // 24 bit depth
		//		cam.targetTexture = rt;
	}

	void OnRenderImage (RenderTexture source, RenderTexture destination){
		Graphics.Blit(source,destination,mat);
		//mat is the material which contains the shader
		//we are passing the destination RenderTexture to
	}
	
	// Update is called once per frame
	void Update () {
		
	}
}


二、回到Unity主界面,将material文件拖拽给DepthCamera相机脚本,并将Audio Listener取消勾选。

之后,如图将Main Camera的Camera方框取消勾选:


在编辑界面即可看到深度图输出:


看到全黑的cube原因是相机的远裁剪平面设置的太远了。将DepthCamera的Clipping Planes far调整近一些:


即可看到灰度深度图:


三、保存深度图到文件Duplicate复制DepthCamera,并重新命名SnapDepthCamera,再添加一个脚本文件SnapDepthCamera.cs,输入以下代码:

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

[ExecuteInEditMode]   // 可以在编辑界面看到深度绘制效果
public class SnapDepthCamera : MonoBehaviour {
	
	public Material mat;
	public int width = 512;
	public int height= 512;

	private Camera cam;
	private RenderTexture rt;
	private int image_id = 0;
	private bool SnapFlag = false;

	void Start () {
		cam = GetComponent<Camera>();   //获取当前绑定到脚本的相机

		cam.depthTextureMode = DepthTextureMode.Depth;

		rt = new RenderTexture (width, height, 24);  // 24 bit depth
		cam.targetTexture = rt;
	}

	void OnRenderImage (RenderTexture source, RenderTexture destination){
		Graphics.Blit(source,destination,mat);
		//mat is the material which contains the shader
		//we are passing the destination RenderTexture to

		if(SnapFlag) {
			RenderTexture currentRT = RenderTexture.active;   // save current active rendertexture
			RenderTexture.active = destination;

			Texture2D image = new Texture2D(destination.width, destination.height,TextureFormat.RGB24, false);
			image.ReadPixels(new Rect(0, 0, destination.width, destination.height), 0, 0);
			image.Apply();

			savePNG (image, "./depthImages/camera_image" + image_id + ".png");

			image_id++;
			RenderTexture.active = currentRT; // restore 
		}
	}

	private void savePNG(Texture2D image, string path_file) {
		// store the texture into a .PNG file
		byte[] bytes = image.EncodeToPNG ();

		// save the encoded image to a file
		System.IO.File.WriteAllBytes (path_file, bytes);
	}

	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown ("p")) {
			SnapFlag = true;
		} else
			SnapFlag = false;
	}
}
注意,在Update里我们不做保存操作,保存操作放到OnRenderImage中完成。

之后在项目首页新建文件夹:depthImages/,之后运行程序,按'p'键即可保存深度图。



2016-11-08 13:57:00 SilverFoxGame 阅读数 44

[Unity3D]深度相机 Depth Camera

作为3D世界里最重要的窗口,摄像机的应用就显得很重要,毕竟在屏幕上看到的一切都得用摄像机矩阵变换得来的嘛。
论坛上看到了一篇帖子讲非天空盒的背景做法,让我想起其实很多界面合成画面可以用摄像机之间的交互来实现(避开用GUI,效率问题我没尝试过,但是貌似用深度相机比gui好?以后试验下)。
 
首先说下深度相机,就是用2个或者2个以上的相机,设置好参数后自动到屏幕视觉合成的效果,应用上两个方面:1,背景图 2,用户界面。
 
步骤:
1.建立第二个相机,设置 Clear Flags 属性为 Depth Only (深度模式)
把摄像机和摄像机面前要投影的东西放到场景以外开不到的地方。

 
2.设置Depth属性
主摄像机默认是-1 ,如果你的物体要显示在他层面之上,就设比他大的数,不然就设比他小的数
 
3.设置贴图的Aniso Level属性到最高(9)
这样贴图就能清晰些。
 
4.最后去处摄像机自带的没用的组件
去除掉Audio Listener之类的东西。
 

 

放前面当界面用,放背后可以当背景,做些什么远处的树啊山啊之类的不错。
这样的话,车仪表盘指针就可以编程让他动了。 ^ ^

 

 

Camera属性详解

http://www.cnblogs.com/rainmj/p/5335623.html

 

posted on 2016-11-08 13:57 jiahuafu 阅读(...) 评论(...) 编辑 收藏

2014-03-11 09:59:24 u013265457 阅读数 3120

  Unity3D Depth Camera(深度相机)的应用

  作为3D世界里最重要的窗口,摄像机的应用就显得很重要,毕竟在屏幕上看到的一切都得用摄像机矩阵变换得来的嘛。

  论坛上看到了一篇帖子讲非天空盒的背景做法,让我想起其实很多界面合成画面可以用摄像机之间的交互来实现(避开用GUI,效率问题我没尝试过,但是貌似用深度相机比gui?以后试验下)

  首先说下深度相机,就是用2个或者2个以上的相机,设置好参数后自动到屏幕视觉合成的效果,应用上两个方面:1,背景图 2,用户界面。

  步骤:

  1.建立第二个相机,设置 Clear Flags 属性为 Depth Only (深度模式)

  把摄像机和摄像机面前要投影的东西放到场景以外开不到的地方。

  2.设置Depth属性

  主摄像机默认是-1 ,如果你的物体要显示在他层面之上,就设比他大的数,不然就设比他小的数

  3.设置贴图的Aniso Level属性到最高(9)

  这样贴图就能清晰些。

  4.最后去处摄像机自带的没用的组件

  去除掉Audio Listener之类的东西。

  放前面当界面用,放背后可以当背景,做些什么远处的树啊山啊之类的不错。

  这样的话,车仪表盘指针就可以编程让他动了。

2013-10-24 10:21:08 xuanjian6 阅读数 1035
作为3D世界里最重要的窗口,摄像机的应用就显得很重要,毕竟在屏幕上看到的一切都得用摄像机矩阵变换得来的嘛。
论坛上看到了一篇帖子讲非天空盒的背景做法,让我想起其实很多界面合成画面可以用摄像机之间的交互来实现(避开用GUI,效率问题我没尝试过,但是貌似用深度相机比gui好?以后试验下)。
首先说下深度相机,就是用2个或者2个以上的相机,设置好参数后自动到屏幕视觉合成的效果,应用上两个方面:1,背景图 2,用户界面。
步骤:
1.建立第二个相机,设置 Clear Flags 属性为 Depth Only (深度模式)
把摄像机和摄像机面前要投影的东西放到场景以外开不到的地方。
2.设置Depth属性
主摄像机默认是-1 ,如果你的物体要显示在他层面之上,就设比他大的数,不然就设比他小的数
3.设置贴图的Aniso Level属性到最高(9)
这样贴图就能清晰些。
4.最后去处摄像机自带的没用的组件
去除掉Audio Listener之类的东西。
放前面当界面用,放背后可以当背景,做些什么远处的树啊山啊之类的不错。

这样的话,车仪表盘指针就可以编程让他动了。 ^ ^


转自 http://prolove10.blog.163.com/blog/static/138411843201010184026134/

没有更多推荐了,返回首页