我的问题是,在使用库 STB 图像加载任何类型的图像时,我收到下一个错误:BAD PNG SIG,即使它甚至不是 PNG,在我尝试创建 OBJECT 类之前,所有代码都有效我正在学习 OpenGL,现在我得到的结果是下一个:
首先,我没有发现任何明显的错误,除了我应该看到两个纹理而不仅仅是板条箱的事实之外,
如果我运行程序但使用不同的纹理,发生的另一件事是我得到一个 debugBreak:
纹理生成/加载不同部分的代码如下:
纹理创建/添加:
TEXTURE tex1("res/textures/container.jpg", FILTER_LINEAR, GL_RGB, GL_TEXTURE_2D);
TEXTURE tex2("res/textures/dog.jpg", FILTER_NEAREST, GL_RGBA, GL_TEXTURE_2D);
box1.AddTextures(tex1);
box1.AddTextures(tex2);
这是纹理类:
class TEXTURE{
private:
unsigned int m_TextureID;
std::string m_filepath;
int m_width, m_height, m_BPP;
unsigned int m_TextureType;
public:
TEXTURE(std::string filepath, FILTERING_OPTIONS opt, unsigned int RGB_CHANNEL, unsigned int TEXTURE_TYPE, bool FLIP_IMAGE = 0, bool MIPMAP = 1);
~TEXTURE();
void Bind(unsigned int slot = 0);
void Unbind();
inline int GetWidth() const { return m_width; }
inline int GetHeight() const { return m_height; }
};
它的构造函数是下一个:
TEXTURE::TEXTURE(std::string filepath, FILTERING_OPTIONS opt, unsigned int RGB_CHANNEL, unsigned int TEXTURE_TYPE, bool FLIP_IMAGE, bool MIPMAP) : m_filepath(filepath), m_TextureType(TEXTURE_TYPE){
//stbi_set_flip_vertically_on_load(FLIP_IMAGE);
stbi_set_flip_vertically_on_load(1);
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT));
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glCall(glTexParameterfv(TEXTURE_TYPE, GL_TEXTURE_BORDER_COLOR, borderColor));
if (MIPMAP) {
switch (opt)
{
case FILTER_NEAREST:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
break;
case FILTER_LINEAR:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
break;
case BOTH:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
break;
default:
std::cerr << "[Error]: Wrong option parameter" << std::endl;
return;
break;
}
}
else {
switch (opt)
{
case FILTER_NEAREST:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
break;
case FILTER_LINEAR:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
break;
case BOTH:
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
glCall(glTexParameteri(TEXTURE_TYPE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
break;
default:
std::cerr << "[Error]: Wrong option parameter" << std::endl;
return;
break;
}
}
unsigned char* data = stbi_load(filepath.c_str(), &m_width, &m_height, &m_BPP, 0);
glCall(glGenTextures(1, &m_TextureID));
glCall(glBindTexture(m_TextureType, m_TextureID));
std::cerr << stbi_failure_reason() << std::endl;
if (data)
{
glCall(glTexImage2D(TEXTURE_TYPE, 0, GL_RGB, m_width, m_height, 0, RGB_CHANNEL, GL_UNSIGNED_BYTE, data));
glCall(if (MIPMAP) glGenerateMipmap(TEXTURE_TYPE));
}
else
{
std::cout << "Failed to load texture" << std::endl;
};
stbi_image_free(data);
}
并且加载是由 OBJECT 类进行的:
这会将纹理添加到向量中:
void OBJECT::AddTextures(TEXTURE texture){
textures.push_back(texture);
}
这会加载对象(和纹理):
void OBJECT::Show(bool INDEXED, callbackFunction preRenderFunction){
vb.Bind();
va.Bind();
shader.Bind();
shader.Use();
for (unsigned int i = 0; i < textures.size(); i++) {
textures[i].Bind(i);
}
preRenderFunction(this);
if (INDEXED) {
ib.Bind();
glCall(glDrawElements(GL_TRIANGLES, ib.GetLength() , GL_UNSIGNED_INT, 0));
}else glDrawArrays(GL_TRIANGLES, 0, vb.GetLength());
}
我认为相关的所有代码也是,这里是我的项目的文件树(顺便说一句,我正在使用 Visual Studio):
C:.
├───res
│ ├───shaders
│ └───textures
├───src
│ ├───include
│ └───vendor
│ ├───glm
│ │ ├───detail
│ │ ├───ext
│ │ ├───gtc
│ │ ├───gtx
│ │ └───simd
│ ├───imgui
│ └───stb_image
└───x64
├───Debug
│ └───OpenGL-PLSDFMTT.tlog
└───Release
└───OpenGL-PLSDFMTT.tlog
我尝试使用VS的调试器来观察发生了什么,在它没有崩溃的情况下,指向图像数据的数据指针为空(数据为空),当它有数据时,它崩溃了,我尝试查看我的逻辑,但这一切似乎都没问题,这就是我所尝试的(所有这一切都在 4 小时内完成)。
在将
stbi_image
头文件包含到 one C 或 C++ 源文件中以创建实现之前,请执行
#define STB_IMAGE_IMPLEMENTATION
或者添加
#define STBI_FAILURE_USERMSG //generate user friendly error messages
之后
#include "stb_image.h"
一旦包含了
stbi_image
实现,要加载图像,请执行
unsigned char *pixels = stbi_load(filename, &width, &height, &channels, 0);
但在做其他事情之前,应该进行强制错误检查
if (!pixels) {
std::cout
<< "unable to load image: "
<< stbi_failure_reason()
<< "\n";
//throw;
}
从现在开始,我们可以放心地假设图像已加载,并且
pixels
、width
、height
和 channels
字段中的值可以安全使用。
额外检查,例如如果尺寸是 2 的幂(对于对齐很重要)、通道数等等,肯定不会造成伤害。