我把我的测试申请寄给了几个人。第一个测试器的结果与我的相同,但其他两个测试人员有一些奇怪的东西。由于某些原因,图像,这应该是原来的大小在左下角,他们认为是伸展到全屏幕。此外,他们看不到GUI元素(但是,如果鼠标找到按钮,按钮就能工作)。我会预订,这不是拉伸的图像重叠的按钮,我发送他们的版本与透明的图像和按钮仍然没有绘制。对于GUI绘图,我使用Nuklear。我会给屏幕截图和代码,负责定位问题的形象。是什么导致了这一切?
int width, height;
{
fs::path const path = fs::current_path() / "gamedata" / "images" / "logo.png";
unsigned char *const texture = stbi_load(path.u8string().c_str(), &width, &height, nullptr, STBI_rgb_alpha);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
stbi_image_free(texture);
}
...
{
float const x = -1.0f + width * 2.0f / xResolution;
float const y = -1.0f + height * 2.0f / yResolution;
float const vertices[30] = {
/* Position */ /* UV */
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, y, 0.0f, 0.0f, 1.0f,
x, y, 0.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
x, -1.0f, 0.0f, 1.0f, 0.0f,
x, y, 0.0f, 1.0f, 1.0f
};
glBufferData(GL_ARRAY_BUFFER, 30 * sizeof(float), vertices, GL_STATIC_DRAW);
}更新
通过反复尝试,我意识到问题是由负责渲染背景和徽标的类引起的,它们都是错误的。单独的,他们的工作,它应该,但一旦其他东西被添加到游戏循环,一切都崩溃了。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
background.render();
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
logo.render();
nk_glfw3_render();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);这些课是我自己写的,所以很可能我漏掉了什么。发现一个错误,另一个错误,因为它们几乎是一样的。到目前为止,我还不能确定,这些类中到底有什么是错误的,…
[ Background.hpp / Background.cpp ]
发布于 2018-07-02 23:06:09
我在发布的代码中发现了一些错误。以戏剧性的方式,我将在最后揭露罪魁祸首。
空,用作整数。
例如,
glBindTexture(GL_TEXTURE_2D, NULL); // IncorrectglBindTexture函数接受整数参数,而不是指针。以下是正确的版本:
glBindTexture(GL_TEXTURE_2D, 0); // Correct这也适用于glBindBuffer和glBindVertexArray。
髓构造函数定义为显式
explicit关键字只影响一元构造函数(接受一个参数的构造函数)。它不影响具有任何其他参数的构造函数。
explicit Background() noexcept; // "explicit" does not do anything.
Background() noexcept; // Exact same declaration as above.构造函数被错误地定义为as以外。
noexcept关键字的意思是“此函数永远不会抛出异常”。但是,它包含以下代码,这些代码可以抛出:
new Shader("image")根据标准,这可以抛出一个std::bad_alloc。因此,noexcept注释是不正确的。请参阅操作员在现实生活中会抛出异常吗?
在更实际的注意事项上,构造函数从磁盘读取图像。这可能会失败,抛出异常是处理此问题的一种合理方法。
noexcept关键字在这里并不特别有用。也许编译器可以在调用站点生成更少的代码,但这可能会产生无穷小的差别,因为构造函数是冷代码( code = not )。noexcept限定符对于选择不同的泛型算法非常有用,请参阅除了有用之外,什么是有用的?
无错误处理
请记住,如果发生错误,stdbi_load将返回NULL。这个案子没有处理。
违反了三条规则
尽管Background类定义了析构函数,但它并不定义复制构造函数或复制赋值运算符。虽然这并不能保证你的程序不正确,但这有点像在厨房柜台上留下一把上了膛的、带着子弹的枪,希望没有人碰它。这被称为三条规则,修复起来很简单。添加已删除的复制构造函数和复制赋值操作符。
// These three go together, either define all of them or none.
// Hence, "rule of three".
Background(const Background &) = delete;
Background &operator=(const Background &) = delete;
~Background();请参阅三的规则是什么?
缓冲区被错误删除。
这是台词:
glDeleteBuffers(1, &VBO);简短的版本..。您应该将它移到Background::~Background()中。
长篇版本..。删除缓冲区时,不会从VAO中删除该缓冲区,但是可以立即重用该名称。根据OpenGL 4.6规范 5.1.2:
当缓冲区、纹理或呈现缓冲区对象被删除时,与绑定到当前上下文的容器对象的任何附件分离,.
因此,因为VAO目前没有绑定,所以删除VBO不会从VAO中删除VBO (如果VAO是绑定的,这将是不同的)。但是,第5.1.3节:
当缓冲区、纹理、采样器、渲染缓冲区、查询或同步对象被删除时,其名称立即无效(例如标记为未使用),但基础对象在不再使用之前不会被删除。
因此VBO将保持不变,但名称可能会被重用。这意味着稍后对glGenBuffers的调用可能会给您提供相同的名称。然后,当您调用glBufferData时,它会覆盖您的背景和徽标中的数据。或者,glGenBuffers可能为您提供一个完全不同的缓冲区名称。这是完全依赖于实现的,这解释了为什么在不同的计算机上看到不同的行为。
通常,在使用完缓冲区之前,我将避免调用glDeleteBuffers。您可以在技术上更早地调用glDeleteBuffers,但这意味着您可以从glGenBuffers获得相同的缓冲区。
https://stackoverflow.com/questions/51138945
复制相似问题