我正在用C和X11制作游戏。我已经尝试了很长一段时间才找到一种方法,在一个窗口上逐帧放置不同颜色的像素。我已经看到完全开发的游戏每秒可以获得数千帧。这样做最有效的方法是什么?
我看过XImages的2色位图,在黑白色的淡入淡出时分配了256种颜色,并使用带有XImages的XPutPixel(我无法想象如何正确创建XImage,以后可能会放置像素在它上面。)
我已经创建了一个用于创建随机图像的循环,但它显然是逐个像素而不是逐帧,并且需要18秒来渲染整个帧。
XColor pixel;
for (int x = 0; x < currentWindowWidth; x++) {
for (int y = 0; y < currentWindowHeight; y++) {
pixel.red = rand() % 256 * 256; //Converting 16-bit colour to 8-bit colour
pixel.green = rand() % 256 * 256;
pixel.blue = rand() % 256 * 256;
XAllocColor(display, XDefaultColormap(display, screenNumber), &pixel); //This probably takes the most time,
XSetForeground(display, graphics, pixel.pixel); //as does this.
XDrawPoint(display, window, graphics, x, y);
}
}
答案 0 :(得分:1)
每秒数千帧是不可能的。监视器频率约为100 Hz,或每秒100个周期,大致是最大帧速率。这仍然非常快。人眼不会提高帧速率。
显示器响应时间约为5毫秒,因此屏幕上的任何一个点都不能每秒刷新超过200次。
8位是1字节,因此8位图像每像素使用一个字节,每个像素从0到256.像素没有红色,蓝色,绿色分量。而是每个像素指向颜色表中的索引。颜色表可容纳256种颜色。有一个技巧可以保持像素相同并改变颜色表,这会使图像淡入淡出或做其他奇怪的事情。
在24位图像中,每个像素都有蓝色,红色和绿色分量。每种颜色为1个字节,因此每个像素为3个字节或24位。
uint8_t red = rand() % 256;
uint8_t grn = rand() % 256;
uint8_t blu = rand() % 256;
16位图像使用奇数格式存储红色,蓝色,绿色。 16不能被3整除,通常2种颜色被分配5位,第3种颜色被6位。然后你必须在一个uint16_t
大小的像素上拟合这些颜色。探索这个可能不值得。
例程的缓慢是因为您一次绘制一个像素。您应该绘制到缓冲区,然后每帧渲染一次缓冲区。您可以考虑使用其他框架工作,如SDL。其他游戏可能会使用像OpenGL这样的东西,它利用GPU优化进行矩阵操作等。
答案 1 :(得分:0)
您必须使用GPS。 GPU具有针对图形优化的高度并行架构(因此得名)。要访问GPUS,您将使用api luke OpenGL或Vulcan或使用游戏引擎。
答案 2 :(得分:0)
经过三个星期左右的测试后,我终于想出了如何做到这一点,而且相当简单。正如我在OP中所说,XAllocColor和XSetForground需要相当多的时间(相对)才能工作。 XDrawPoint也很慢,因为它不仅仅是将像素放在图像上的某个点上。
首先我测试了Xlib的颜色格式是如何工作的(对于无符号的long int表示为pixel.pixel,这是我需要的XAllocColor),它似乎有100%的红色设置为16711680,100%绿色设置为65280,100%蓝色设置为255,这显然是一种模式。我发现最大值是所有颜色的50%,4286019447,这是一个坚实的灰色。
接下来,我确保我的系统支持我的XVisualInfo,并使用XMatchVisualInfo([预期的视觉信息值])进行测试。这确保了我将使用的深度和TrueColor类的工作原理。
最后,我从根窗口的图像中复制了一个XImage进行操作。我对窗口上的每个像素使用XPutPixel并将其设置为0到4286019448之间的随机值,从而创建随机图像。然后我使用XPutImage将图像粘贴到窗口。
这是最终的代码:
if (!XMatchVisualInfo(display, screenNumber, 24, TrueColor, &visualInfo)) {
exit(0);
}
frameImage = XGetImage(display, rootWindow, 0, 0, screenWidth, screenHeight, AllPlanes, ZPixmap);
while (1) {
for (unsigned short x = 0; x < currentWindowWidth; x += pixelSize) {
for (unsigned short y = 0; y < currentWindowHeight; y += pixelSize) {
XPutPixel(frameImage, x, y, rand() % 4286019447);
}
}
XPutImage(display, window, graphics, frameImage, 0, 0, 0, 0, currentWindowWidth, currentWindowHeight);
}
这会在屏幕上放置一个随机图像,在全屏上以每秒140帧的速度稳定显示。我不一定知道这是否是最有效的方式,但它比我尝试过的任何其他方法都要好。如果有任何方法可以让它变得更好,请告诉我。