Проблема загрузки текстуры OpenGL - PullRequest
1 голос
/ 16 декабря 2009

Это очень расплывчатая проблема, поэтому, пожалуйста, не стесняйтесь прояснить что-либо об этом проекте.

Я работаю над очень большим приложением, и недавно возникла очень запутанная ошибка, связанная с текстурированием. Некоторые текстуры, которые мы загружаем, загружаются - я прошел по коду, и он запускается - но все рендеры OpenGL для этих текстур - это странная розово-белая полосатая текстура.

Что бы вы предложили даже начать отладку этой ситуации?

  • Проект является многопоточным, но мьютекс гарантирует, что все вызовы OpenGL не прерываются ничем другим.
  • Некоторые текстуры загружаются, некоторые нет. Они все загружены одинаково.
  • Я убедился, что все текстуры существуют
  • «Розовые / белые» текстуры определенно загружаются в память - они становятся видимыми вскоре после того, как я загружаю любую другую текстуру в OpenGL.

Я озадачен и понятия не имею, что еще может быть не так. Есть ли команда OpenGL, которую можно вызвать после glTexImage, которая заставит текстуру стать пригодной для использования?

Edit: Дело не в сбоях команд, это в основном проблема синхронизации. Розовые / белые текстуры появляются некоторое время, пока не будет загружено больше текстур. Это почти как если бы текстуры были поставлены в очередь, а очередь просто пауза в какой-то момент.

Следующее редактирование: у меня правильно работает журнал glIntercept, и он выводит его (до сбоя всей программы)

http://freetexthost.com/1kdkksabdg

Следующее редактирование: я точно знаю, что текстуры загружаются в память OpenGL, но по какой-то причине они не отображаются в самой программе.

Ответы [ 7 ]

3 голосов
/ 16 декабря 2009

Если ваша текстура окрашена неправильно, скорее всего, вы загружаете неправильный порядок RGB. Убедитесь, что в glTexImage2D вы используете правильные перечисления для вашего формата изображения. Убедитесь, что количество компонентов указано правильно, и вы получаете порядок пикселей RGB в правильном аргументе формата.

Хотя, вероятно, это не связано с неправильным отображением текстур, OpenGL не поддерживает многопоточные отрисовки, поэтому убедитесь, что вы не выполняете никаких операций рисования в потоке, отличном от потока, которому принадлежит контекст.

Редактировать: У вас есть эталонный рендерер, чтобы вы могли убедиться, что пиксели изображения загружаются должным образом? Я настоятельно рекомендую написать небольшую подпрограмму для загрузки, а затем сразу же сохранить пиксели в файл, чтобы вы могли быть уверены, что получаете правильные результаты текстуры.

1 голос
/ 16 декабря 2009

Проверьте ваши координаты текстуры. Если они установлены неправильно, вы можете увидеть только один или два текселя, сопоставленных с целыми примитивами. Помните, OpenGL - это конечный автомат. Проверьте, не изменяете ли вы координаты текстуры в неправильное время. Возможно, вы устанавливаете координаты текстуры в более поздней точке вашего кода, затем, когда вы вернетесь к перерисовке этих элементов, состояние будет приемлемым для сопоставления вашей текстуры с кодом.

Если это просто проблема с синхронизацией, когда загрузка OpenGL-вызовов текстуры не выполняется вовремя и ваш код многопоточности корректен, попробуйте добавить вызов glFlush () после загрузки текстур. glFlush () вызывает выполнение всех ожидающих команд OpenGL.

1 голос
/ 16 декабря 2009

Когда вы говорите:

Проект является многопоточным, но мьютекс гарантирует, что все вызовы OpenGL не прерываются ничем другим.

Мне это не кажется достаточно сильной защитой: помните, что OpenGL - это конечный автомат с большим количеством внутреннего состояния. Вы должны убедиться, что состояние OpenGL соответствует ожидаемому при выполнении вызовов, и чтобы определенные последовательности вызовов не прерывались вызовами из других потоков.

Я не эксперт по безопасности потоков OpenGL, но мне кажется, в чем может быть ваша проблема.

0 голосов
/ 26 ноября 2010

Можно загружать текстуры в другом потоке, не получая белую текстуру. Проблема в том, что - как только вы инициализировали окно 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;
}
0 голосов
/ 01 февраля 2010

Если вы используете GLIntercept для проверки вашего кода, обязательно включите: ThreadChecking = True; в файле gliConfig.ini.

При просмотре журнала кажется, что довольно много вызовов OpenGL являются основными вне основного контекста.

0 голосов
/ 08 января 2010

Вы не можете загрузить текстуру в потоке и использовать ее в другом потоке, потому что вы увидите красивую белую текстуру. Чтобы сделать это возможным, вы должны загрузить контекст OpenGL между разными потоками, прежде чем использовать какую-либо функцию OpenGL.

0 голосов
/ 16 декабря 2009

Проверьте размер и сжатие тех изображений, которые вы используете в качестве текстур. я думаю, что размер текстуры opengl должен быть степенью 2 ...

...