OpenGL Extensions in Qt 4 - opengl

it's possible enable/use OpenGL (specific version) in Qt 4 (on Desktop) or I have to use glew, etc?

Rather than Glew you can include gl3.h, it's probably the simplest and most pain free way and works with compatibility mode as well as core. It's also well worth checking out GLXX it's a newer lib written in C++ so its more object orientated and provides handy functions for querying capabilities and so on.
You could look at manually binding just the extensions you need, possibly making your own Qt classes.
Other alternatives are Glee (A bit out of date now, only up to OpenGL 3.0) and gl3w (a script to generate header files for you, but only seems to support OpenGL 3/4 core).
Also if you want a object orientated library for OpenGL itself OGLplus looks good, doesn't do extensions though.

Qt has wrappers for some extentions like QPixelBuffers otherwise you can just use glew to enable the extentions

My way to do that (Windows)... You need www.opengl.org/registry/api/glext.h
I'm using this python script to generate glex.h (p_glext.h) and glex.cpp from glext.h
p_glext.h is copy of glext.h without prototypes.
//glex.h
#ifndef GLEX_H
#define GLEX_H
#include "p_glext.h"
extern void glexInit();
extern PFNGLBLENDCOLORPROC glBlendColor;
extern PFNGLBLENDEQUATIONPROC glBlendEquation;
extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
...
//glex.cpp
...
void glexInit() {
glBlendColor = (PFNGLBLENDCOLORPROC)wglGetProcAddress("glBlendColor");
glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation");
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)wglGetProcAddress("glDrawRangeElements");
...
}
that's simple enough to me

Related

How do I use Legacy OpenGL calls with QT6?

I'm new to Qt and am trying to import some older C++ openGL code. I'm currently using Qt 6.4. I've subclassed my OpenGL-using class to QOpenGlFunctions.
Many of the glFoo calls "work" but the class also uses calls like glEnableClientState, glVertexPointer, glNormalPointer, glTexCoordPointer, glDisableClientState, glColor4fv, & glMaterialfv which come up with errors like undefined reference to __imp_glTextCoordPointer. Looking at the documentation these appear to no long be supported by "default" but it looks like they are supported using older versions of QOpenGlFunctions such as QOpenGlFunction_1_4 (https://doc-snapshots.qt.io/qt6-dev/qopenglfunctions-1-4.html).
Trying to change my subclass from QOpenGLFunctions to QOpenGLFunctions_1_4 complains that really only QOpenGLFunctions_1_4_CoreBackend and QOpenGLFunctions_1_4_DeprecatedBackend exist but there appears to be no documentation on those and if I subclass to one of them I start seeing complaints about my constructor...
How do I actually access the functions from these older versions of the class?
This question was answered by Chris Kawa over at the Qt Forums and it worked for me! Here is his answer:
OpenGL 3.1 introduced profiles. Core profile does not support these old functions and Compatibility profile does.
So first you have to make sure you have a context in version either lower than 3.1 (which does not support profiles) or 3.1 and up set up to use Compatibility profile. AFAIK Qt does not support OpenGL < 3.1 anymore, so you only have the latter option.
If you're not sure what context you have you can simply do qDebug() << your_context and it will print out all the parameters, or you can query individual fields of it e.g. your_conext->format()->profile(). If your context is not set correctly the simplest way is to set it up like this before any OpenGL is initialized in your app:
QSurfaceFormat fmt;
fmt.setVersion(3,1);
fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
fmt.setOptions(QSurfaceFormat::DeprecatedFunctions);
QSurfaceFormat::setDefaultFormat(fmt);
When you have the correct context you can access the deprecated functions like this:
QOpenGLFunctions_1_4* funcs = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_1_4>(context());
if(funcs)
{
//do OpenGL 1.4. stuff, for example
funcs->glEnableClientState(GL_VERTEX_ARRAY);
}
else
{
// Not a valid context?
}
And for anyone as amateur as I am, context() comes from QOpenGLWidget::context() which returns a QOpenGLContext*

Loading OpenGL > 1.1 functions Windows

I'm having trouble setting up OpenGL with MSVS 2013. I'm aware that the opengl32.dll on my Windows
platform located at C:\Windows\System32 is an implementation of OpenGL 1.1.
What I'm trying to do is to load the newer OpenGL > 1.1 functions such as glBindBuffer and glBufferData. I have read that it's possible getting a pointer to the function using wglGetProcAddress. When using this function the returned pointer is always null, all the original functions in the dll using GetProcAddress(OpenGL32DLL, "...") work perfectly except the newer functions don't seem to load.
I'm hoping anybody here can help me go through my setup and point out what I did wrong or if I have missed something.
So here we go:
I have downloaded OpenGL Extensions Viewer 4.4 which points out I'm able to perfectly run upto OpenGL 2.1 which
should be more than enough to use or load glBindBuffer and glBufferData.
I downloaded Microsoft SDKs/v7.1 which includes the headers: gl/glu.h and gl/gl.h; I also downloaded the GLEXT extensions API
from here and linked the glext.lib + included the headers.
Files in the Linker:
C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\OpenGL32.Lib
C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\GlU32.Lib
C:\Users\user\Desktop\glext\lib\glext.lib
The CPP files included:
C:\Program Files\Microsoft SDKs\Windows\v7.1\Include -> GL.h, GLU.h
C:\Users\user\Desktop\glext\include -> glcorearb.h, glext.h, wglext.h
Instead of handling all these details yourself, I suggest you just grab yourself a copy of GLEW ( http://glew.sourceforge.net/ ) which handles all of this for you in a standard way. I currently use it on several published products without issues.
In your example, you'd be able to do the following:
if (GL_ARB_multi_bind) {
//glBindBuffer is available.
}
(Of course, after a call to glewInit(), possibly with glewExperimental = TRUE; - see documentation for details.)
When using this function the returned pointer is always null, all the original functions in the dll using GetProcAddress(OpenGL32DLL, "...") work perfectly except the newer functions don't seem to load.
Do you have a valid OpenGL context created and made current on the calling thread? In Windows extension functions are technically per-context, i.e. you have to get the pointers to the functions for each OpenGL context you create and make sure to use the right function pointers with the right context.
This of course also means that you must have a OpenGL context to begin with. The usual sequence of setting up an OpenGL context in Windows is:
pseudocode
struct glctx {
HGLRC rc
// dictionary for explanation purposes
// one would normally just have a bunch of
// structure elements here
functionpointer[string:name] extensionfunction
}
if not window_with_desired_pixelformat_exists: {
wnd := create_a_window
pixelformat := select_pixelformat
wnd→set_pixelformat pixelformat
}
dc := wnd→getDC
glctx ctx
ctx→rc := wglCreateContext(dc)
wglMakeCurrent(dc, ctx→rc);
foreach(fname in extensionfunctions_names): {
ctx→extensionfunction[name] = wglGetProcAddress(name)
}
I think that the problem is that there is no current context while calling wglGetProcAddress.
Function pointers can be specific for a precise pixel format, determined by tge context creation procedure.

Including C++ headers in user mode programs built with NT DDK

So...I have a kernel mode component and a user mode component I'm putting together using the turnkey build environment of the NT DDK 7.1.0. The kernel component is all .c/.h/.rc files. The user mode component is .cpp/.c/.h/.rc files.
At first it seemed simplest to use build for both, as I saw you could modify the ./sources file of the user mode component to say something like:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
UMTYPE = windows
UMENTRY = winmain
USE_MSVCRT = 1
That didn't seem to cause a problem and so I was pleased, until I tried to #include <string> (or <memory>, or whatever) Doesn't find that stuff:
error C1083: Cannot open include file: 'string': No such file or directory
Still, it's compiling the user mode piece with C++ language semantics. But how do I get the standard includes to work?
I don't technically need to use the DDK build tool for the user mode piece. I could make a visual studio solution. I'm a bit wary as I have bumped into other annoyances, like the fact that the DDK uses __stdcall instead of __cdecl by default... and there isn't any pragma or compiler switch to override this. You literally have to go into each declaration you care about and change it, assuming you have source to do so. :-/
I'm starting to wonder if this is just a fractal descent into "just because you CAN doesn't mean you SHOULD build user mode apps with the DDK. Here be dragons." So my question isn't just about this particular technical hurdle, but rather if I should abandon the idea of building a C++ user mode component with the DDK tools...just because the kernel component is pure C.
To build a user mode program with WINDDK you need to add some variables to your SOURCES file:
386_STDCALL=0 to use cdecl calling convention by default
USE_STL=1 to use STL
USE_NATIVE_EH=1 to add a support for exception handling
Everything else you already have.
I'll put my full SOURCES file for reference:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
TARGETPATH = obj
UMTYPE = console
UMENTRY = main
USE_MSVCRT = 1
USE_NATIVE_EH=1
USE_STL=1
386_STDCALL=0
SOURCES= main.cpp
And main.cpp:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "bla bla bla!";
cout << s;
return 0;
}
Have fun!
Quick Answer
Abandon the idea of building user-mode components with DDK tools (although I find the concept fascinating :-P)
Your kernel mode component should be built separately from the user mode components as a matter of good practice.
Vague thoughts
Off the top of my head, and this really speaking from limited experience...there are a lot of subtle differences that can creep up if you try to mix the two together.
Using your own example of __cdecl vs __stdcall; You have two different calling conventions. _cdecl is all kernel stuff and all of the C++ methods are wrapped around in WINAPI (_stdcall) passing conventions and __stdcall will clean do auto stack clean up and expect frame pointers inserted all over the place. And if you by accident use compiler options to trigger a __fastcall, it would be a pain to debug.
You can definitely hack something together, but do you really want to keep track of that in your user-space code and build environment? UGH I say.
Unless you have very specific engineering reasons to mix the two environments, (and no a unified build experience is not a valid reason, because you can get that from a batch file called buildall.bat) I say use the separate toolchains.

OpenGL Multitexturing - glActiveTexture is NULL

I have started a new project, which I want to use multitexturing in.
I have done multixexturing before, and is supported by my version of OpenGL
In the header I have:
GLuint m_TerrainTexture[3];//heightmap, texture map and detail map
GLuint m_SkyboxTexture[5]; //left, front, right, back and top textures
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
PFNGLACTIVETEXTUREARBPROC glActiveTexture;
In the constructor I have:
glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress((LPCSTR)"glActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress((LPCSTR)"glMultiTexCoord2fARB");
if(!glActiveTexture || !glMultiTexCoord2fARB)
{
MessageBox(NULL, "multitexturing failed", "OGL_D3D Error", MB_OK);
}
glActiveTexture( GL_TEXTURE0_ARB );
...
This shows the message box "multitexturing failed" and the contents of glActiveTexture is 0x00000000
when it gets to glActiveTexture( GL_TEXTURE0_ARB ); I get an access violation error
I am implementing the MVC diagram, so this is all in my terrain view class
You quoted your code to load the extensions like following:
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
PFNGLACTIVETEXTUREARBPROC glActiveTexture;
glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress((LPCSTR)"glActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress((LPCSTR)"glMultiTexCoord2fARB");
This is very problematic, since it possibly redefines already existing symbols. The (dynamic) linker will eventually trip over this. For example it might happen that the assignment to the pointer variable glActiveTexture goes into some place, but whenever a function of the same name is called it calls something linked in from somewhere else.
In C you usually use a combination of preprocessor macros and custom prefix to avoid this problem, without having to adjust large portions of code.
PFNGLMULTITEXCOORD2FARBPROC myglMultiTexCoord2fARB;
#define glMultiTexCoord2fARB myglMultiTexCoord2fARB
PFNGLACTIVETEXTUREARBPROC myglActiveTexture;
#define glActiveTexture myglActiveTexture
glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress((LPCSTR)"glActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress((LPCSTR)"glMultiTexCoord2fARB");
I really don't know of any other reason why things should fail if you have a valid render context active and the extensions supported.
GLEE is a dead library; it hasn't been updated in a long time.
GLEW is a fine extension loading library, but it has some issues working with core 3.2 and above.
I would suggest GL3W. The beauty of it is that it is self-updating; it downloads and parses the headers by itself. The downside is that you need a Python 2.6 installation to generate the loader. But it provides reasonably good results otherwise.
I recommend GLEW/GLEE for extension management.
Rastertek tutorial has the complete setup required to make wglGetProcAddress to work. GLEW doesn't work for me either, I've tried everything I could think of and I asked many people about it but it simply doesn't work in VS 2012, not to mention the enormous frustration I experienced when I wanted to compile a shader.

Using OpenGL extensions On Windows

I want to use the functions exposed under the OpenGL extensions. I'm on Windows, how do I do this?
Easy solution: Use GLEW. See how here.
Hard solution:
If you have a really strong reason not to use GLEW, here's how to achieve the same without it:
Identify the OpenGL extension and the extension APIs you wish to use. OpenGL extensions are listed in the OpenGL Extension Registry.
Example: I wish to use the capabilities of the EXT_framebuffer_object extension. The APIs I wish to use from this extension are:
glGenFramebuffersEXT()
glBindFramebufferEXT()
glFramebufferTexture2DEXT()
glCheckFramebufferStatusEXT()
glDeleteFramebuffersEXT()
Check if your graphic card supports the extension you wish to use. If it does, then your work is almost done! Download and install the latest drivers and SDKs for your graphics card.
Example: The graphics card in my PC is a NVIDIA 6600 GT. So, I visit the NVIDIA OpenGL Extension Specifications webpage and find that the EXT_framebuffer_object extension is supported. I then download the latest NVIDIA OpenGL SDK and install it.
Your graphic card manufacturer provides a glext.h header file (or a similarly named header file) with all the declarations needed to use the supported OpenGL extensions. (Note that not all extensions might be supported.) Either place this header file somewhere your compiler can pick it up or include its directory in your compiler's include directories list.
Add a #include <glext.h> line in your code to include the header file into your code.
Open glext.h, find the API you wish to use and grab its corresponding ugly-looking declaration.
Example: I search for the above framebuffer APIs and find their corresponding ugly-looking declarations:
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); for GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei, GLuint *);
All this means is that your header file has the API declaration in 2 forms. One is a wgl-like ugly function pointer declaration. The other is a sane looking function declaration.
For each extension API you wish to use, add in your code declarations of the function name as a type of the ugly-looking string.
Example:
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
Though it looks ugly, all we're doing is to declare function pointers of the type corresponding to the extension API.
Initialize these function pointers with their rightful functions. These functions are exposed by the library or driver. We need to use wglGetProcAddress() function to do this.
Example:
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) wglGetProcAddress("glGenFramebuffersEXT");
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) wglGetProcAddress("glBindFramebufferEXT");
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) wglGetProcAddress("glFramebufferTexture2DEXT");
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) wglGetProcAddress("glCheckFramebufferStatusEXT");
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) wglGetProcAddress("glDeleteFramebuffersEXT");
Don't forget to check the function pointers for NULL. If by chance wglGetProcAddress() couldn't find the extension function, it would've initialized the pointer with NULL.
Example:
if (NULL == glGenFramebuffersEXT || NULL == glBindFramebufferEXT || NULL == glFramebufferTexture2DEXT
|| NULL == glCheckFramebufferStatusEXT || NULL == glDeleteFramebuffersEXT)
{
// Extension functions not loaded!
exit(1);
}
That's it, we're done! You can now use these function pointers just as if the function calls existed.
Example:
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colorTex[0], 0);
Reference: Moving Beyond OpenGL 1.1 for Windows by Dave Astle — The article is a bit dated, but has all the information you need to understand why this pathetic situation exists on Windows and how to get around it.
A 'Very strong reason' not to use GLEW might be that the library is not supported by your compiler/IDE. E.g: Borland C++ Builder.
In that case, you might want to rebuild the library from source. If it works, great, otherwise manual extension loading isnt as bad as it is made to sound.
#Kronikarz: From the looks of it, GLEW seems to be the way of the future. NVIDIA already ships it along with its OpenGL SDK. And its latest release was in 2007 compared to GLEE which was in 2006.
But, the usage of both libraries looks almost the same to me. (GLEW has an init() which needs to be called before anything else though.) So, you don't need to switch unless you find some extension not being supported under GLEE.
GL3W is a public-domain script that creates a library which loads only core functionality for OpenGL 3/4. It can be found on github at:
https://github.com/skaslev/gl3w
GL3W requires Python 2.6 to generate the libraries and headers for OpenGL; it does not require Python after that.