3D游戏中的相机震动效果

      “震屏”作为一种游戏中的表现手段,被用来表达震撼的效果(例如用在技能的表现上)。

由于这类效果往往可以使用很小的开销达到不错的效果,所以在游戏中出现率较高。下面我将介绍一种在3D游戏中简单的震屏实现方法。

      首先,之所以称之为“震屏”,是因为并不是真正的场景本身晃动,而是玩家所见的屏幕(摄像机)产生了震动。而摄像机所观察的方向(CamDir)作为一个三维的向量,改变CamDir即可产生屏幕晃动的效果,于是CamDir + dirOffset就是我们实现震屏效果的核心。

      游戏中玩家主动旋转视角改变的主要内容也是CamDir,那么震屏与其不同之处在哪里呢?主要有以下两点:

      1.相机不是随意旋转的,而是以玩家当前观察的视向为基准进行改变的。

      2.相机在"震屏"效果结束后,需要保证初始的CamDir是不变的。

为了保证这两点,一个简单有效的方式是对CameraShake进行奇偶帧区分,奇偶帧指的是我们在游戏中每一帧需要运行的代码,例如Unity中的Update()。在奇偶帧中我们分别做一次相机偏移和一次相机归位,即:

void CameraShake()
{
	++iOddTick;
	iOddTick %= 2;
	if(iOddTick)
	{
		// calculate offset;
	}
	else
	{
		offset = -offset;
	}
	m_CamDir += offset;
}
      其次,屏幕的震动幅度往往应该与“震源”的距离成反比,引起震动的事物与我们越远,对摄像机的影响也就越小。

      然后,offset是以CamDir为基础。那么震幅的取值应该是一个相对随机的值,这个核心取值我们可以采用一维的柏林噪声函数。于是整个震屏效果可以如下表述:

void CameraShake(float deltaTime)
{
	++iOddTick;
	iOddTick %= 2;
	if(iOddTick)
	{
		// calculate offset;
		offset = m_CamDir * (constantNum / distanceToCamera) * PerlinNoise1D(deltaTime);
	}
	else
	{
		offset = -offset;
	}
	m_CamDir += offset;
}

      关于柏林函数的介绍,可以参见这篇博客。之所以采用柏林函数,一方面是因为其表现相对固定(一旦叠加的函数确定下来),对于震屏效果,我们期望的是一种相对稳定的效果,直接采用Rand()的方式可能会造成过度随机;另一方面,柏林函数是一种连续的函数,可以根据时间计算得到连续而且而非离散的值。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值