一个像素一个像素的 3d 图形程序表现怪异 [通过拖动 window 来加快绘图速度]
Weirdly behaving pixel by pixel 3d graphing program [Faster drawing by dragging the window]
所以我使用 Allegro 4 库在 C++ 中编写了一个简单的 3d 绘图程序。我用最简单的方法,逐像素绘制。通常,由于 Allegro 的工作方式,在屏幕上放置单个像素非常慢,要绘制分辨率为 640x480 的图形,我必须等待一两分钟。
所以我正在为我的伙伴渲染图像,所以我拖动 windows 来获得一个好的屏幕截图,我发现通过拖动 window 和渲染图片,它只要我按住 window,速度就会大大加快。从 2 分钟开始,它在 10 秒内绘制了所有内容。
造成这种奇怪行为的原因是什么?是跟Windows' windows有关还是Allegro本身造成的?有什么解释吗?
还有我的代码
#include <allegro.h>
#include <iostream>
#include <math.h>
using namespace std;
float MAX_Z = 1;
float MIN_Z =-1;
float SCALE =50;
inline void init(unsigned int width, unsigned int height)
{
allegro_init();
set_color_depth(24);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, width, height, 0, 0);
install_timer();
install_keyboard();
install_mouse();
}
inline void deinit()
{
clear_keybuf();
allegro_exit();
}
int get_z_color (float z)
{
if (z >= 0)
{
return makecol(255, (z/MAX_Z)*255, (z/MAX_Z)*255);
}
else
{
return makecol(255 - (z/MIN_Z)*255,0, 0);
}
}
float get_z (float x, float y)
{
return sin(sqrt(pow(x,2)+pow(y,2)));
}
float int_to_float (int a)
{
return a;
}
int main()
{
unsigned int res_width, res_height;
cout << "Window size (W,H): ";
cin >> res_width >> res_height;
cout << endl << "Initiating in " << res_width << "x" << res_height << " resolution..." << endl;
init(res_width,res_height);
cout << "Success! Drawing graph..." << endl;
for (int y=0; y<res_height; y++)
{
for (int x=0; x<res_width; x++)
{
float valued_x = (int_to_float(x)-(int_to_float(res_width)/2))/SCALE;
float valued_y = (int_to_float(-y)+(int_to_float(res_height)/2))/SCALE;
_putpixel24(screen,x,y,get_z_color(get_z(valued_x,valued_y)));
//cout << "Drawing (" << valued_x << "," << valued_y << ")" << endl;
}
}
cout << "Graph drawn." << endl;
cin >> new char;
cout << "Closing...";
deinit();
return 0;
}
END_OF_MAIN()
无论您使用什么库,在屏幕表面上绘图总是一项成本高昂的操作。
我从未使用过 Allegro(我使用的是 SDL),但我猜 windows 会在每次放置一个像素时重新绘制屏幕表面,并通过拖动 windows 周围,你阻止了重绘的实际发生。
如果您希望您的程序性能得到显着提升,您应该始终绘制到一个 off-screen 表面,并在绘制结束后将整个表面 blit 到屏幕表面(这是一个基本的双缓冲技术)。
正如我所说,我从未使用过 Allegro,但据我所知,你可以做类似的事情:
int main()
{
unsigned int res_width, res_height;
cout << "Window size (W,H): ";
cin >> res_width >> res_height;
cout << endl << "Initiating in " << res_width << "x" << res_height << " resolution..." << endl;
init(res_width,res_height);
BITMAP *temporaryBitmap = create_bitmap(res_width, res_height);
cout << "Success! Drawing graph..." << endl;
for (int y=0; y<res_height; y++)
{
for (int x=0; x<res_width; x++)
{
float valued_x = (int_to_float(x)-(int_to_float(res_width)/2))/SCALE;
float valued_y = (int_to_float(-y)+(int_to_float(res_height)/2))/SCALE;
_putpixel24(temporaryBitmap,x,y,get_z_color(get_z(valued_x,valued_y)));
//cout << "Drawing (" << valued_x << "," << valued_y << ")" << endl;
}
}
blit(temporaryBitmap, screen, 0, 0, 0, 0, temporaryBitmap->w, temporaryBitmap->h);
cout << "Graph drawn." << endl;
cin >> new char;
cout << "Closing...";
destroy_bitmap(temporaryBitmap);
deinit();
return 0;
}
所以我使用 Allegro 4 库在 C++ 中编写了一个简单的 3d 绘图程序。我用最简单的方法,逐像素绘制。通常,由于 Allegro 的工作方式,在屏幕上放置单个像素非常慢,要绘制分辨率为 640x480 的图形,我必须等待一两分钟。
所以我正在为我的伙伴渲染图像,所以我拖动 windows 来获得一个好的屏幕截图,我发现通过拖动 window 和渲染图片,它只要我按住 window,速度就会大大加快。从 2 分钟开始,它在 10 秒内绘制了所有内容。
造成这种奇怪行为的原因是什么?是跟Windows' windows有关还是Allegro本身造成的?有什么解释吗?
还有我的代码
#include <allegro.h>
#include <iostream>
#include <math.h>
using namespace std;
float MAX_Z = 1;
float MIN_Z =-1;
float SCALE =50;
inline void init(unsigned int width, unsigned int height)
{
allegro_init();
set_color_depth(24);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, width, height, 0, 0);
install_timer();
install_keyboard();
install_mouse();
}
inline void deinit()
{
clear_keybuf();
allegro_exit();
}
int get_z_color (float z)
{
if (z >= 0)
{
return makecol(255, (z/MAX_Z)*255, (z/MAX_Z)*255);
}
else
{
return makecol(255 - (z/MIN_Z)*255,0, 0);
}
}
float get_z (float x, float y)
{
return sin(sqrt(pow(x,2)+pow(y,2)));
}
float int_to_float (int a)
{
return a;
}
int main()
{
unsigned int res_width, res_height;
cout << "Window size (W,H): ";
cin >> res_width >> res_height;
cout << endl << "Initiating in " << res_width << "x" << res_height << " resolution..." << endl;
init(res_width,res_height);
cout << "Success! Drawing graph..." << endl;
for (int y=0; y<res_height; y++)
{
for (int x=0; x<res_width; x++)
{
float valued_x = (int_to_float(x)-(int_to_float(res_width)/2))/SCALE;
float valued_y = (int_to_float(-y)+(int_to_float(res_height)/2))/SCALE;
_putpixel24(screen,x,y,get_z_color(get_z(valued_x,valued_y)));
//cout << "Drawing (" << valued_x << "," << valued_y << ")" << endl;
}
}
cout << "Graph drawn." << endl;
cin >> new char;
cout << "Closing...";
deinit();
return 0;
}
END_OF_MAIN()
无论您使用什么库,在屏幕表面上绘图总是一项成本高昂的操作。
我从未使用过 Allegro(我使用的是 SDL),但我猜 windows 会在每次放置一个像素时重新绘制屏幕表面,并通过拖动 windows 周围,你阻止了重绘的实际发生。
如果您希望您的程序性能得到显着提升,您应该始终绘制到一个 off-screen 表面,并在绘制结束后将整个表面 blit 到屏幕表面(这是一个基本的双缓冲技术)。
正如我所说,我从未使用过 Allegro,但据我所知,你可以做类似的事情:
int main()
{
unsigned int res_width, res_height;
cout << "Window size (W,H): ";
cin >> res_width >> res_height;
cout << endl << "Initiating in " << res_width << "x" << res_height << " resolution..." << endl;
init(res_width,res_height);
BITMAP *temporaryBitmap = create_bitmap(res_width, res_height);
cout << "Success! Drawing graph..." << endl;
for (int y=0; y<res_height; y++)
{
for (int x=0; x<res_width; x++)
{
float valued_x = (int_to_float(x)-(int_to_float(res_width)/2))/SCALE;
float valued_y = (int_to_float(-y)+(int_to_float(res_height)/2))/SCALE;
_putpixel24(temporaryBitmap,x,y,get_z_color(get_z(valued_x,valued_y)));
//cout << "Drawing (" << valued_x << "," << valued_y << ")" << endl;
}
}
blit(temporaryBitmap, screen, 0, 0, 0, 0, temporaryBitmap->w, temporaryBitmap->h);
cout << "Graph drawn." << endl;
cin >> new char;
cout << "Closing...";
destroy_bitmap(temporaryBitmap);
deinit();
return 0;
}