Sign in to follow this  

OpenGL What OpenGL Implementation Do Real Games Use?

Recommended Posts

Neither GLUT nor FreeGLUT are OpenGL implementations. They are windowing layers for OpenGL. Mesa3D is a software implementation that provides limited possibilities for hardware acceleration.


If you're on Windows, there's pretty much only one sensible option; you use the default implementation that the operating system provides. The benefit with using that implementation is that each hardware manufacturer provides their own hardware driver for it. Just link the standard opengl32.lib that ships with your compiler to use it.

Share this post

Link to post
Share on other sites
Mesa3D is the primary implementation of OpenGL on UNIX and supports several hardware graphics adapters (More than the default implementation in Windows infact).

But, yes it can also be compiled to be software only. Edited by Karsten_

Share this post

Link to post
Share on other sites
Define what an “actual” 3D game is?
Low-level indie games could use anything.  Many people use wrappers such as SDL or SMFL, but this is mainly just for helping them through the learning process or to get quick but not-so-serious results.
Medium-level indie games get closer to the direct API of choice, but it is not consistent enough to say what they “commonly” use, and at this point the target platform becomes much more of a decision-maker.  Of course the mobile industry is booming so it is worth mentioning that for mobile platforms they will all be using raw OpenGL ES 2.0.
But at this level those who are developing for Windows start to lean more towards DirectX and start to grow their own cross-platform engine (assuming you are not interesting in those who are using Unity 3D, Unreal Engine, etc., since you seem to want to get hands-on with your work).
At this level it is not always feasible in terms of skill or finances to make a DirectX port of an existing OpenGL engine, but even those who stick to OpenGL start to tend more towards raw OpenGL (no wrappers, just raw OpenGL).
At the AAA end of the scale things become more consistent but there is still no single answer.
By this point OpenGL is rarely used at all except for OpenGL ES 2.0 for mobiles.  Consoles and hand-helds (such as Nintendo 3DS) often provide an OpenGL (or OpenGL ES 2.0) layer but developers avoid this for performance reasons—it is always faster to use the native API.
That carries over to PC, in which the native API is DirectX.  As a result, most “actual” games (you didn’t define it so I can only assume what you meant) for the desktop market use DirectX when possible and OpenGL when no other options are available, and they strictly use raw OpenGL.
Generally the big game developers prefer to avoid OpenGL altogether if possible because it is like developing for Android—there are too many inconsistent implementations across vendors and the drivers are usually shoddy.  What works on one machine is guaranteed not to work on some other machine out there.
Another reason is that with the expectations on today’s graphics, they will require OpenGL 4.3, which requires users of Windows to upgrade manually if they have not already on Windows.
Valve is trying to put an end to this situation, and we may well start to see much better drivers (which means performance) and more consistent results in the future.
OpenGL is worth learning for 2 reasons:
  • There may be a surge in OpenGL games if Valve is successful in its Linux pursuit.
  • The mobile industry is booming and is a great place to start making your own indie games.
But if we assume that by “actual” you meant “AAA”, while there are always exceptions, the main answer is that they are using DirectX 11 first, then DirectX 9, then raw OpenGL if targeting Linux or Macintosh.  Generally speaking.
And which implementation?  I think you meant to answer which version.  You don’t get to pick your implementation—that is up to the vendors to implement.
The version you want is up to you.  Lower versions work across more machines, but your graphics will be pretty poor.  If you want compute shaders you will need core version 4.3 or GL_ARB_compute_shader extension.  If you use extensions, prepare for headaches as you implement all the fall-backs for unsupported features.  One more reason why the big guys stay away from OpenGL when possible.
L. Spiro Edited by L. Spiro

Share this post

Link to post
Share on other sites

As far as I know it is like this:


In *nix world you get: Mesa (up to 3.1 spec), proprietary GPU driver's implementation (up to 4.3 for nVidia, 4.2 for AMD) and OSS driver's implementation (i have no idea, enough to play Quake3 based games).

In Windows you get: Microsoft implementation (1.1 spec) and GPU driver's implementation (up to 4.3 for nVidia, 4.2 for AMD).

In OSX you get: Apple's implementation (up to 3.2 for everyone).


EDIT: Corrected Mesa's and Apple's spec implementations.

Edited by TheChubu

Share this post

Link to post
Share on other sites

Just to clarify to MrJoshL, we don't really "choose" what implementation to use (unless we want to force software rendering and we explicitly do so)


If we want hardware acceleration (aka get access to GPU), we'll just load the OpenGL implementation that is installed in the system (for NVIDIA cards, it's NVIDIA's, for ATI cards, it's ATI's). Since they're implementations, they implement everything they're supposed to, otherwise we would get a crash or a "cannot load routine from library" error and exit.


In Windows, the OGL system is called OpenGL "ICD" (Installable Client Driver). When the driver (ati, nvidia, intel, sis, s3, powervr, 3dfx, etc) didn't provide an OpenGL implementation, the application will be routed to a software implementation developed by Microsoft which is very outdated (supports 1.1 spec) so if you're using something higher, your application it will just fail to load (it's as if DirectX wouldn't be installed for Direct3D games)

When the driver did provide the implementation, the ICD will route to the driver's DLL.


In Linux, something very similar happens. Most distros ship the Mesa software implementation (which is usually very up to date), and if you install proprietary drivers, the installation messes with distro's folders & symbolic links to use the driver's OGL implementation instead of Mesa's.

Every now and then the installer (either driver's or distro's package manager) may mess the installation and try to mix Mesa dlls with driver's and X11 will crash when launching a GL application (been there....... multiple times). The situation has improved a lot though, in the last couple of years.


In Mac, I have no idea how it works, but afaik Apple controls the implementation being shipped.



You can of course ship your game with Mesa DLLs (since it's the only implementation I'm aware of that could be licensed for that) and always use Mesa's implementation, but almost nobody would like to do that.


GLUT & FreeGLUT are layers that simplify the creation of a GL context, and may deal with all this trouble (i.e. not having the right ICD installed, not having required GL version, loading extensions, etc) because this is all messing with DLL & function loading that has nothing to do with rendering triangles to the screen.

Edit: We just want to load the installed implementation and start rendering with hardware acceleration.

Edited by Matias Goldberg

Share this post

Link to post
Share on other sites

For the OPs benefit - GLUT, GLFW, etc are nothing more than helper libraries.  Their job is to deal with the painful (and non-cross-platform) task of creating a window, initializing a GL context, getting function pointers, etc.  This next bit is important.  Aside from that, they really have nothing much to do with GL itself; they just wrap the native API calls that would otherwise be used to get things up and running.


One major reason why they exist is for e.g. tutorials, sample code, and the like.  The native API code to do all this stuff can be huge, and when you're making a tutorial you really don't want the tutorial-specific code to be swamped by all of this extra stuff.  You want to focus on the lines of code that are relevant to the tutorial.


They can also serve another purpose in terms of providing a (at least) reasonably cross-platform way of getting a GL context up.  Some even provide other services (input, sound, etc) which may range in implementation from simplistic to comprehensive, but for the purposes of OpenGL itself, once that context is up, they step back and everything is just native GL code from there.


If you want to see how a real-life commercial game handles window and GL context creation, you could do a lot worse than look at the source code for one.

Share this post

Link to post
Share on other sites

In Mac, I have no idea how it works, but afaik Apple controls the implementation being shipped.

I've read Apple provides some lower level API that driver developers code for. So Apple gets a hold of everything down to which gl calls can be made and then gives control to the driver implementation. That's all I know though...

Share this post

Link to post
Share on other sites

Define what an “actual” 3D game is?

Sorry for being ambiguous, but what I meant by an "actual" OpenGL graphics application is something that utilizes the 3D capabilities of OpenGL, and isn't just drawing quads to the screen.


So if I had a list of all the things I need, and only the things I need, would this be correct:

1. opengl32.lib OR opengl32.a

2. gl.h

3. glew

4. glext

5. glu

6. wglext

Share this post

Link to post
Share on other sites
edit: I misread one of your points which made my response quite strange and incorrect. I'm rewriting it from the beginning in case someone read my old one.

Point 1 and 2 are necessary and are shipped with your compiler, or at least installed if you install any OpenGL distribution. Point 3 and 4 are necessary, and point 5 is useless, if you intend to go with the modern approach of OpenGL. Point 6 is necessary for the same reason, and not needed if you're not going with the modern approach, but it's for Windows only. You may need glxext to access the GLX extensions for other platfoms as well. Edited by Brother Bob

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Announcements

  • Forum Statistics

    • Total Topics
    • Total Posts
  • Similar Content

    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By aejt
      I recently started getting into graphics programming (2nd try, first try was many years ago) and I'm working on a 3d rendering engine which I hope to be able to make a 3D game with sooner or later. I have plenty of C++ experience, but not a lot when it comes to graphics, and while it's definitely going much better this time, I'm having trouble figuring out how assets are usually handled by engines.
      I'm not having trouble with handling the GPU resources, but more so with how the resources should be defined and used in the system (materials, models, etc).
      This is my plan now, I've implemented most of it except for the XML parts and factories and those are the ones I'm not sure of at all:
      I have these classes:
      For GPU resources:
      Geometry: holds and manages everything needed to render a geometry: VAO, VBO, EBO. Texture: holds and manages a texture which is loaded into the GPU. Shader: holds and manages a shader which is loaded into the GPU. For assets relying on GPU resources:
      Material: holds a shader resource, multiple texture resources, as well as uniform settings. Mesh: holds a geometry and a material. Model: holds multiple meshes, possibly in a tree structure to more easily support skinning later on? For handling GPU resources:
      ResourceCache<T>: T can be any resource loaded into the GPU. It owns these resources and only hands out handles to them on request (currently string identifiers are used when requesting handles, but all resources are stored in a vector and each handle only contains resource's index in that vector) Resource<T>: The handles given out from ResourceCache. The handles are reference counted and to get the underlying resource you simply deference like with pointers (*handle).  
      And my plan is to define everything into these XML documents to abstract away files:
      Resources.xml for ref-counted GPU resources (geometry, shaders, textures) Resources are assigned names/ids and resource files, and possibly some attributes (what vertex attributes does this geometry have? what vertex attributes does this shader expect? what uniforms does this shader use? and so on) Are reference counted using ResourceCache<T> Assets.xml for assets using the GPU resources (materials, meshes, models) Assets are not reference counted, but they hold handles to ref-counted resources. References the resources defined in Resources.xml by names/ids. The XMLs are loaded into some structure in memory which is then used for loading the resources/assets using factory classes:
      Factory classes for resources:
      For example, a texture factory could contain the texture definitions from the XML containing data about textures in the game, as well as a cache containing all loaded textures. This means it has mappings from each name/id to a file and when asked to load a texture with a name/id, it can look up its path and use a "BinaryLoader" to either load the file and create the resource directly, or asynchronously load the file's data into a queue which then can be read from later to create the resources synchronously in the GL context. These factories only return handles.
      Factory classes for assets:
      Much like for resources, these classes contain the definitions for the assets they can load. For example, with the definition the MaterialFactory will know which shader, textures and possibly uniform a certain material has, and with the help of TextureFactory and ShaderFactory, it can retrieve handles to the resources it needs (Shader + Textures), setup itself from XML data (uniform values), and return a created instance of requested material. These factories return actual instances, not handles (but the instances contain handles).
      Is this a good or commonly used approach? Is this going to bite me in the ass later on? Are there other more preferable approaches? Is this outside of the scope of a 3d renderer and should be on the engine side? I'd love to receive and kind of advice or suggestions!
    • By nedondev
      I 'm learning how to create game by using opengl with c/c++ coding, so here is my fist game. In video description also have game contain in Dropbox. May be I will make it better in future.
    • By Abecederia
      So I've recently started learning some GLSL and now I'm toying with a POM shader. I'm trying to optimize it and notice that it starts having issues at high texture sizes, especially with self-shadowing.
      Now I know POM is expensive either way, but would pulling the heightmap out of the normalmap alpha channel and in it's own 8bit texture make doing all those dozens of texture fetches more cheap? Or is everything in the cache aligned to 32bit anyway? I haven't implemented texture compression yet, I think that would help? But regardless, should there be a performance boost from decoupling the heightmap? I could also keep it in a lower resolution than the normalmap if that would improve performance.
      Any help is much appreciated, please keep in mind I'm somewhat of a newbie. Thanks!
    • By test opty
      I'm trying to learn OpenGL through a website and have proceeded until this page of it. The output is a simple triangle. The problem is the complexity.
      I have read that page several times and tried to analyse the code but I haven't understood the code properly and completely yet. This is the code:
      #include <glad/glad.h> #include <GLFW/glfw3.h> #include <C:\Users\Abbasi\Desktop\std_lib_facilities_4.h> using namespace std; //****************************************************************************** void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow *window); // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; //******************************* int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfw window creation GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "My First Triangle", nullptr, nullptr); if (window == nullptr) { cout << "Failed to create GLFW window" << endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad: load all OpenGL function pointers if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { cout << "Failed to initialize GLAD" << endl; return -1; } // build and compile our shader program // vertex shader int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); glCompileShader(vertexShader); // check for shader compile errors int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog); cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl; } // fragment shader int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog); cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl; } // link shaders int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // check for linking errors glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog); cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // set up vertex data (and buffer(s)) and configure vertex attributes float vertices[] = { -0.5f, -0.5f, 0.0f, // left 0.5f, -0.5f, 0.0f, // right 0.0f, 0.5f, 0.0f // top }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), //and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO // as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally // modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind // VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); // uncomment this call to draw in wireframe polygons. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // render loop while (!glfwWindowShouldClose(window)) { // input // ----- processInput(window); // render // ------ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw our first triangle glUseProgram(shaderProgram); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to // bind it every time, but we'll do so to keep things a bit more organized glDrawArrays(GL_TRIANGLES, 0, 3); // glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) glfwSwapBuffers(window); glfwPollEvents(); } // optional: de-allocate all resources once they've outlived their purpose: glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // glfw: terminate, clearing all previously allocated GLFW resources. glfwTerminate(); return 0; } //************************************************** // process all input: query GLFW whether relevant keys are pressed/released // this frame and react accordingly void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } //******************************************************************** // glfw: whenever the window size changed (by OS or user resize) this callback function executes void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } As you see, about 200 lines of complicated code only for a simple triangle. 
      I don't know what parts are necessary for that output. And also, what the correct order of instructions for such an output or programs is, generally. That start point is too complex for a beginner of OpenGL like me and I don't know how to make the issue solved. What are your ideas please? What is the way to figure both the code and the whole program out correctly please?
      I wish I'd read a reference that would teach me OpenGL through a step-by-step method. 
  • Popular Now