在 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++;
}

它可以正常工作,但帧速率非常不稳定(范围从 100fps 到 380 fps)。这正常吗?或者,这是在 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

感谢您添加代码和环境。我一直在试验您的代码,但我不确定我是否真正了解问题所在 - 无论是渲染时间的变化还是其他原因。无论如何,评论有点多,所以我做了一个答案,人们也许可以讨论它。

基本上,我真的不认为期望在多用户操作系统上与 X11 服务器交互的程序具有确定性是合理的 - 其次,我也不确定这很重要。

我稍微更改了您的代码以测量 100 帧的时间,在我的机器上,它在 20,000 微秒和 150,000 微秒之间变化,平均值相当一致地在 80,000 微秒左右。因此,100帧的平均时间为80ms,或每帧0.8ms,范围为每帧0.2-1.5ms。

对于流畅的动画,您将需要 25-30 fps,即每帧 33-40 毫秒。因此,您的渲染时间约为每 30 毫秒发生一次 0.8 毫秒,约占帧时间的 2-3%,最坏情况仅为 5%(30 毫秒帧为 1.5 毫秒)。

因此,我认为您的代码更有可能拥有所需的帧,并且能够在需要渲染之前平均等待/休眠 24 毫秒,因此您将有足够的时间在手头,并且 0.8-1.5 毫秒的变化在 30 毫秒的帧速率中不会很明显。

最新更新