首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL应用程序在不同计算机上的工作方式不同

OpenGL应用程序在不同计算机上的工作方式不同
EN

Stack Overflow用户
提问于 2018-07-02 14:56:40
回答 1查看 402关注 0票数 1

我把我的测试申请寄给了几个人。第一个测试器的结果与我的相同,但其他两个测试人员有一些奇怪的东西。由于某些原因,图像,这应该是原来的大小在左下角,他们认为是伸展到全屏幕。此外,他们看不到GUI元素(但是,如果鼠标找到按钮,按钮就能工作)。我会预订,这不是拉伸的图像重叠的按钮,我发送他们的版本与透明的图像和按钮仍然没有绘制。对于GUI绘图,我使用Nuklear。我会给屏幕截图和代码,负责定位问题的形象。是什么导致了这一切?

[ 良好行为 / 不良行为 ]

代码语言:javascript
复制
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);
}

更新

通过反复尝试,我意识到问题是由负责渲染背景和徽标的类引起的,它们都是错误的。单独的,他们的工作,它应该,但一旦其他东西被添加到游戏循环,一切都崩溃了。

代码语言:javascript
复制
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 ]

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-02 23:06:09

我在发布的代码中发现了一些错误。以戏剧性的方式,我将在最后揭露罪魁祸首。

空,用作整数。

例如,

代码语言:javascript
复制
glBindTexture(GL_TEXTURE_2D, NULL); // Incorrect

glBindTexture函数接受整数参数,而不是指针。以下是正确的版本:

代码语言:javascript
复制
glBindTexture(GL_TEXTURE_2D, 0); // Correct

这也适用于glBindBufferglBindVertexArray

髓构造函数定义为显式

explicit关键字只影响一元构造函数(接受一个参数的构造函数)。它不影响具有任何其他参数的构造函数。

代码语言:javascript
复制
explicit Background() noexcept; // "explicit" does not do anything.

Background() noexcept; // Exact same declaration as above.

构造函数被错误地定义为as以外。

noexcept关键字的意思是“此函数永远不会抛出异常”。但是,它包含以下代码,这些代码可以抛出:

代码语言:javascript
复制
new Shader("image")

根据标准,这可以抛出一个std::bad_alloc。因此,noexcept注释是不正确的。请参阅操作员在现实生活中会抛出异常吗?

在更实际的注意事项上,构造函数从磁盘读取图像。这可能会失败,抛出异常是处理此问题的一种合理方法。

noexcept关键字在这里并不特别有用。也许编译器可以在调用站点生成更少的代码,但这可能会产生无穷小的差别,因为构造函数是冷代码( code = not )。noexcept限定符对于选择不同的泛型算法非常有用,请参阅除了有用之外,什么是有用的?

无错误处理

请记住,如果发生错误,stdbi_load将返回NULL。这个案子没有处理。

违反了三条规则

尽管Background类定义了析构函数,但它并不定义复制构造函数或复制赋值运算符。虽然这并不能保证你的程序不正确,但这有点像在厨房柜台上留下一把上了膛的、带着子弹的枪,希望没有人碰它。这被称为三条规则,修复起来很简单。添加已删除的复制构造函数和复制赋值操作符。

代码语言:javascript
复制
// 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();

请参阅三的规则是什么?

缓冲区被错误删除。

这是台词:

代码语言:javascript
复制
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获得相同的缓冲区。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51138945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档