【问题标题】:Stb_image creates weird artifactsStb_image 创建奇怪的伪影
【发布时间】:2021-06-11 09:28:48
【问题描述】:

您好,我正在为我的 openGL 项目制作图像和纹理类,当我添加 stb_image 时,一些纹理开始在图像边缘添加噪点。

图像类:

    Image::Image() {
        width = 0;
        height = 0;
        channels = 0;
        data = NULL;
    }

    Image::Image(const Image& image) {
        width = image.width;
        height = image.height;
        channels = image.channels;

        int allocation = image.width * image.height * image.channels;
        data = new unsigned char[allocation];
        std::memcpy(data, image.data, allocation);
    }

    Image& Image::operator=(const Image& image) {
        if (this != &image && image.data != nullptr) {
            if(data != NULL)
                delete[] data;
            data = NULL;

            int allocation = image.width * image.height * image.channels;
            data = new unsigned char[allocation];
            std::memcpy(data, image.data, allocation);

            width = image.width;
            height = image.height;
            channels = image.channels;
            filepath = image.filepath;
        }

        return *this;
    }

    Image::Image(const std::string& _filepath) {
        width = 0;
        height = 0;
        channels = 0;
        data = NULL;
        filepath = _filepath;

        data = stbi_load(filepath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
        
        if (data == NULL) {
            Debug::systemErr("Couldn't load image: " + filepath);
        }
    }

    Image::~Image() {
        if (data != NULL) {
            delete[] data;
        }

        data = NULL;
    }

    bool Image::hasData() const{
        return (data != NULL);
    }

纹理类:

Texture::Texture() {
        textureID = 0;
    }

    Texture::Texture(const Texture& texture) {
        image = Image(texture.image);
        textureID = 0;
    }

    Texture::Texture(const std::string& path) {
        image = Image(path);
        textureID = 0;
    }

    Texture& Texture::operator=(const Texture& texture) {
        textureID = texture.textureID;
        image = texture.image;

        return *this;
    }

    Texture::~Texture() {
        destroy();
    }

    void Texture::destroy() {
        glDeleteTextures(1, &textureID);
    }

    void Texture::create() {
        if (!isCreated && image.hasData()) {

            glGenTextures(1, &textureID);
            glBindTexture(GL_TEXTURE_2D, textureID);

            //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.data);

            glGenerateMipmap(GL_TEXTURE_2D);

            isCreated = true;
        }
    }

图片为 128x128 像素

这是它在paint.net 中的样子:

这是渲染时的样子:

我相信图像加载很好,因为我用图像类设置了窗口的图标,看起来很好。我认为问题源于纹理类。

已解决 感谢 Jérôme Richard 为我解决了这个问题。这不起作用的原因是,即使我将 rgba 用于通道,图像仍然以 rgb 形式返回。然后当我尝试复制数据时,而不是做 4 * width * height 的大小。我会做 3 * 宽度 * 高度。所以在 stbi_load() 之后,我只放了 channels = 4。

【问题讨论】:

  • Image::Imagestbi_load之后的channels的值是多少?我猜这不是 3 吗?
  • 哦,拍你的权利,所以我应该忽略 stb_image 返回的内容并将 4 用于 rgba 对吗?
  • 我认为可以代替STBI_rgb_alpha。我还建议在检查通道数之后添加一个断言是您期望的;)。
  • 好的,非常感谢!
  • @JérômeRichard 您应该发布答案,以便将其选为已接受。

标签: c++ image parsing opengl textures


【解决方案1】:

您应该更仔细地阅读 stbi 文档。就在开头:

   int x,y,n;
   unsigned char *data = stbi_load(filename, &x, &y, &n, 0);

... 将 '0' 替换为 '1'..'4' 以强制每个像素有那么多组件
... 但 'n' 将始终是您说 0 时的数字

因此,如果您将 0 以外的任何内容作为最后一个参数传递,这就是您将获得的通道数。在这种情况下,您应该忽略n,并按照您请求的频道数量进行操作。另一方面,您的代码以另一种方式执行此操作:它请求四个通道,然后使用返回的n(在您的代码中称为channels)作为事实来源。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2018-06-20
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多