稳定的类似恒温器的算法,其中输入变化可以是大的和突然

时间:2011-06-25 13:11:29

标签: objective-c c algorithm function math

[编辑:我找到了答案 - 见下文]

我在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 lot并将其自身切换回下一帧。它会一直闪烁。

我尝试保留一种前一个值的加权平均值,每个帧执行类似shapes_drawn_recently = 0.9 * shapes_drawn_recently + 0.1 * shapes_just_drawn的操作,但当然它只会因为反馈循环的性质而减慢闪烁。

有解决这个问题的好方法吗?

我的项目是在Objective-C中,但是通用算法或伪代码也很好。

感谢。

编辑:请注意我不是要求关于渲染性能的一般建议。我需要回答一个具体的问题,即如何将先前帧中绘制的形状考虑在内而不会出现闪烁。

3 个答案:

答案 0 :(得分:2)

一种可能的方法是不仅仅关心要绘制多少个形状;考虑对象的重要性;实质上将要绘制的对象数量映射到 绘制的对象的最小重要性。

例如,可以使用反对数:

// 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个其他物体;手指和眼睛都被剔除了。

答案 1 :(得分:1)

让每个对象记住它是否被绘制在前一帧。

在确定是否应该绘制此框架时,如果没有绘制最后一帧,则更宽松。所以......

if (how_big_it_looks * (1.2 if drawn last frame, 1.0 if not) / shapes_drawn > constant2) then draw

Voila,没有闪烁。简直不敢相信我没想到这一点。

答案 2 :(得分:1)

我有两种可能的解决方案。

无状态解决方案:对于每个框架,您都拥有形状的“预算”。按重要性对形状进行排序,并从最重要的形状开始选择形状,直到用完预算为止。画那些。由于前一帧没有保留状态,因此该系统不会振荡。

有状态解决方案:您可以将绘制的形状的最小重要性 k 控制为连续变量,调整它以便绘制正确数量的形状,< EM>米。变量 k 基于 n 进行调整, 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 增加或减少的速度有多快:以恒定速率或与误差成比例?

看看使用状态(例如反馈)时有多复杂?我建议尝试无状态版本。