OpenGL纹理加载问题

时间:2009-12-16 17:37:20

标签: debugging opengl 3d texturing

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

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

您建议甚至开始调试这种情况?

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

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

编辑: 这不是命令失败,而是主要是时间问题。粉色/白色纹理会显示一段时间,直到加载更多纹理。这几乎就像纹理排队一样,队列只是暂停了一段时间。

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

http://freetexthost.com/1kdkksabdg

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

7 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:1)

当你说:

  

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

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

我不是OpenGL线程安全专家,但在我看来你的问题可能就在哪里。

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

查看日志似乎有很多OpenGL调用在主要上下文之外。

答案 6 :(得分:0)

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

您可以使用此课程:

Context.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

Context.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;
}