Russian Qt Forum

Программирование => Алгоритмы => Тема начата: Авварон от Май 19, 2018, 22:25



Название: Прогрессия
Отправлено: Авварон от Май 19, 2018, 22:25
Возникла для самообразования задачка. Вот, допустим, у нас есть картинка, 13*13 пикселей с мипмапами (т.е. серия картинок 13*13, 6*6, 3*3, 1*1).
И хотим мы просуммировать, допустим, ширины - 13+6+3+1 = 23. Понятно, что можно сделать это циклом за O(levels), где levels - кол-во мипмапов (4 в данном примере).
А можно ли за линейное время?
Пффф, это же убывающая геометрическая прогрессия (https://ru.wikipedia.org/wiki/Геометрическая_прогрессия), подумал я. Для неё есть формула суммы - b1*(1 - q^n) / (1 - q).
Немного мат. преобразований и получаем такую формулу:
Код:
int sum(int width, int levels) 
{
    return 2 * width * ((1 << levels) - 1) / (1 << levels);
}
Но вот беда sum(13, 4) = 24, а не 23. И в самом деле, int(13+6.5+3.25+1.625) = int(24,375) = 24.
Внимание вопрос, а как же получить "неточную" (с учетом округлений) сумму?


Название: Re: Прогрессия
Отправлено: Igors от Май 20, 2018, 07:30
И хотим мы просуммировать, допустим, ширины - 13+6+3+1 = 23.
А что это за суммирование, в чем его смысл?


Название: Re: Прогрессия
Отправлено: Авварон от Май 20, 2018, 10:20
Хороший вопрос, изначально я хотел высчитать offset N-й мипмапы, т.е.

Код:
Σ(level) bytesPerImage(std::max(width >> level, 1), std::max<(height >> level, 1))

где bytesPerImage:
Код:
qsizetype bytesPerImage(w, h) { h * ((w * bitsPerPixel(format) + 31) >> 5) << 2}
width, height - максимальные размеры картинки


Название: Re: Прогрессия
Отправлено: Igors от Май 21, 2018, 08:46
изначально я хотел высчитать offset N-й мипмапы, т.е.
Все равно не дошло. Возможно Вы хотели просто посчитать масштаб(ы) чтобы переводить x,y пикселя из оригинальной текстуры в одну из уменьшенных MIP'ов. Ну степени двойки этот масштаб никак не равен и должен быть флоат. Но он не зависит от переводимого пикселя, просчитать (в цикле) один раз и кешировать.


Название: Re: Прогрессия
Отправлено: qate от Май 21, 2018, 10:08
А если хранить размеры картинок степени двойки сразу ?


Название: Re: Прогрессия
Отправлено: Авварон от Май 21, 2018, 13:21
изначально я хотел высчитать offset N-й мипмапы, т.е.
Все равно не дошло. Возможно Вы хотели просто посчитать масштаб(ы) чтобы переводить x,y пикселя из оригинальной текстуры в одну из уменьшенных MIP'ов. Ну степени двойки этот масштаб никак не равен и должен быть флоат. Но он не зависит от переводимого пикселя, просчитать (в цикле) один раз и кешировать.

мне нужно что-то типа uchar *pos = data + mipmapOffset(level) + bytesPerLine(level) * y + x;

Ну да, пока просто просчитал в цикле и закешировал результаты.
Как я понимаю, хитрую формулу написать не получится (ведь оффсет - это уже не прогрессия, а комбинация арифм и геом прогрессий)?


Название: Re: Прогрессия
Отправлено: Igors от Май 22, 2018, 13:12
мне нужно что-то типа uchar *pos = data + mipmapOffset(level) + bytesPerLine(level) * y + x;
Если мы мапируемся в одну из MIP, то один пиксель (куда попали) не имеет смысла, нужны его коодинаты обязательно в флотах чтобы интерполировать значение с учетом соседних пыкселей (часто bilinear)


Название: Re: Прогрессия
Отправлено: Авварон от Май 22, 2018, 14:28
Если мы мапируемся в одну из MIP, то один пиксель (куда попали) не имеет смысла, нужны его коодинаты обязательно в флотах чтобы интерполировать значение с учетом соседних пыкселей (часто bilinear)

Это всё очень интересно, но у меня файлики с текстурами, там нет флоатов и не надо ничо "ынтерполировать". Мипмапа либо есть (и ее "пыксели" целочисленны), либо её нет, и тут уже ОГЛ будет разбираться что и как интерполировать.

Так-то да, попиксельный доступ особо не нужен, но хочется иметь метод типа scanLine(int y) для того, чтобы ворочать не здоровенным куском данных, а хотя бы построчно.


Название: Re: Прогрессия
Отправлено: Igors от Май 22, 2018, 14:36
и тут уже ОГЛ будет разбираться что и как интерполировать.
Кстати он умеет сам создавать MIPы на ходу

Так-то да, попиксельный доступ особо не нужен, но хочется иметь метод типа scanLine(int y) для того, чтобы ворочать не здоровенным куском данных, а хотя бы построчно.
Не знаю чего Вы хотите добиться. В софтверных реализациях текстура обычно подгружается страницами, вытесняются обычным LRU. В любом случае нужно знать "область интереса" (интересующее место в MIP)


Название: Re: Прогрессия
Отправлено: Авварон от Май 22, 2018, 14:51
Не знаю чего Вы хотите добиться. В софтверных реализациях текстура обычно подгружается страницами, вытесняются обычным LRU. В любом случае нужно знать "область интереса" (интересующее место в MIP)

Считать текстуру из файлика. Понятно, что можно сделать типа memcpy(file.readAll().data(), buffer, file.size()) (за вычетом хедера), но хочется читать мипмапы построчно, а не загружать весь файл в память.


Название: Re: Прогрессия
Отправлено: Авварон от Май 22, 2018, 15:09
Да даже ладно, фиг с ним с построчным доступом, всё равно надо посчитать оффсет мипмапы, чтобы знать, куда грузить кусок данных