我目前正在使用 SDL2 在 C++ 中进行一些工作,需要能够在每次更新时在屏幕上绘制大量具有特定颜色值的单独像素。我使用 SDL_RenderDrawPoint 只是为了确保我的程序正常工作,但我确信其性能很糟糕。从粗略搜索来看,使用 SDL_UpdateTexture 并使用具有我所需像素值(默认值为 {0,0,0,0} RGBA)的像素向量更新它,使用窗口大小的纹理似乎是最快的任何像素的值均未更改。
然而,我每次写它的尝试都失败了,我不确定我的误解在哪里。这是我当前的代码,尝试将特定的 RGBA 颜色值绘制到纹理中的特定 x,y 坐标。我假设我使用 x,y 值访问的缓冲区部分不正确,但我不确定如何使其正确。
感谢任何帮助,包括如何在没有纹理的情况下有效地完成此操作的建议(如果有更好的方法)。
SDL_Texture* windowTexture = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, screenWidth, screenHeight);
unsigned int* lockedPixels = nullptr;
std::vector<int> pixels(screenHeight*screenWidth*4, 0);
int pitch = 0;
int start = (y * screenWidth + x) * 4;
pixels[start + 0] = B;
pixels[start + 1] = G;
pixels[start + 2] = R;
pixels[start + 3] = A;
SDL_UpdateTexture(windowTexture, nullptr, pixels.data(), screenWidth * 4);
像素格式
RGBA8888
意味着每个像素都是 32 位元素,每个通道(即红色、绿色、蓝色或 alpha)按此顺序占用 8 位。
您可能想要将
pixels
声明为包含“32 位无符号整数”类型。 unsigned int
通常为 32 位,但也可能更大。
std::vector<Uint32> pixels(screenHeight*screenWidth, 0); // Note: no *4
各个 R、G、B、A 值(均应为 8 位无符号整数)可以通过使用移位和按位 OR 组合成一个像素:
int start = y * screenWidth + x; // Note: no *4
pixels[start] = (R << 24U) | (G << 16U) | (B << 8U) | A;
最后,您可能想要不硬编码
SDL_UpdateTexture
的最后一个参数(即音高)。相反,请使用 screenWidth * sizeof(Uint32)
。
上面的实现基本上是“RGBA8888”的直接实现,并允许您访问单个像素。 或者,您也可以声明一个包含 8 位无符号整数的四倍大小的数组。然后,前四个索引将对应于第一个像素的 R、G、B、A 值,接下来的四个索引将对应于第二个像素的 R、G、B、A 值,依此类推。 哪一个更快取决于确切的系统和用例(最常见的操作是在像素上还是在单个通道上)。
PS。除了
Uint32
,您还可以使用 std::uint32_t
标头中的 C++ 自己的 cstdlib
。
为方便起见,请使用 SDL_MapRGB 或 SDL_MapRGBA 为您计算任何格式的值。 `
SDL_PixelFormat* format = SDL_AllocFormat(SDL_GetWindowPixelFormat(window));
...
Uint32 color = SDL_MapRGBA(format, R, G, B, A);
...
SDL_FreeFormat(format);
`