用到摄像机的“深度“替代到摄像机的距离

很多时候,我们需要根据对象距离摄像机的距离来设置属性,但是求距离往往是要计算开方的,这个运算量有点儿大,如果每帧对大量物体进行求距离运算,还是有一些负担的。但是,在很多情况下,实际上对象到摄像机的距离可以用对象相对于摄像机的“深度”来代替,这里所说的深度就是对象在摄像机坐标系下的Z轴的绝对值,不是0到1区间那个深度,是原始深度。使用对象相对于摄像机的深度来替代对象相对于摄像机的距离,不但运算量小很多,而且有时候效果更好,更符合直观感受。

下面是一个使用物体相对于摄像机“深度”控制物体缩放的代码示例:

using UnityEngine;

publicclassScaleByOpObjHover : MonoBehaviour
{
	[SerializeField]
	float hoverMulti = 1.5f;
	[SerializeField]
	float camMulti = 1;

	OperationObject _obj;
	OperationObject obj { get { if (!_obj) _obj = GetComponentInParent<OperationObject>(); return _obj; } }

	Vector3 scaleInit;

	voidStart()
	{
		scaleInit = transform.localScale;
	}

	voidUpdate()
	{
		Vector3 posCam = Camera.main.transform.InverseTransformPoint(obj.transform.position);
		Vector3 scale = scaleInit * camMulti * (10f + Mathf.Abs(posCam.z)) ;
		Vector3 scaleHovered = scale * hoverMulti;
		transform.localScale = Vector3.Lerp(transform.localScale, obj.hovered ? scaleHovered : scale, Time.deltaTime * 10);
	}
}

如果是在ShaderGraph中进行类似的控制,目前我知道的办法是两个:

一个是使用ScreenWorld节点,将其输出使用Split节点分离,使用分离后的A输出就是当前正在渲染的像素的基于真实坐标的“深度值”,或者说基于摄像机坐标系的Z轴的值的绝对值。这里需要注意的是不要使用SceneDepth的值,这个值是在渲染该像素之前生成的,不是当前渲染的像素的深度,经常用来与当前渲染的“深度”做对比。

另一个办法是使用Position节点,选择该节点的Eye选项输出的Z值应该就是基于摄像机坐标系的,这个Z值的绝对值应该就是相对于这个摄像机的“深度”,不过这个这个我没做过比较充分的测试,只是简单测试了一下。

猜你喜欢

转载自blog.csdn.net/ttod/article/details/129360162