1

这是一个非常模糊的问题,因此请随时澄清有关此项目的任何内容。

我正在开发一个非常大的应用程序,最近出现了一个关于纹理的非常令人困惑的错误。我们正在加载的一些纹理正在被加载——我已经逐步完成了代码,它运行了——但是这些纹理的所有 OpenGL 渲染都是一个奇怪的粉红色/白色条纹纹理。

你有什么建议甚至开始调试这种情况?

  • 该项目是多线程的,但互斥锁确保所有 OpenGL 调用都不会被其他任何东西打断。
  • 有些纹理正在加载,有些则没有。它们都以完全相同的方式加载。
  • 我确保所有纹理都存在
  • “粉色/白色”纹理肯定会加载到内存中——在我将任何其他纹理加载到 OpenGL 后不久,它们就会变得可见。

我很困惑,不知道还有什么问题。是否有可以在 glTexImage 之后调用的 OpenGL 命令来强制纹理变得可用?

编辑:这与命令失败无关,主要是时间问题。粉红色/白色纹理会显示一段时间,直到加载更多纹理。就好像纹理在排队,而队列只是在某个时间暂停。

下一个编辑:我让 glIntercept 日志正常工作,这就是它输出的内容(在整个程序崩溃之前)

http://freetexthost.com/1kdkksabdg

下一个编辑:我知道纹理加载在 OpenGL 内存中,但由于某种原因,它们没有在程序本身中渲染。

4

7 回答 7

3

如果您的纹理颜色不正确,很可能是您加载了错误的 RGB 顺序。确保在 glTexImage2D 中为图像格式使用正确的枚举。确保组件的数量是正确的,并且您在格式参数中获得了正确的 RGB 像素顺序。

虽然可能与您的纹理显示错误无关,但 OpenGL 不支持多线程绘制,因此请确保您没有在与拥有上下文的线程不同的线程上进行任何绘制工作。

编辑:您是否有参考渲染器,以便您可以验证图像像素是否按预期加载?我强烈建议编写一个小程序来加载,然后立即将像素保存到文件中,这样您就可以确保获得正确的纹理结果。

于 2009-12-16T17:42:17.483 回答
1

当你说:

该项目是多线程的,但互斥锁确保所有 OpenGL 调用都不会被其他任何东西打断。

这对我来说听起来不够强大:请记住,OpenGL 是一个具有大量内部状态的状态机。您需要确保 OpenGL 状态是您在进行调用时所期望的状态,并且某些调用序列不会被来自其他线程的调用打断。

我不是 OpenGL 线程安全方面的专家,但在我看来,这似乎是您的问题所在。

于 2009-12-16T20:24:22.793 回答
1

检查你的纹理坐标。如果它们设置错误,您只能看到一两个纹理像素映射到整个图元。请记住,OpenGL 是一个状态机。检查您是否在错误的时间更改纹理坐标状态。您可能稍后在代码中设置纹理坐标,然后当您重新绘制这些元素时,可以接受将纹理映射到代码的状态。

如果仅仅是时间问题,纹理加载 OpenGL 调用没有及时执行,并且您的线程代码是正确的,请尝试在加载纹理后添加对 glFlush() 的调用。glFlush() 导致所有挂起的 OpenGL 命令执行。

于 2009-12-16T20:43:45.767 回答
0

检查用作纹理的图像的大小和压缩率。我认为opengl纹理大小必须是2的幂...

于 2009-12-16T17:42:15.487 回答
0

您不能在线程中加载纹理并在其他不同线程中使用它,因为您会看到美丽的白色纹理。为此,您必须在使用任何 OpenGL 函数之前在不同线程之间加载 OpenGL 上下文。

于 2010-01-08T11:07:40.347 回答
0

如果您使用 GLIntercept 检查您的代码,请确保启用: ThreadChecking = True; 在 gliConfig.ini 文件中。

查看日志,似乎有相当多的 OpenGL 调用在主要上下文之外是主要的。

于 2010-02-01T13:57:45.743 回答
0

可以在另一个线程中加载纹理而不会得到白色纹理。问题是——一旦你初始化了 OpenGL 窗口——OpenGL 上下文被“绑定”到这个线程。在加载纹理时,您必须在主线程中停用上下文,并且在开始加载它们之前,您必须在此线程中激活上下文。

你可以使用这个类:

上下文.h:

#ifndef CONTEXT_H
#define CONTEXT_H

#include <GL/glut.h>

class Context
{
public:
    static Context* getInstance();

    void bind();
    void unbind();
private:
    Context();
    Context(const Context&);
    ~Context();

    static Context *instance;

    HGLRC hglrc;
    HDC hdc;

    class Guard
    {
    public:
        ~Guard()
        {
            if (Context::instance != 0) {
                delete Context::instance;
            }
        }
    };
    friend class Guard;
};

#endif

上下文.cpp:

#include "Context.h"

Context* Context::getInstance()
{
    static Guard guard;
    if(Context::instance == 0) {
        Context::instance = new Context();
    }
    return Context::instance;
}

void Context::bind()
{
    wglMakeCurrent(this->hdc, this->hglrc);
}

void Context::unbind()
{
    wglMakeCurrent(NULL, NULL);
}

Context::Context()
{
    this->hglrc = wglGetCurrentContext();
    this->hdc = wglGetCurrentDC();
}

Context::~Context()
{
}

Context *Context::instance = 0;

这就是你必须做的:

int state = 0;

void main()
{
    // Create the window.
    glutCreateWindow(TITLE);

    // Set your loop function.
    glutDisplayFunc(&loop);

    // Initialize the singleton for the 1st time.
    Context::getInstance()->bind();

    glutMainLoop();
}

void loop()
{
    if (state == 0) {
        Context::getInstance()->unbind();
        startThread(&run);
    } else if (state == 1) {
        // Rebind the context to the main thread (just once).
        Context::getInstance()->bind();
        state = 2;
    } else if (state == 2) {
        // Draw your textures, lines, etc.
    } else {
        // Draw something (but no textures).
    }
}

void run()
{
    Context::getInstance()->bind();

    // Load textures...

    Context::getInstance()->unbind();
    state = 1;
}
于 2010-11-26T15:56:33.303 回答