Gaffer建议在先前状态和当前状态之间进行线性插值以进行渲染。当前状态与前一状态相隔1个完整的固定时间步长。但是,为什么不直接将剩余的dt插入到正常的模拟器中,渲染场景,然后丢弃新的状态,直到一个完整的步骤结束?
使用Windows的QueryPerformanceCounter的真实示例:
QueryPerformanceCounter(&after);
float dt = (double)(after.QuadPart-before.QuadPart)/(double)freq.QuadPart;
before = after;
float step = 1.0f/60.0f;
while (dt > step){
Simulate(step);
dt -= step;
}
Render(dt);
我假设这只是一个性能问题,以避免每帧都运行模拟,而是对一个新的状态进行更便宜的线性插值,您只需计算一次。
1条答案
按热度按时间gcxthw6b1#
这不仅仅是“一个表演的事情”。在更新循环结束时再次运行集成步骤将违反本文所倡导的内容:
问题是,物理模拟的行为取决于您传入的delta时间。
通过在更新循环结束时传递一个小于固定时间步长的
dt
,您会导致物理模拟不一致的问题。使用线性插值来基于先前的固定时间步长计算来估计当前状态,通过确保总是使用相同的固定时间步长来执行积分步骤并且在插值步骤中消耗剩余的帧时间来避免该问题。但是为什么不直接将剩余的dt插入到正常的模拟器中,渲染场景,然后丢弃新的状态,直到一个完整的步骤结束?
这句话我听不懂。如果通过“剩余dt”,OP指的是消耗固定时间步长后剩余的分数dt,那么将该分数dt插入积分步骤就是上述问题。
另一方面,OP可能意味着通过固定的时间步长来接近总帧时间,然后丢弃剩余的分数dt而不进行仿真。如果这是意图,则结果可能是口吃,因为物理和渲染不同步:
这意味着我们在与渲染时间略有不同的时间显示物理模拟的状态,导致屏幕上物理模拟的微妙但视觉上不愉快的口吃。