OpenGL是非常特定于计算机的

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

在另一台机器上测试之前,我总是会问他们的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个课程,否则我不能给你一个简单的例子

    编辑,一小段代码渲染一个对象

    网格类将这些结构添加到对象,以便知道要绘制的内容:

    // 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;
    

    对于每个“绘图”调用,它都会返回一个字符串,以便网格类可以绑定适当的材质。

    //-----------------------------------------------------------------------
    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;
    }
    

    我敢打赌,你通过你的VAO绑定了GL_ELEMENT_ARRAY_BUFFER

    在过去(几​​年前),在某些版本的NVidia驱动程序(我没有任何关于哪个版本的记录)的问题上,我曾经遇到过这些问题,这些都会导致应用程序崩溃。

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

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

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

    链接地址: http://www.djcxy.com/p/38489.html

    上一篇: OpenGL being very machine specific

    下一篇: OpenGL3 SFML 2.0rc FPS