问题描述
||
[编辑:我找到了答案-见下文]
我在iPhone上拥有3D游戏世界(图形速度有限),并且我已经在根据其大小和与相机的距离来调整是否在屏幕上绘制每个形状。就像是...
if (how_big_it_looks_from_the_camera > constant) then draw
我现在想做的是还要考虑要绘制多少个形状,以便在游戏世界的繁忙区域中,我可以绘制的图形比以前少。
我试图通过将how_big_it_looks除以上一帧绘制的形状的数量来做到这一点(嗯,这个的平方根,但是我正在简化-问题是相同的)。
if (how_big_it_looks / shapes_drawn > constant2) then draw
但是检查是在代表许多绘制形状的对象级别进行的,如果打开了包含许多形状的对象,则它将增加shapes_drawn批次并将自身切换回下一帧。闪烁闪烁。
我尝试通过每帧做类似shapes_drawn_recently = 0.9 * shapes_drawn_recently + 0.1 * shapes_just_drawn
的方式来保持先前值的加权平均值,但是由于反馈回路的性质,它当然只会减慢闪烁。
有解决这个问题的好方法吗?
我的项目在Objective-C中,但是通用算法或伪代码也很好。
谢谢。
编辑:请注意,我并没有要求有关渲染性能的一般建议。我需要一个具体问题的答案,即如何考虑前几帧中绘制的形状而不会出现闪烁。
解决方法
一种可能的方法是,不仅仅在乎要绘制多少个形状。考虑对象的重要性;本质上将要绘制的对象的数量映射到要绘制的对象的最小重要性。
例如,可以使用反对数:
// pseudocode
minimumImportance(count) = 1 / log(count)
以此为例。 minimumImportance(100)= 1 / log(100)= 1/2 = 0.5;但minimumImportance(1000)得到0.333。
在此方案中,0.0是最重要的,1.0是最小的;但这可以通过稍微改写功能来反转:
minimumImportance(count) = 1 - 1 / log(count)
在函数中添加一些模糊测试也很明智,但这留给读者练习。
编辑:详细地说,这意味着对象应该具有相关的重要性,这意味着在任何给定的情况下,您可能有1个重要性对象0,10个重要性0.10,100个重要性0.12等。
此外,这种方案还有一个额外的好处:如果每个单独的形状也都具有重要性;您可以简单地将形状的重要性与整个对象的重要性相乘,以获得加权重要性;允许在繁忙情况下进行动态详细处理。
例如:玩家模型的重要性为0.5;躯干,手臂,腿和头部的重要性为0.0,而眼睛的重要性为0.5;和手指的重要性为0.7。
如果播放器是屏幕上唯一的东西,则将详细绘制它。但是如果还有1000个其他物件;手指和眼睛被剔除。
, 使每个对象都记住它是否已被绘制。
它决定了是否应该在此帧绘制时比在没有绘制最后一帧时更宽容。所以...
if (how_big_it_looks * (1.2 if drawn last frame,1.0 if not) / shapes_drawn > constant2) then draw
瞧,没有闪烁。简直不敢相信我没想到这一点。
, 我有两种可能的解决方案。
无状态解决方案:对于每个框架,您都有一个“预算”形状。按重要性对形状进行排序,并从最重要的形状开始选择形状,直到用完预算。画那些。由于没有从前一帧保留的状态,因此该系统不会振荡。
有状态的解决方案:您可以将绘制形状的最小重要性k作为连续变量进行控制,并对其进行调整,以便绘制正确的形状数m。变量k根据n(最后一帧绘制的形状数)进行调整,以消除小振荡。
// If k stayed the same last frame,make it less likely to change this frame
// This is called \"hysteresis\" and is very common in control systems
if k changed last frame then
threshold = 0.1
else
threshold = 0.2
end
if (1-threshold)*m < n < (1+threshold)*m then
// k is close to correct,don\'t change it
else
if n < m then
if all shapes were drawn last frame then
// don\'t change k
else
// increase k
end
else
// decrease k
end
end
这里有一堆参数需要调整。阈值是多少? k增加或减少的速度有多快:以恒定的速率或与误差成正比?
看看使用状态(例如反馈)时要复杂得多吗?我建议尝试无状态版本。