在 CImg 中实现动画循环的正确方法
The correct way to implement an animation loop in 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 毫秒的帧速率中不会很明显。
- 方法内部但循环仍得到预期的不合格id错误C++
- 在 c++ 中实现嵌套循环的更短方法吗?
- 如何在C++中循环访问未知对象方法?
- EnQueue 方法在循环队列中未正确返回C++?
- C++模板方法中的循环依赖关系
- 为什么这种方法会进入无限循环?
- 编写按初始值循环的循环的更好方法是什么
- 循环遍历标准的正确方法::array<char*, N>
- 类方法 - 数据结构中 For 循环的运行时错误
- 循环依赖,在继承类的情况下使用覆盖方法
- 从列表/向量制作嵌套 for 循环的最佳方法是什么?
- 从基于迭代器的for循环转换后,如何在map::find()中调用方法
- 是否可以在基于范围的 for 循环中使用模板化的开始/结束方法
- 还有其他方法可以为乘法表编写循环以获取运行时值吗?
- 如何避免模板方法的循环依赖
- 使用虚拟变量对 std::vector 内部循环进行切片的最佳方法
- 有什么方法可以在 c++ 中组织"cycling"(循环)数字?
- 我应该避免在循环中重复访问相同的方法吗?
- 遍历 STL 映射(集/多集)的最佳方法,同时元素可能会在循环期间被删除并重新插入?
- 在 C 中并行化嵌套循环的几种方法之间的差异,C++使用 OpenMP