I’ve wasted so much time on this I just need to stop and ask for help already. Over the last few years I’ve been picking away at OpenGL and only ever got the legacy 2.x API to work which has been fine for making 2D games but I wanted to at least learn the modern API and shaders.
Here’s a snippet I cobbled together from a test program. It merely wants to draw a triangle. The actual OpenGL is from a tutorial and I don’t see how anything could be simpler than this. The only thing curious to me is why I can’t load the version of OpenGL I want from SDL. If I attempt to load 4.0 (with SDL_GL_SetAttribute) GL_VERSION returns null but if I load 3.3 it works and GL_VERSION returns 4.1 anyways (I’m a Mac from 2015).
I removed the error handling code here but I don’t get any errors, just a black screen. Despite the tutorial I was following not using a shader they still got a white triangle (I added a shader also but it still didn’t work so I removed it to reduce complexity). The only thing I can think of is they were using GLEW and it did some init that SDL isn’t doing but I doubt it. This is barebones simple OpenGL here.
Any ideas on what’s wrong with this? I don’t care about this example in particular I just want to draw ANYTHING using OpenGL 3.3 so I can move forward.
TVec2 = record
x, y: GLfloat;
verts: array[0..2] of TVec2;
// run sdl window
if SDL_Init(SDL_INIT_VIDEO) < 0 then
Fatal('SDL could not initialize! '+SDL_GetError);
// load function pointers
if Load_GL_VERSION_3_3 = false then
Fatal('OpenGL is not loaded');
I also wanted something reusable, so I implemented classes in separate
units that I can reuse between projects. Instead of 100's of loosely
scattered OpenGL API calls. I was actually going to contribute all this
work as part of my Lazarus Graphics Programming Contest entry, but I
might just release it earlier than that.
Anyway, attached is one such unit setting up my display. I use
proprietary NVIDIA drivers under FreeBSD, and I only target OpenGL 4.x
with my code. It works perfectly here.
My program code is pretty much like this:
while running do
// do the "gaming loop" here
// clean-up code here
> On May 24, 2017, at 7:18 PM, Graeme Geldenhuys <[hidden email]> wrote:
>> Any ideas on what’s wrong with this?
Ok, I got an answer from a person on YouTube and figured this out.
The problem was 1) that SDL is returning a different version then I asked for and I didn’t do proper error checking. glEnableVertexAttribArray was failing for example because with OpenGL 4.1 (or earlier) a VAO is required before using VBO’s and 2) again, since 4.x, a shader is required to even draw white triangle. The demos I saw must have been on some version of 3.x but I was on 4.1.
I’m still now sure how to guarantee SDL returns the version I want and it looks in your code you didn’t even try to specify anything besides core compatibility, not that it makes any difference because I always get 4.1 on my Mac or 2.1 and GLSL 1.2 for legacy mode. This begs the question of how I can write shaders if on any given computer I get a different version of GLSL.
At least I got it working FINALLY after so much hassle but everything I do could easily break on others computers so...
Then you can create the SDL and load the appropriate OpenGL function prototypes using:
glClear := SDL_GL_GetProcAddress('glClear');
It's up to you to know which functions are part of which which OpenGL spec, and you should need to load the functions dynamically to stubs:
var glClear: procedure(mask: GLbitfield); cdecl;
Don't forget, if you want a specific values for stencil bits, pixel order, multisampling levels and other stuff, you need to set those values before you create a window. Check the return values of SDL_CreateWindow and SDL_GL_CreateContext to see if anything above fails, for example the target device doesn't support OpenGL 4.0.
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); // 8x anti-aliasing, must be called before SDL_CreateWindow
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 16); // 16 bit stencil buffer, must be called before SDL_CreateWindow
> On May 25, 2017, at 2:30 PM, Anthony Walter <[hidden email]> wrote:
> You need to tell SDL what OpenGL kind and version before you create a window. For example if you want OpenGLES 2.0 you would write:
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
> If you want normal OpenGL 4.0 you would write:
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
That’s just a hint to SDL but it doesn’t guarantee anything. See my example below where I asked for 3.3 but got 4.1. I learned I can use a lower version of GLSL so I can enforce that version but for OpenGL I’m stuck on 4.1 or 2.1, at least on my Mac. That wouldn’t be a problem I guess but I’m trying to follow tutorials which have subtle things not work but I’m not using the same version as them. Maybe it doesn’t matter though and 4.1 will run on older graphics cards? No idea but it’s worrying.
Are you loading the OpenGL API functions using SDL_GL_GetProcAddress? You really should be doing that or you're asking for problems.
Anyways, if you want maximum capability you should probably use ES version 2, as it's supported on the most devices. It requires you to drop the fixed function pipeline, that is dropping glBegin/glEnd and using GLSL vertex and fragment shaders. It's mostly like OpenGL 2.0, with a few differences, like there is no glMatrixMode.
And if you're not using GLSL shaders, then you don't need anything greater than Open 1.5. You can see the list of changes at the link below. With the exception of frame buffer objects (better known as render to texture) in version 3.0 and up, there's likely very little you're going to need in the 3.0+ realm of APIs you're ever going to need.
In our previous episode, Anthony Walter said:
> And if you're not using GLSL shaders, then you don't need anything greater
> than Open 1.5. You can see the list of changes at the link below. With the
> exception of frame buffer objects (better known as render to texture) in
> version 3.0 and up, there's likely very little you're going to need in the
> 3.0+ realm of APIs you're ever going to need.
On 2017-05-23 22:13, Ryan Joseph wrote:
> I’ve wasted so much time on this I just need to stop and ask for help
> already. Over the last few years I’ve been picking away at OpenGL and
> only ever got the legacy 2.x API to work which has been fine for
> making 2D games but I wanted to at least learn the modern API and
Not sure what ZenGL uses for opengl version but why do you struggle to
use opengl directly instead of using a wrapper like zengl that has
already made the functions available for you...
The only problem with using a wrapper like zengl or andorra is that of
course it could go stale and not be updated, I'm not even sure if it
uses 2.x, I have forgotten.
> if SDL_Init(SDL_INIT_VIDEO) < 0 then
> Fatal('SDL could not initialize! '+SDL_GetError);
> // load function pointers
> if Load_GL_VERSION_3_3 = false then
> Fatal('OpenGL is not loaded');
> // NOTE: 4.0 doesn't work, GL_VERSION return null
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
> SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
> SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
> On May 25, 2017, at 7:02 PM, Anthony Walter <[hidden email]> wrote:
> Are you loading the OpenGL API functions using SDL_GL_GetProcAddress? You really should be doing that or you're asking for problems.
> Anyways, if you want maximum capability you should probably use ES version 2, as it's supported on the most devices. It requires you to drop the fixed function pipeline, that is dropping glBegin/glEnd and using GLSL vertex and fragment shaders. It's mostly like OpenGL 2.0, with a few differences, like there is no glMatrixMode.
I loaded the functions using Load_GL_VERSION_3_3 (and similar) from the Free Pascal RTL and it seems to correctly load the functions.
Right now I’m using 2.1 and the fixed pipeline because I don’t really need shaders but I’m learning shaders and matrix transforms now so if there’s any performance benefit I can update my code base.
> On May 26, 2017, at 11:56 AM, [hidden email] wrote:
> All these calls look kind of tedious, instead of using a wrapper. But maybe you want to learn opengl at its heart and not use a wrapper.. and learn all the fine details the hard way (full respect for that).
Imo I think it pays off to learn the actual graphics pipeline and what the process is really doing from direct memory in CPU to GPU. Graphics are so sensitive to performance and minor optimizations it would no doubt bother me deep down inside if I didn’t have 100% control over the process. Overall it’s only a minor part of the code actually so once you get it down it can be buried and not worried about later.