Reputation: 4749
My brain tends to favor structuring concepts in hierarchical, object-oriented, component-like ways. Unfortunately, this is preventing me from understanding OpenGL--and i suspect the source of my confusion is in my misunderstanding of what the "OpenGL state machine" is. You got the graphics pipeline, but that is really specific to the individual program objects that draw the user's graphical components, right?
Upvotes: 4
Views: 12064
Reputation: 668
From my POV, the expression "state machine" is misleading here. When I hear "state machine", I automatically think of a finite automaton that has a small number of defined states. It is always in one of those states and reacts to some input to determine what the next state and the output will be.
This is not what OpenGL does, however. (Mathematically, you can think of it as such an automaton but if you do, you artificially create tons of possible states which is not helpful).
Yes, the OpenGL API is "stateful" API. You tell it lots of things that it remembers inside its "state" which is basically a set of variables. Then, you ask it to render something, and OpenGL will use the state that you have set previously to determine what to do exactly with the data that is to be rendered.
By the way: I found Joey de Vries's tutorial really helpful to understand what OpenGL does. See https://learnopengl.com/Getting-started/OpenGL for more info.
Upvotes: 4
Reputation: 162164
What is this state machine?
Imagine a switchboard with a couple dozen of switches dials. This switchboard is connected to machines in a processing plant and depending on how the switches are toggled, stuff that enteres processing plant on one side will travel through the plant in a certain path. Change the state of some of these switches and things will go another way.
There are also state machines, where the switches and dials are changed when stuff passes through a certain processing step; OpenGL is not of that kind.
A OpenGL context is such a switchboard with a processing plant behind it. The switchboard is what you control through the API, the processing plant is what makes the pictures.
What are the different states it can exist in?
Too many to list. For every switch the number of states multiplies by the number of positions that switch can be in. Say you've got 20 toggle switches, one dial with 5 positions and one dial with 7 positions, then you've got 2^20 * 5 * 7 = 36700160
possible different states. Some versions of OpenGL have over 300 state variables and many of them are not just boolean. So it's a futile endeavour trying to list each and every possible state.
Is it also event-driven?
No!
What inputs affect the different states the machine can be in?
Explicit calls of state changing functions of the OpenGL API; that and the default initial state.
Can hierarchical, OOP concepts be applied to this state machine?
No. Or rather, you can try, but truth to be told, the only truthfull representation would be that of a single OpenGL context class holding all the state.
There are a few things within a OpenGL context, that behave like individual objects with their own state. Textures for example, however these objects are closely tied to the OpenGL context itself and can not be looked at independently.
A personal note on your remark
My brain tends to favor structuring concepts in hierarchical, object-oriented, component-like ways.
Stop doing that! Computers don't work like that. OOP is a method to structure projects, but its not a very good tool to understand some preexisting system. Especially systems that are inherently nonheirachical.
I strongly suggest you expand your horizon by learning other ways to structure projects. How about learning functional programming? Haskell would be one of the popular FP languages right now and for the learning experience its exceptionally good, due to its focus on being a pure language. Here's a very good online book/tutorial: http://learnyouahaskell.com/chapters – be prepared to have your mind bent; some things may look like they are OOP, but they're not; running up against those walls may seem frustrating, but the benefit, when it finally clicks in your head and "you get it" (= have epiphanies) are truely worth it.
Note that OpenGL is neither functional nor truely OOP. And due to not being functional it doesn't map very well into purely functional programming. There are OpenGL bindings for Haskell, but they are implemented through something called a "monad"; monads is what functional programs use to get in touch with state or even driven environments.
Another resource I recommend is https://mitpress.mit.edu/sicp/full-text/book/book.html – every programmer out there should have read it.
Upvotes: 18
Reputation: 190
to be honest i found the best way to understand this in the way that you want to understand it is in object orientated programming
from everything i have understood about opengl here is my best explanation of what opengl api is
firstly if you compare it to other api such as SDL , its probably alot more complicated and different , using api to try to describe it really doesnt do it justice
so in terms of object orientated programming
imagine if you have a class , this class is private , all the methods of its working is not intended to be viewed by the user, however it also has a default state so that if you use it "right out of the box" it will do what it does in that default state(which is pretty much nothing)
when you create a context its like you created an instance of this class(and you can create as many instances of this class as you like i.e you can also create more than one context) which is required to run opengl , and in OOP as you now you cannot use a class until you created an object/instance from it, the only difference is that the constructor takes your hardware/os/other api/hardware information to complete the instance/object so that it is usable, or plug it into some "screen"
however the methods(functions) and fields(data storage) that are contained in this class are what gives you the power to do everything you want to do with it and use this instance, of course how you do certain things are based on the methods you cannot change anything of this class/instance/object without using its methods/fields(the ones that you are allowed to use i.e are public ), you cant just say i want to do so and so on my own, or choose where to store the fields(externally etc) , all of them must pertain to the instance and class and methods, and in this instance/object/class there is hundred of methods and fields(opengl 4.5 has over 500 commands(methods/fields) which effect this instance/class) and whatever you do to it, changes this particular instance/object as if you have some clay and are molding it to which ever way you want it to be, of course there are certain things you must put plug into this instance externally such as shaders which have their certain functions
so it really is kind of like a remote to a tv screen, it has its methods/buttons which affect the context(screen/tv/monitor) that displays based on what you push on the remote/instance/methods/functions with the difference in this analogy that it takes more then just button pushes but data also and all the various ways you can present it(which is what you draw to the screen)
Upvotes: 0
Reputation: 2030
This is a very broad question, so I'll just give you the overview.
The state machine is the combination of the complete OpenGL API and the currently selected rendering context. The rendering context contains all of the states that makes up the state machine, while the OpenGL API provides the inputs that change these states.
There are too many to list. For example, the capabilities toggled by glEnable
and glDisable
(e.g. GL_TEXTURE_2D
, GL_FOG
, GL_BLEND
) are part of the state. The name of the current texture set with glBindTexture
; the name of the current shader program from glUseProgram
; the contents of the modelview and projection matrices plus the state of glMatrixMode
that tells which matrix any glMultMatrix
(etc.) calls will affect; and so on, are all part of the state
The initial state of the machine is given by the OpenGL specification, modulo the GPU drivers. The only inputs that can put the machine into a different state are calls to the OpenGL API.
This question is vague. What are "hierarchical, OOP concepts"?
It's possible to take an object-oriented approach to wrapping the OpenGL API. You can create a "Texture" object class that allocates a texture name using glGenTextures
when initialized, and provides methods for uploading the texture image or changing texture parameters that always call glBindTexture
before calling the relevant APIs for the methods. This approach is generally tricky as you still have to keep track of what the current state is through object and sub-object method calls.
OpenGL provides several "stacks" (vis. glPushMatrix
, glPushAttrib
) that are meant to help manage hierarchies of objects. By pushing some part of the current state onto the stack, calling methods of a child object, and then popping that state off of the stack, you can restore the state to the one expected by the parent object.
The general object-oriented approach to using the OpenGL API is through a scenegraph - a directed, acyclic graph of objects, where each object represents some change to the state machine's state. The object pushes to one or more OpenGL stacks, applies its state using OpenGL API calls, calls methods of its child objects, and then pops off of those OpenGL stacks to restore the previous state.
Upvotes: 5