OpenGL非常特定于机器

Inv*_*lid 8 c++ opengl glew render sfml

最近我开始在C++中使用OpenGL进行一些3D渲染,但奇怪的是它似乎只适用于几台机器.我正在使用OpenGL 3.0或更高版本(目前设置为3.0)使用顶点数组对象(不确定它是如何被调用的,但API修订版删除了glBegin,glEnd等).

在另一台机器上测试之前,我总是要求他们的GPU驱动程序,大多数都支持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
  • glIsProgram
  • glIsShader
  • glLinkProgram
  • 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_BUFFER.最后我使用顶点数组对象实际渲染对象,显然我设置了属性指针,封装了绘制调用和程序用法,它总是使用索引绘图.

此外,我广泛搜索谷歌和堆栈溢出本身的答案.但是所有问题都与OpenGL无法在任何地方工作有关,例如,某些API调用未按顺序调用或根本不调用.遗憾的是,这些答案都不适用于我,它一直在我自己的机器和我可以直接访问的其他机器上工作,但是当我将应用程序发送给其他人在他们的机器上进行测试时,它从未起作用.

希望这是特定的XD

编辑,从下面的帖子复制

每个测试都在windows vista或7上完成.我已经对每个API调用进行了OpenGL错误检查,似乎没有任何错误.我无法在自己的机器上重现它,但在其他机器上进行了一些跟踪后,我发现它不会崩溃直到渲染.设置工作正常,它可以很好地创建所有缓冲区和对象,但是一旦我尝试渲染网格(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
};
Run Code Online (Sandbox Code Playgroud)

哦,顺便说一下,'几何标签'只是一个字符串,在这个字符串下可以"放置"多个绘图调用,耦合定义:

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

// Define Geometry ordered by tag
typedef std::map<const std::string, GeometryList> GeometryMap;
Run Code Online (Sandbox Code Playgroud)

对于每个'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();
}
Run Code Online (Sandbox Code Playgroud)

编辑,网格调用所有上述方法来实际渲染对象

lockVertexAttributes()只是确保所有属性指针都绑定到正确的顶点缓冲区.HardwareProgram的bind方法只是检查程序是否已编译并调用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;
}
Run Code Online (Sandbox Code Playgroud)

rot*_*lup 5

我的赌注是你GL_ELEMENT_ARRAY_BUFFER通过你的VAO 绑定.

我在过去(几​​年前)遇到过某些版本的NVidia驱动程序(虽然我没有关于哪个版本的记录),但这纯粹会使应用程序崩溃.

我当时的解决方法是依靠VAO设置GL_ARRAY_BUFFER绑定和顶点attrib指针,但我明确地重新定义了GL_ELEMENT_ARRAY_BUFFER绑定后的绑定glBindVertexArray.

我认为这个问题现在已经解决了,但是一些老司机可能会遇到这个问题.

您能看到有问题的平台配置模式吗?