Stb_image 创建奇怪的工件
Stb_image creates weird artifacts
您好,我正在为我的 openGL 项目制作图像和纹理 class,当我添加 stb_image 时,一些纹理开始在图像边缘添加噪点。
图片class:
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);
}
纹理class:
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 中的样子:
这是渲染后的样子:
我相信图像加载没问题,因为我用图像 class 设置了 window 的图标,看起来不错。我认为问题出在纹理 class.
已解决
感谢 Jérôme Richard 为我解决了这个问题。这不起作用的原因是即使我将 rgba 设置为通道,图像仍然以 rgb 返回。然后当我尝试复制数据时,而不是为大小做 4 * width * height 。我会做 3 * 宽度 * 高度。所以在 stbi_load() 之后,我只是把 channels = 4.
您应该更仔细地阅读 stbi 文档。它就在开头:
int x,y,n;
unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
... replace '0' with '1'..'4' to force that many components per pixel
... but 'n' will always be the number that it would have been if you said 0
因此,如果您将 0
以外的任何内容作为最后一个参数传递,那就是您将获得的频道数。在这种情况下,您应该忽略 n
并按照您请求的频道数进行操作。另一方面,您的代码以另一种方式执行:它请求四个通道,然后使用返回的 n
(在您的代码中称为 channels
)作为真实来源。
您好,我正在为我的 openGL 项目制作图像和纹理 class,当我添加 stb_image 时,一些纹理开始在图像边缘添加噪点。
图片class:
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);
}
纹理class:
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 中的样子:
这是渲染后的样子:
我相信图像加载没问题,因为我用图像 class 设置了 window 的图标,看起来不错。我认为问题出在纹理 class.
已解决 感谢 Jérôme Richard 为我解决了这个问题。这不起作用的原因是即使我将 rgba 设置为通道,图像仍然以 rgb 返回。然后当我尝试复制数据时,而不是为大小做 4 * width * height 。我会做 3 * 宽度 * 高度。所以在 stbi_load() 之后,我只是把 channels = 4.
您应该更仔细地阅读 stbi 文档。它就在开头:
int x,y,n; unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
... replace '0' with '1'..'4' to force that many components per pixel
... but 'n' will always be the number that it would have been if you said 0
因此,如果您将 0
以外的任何内容作为最后一个参数传递,那就是您将获得的频道数。在这种情况下,您应该忽略 n
并按照您请求的频道数进行操作。另一方面,您的代码以另一种方式执行:它请求四个通道,然后使用返回的 n
(在您的代码中称为 channels
)作为真实来源。