OpenGL and SDL frustrations

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

OpenGL and SDL frustrations

Ryan Joseph
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.

=====

type
        TVec2 = record
                x, y: GLfloat;
        end;

var
        verts: array[0..2] of TVec2;
        bufferID: GLuint;
        vao: GLuint;
       
// 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');

SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// 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);
               
// create window
window := SDL_CreateWindow('SDL Tutorial', SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN + SDL_WINDOW_OPENGL);
context := SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
SDL_GL_SetSwapInterval(1);

writeln('Vendor: ', glGetString(GL_VENDOR));
writeln('OpenGL Version: ', glGetString(GL_VERSION));
writeln('GLSL Version: ', glGetString(GL_SHADING_LANGUAGE_VERSION));

// NOTE: despite SDL_GL_SetAttribute asking for 3.3 and 4.0 failing GL_VERSION still returns 4.1
// Vendor: Intel Inc.
// OpenGL Version: 4.1 INTEL-10.25.13
// GLSL Version: 4.10

// setup
glViewPort(0, 0, width, height);

// simplest example possible
// https://www.youtube.com/watch?v=Dyue3MzJDss
verts[0].x := 0.0;
verts[0].y := 1.0;
verts[1].x := -1.0;
verts[1].y := -1.0;
verts[2].x := 1.0;
verts[2].y := -1.0;

// NOTE: glEnableVertexAttribArray returns an error if I don't bind a vao
glGenVertexArrays(1, @vao);
glBindVertexArray(vao);

// gen array buffer and bind to verts
glGenBuffers(1, @bufferID);
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), @verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(TVec2), nil);

// draw loop
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(window);
...


Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Graeme Geldenhuys-6
On 2017-05-24 04:13, Ryan Joseph wrote:

> Any ideas on what’s wrong with this?

I actually used the Java + OpenGL tutorials on YouTube, and translating
those examples to Object Pascal + OpenGL + SDL2 was pretty easy.

This is my favourite one, and uses "modern OpenGL" only.

 
https://www.youtube.com/watch?v=VS8wlS9hF8E&list=PLRIWtICgwaX0u7Rf9zkZhLoLuZVfUksDP

   "OpenGL 3D Game Tutorial" by ThinMatrix.

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:

    TDisplayManager.CreateDisplay;

    while running do
    begin
      // do the "gaming loop" here
      TDisplayManager.UpdateDisplay;
    end;

    // clean-up code here
    TDisplayManager.CloseDisplay;



Regards,
   Graeme

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

My public PGP key:  http://tinyurl.com/graeme-pgp

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

displaymanager.pas (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Ryan Joseph

> 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...

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Anthony Walter-3
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_Init(SDL_INIT_VIDEO);
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);

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

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Ryan Joseph

> 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_Init(SDL_INIT_VIDEO);
> 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.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Anthony Walter-3
In reply to this post by Anthony Walter-3
Oh and another note, you cannot load your gl function such as (glClear in my previous reply, this time I use glGenTextures):

var glGenTextures: procedure(n: GLsizei; var textures: GLuint); cdecl;

Until you create and make current your OpenGL context.
SDL_GL_MakeCurrent(window, context); // after this is done the first time you can then load the OpenGL functions matching your requested version

So the order is

SDL_Init()
SDL_GL_SetAttribute() multiple times
SDL_CreateWindow() returns your window
SDL_GL_CreateContext() returns your context
SDL_GL_MakeCurrent() makes gl functions available
SDL_GL_GetProcAddress() for every gl function in your requested version 

Then you are done initializing everything and can write a game/demo/whatever thing you want.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Anthony Walter-3
In reply to this post by Ryan Joseph
Ryan,

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.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Marco van de Voort
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.
>
> https://www.khronos.org/opengl/wiki/History_of_OpenGL#Summary_of_version_changes

PBO speeds up texture upload on most DX10+ cards.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

noreply
In reply to this post by Ryan Joseph
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
> shaders.

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');
>
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> SDL_GL_CONTEXT_PROFILE_CORE);
> // 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);
>

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).
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Ryan Joseph
In reply to this post by Anthony Walter-3

> On May 25, 2017, at 7:02 PM, Anthony Walter <[hidden email]> wrote:
>
> Ryan,
>
> 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.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: OpenGL and SDL frustrations

Ryan Joseph
In reply to this post by noreply

> 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.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Loading...