Каков наиболее эффективный способ размещения нескольких цветов в окне, особенно в покадровом формате? - PullRequest
0 голосов
/ 05 мая 2018

Я делаю игру с C и X11. Я довольно долго пытался найти способ разместить пиксели разного цвета в окне, кадр за кадром. Я видел, как полностью разработанные игры получают тысячи кадров в секунду. Какой самый эффективный способ сделать это?

Я видел 2-цветные растровые изображения с XImages, выделяющие 256 цветов на черно-белом затухании и использующие XPutPixel с XImages (что я не смог понять, как правильно создать XImage, в который позже можно было бы поместить пиксели на нем).

Я сделал это для цикла for, который создает случайное изображение, но он, очевидно, попиксельный, а не покадровый, и на рендеринг одного целого кадра уходит 18 секунд.

XColor pixel;
for (int x = 0; x < currentWindowWidth; x++) {
    for (int y = 0; y < currentWindowHeight; y++) {
        pixel.red = rand() % 256 * 256; //Converting 16-bit colour to 8-bit colour
        pixel.green = rand() % 256 * 256;
        pixel.blue = rand() % 256 * 256;
        XAllocColor(display, XDefaultColormap(display, screenNumber), &pixel); //This probably takes the most time,
        XSetForeground(display, graphics, pixel.pixel); //as does this.
        XDrawPoint(display, window, graphics, x, y);
    }
}

Ответы [ 3 ]

0 голосов
/ 05 мая 2018

Вы должны использовать GPS. Графические процессоры имеют высокопараллельную архитектуру, оптимизированную для графики (отсюда и название). Для доступа к GPUS вы будете использовать Api Luke OpenGL или Vulcan или использовать игровой движок.

0 голосов
/ 25 мая 2018

После трех или более недель экспериментов я наконец-то понял, как это сделать, и это было довольно просто. Как я уже говорил в OP, XAllocColor и XSetForground занимают довольно много времени (относительно) для работы. XDrawPoint также работал медленно, так как он делает больше, чем просто помещает пиксель в точку на изображении.

Сначала я проверил, как работает цветовой формат Xlib (для unsigned long int, представленного как pixel.pixel, для которого я и нуждался в XAllocColor), и для него установлено, что 100% красного установлено в 16711680, 100% зеленого установлено в 65280 и 100% синий установлен на 255, что, очевидно, является шаблоном. Я обнаружил, что максимум составляет 50% всех цветов, 4286019447, который является сплошным серым.

Затем я убедился, что моя система XVisualInfo будет поддерживаться моей системой с помощью теста с использованием XMatchVisualInfo ([ожидаемые значения визуальной информации]). Это гарантирует глубину, которую я буду использовать, и класс TrueColor работает.

Наконец, я сделал XImage, скопированный из изображения корневого окна для манипуляции. Я использовал XPutPixel для каждого пикселя в окне и установил случайное значение между 0 и 4286019448, создав случайное изображение. Затем я использовал XPutImage, чтобы вставить изображение в окно.

Вот окончательный код:

if (!XMatchVisualInfo(display, screenNumber, 24, TrueColor, &visualInfo)) {
    exit(0);
}
frameImage = XGetImage(display, rootWindow, 0, 0, screenWidth, screenHeight, AllPlanes, ZPixmap);
while (1) {
    for (unsigned short x = 0; x < currentWindowWidth; x += pixelSize) {
        for (unsigned short y = 0; y < currentWindowHeight; y += pixelSize) {
            XPutPixel(frameImage, x, y, rand() % 4286019447);
        }
    }
    XPutImage(display, window, graphics, frameImage, 0, 0, 0, 0, currentWindowWidth, currentWindowHeight);
}

Это помещает случайное изображение на экран со стабильными 140 кадрами в секунду на весь экран. Я не обязательно знаю, является ли это наиболее эффективным способом, но он работает лучше, чем все, что я пробовал. Дайте мне знать, если есть какой-нибудь способ сделать это лучше.

0 голосов
/ 05 мая 2018

Тысячи кадров в секунду не возможно. Частота монитора составляет около 100 Гц, или 100 циклов в секунду, это примерно максимальная частота кадров. Это все еще очень быстро. Человеческий глаз не поймет более высокую частоту кадров.

Время отклика монитора составляет около 5 мс, поэтому любая отдельная точка на экране не может обновляться более 200 раз в секунду.

8-битный - 1 байт, поэтому 8-битное изображение использует один байт на пиксель, каждый пиксель - от 0 до 256. Пиксель не имеет красного, синего, зеленого компонента. Вместо этого каждый пиксель указывает на индекс в таблице цветов. Таблица цветов содержит 256 цветов. Есть хитрость, когда вы сохраняете пиксели одинаковыми и меняете таблицу цветов, это заставляет изображение постепенно исчезать или делать другие странные вещи.

В 24-битном изображении каждый пиксель имеет синий, красный, зеленый компонент. Каждый цвет составляет 1 байт, поэтому каждый пиксель составляет 3 байта или 24 бита.

uint8_t red = rand() % 256; 
uint8_t grn = rand() % 256;
uint8_t blu = rand() % 256;

16-битное изображение использует нечетный формат для хранения красного, синего и зеленого. 16 не делится на 3, часто 2 цвета назначаются 5 битам, а третий цвет получает 6 битов. Затем вы должны разместить эти цвета на одном пикселе размером uint16_t. Вероятно, не стоит это изучать.

Медлительность вашей рутины в том, что вы рисуете по одному пикселю за раз. Вместо этого вы должны рисовать в буфер и визуализировать буфер один раз за кадр. Вы можете рассмотреть возможность использования других фреймов, таких как SDL. Другие игры могут использовать такие вещи, как OpenGL, который использует преимущества оптимизации графического процессора для работы матрицы и т. Д.

...