OpenGL being very machine specific

Recently I started using OpenGL in C++ for some 3D rendering, but oddly enough it seems to only work on a few machines. I'm using OpenGL 3.0 or higher (at the moment it is set to 3.0) using vertex array objects (not sure how its called, but the API revision that removed glBegin, glEnd and such).

Before testing it on another machine I always ask for their GPU drivers, most of them support OpenGL 4.2, if not, I make sure they at least support 3.0. Yet on some machines my application simply crashes, or doesn't render anything, OpenGL does not throw any errors (I check errors at least once each frame). It works perfectly fine on my own machine though, and in some cases my machine is even older than some machines on which it doesn't work.

I started using only OpenGL itself and GLEW, but switched to SFML and GLEW for ease of use and some other features I like, OpenGL itself didn't change its behavior though. I did rewrite the engine I was working on at some point to encapsulate all the GL calls and incorporate vertex array objects and some other features, in fact I can give you a list of all the API calls the application uses. Obviously it doesn't use of all of them in the test application, but these are all the calls I use in the engine (this is the bare minimum to be able to render, so yes, the engine is not even near finished):

  • 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
  • In short, the Shader and ShaderProgram part is nothing special, I have some methods to create/compile them, set some attribute locations beforehand and finally set attributes/uniforms. The buffer objects aren't anything special either, you can write, read and map the buffers, at the moment I'm only using GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER. Finally I'm using vertex array objects to actually render objects, obviously I set attribute pointers, and encapsulated draw calls and program usage, it always uses indexed drawing.

    Also, I extensively searched on google and on stack overflow itself for an answer. But all the problems have to do with OpenGL not working anywhere, eg some API calls weren't called in order or not at all. Sadly none of these answers work for me, it has always worked on my own machine and other machines I can directly access, but it has never worked when I send the application to someone else to test it on their machine.

    Hope this was specific enough XD

    EDIT, copy from post down below

    Every test is done on either windows vista or 7. I've thrown in an OpenGL error check for about each and every API call, and none seem to catch any error. I'm not able to reproduce it on my own machine, but after some more tracing on other machines I found that it does not crash untill rendering. The setup works fine, it creates all the buffers and objects perfectly fine, but as soon as I try to render a mesh (VAO) it crashes without any errors (well except .exe has stopped working). I suspect the commands glUseProgram or glDrawElements

    About an example, unless you want to search through about 10 classes, I can't give you a short example

    EDIT, tiny bit of code rendering an object

    Mesh class adds these structs to the object so it knows what to draw:

    // Define Geometry (draw command)
    struct Geometry
    {
        // Primitives
        PrimitiveType primitiveType;
    
        // Indices
        IndexType indexType;
        unsigned int count;  // elements
        unsigned int offset; // bytes
    };
    

    Oh, btw, a 'geometry tag' is just a string under which multiple draw calls can be 'put', couple definitions:

    // Define a list of primitives
    typedef std::vector<Geometry> GeometryList;
    
    // Define Geometry ordered by tag
    typedef std::map<const std::string, GeometryList> GeometryMap;
    

    For every 'draw' call it returns a string so the mesh class can bind the appropiate material.

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

    EDIT, the mesh calling all the above methods to actually render the object

    the lockVertexAttributes() just makes sure all the attribute pointers are bound to the correct vertex buffer. The bind method of the HardwareProgram does nothing more than checking if the programs is compiled and calling 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;
    }
    

    My bet would be that you're binding the GL_ELEMENT_ARRAY_BUFFER through your VAO.

    I've had issues in the past (a few years back) with this on certain versions of NVidia drivers (I don't have any record of which version(s) though), where this purely crashed the application.

    My workaround at the time was to rely on VAO to set GL_ARRAY_BUFFER binding and vertex attrib pointers, but I explicity redefined the GL_ELEMENT_ARRAY_BUFFER binding after the glBindVertexArray .

    I think the problem is now solved, but some old drivers around may exhibit the problem.

    Can you see a pattern for the configuration of platforms that have the problem ?

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

    上一篇: OpenGL3如何扩展GL

    下一篇: OpenGL是非常特定于计算机的