SDL_CreateSurfaceFrom (SDL3) 读取我的数据有误吗?

Is SDL_CreateSurfaceFrom (SDL3) reading my data wrong?

提问人:Regis-1 提问时间:10/18/2023 最后编辑:genpfaultRegis-1 更新时间:10/18/2023 访问量:38

问:

我正在尝试从 Perlin 噪声创建 SDL 纹理。我创建了一个数组,并用噪声值乘以 255 填充了它。当我打印出值时,它们似乎没问题:uint8_t

127, 137, 134, 136, 127, 127, 127, 118, 120, 117, 137, 148, 144, 
146, 137, 137, 137, 128, 130, 127, 134, 144, 141, 143, 134, 134, 
134, 125, 127, 124, 136, 146, 143, 145, 136, 136, 136, 127, 129, 
126, 127, 137, 134, 136, 127, 127, 127, 118, 120, 117, 127, 137, 
134, 136, 127, 127, 127, 118, 120, 117, 127, 137, 134, 136, 127, 
127, 127, 118, 120, 117, 118, 128, 125, 127, 118, 118, 118, 109, 
111, 108, 120, 130, 127, 129, 120, 120, 120, 111, 113, 110, 117, 
127, 124, 126, 117, 117, 117, 108, 110, 106

(例如 10x10 Perlin 噪声)

之后,我调用具有有效宽度、高度、间距(我认为)和像素格式的 SDL,然后从该表面创建纹理并尝试渲染它。不幸的是,输出不是我想要的,主要是黑屏或白屏。CreateSurfaceFromSDL_PIXELFORMAT_INDEX8

我也尝试过这些像素格式,但只有最后一个给出了一些输出,但仍然不完全正确:

SDL_PIXELFORMAT_UNKNOWN
SDL_PIXELFORMAT_INDEX4LSB
SDL_PIXELFORMAT_INDEX4MSB
SDL_PIXELFORMAT_INDEX1LSB
SDL_PIXELFORMAT_INDEX1MSB

这是输出: SDL_PIXELFORMAT_INDEX1MSB输出

这里还有代码:

uint8_t sdlPixels[_perlinWidth*_perlinHeight];
for (int i = 0; i < _perlinWidth*_perlinHeight; i++) {
    sdlPixels[i] = static_cast<uint8_t>(_pixels[i]*255);
    std::cout << (int)sdlPixels[i] << ", ";
}

SDL_Surface* surface = Renderer::GetInstance()->CreateSurfaceFrom(
    sdlPixels, _perlinWidth, _perlinHeight, _perlinWidth, SDL_PIXELFORMAT_INDEX8);
_perlinTexture = Renderer::GetInstance()->CreateTextureFromSurface(surface);
delete [] _pixels; _pixels = nullptr; // clean the _pixel data

下面是 Renderer 函数(简单映射的 SDL 函数):

SDL_Surface* Renderer::CreateSurfaceFrom(void* pixels, int width, int height,
        int pitch, Uint32 format) {

    return SDL_CreateSurfaceFrom(pixels, width, height, pitch, format);
}

SDL_Texture* Renderer::CreateTextureFromSurface(SDL_Surface* surface) {
    SDL_Texture* out = SDL_CreateTextureFromSurface(_renderer, surface);
    SDL_DestroySurface(surface); // free surface (we already have a texture)
    return out;
}

像素数据在我作为参数给出的格式中是否无效,或者我在 SDL3 中从 SDL_Surface 创建纹理时是否遗漏了某些内容?

C++ 纹理 SDL 像素格式

评论


答:

1赞 Botje 10/18/2023 #1

您想要的像素格式是 。这意味着您的输入指向调色板中的 8 位索引数组。 为了从中创建纹理,调色板需要包含有意义的值。SDL_INDEX8sdlPixels

您可以使用以下方式执行此操作:SDL_SetPaletteColorsSDL_SetSurfacePalette

SDL_Palette* pal = SDL_CreatePalette(256 /* colors */);
std::vector<SDL_Color> colors(256);
for (int i = 0; i < 256; i++) {
  colors[i] = { i, i, i, 0xFF };
}
SDL_SetPaletteColors(pal, colors.data(), 0, 256);

SDL_Surface* surface = Renderer::GetInstance()->CreateSurfaceFrom(
    sdlPixels, _perlinWidth, _perlinHeight, _perlinWidth, SDL_PIXELFORMAT_INDEX8);
SDL_SetSurfacePalette(surface, pal); // <-- use the palette
_perlinTexture = Renderer::GetInstance()->CreateTextureFromSurface(surface);

尽管从阅读代码来看,这确实修改了像素格式的调色板......🤔

评论

0赞 Regis-1 10/18/2023
谢谢,这解决了我的问题。事实上,我还没有为这个表面创建或尝试过任何调色板。因此,如果我想为我的 Perlin 噪声贴图(带阈值)创建颜色,我需要为此创建另一个调色板并替换灰度调色板?
0赞 Botje 10/18/2023
这听起来很有道理,是的。不确定程序的其余部分是什么样子的,但一种常见的替代方法是让着色器在运行时通过查询给定输入颜色通道的 1x256 纹理来查找调色板。
0赞 Regis-1 10/18/2023
好的,明白了。我将阅读有关着色器和 SDL 调色板的更多信息(对我来说,这是第一次接触这些调色板)。再次感谢您的帮助。