OpenGL сильно зависит от машины

Недавно я начал использовать OpenGL в C++ для 3D-рендеринга, но, как ни странно, он работает только на нескольких машинах. Я использую OpenGL 3.0 или выше (, на данный момент он установлен на 3.0 ), используя объекты массива вершин (, не знаю, как это называется, но версия API, в которой удалены glBegin, glEnd и тому подобное ).

Прежде чем тестировать его на другой машине, я всегда спрашиваю их драйверы графического процессора, большинство из них поддерживают OpenGL 4.2, если нет, я удостоверяюсь, что они поддерживают хотя бы 3.0. Тем не менее, на некоторых машинах мое приложение просто дает сбой или ничего не отображает, OpenGL не выдает никаких ошибок (Я проверяю ошибки по крайней мере один раз в каждом кадре ). Однако на моей собственной машине он прекрасно работает, а в некоторых случаях моя машина даже старше, чем некоторые машины, на которых он не работает.

Я начал использовать только сам OpenGL и GLEW, но переключился на SFML и GLEW из-за простоты использования и некоторых других функций, которые мне нравятся, хотя сам OpenGL не изменил своего поведения. В какой-то момент я переписал движок, над которым работал, чтобы инкапсулировать все вызовы GL и включить объекты массива вершин и некоторые другие функции, фактически я могу дать вам список всех вызовов API, которые использует приложение. Очевидно, что в тестовом приложении используются не все из них, но это все вызовы, которые я использую в движке (, это самый минимум для возможности рендеринга, так что да,двигатель даже близко не закончен):

  • glAttachShader
  • glBindAttribLocation
  • glBindBuffer
  • glBindVertexArray
  • glBufferData
  • glBufferSubData
  • glClear
  • glClearColor
  • glClearDepth
  • glCompileShader
  • glCreateProgram
  • glCreateShader
  • glCullFace
  • glDeleteBuffers
  • glDeleteProgram
  • glDeleteShader
  • glDeleteVertexArrays
  • glDepthFunc
  • glDepthMask
  • glDepthRange
  • glDisableVertexAttribArray
  • glDrawElements
  • glEnable
  • glEnableVertexAttribArray
  • glFrontFace
  • glGenBuffers
  • glGenVertexArrays
  • glGetAttribLocation
  • glGetBufferParameteriv
  • glGetBufferSubData
  • glGetError
  • glGetIntegerv
  • glGetProgramInfoLog
  • glGetProgramiv
  • glGetShaderInfoLog
  • glGetShaderiv
  • glGetShaderSource
  • glGetUniformLocation
  • глиспрограмма
  • глисшейдер
  • glLinkПрограмма
  • glMapBufferRange
  • glPixelStorei
  • glShaderSource
  • glUniform (1i, 1ui, 1f, 2f, 3f, 4f, Matrix3fv, Matrix4fv)
  • glUnmapBuffer
  • glUseProgram
  • glVertexAttrib (1i, 1ui, 1f, 2f, 3f, 4f)
  • glVertexAttribPointer

Короче говоря, часть Shader и ShaderProgram не представляет собой ничего особенного, у меня есть несколько методов для их создания/компиляции, предварительной установки некоторых местоположений атрибутов и, наконец, установки атрибутов/униформы. Буферные объекты тоже не являются чем-то особенным, вы можете записывать, читать и отображать буферы, на данный момент я использую только GL _ARRAY _BUFFER и GL _ELEMENT _ARRAY _БУФЕР. Наконец, я использую объекты массива вершин для фактического рендеринга объектов, очевидно, я устанавливаю указатели атрибутов и инкапсулирую вызовы отрисовки и использование программы, он всегда использует индексированное рисование.

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

Надеюсь, это было достаточно конкретно XD

РЕДАКТИРОВАТЬ, скопировать из поста ниже

Каждый тест выполняется либо в Windows Vista, либо в 7. Я добавил проверку ошибок OpenGL для каждого вызова API, и ни один из них, похоже, не обнаружил никакой ошибки. Я не могу воспроизвести его на своей машине, но после еще нескольких трассировок на других машинах я обнаружил, что он не падает до рендеринга. Установка работает нормально, она создает все буферы и объекты прекрасно, но как только я пытаюсь отрендерить сетку (VAO ), она вылетает без ошибок (, за исключением того, что.exe перестал работать ). Я подозреваю, что команды glUseProgram или glDrawElements

О примере, если вы не хотите искать по примерно 10 классам, я не могу дать вам короткий пример

РЕДАКТИРОВАТЬ, крошечный фрагмент кода, отображающий объект

Класс Mesh добавляет эти структуры к объекту, чтобы он знал, что рисовать:

// Define Geometry (draw command)
struct Geometry
{
    // Primitives
    PrimitiveType primitiveType;

    // Indices
    IndexType indexType;
    unsigned int count;  // elements
    unsigned int offset; // bytes
};

О, кстати, «тег геометрии» — это просто строка, под которой можно «поместить» несколько вызовов отрисовки, пара определений:

// Define a list of primitives
typedef std::vector<Geometry> GeometryList;

// Define Geometry ordered by tag
typedef std::map<const std::string, GeometryList> GeometryMap;

Для каждого вызова 'draw' он возвращает строку, чтобы класс сетки мог связать соответствующий материал.

//-----------------------------------------------------------------------
const std::string HardwareObject::nextGeometryTag()
{
    // Loop back
    GeometryMap::const_iterator end = _geometry.end();
    if(_activeGeometry == end)
    {
        // Bind and go to begin
        glBindVertexArray(_GL_VertexArray);
        _activeGeometry = _geometry.begin();
    }

    // Check if new tag exists
    else if(++_activeGeometry == end)
    {
        // Unbind and return empty tag
        glBindVertexArray(0);
        return "";
    }
    return _activeGeometry->first;
}

//-----------------------------------------------------------------------
bool HardwareObject::drawGeometryTag() const
{
    // Validate current tag
    if(_activeGeometry == _geometry.end()) return false;

    // Draw each geometry call of tag
    for(GeometryList::const_iterator it = _activeGeometry->second.begin(); it != _activeGeometry->second.end(); ++it)
        glDrawElements(it->primitiveType, it->count, it->indexType, (void*)it->offset);

    // GL Error
    return !Console::GET().getError("HardwareObject Drawing");
}

//-----------------------------------------------------------------------
void HardwareObject::resetGeometryTag()
{
    _activeGeometry = _geometry.end();
}

РЕДАКТИРОВАТЬ, сетка, вызывающая все вышеперечисленные методы для фактического рендеринга объекта

lockVertexAttributes ()просто гарантирует, что все указатели атрибутов привязаны к правильному буферу вершин. Метод привязки HardwareProgram не делает ничего, кроме проверки того, скомпилированы ли программы и вызывает glUseProgram

//-----------------------------------------------------------------------
bool Mesh::render()
{
    // Lock vertex attributes
    if(!lockVertexAttributes()) return false;

    // To avoid errors
    _object.resetGeometryTag();

    // Loop while there's a tag
    for(std::string tag = _object.nextGeometryTag(); tag != ""; tag = _object.nextGeometryTag())
    {
        // Find material
        MaterialMap::const_iterator it = _materials.find(tag);
        if(it == _materials.end()) continue;

        // Bind material (get program directly)
        const HardwareProgram *prog = it->second->getProgram();
        if(!prog) continue;
        if(!prog->bind()) continue;

        // Draw tag
        _object.drawGeometryTag();
    }

    // Ok!
    return true;
}
7
задан Invalid 1 August 2012 в 12:21
поделиться