Стабильный подобный термостату алгоритм, при котором входные изменения могут быть большими и внезапными - PullRequest
0 голосов
/ 25 июня 2011

[Редактировать: я нашел ответ - см. Ниже]

У меня есть трехмерный игровой мир на iPhone (ограниченная графическая скорость), и я уже регулирую, рисую ли я каждую фигуру на экране в зависимости от ее размера и расстояния от камеры. Что-то вроде ...

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

Но проверка происходит на уровне объектов, которые представляют множество нарисованных фигур, и если объект, содержащий много фигур, включен, он увеличивает участки shape_drawn и отключает себя в следующем кадре. Мерцает, включается и выключается.

Я пытался сохранить своего рода средневзвешенное значение предыдущих значений, каждый кадр делал что-то вроде shapes_drawn_recently = 0.9 * shapes_drawn_recently + 0.1 * shapes_just_drawn, но, конечно, это только замедляло мерцание из-за характера цикла обратной связи.

Есть ли хороший способ решить эту проблему?

Мой проект в Objective-C, но общий алгоритм или псевдокод тоже хороши.

Спасибо.

Редактировать: Обратите внимание, я не прошу общих советов по производительности рендеринга. Мне нужен ответ на конкретный вопрос о том, как учитывать фигуры, нарисованные в предыдущих кадрах, без мерцания.

Ответы [ 3 ]

2 голосов
/ 25 июня 2011

Один из возможных подходов состоит в том, чтобы вместо того, чтобы заботиться о том, сколько фигур нужно нарисовать;рассмотреть важность объектов;по существу, отображение числа объектов, которые должны быть нарисованы, с минимальной важностью для объекта, на быть нарисованным.

Например, можно использовать обратный логарифм:

// pseudocode
minimumImportance(count) = 1 / log(count)

Это дает, как пример;минимальное значение (100) = 1 / log (100) = 1/2 = 0,5;но минимальное значение (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 голос
/ 26 июня 2011

У меня есть два возможных решения для вас.

Решение без сохранения состояния: Для каждого кадра у вас есть «бюджет» форм. Сортируйте фигуры по важности и выбирайте фигуры, начиная с самой важной, пока не израсходуете бюджет. Нарисуй их. Поскольку в предыдущем кадре состояние не сохраняется, эта система не будет колебаться.

Решение с учетом состояния: Вы управляете минимальной важностью k нарисованных фигур как непрерывной переменной, регулируя ее так, чтобы рисовалось правильное количество фигур, м . Переменная 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 увеличивается или уменьшается: с постоянной скоростью или пропорционально погрешности?

Посмотрите, насколько все сложнее, когда вы используете состояние (например, обратная связь)? Я предлагаю попробовать версию без состояния.

1 голос
/ 25 июня 2011

Сделайте так, чтобы каждый объект запоминал, был ли он нарисован или нет в предыдущем кадре.

Если бы он был более снисходительным, решая, следует ли рисовать этот кадр, чем вы, если бы он не рисовалбыл нарисован последний кадр.Итак ...

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

Вуаля, без мерцания.Не могу поверить, что я не подумала об этом раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...