Правильный способ реализации цикла анимации в CImg

Я пытаюсь использовать CImg для визуализации своей программы. Я не хочу использовать OpenGL, потому что пытаюсь написать небольшой движок рендеринга (исключительно для собственного интереса, а не для задания!!!).

Я хочу создать цикл анимации в CImg.

Это моя петля.

while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {

    img.fill(0);                           // Set pixel values to 0 (color : black)
    img.draw_text(t%WIDTH,30,"Hello World",purple); // Draw a purple "Hello world" at coordinates (100,100).

    img.draw_text(10,10, ( "Time used for rendering :: " + std::to_string( 1.0 / ( duration.count()/cnt/1000000.0 ) ) ).c_str(), purple);

    disp.render(img);
    disp.paint();

    if (t % (int)cnt == 0) {
        tmp = std::chrono::high_resolution_clock::now();
        duration = std::chrono::duration_cast<std::chrono::microseconds>(tmp - start);
        start = std::chrono::high_resolution_clock::now();
    }
    t++;

}

Он работает нормально, но частота кадров очень нестабильна (от 100 до 380 кадров в секунду). Это нормально? Или это правильный способ создания цикла анимации в CImg?

Я прочитал документацию CImg и сказал

Не следует использовать для общего использования CImgDisplay, так как display() более полезен.

Но когда я так выразился,

while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {

    img.fill(0);                           // Set pixel values to 0 (color : black)
    img.draw_text(t%WIDTH,30,"Hello World",purple); // Draw a purple "Hello world" at coordinates (100,100).

    img.draw_text(10,10, ( "Time used for rendering :: " + std::to_string( 1.0 / ( duration.count()/cnt/1000000.0 ) ) ).c_str(), purple);

    disp.display(img);

    if (t % (int)cnt == 0) {
        tmp = std::chrono::high_resolution_clock::now();
        duration = std::chrono::duration_cast<std::chrono::microseconds>(tmp - start);
        start = std::chrono::high_resolution_clock::now();
    }
    t++;

}

Этот FPS падает до 11. Итак, что пошло не так?

Заранее спасибо.

~~~~~~~~~~~~~~~~~~~~~~ Я линия ~~~~~~~~~~~~~~~~~~~~~~~~

Редактировать 1:

    //
    //  main.cpp
    //  Render Engine
    //
    //  Created by Ip Daniel on 6/4/18.
    //  Copyright © 2018 Ip Daniel. All rights reserved.
    //

    #include "CImg.h"
    #include <chrono>
    #include <string>
    #include <iostream>

    using namespace cimg_library;

    #define WIDTH 640
    #define HEIGHT 480

    time_t start_time;
    time_t tmp;
    double time_passed = 0;

    int main() {

        CImg<unsigned char> img(WIDTH,HEIGHT,1,3);  // Define a 640x400 color image with 8 bits per color component.
        CImgDisplay disp(img,"My Hello World Loop");
        unsigned int t = 0;
        double cnt = 30;

        auto start = std::chrono::high_resolution_clock::now();
        auto tmp = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(tmp - start);

        unsigned char purple[] = { 255,0,255 };        // Define a purple color

        while (!disp.is_closed() && !disp.is_keyQ() && !disp.is_keyESC()) {

            img.fill(0);                           // Set pixel values to 0 (color : black)
            img.draw_text(t%WIDTH,30,"Hello World",purple); // Draw a purple "Hello world" at coordinates (100,100).

            img.draw_text(10,10, ( "Time used for rendering :: " + std::to_string( 1.0 / ( duration.count()/cnt/1000000.0 ) ) ).c_str(), purple);

    //      disp.display(img);

            disp.render(img);
            disp.paint();

            if (t % (int)cnt == 0) {
                tmp = std::chrono::high_resolution_clock::now();
                duration = std::chrono::duration_cast<std::chrono::microseconds>(tmp - start);
                start = std::chrono::high_resolution_clock::now();
            }


            t++;
        }

        return 0;
    }

Команда для компиляции

g++ -o main main.cpp -O2 -lm -lpthread -I/usr/X11R6/include -L/usr/X11R6/lib -lm -lpthread -lX11


person Jonathan Daniel IP    schedule 06.04.2018    source источник
comment
Ваша позиция x вашего текста увеличивается с каждым кадром, пока не достигнет края и не начнется заново. Возможно ли, что вы получаете самую высокую частоту кадров, когда текст находится у края и обрезается границей? Это позволило бы рендерингу изображения пропустить запись нескольких пикселей и ускориться.   -  person Erik    schedule 06.04.2018
comment
Думаю, нет, потому что я не использовал t для расчета частоты кадров.   -  person Jonathan Daniel IP    schedule 06.04.2018
comment
Пожалуйста, покажите свой полный код... stackoverflow.com/help/mcve, а также укажите свою ОС и способ ее компиляции. Это упрощает помощь.   -  person Mark Setchell    schedule 06.04.2018
comment
Отредактировано. пожалуйста, проверьте   -  person Jonathan Daniel IP    schedule 07.04.2018
comment
Мой ответ решил вашу проблему? Если это так, подумайте о том, чтобы принять его в качестве своего ответа, щелкнув пустую галочку рядом с подсчетом голосов. Если нет, скажите, что не сработало, чтобы я или кто-то еще мог вам помочь. Спасибо. meta.stackexchange. ком/вопросы/5234/   -  person Mark Setchell    schedule 17.04.2018


Ответы (1)


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

По сути, я не думаю, что разумно ожидать, что программа, взаимодействующая с сервером X11, в многопользовательской операционной системе будет настолько детерминированной, и, во-вторых, я также не уверен, что это имеет значение.

Я немного изменил ваш код, чтобы измерить время для 100 кадров, и на моей машине оно варьируется от 20 000 микросекунд до 150 000 микросекунд, при этом среднее значение довольно стабильно составляет около 80 000 микросекунд. Так что это в среднем 80 мс на 100 кадров или 0,8 мс на кадр, и диапазон 0,2-1,5 мс на кадр.

Для плавной анимации вам понадобится 25-30 кадров в секунду, что составляет 33-40 мс на кадр. Таким образом, ваше время рендеринга составляет около 0,8 мс каждые 30 мс, или около 2-3% времени вашего кадра, и только 5% в худшем случае (1,5 мс на 30-мс кадре).

Итак, я думаю, что ваш код, скорее всего, будет иметь кадр, в котором он нуждается, и сможет ждать/засыпать в среднем 24 мс, прежде чем потребуется его рендеринг, поэтому у вас будет много времени и вариация 0,8-1,5 мс в 30 мс. частота кадров не будет заметна.

person Mark Setchell    schedule 07.04.2018