在 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的文档,里面说
Should not be used for common CImgDisplay uses, since display() is more useful.
但是当我这样说的时候,
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
感谢您添加代码和环境。我一直在试验您的代码,但我不确定我是否真的理解问题所在 - 无论是渲染时间的变化还是其他原因。总之,评论有点多所以我做了一个回答,大家可以再讨论一下。
基本上,我真的认为在 multi-user 操作系统上期望与 X11 服务器交互的程序具有确定性是不合理的 - 其次,我也不是当然重要。
我稍微更改了您的代码以测量 100 帧的时间,在我的机器上它在 20,000 微秒和 150,000 微秒之间变化,平均值相当一致地在 80,000 微秒左右。所以这是 100 帧的平均 80 毫秒,或每帧 0.8 毫秒,每帧 0.2-1.5 毫秒的范围。
对于流畅的动画,您需要 25-30 fps,即每帧 33-40 毫秒。所以你的渲染时间大约是每 30 毫秒发生一次 0.8 毫秒,或者你的帧时间的 2-3%,最坏的情况只有 5%(30 毫秒帧上 1.5 毫秒)。
所以,我认为您的代码更有可能拥有所需的帧,并且能够在需要渲染之前平均 wait/sleep 24 毫秒,因此您将有充足的时间和 0.8 -1.5 毫秒的变化在 30 毫秒的帧速率中不会引起注意。
我正在尝试使用 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的文档,里面说
Should not be used for common CImgDisplay uses, since display() is more useful.
但是当我这样说的时候,
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
感谢您添加代码和环境。我一直在试验您的代码,但我不确定我是否真的理解问题所在 - 无论是渲染时间的变化还是其他原因。总之,评论有点多所以我做了一个回答,大家可以再讨论一下。
基本上,我真的认为在 multi-user 操作系统上期望与 X11 服务器交互的程序具有确定性是不合理的 - 其次,我也不是当然重要。
我稍微更改了您的代码以测量 100 帧的时间,在我的机器上它在 20,000 微秒和 150,000 微秒之间变化,平均值相当一致地在 80,000 微秒左右。所以这是 100 帧的平均 80 毫秒,或每帧 0.8 毫秒,每帧 0.2-1.5 毫秒的范围。
对于流畅的动画,您需要 25-30 fps,即每帧 33-40 毫秒。所以你的渲染时间大约是每 30 毫秒发生一次 0.8 毫秒,或者你的帧时间的 2-3%,最坏的情况只有 5%(30 毫秒帧上 1.5 毫秒)。
所以,我认为您的代码更有可能拥有所需的帧,并且能够在需要渲染之前平均 wait/sleep 24 毫秒,因此您将有充足的时间和 0.8 -1.5 毫秒的变化在 30 毫秒的帧速率中不会引起注意。