Stubbing glOrthof to use glOrtho - opengl

I'm writing graphics code that targets both an embedded VxWorks 653 system and Windows (VxWorks is our prime target that we're delivering, and Windows is our desktop environment to test).
Our VxWorks 653 graphics driver uses glOrthof and does not have glOrtho, so our graphics rendering code uses glOrthof. For consistency on Windows, I did this during setup:
glOrthof = (PFNGLORTHOFPROC)wglGetProcAddress("glOrthof");
to get the OpenGL Extension function for glOrthof that our NVidia driver supports.
This works fine for the NVidia drivers, but some of our developers are stuck with Intel drivers. For them I tried this:
glOrthof = (PFNGLORTHOFPROC)&graphics_support_glOrthof;
static void WINAPI graphics_support_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar)
{
glOrtho((GLdouble)left, (GLdouble)right, (GLdouble)bottom, (GLdouble)top, (GLdouble)zNear, (GLdouble)zFar);
}
This stub gets hit when our graphics rendering loop calls glOrthof, and I can see that (via function breakpoints) that glOrtho is being called inside opengl32.dll and the parameters I'm passing in match. However, my display is entirely white, and I'm getting value 1281 (GL_INVALID_VLAUE) as a return code from glGetError().
My solution to fix this is to simply
#define glOrthof glOrtho
on my Windows target, but I'm wondering why this stub is failing?

Related

OpenGL unable to sync "player" FPS to monitor refresh rate

I am trying to write a video player that will play at the the EXACT FPS as the monitor refresh rate (lets say it is 60Hz).
I am writing c++ (VS2010) on windows and using OpenGL.
I have a very strong PC, when no sync is set I can reach to 500FPS.
this is the relevant code:
glfwSwapInterval(1);
while (1)
{
glBindTexture(GL_TEXTURE_2D,Texture[frameIndexInArray]);
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, 1.0f);
...
glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
glFinish();
glfwSwapBuffers(window);
glfwPollEvents();
...
}
the vertical sync option on the graphics driver set to "on".
and I have a grabber that records my output via DP cable. (I know for a fact that it works fine)
my problem is that my player, once in a few hundreds frames is getting out of sync,
the output is: frame(n-1), frame(n), frame(n), frame(n+1) ... (double frame)
or it can also be: frame(n-1), frame(n), frame(n), frame(n+2) ... (double and skip frame)
I tried to use glfwSwapInterval (0) and to set vsync in the graphics driver to "application settings", I tried without glFinish(), I even tried to give the thread high priority with SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
is it possible to get exactly 60FPS? end if so, how?? I could use any advice you have 'cause I literally tried everything I know.
If for some reason you are ever late on a buffer swap, you will wind up drawing 1 frame for at least two monitor refreshes while VSYNC is enabled.
If your driver supports adaptive VSYNC (most NV and AMD drivers do), I would suggest trying that first. That way it will never draw faster than 60 FPS, but if you are slightly late it is not going to penalize you. Check for this WGL extension: WGL_EXT_swap_control_tear and if it is supported, you can pass -1 to glfwSwapInterval (...). The extension does not add any new functions, it just gives meaning to negative values for the swap interval.
GLFW may be too stupid to accept a negative value (I have never tried it), and you might have to interface directly with the platform-specific function: wglSwapIntervalEXT (...)

Segfault with glPopMatrix

I'm porting/testing my code on a Raspberry Pi running Pidora, all updated.
The test is a very simple OpenGL program, which works fine on two other computers. I narrowed down a problem to a glPopMatrix call, which causes a segfault. A trivial reproduction of the problem (the entire draw function) is:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glViewport(0,0,200,200);
float d1=0.0f, d2=0.1f;
glPushMatrix(); //gratuitous push/pop pair to demonstrate
glBegin(GL_TRIANGLES);
glColor4f(1.0f,0.0f,0.0f,0.5f); glVertex3f( 0.00f, 1.0f,d1);
glColor4f(0.0f,1.0f,0.0f,0.5f); glVertex3f( 0.87f,-0.5f,d1);
glColor4f(0.0f,0.0f,1.0f,0.5f); glVertex3f(-0.87f,-0.5f,d1);
glColor4f(1,0,0,1);
glVertex3f(0,0,d2);
glVertex3f(1,0,d2);
glVertex3f(0,1,d2);
glColor4f(1,0,1,1);
glVertex3f( 0, 0,-d2);
glVertex3f(-1, 0,-d2);
glVertex3f( 0,-1,-d2);
glEnd();
glPopMatrix(); //segfault here!
The only reference I could find was this 2011 bug report, which describes effectively the same problem. So far, it seems they only have a workaround:
export GALLIUM_DRIVER=softpipe
export DRAW_USE_LLVM=no
I found only the first line was necessary. However, as suggested by the above, it looks like it might be forcing the OS to use a software fallback. It shows. The program (which as above draws three triangles) runs at about 10Hz.
It's common knowledge that the OpenGL matrix stack is deprecated, but simple usage cases like the above are useful for testing. I would expect glPopMatrix to at least not crash if it's present. Is there a way I can get hardware acceleration but still use this?
The raspberry pi has hardware support for OpenGL ES 1.x/2.x via vendor-specific libraries - but none for desktop GL. Immediate mode (glBegin/glEnd) was never in GLES. You have to use vertex arrays. However, the matrix stack is available in GLES1.x. You have to use egl to get a hw-accelerated context. On the upside, GL on the RPi does not require X11, so you can have an GL overlay just directly on the console, which is very cool. The official RPi firmware comes with the hello_triangle demo, which shows you how to get a valid context, the source can be found in /opt/vc/src/hello_pi/hello_triangle. There are also Ben O. Steen's RPi ports of the examples of the OpenGL ES programming guide/
You are currently using the mesa software renderer, which will be extremely slow on that platform. The crash seems to be a mesa bug, but as mesa doesn't have any hw accleration support for the GPU of the rpi, this should not really matter. The cod you have pasted is valid desktop GL1.x/2.x and should not crash on a conforming implementation.

SDL Won't Use OpenGL driver, defaults to DirectX

I am using SDL 1.2 for a project. It renders things just fine, but I want to do some small pixel shader effects. All of the examples for this show using OpenGl driver for SDL's video subsystem.
So, I start the video subsystem with opengl as the driver, and tell SDL_SetVideoMode() to use SDL_OPENGL. When I go to run the program, it now starts crashing on the SetVideoMode() call, which worked fine without forcing OpenGl).
I went back and ran the program without forcing OpenGl and dumped out SDL_VideoDriverName() and it says I am using the "directx" driver.
My question is two-pronged: what is wrong that it doesn't like the opengl driver, and how to I get SDL to use opengl without problems here? Or, how do I get the SDL surface into DirectX to apply pixel shader effects?
I would prefer to use OpenGl as it would be easier to port code to other platforms.
As an example, I have added this code that breaks when I try to use the OpenGl system:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <SDL.h>
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
{
SDL_putenv("SDL_VIDEODRIVER=opengl");
SDL_Init( SDL_INIT_EVERYTHING );
SDL_VideoInit("opengl",0);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // crashes here
SDL_Surface *mWindow = SDL_SetVideoMode(1024,768,32,SDL_HWSURFACE|SDL_HWPALETTE|SDL_DOUBLEBUF|SDL_OPENGL);
SDL_Quit();
return 0;
}
SDL without the OpenGL option uses DirectX to obtain direct access to a 3D drawing surface. Using OpenGL triggers a whole different codepath in SDL. And using OpenGL with SDL you no longer can use the SDL surface for direct access to the pixels It's very likely your program crashes, because you're still trying to directly access the surface.
Anyway, if you want to use pixel shaders, you no longer must use direct pixel buffer access, as provided by plain SDL. You have to do everything through OpenGL then.
Update
Some of the parameters you give to SDL are mutually exclusive. Also the driver name given to SDL_VideoInit makes no sense if used together with OpenGL (it's only relevant together with DirectDraw to select a specific output device).
Also, because you already did call SDL_Init(SDL_INIT_EVERYTHING) the call to SDL_VideoInit is redundant and maybe harmfull actually.
See this for a fully working OpenGL example:
http://sdl.beuc.net/sdl.wiki/Using_OpenGL_With_SDL

Cross-platform renderer in OpenGL ES

I'm writing an cross-platform renderer. I want to use it on Windows, Linux, Android, iOS.
Do you think that it is a good idea to avoid absolute abstraction and write it directly in OpenGL ES 2.0?
As far as I know I should be able to compile it on PC against standard OpenGL, with only a small changes in code that handles context and connection to windowing system.
Do you think that it is a good idea to avoid absolute abstraction and write it directly in OpenGL ES 2.0?
Your principle difficulties with this will be dealing with those parts of the ES 2.0 specification which are not actually the same as OpenGL 2.1.
For example, you just can't shove ES 2.0 shaders through a desktop GLSL 1.20 compiler. In ES 2.0, you use things like specifying precision; those are illegal constructs in GLSL 1.20.
You can however #define around them, but this requires a bit of manual intervention. You will have to insert a #ifdef into the shader source file. There are shader compilation tricks you can do to make this a bit easier.
Indeed, because GL ES uses a completely different set of extensions (though some are mirrors and subsets of desktop GL extensions), you may want to do this.
Every GLSL shader (desktop or ES) needs to have a "preamble". The first non-comment thing in a shader needs to be a #version declaration. Fortunately for you, the version is the same between desktop GL 2.1 and GL ES 2.0: #version 1.20. The problem is what comes next: the #extension list (if any). This enables extensions needed by the shader.
Since GL ES uses different extensions from desktop GL, you will need to change this extension list. And since odds are good you're going to need more GLSL ES extensions than desktop GL 2.1 extensions, these lists won't just be 1:1 mapping, but completely different lists.
My suggestion is to employ the ability to give GLSL shaders multiple strings. That is, your actual shader files do not have any preamble stuff. They only have the actual definitions and functions. The main body of the shader.
When running on GL ES, you have a global preamble that you will affix to the beginning of the shader. You will have a different global preamble in desktop GL. The code would look like this:
GLuint shader = glCreateShader(/*shader type*/);
const char *shaderList[2];
shaderList[0] = GetGlobalPreambleString(); //Gets preamble for the right platform
shaderList[1] = LoadShaderFile(); //Get the actual shader file
glShaderSource(shader, 2, shaderList, NULL);
The preamble can also include a platform-specific #define. User-defined of course. That way, you can #ifdef code for different platforms.
There are other differences between the two. For example, while valid ES 2.0 texture uploading function calls will work fine in desktop GL 2.1, they will not necessarily be optimal. Things that would upload fine on big-endian machines like all mobile systems will require some bit twiddling from the driver in little-endian desktop machines. So you may want to have a way to specify different pixel transfer parameters on GL ES and desktop GL.
Also, there are different sets of extensions in ES 2.0 and desktop GL 2.1 that you will want to take advantage of. While many of them try to mirror one another (OES_framebuffer_object is a subset of EXT_framebuffer_object), you may run afoul of similar "not quite a subset" issues like those mentioned above.
In my humble experience, the best approach for this kind of requirements is to develop your engine in a pure C flavor, with no additional layers on it.
I am the main developer of PATRIA 3D engine which is based on the basic principle you just mentioned in terms of portability and we have achieved this by just developing the tool on basic standard libraries.
The effort to compile your code then on the different platforms is very minimal.
The actual effort to port the entire solution can be calculated depending on the components you want to embed in your engine.
For example:
Standard C:
Engine 3D
Game Logic
Game AI
Physics
+
Window interface (GLUT, EGL etc) - Depends on the platform, anyway could be GLUT for desktop and EGL for mobile devices.
Human Interface - depends on the porting, Java for Android, OC for IOS, whatever version desktop
Sound manager - depends on the porting
Market services - depends on the porting
In this way, you can re-use 95% of your efforts in a seamless way.
we have adopted this solution for our engine and so far it is really worth the initial investment.
Here are the results of my experience implementing OpenGL ES 2.0 support for various platforms on which my commercial mapping and routing library runs.
The rendering class is designed to run in a separate thread. It has a reference to the object containing the map data and the current view information, and uses mutexes to avoid conflicts when reading that information at the time of drawing. It maintains a cache of OpenGL ES vector data in graphics memory.
All the rendering logic is written in C++ and is used on all the following platforms.
Windows (MFC)
Use the ANGLE library: link to libEGL.lib and libGLESv2.lib and ensure that the executable has access to the DLLs libEGL.dll and libGLESv2.dll. The C++ code creates a thread that redraws the graphics at a suitable rate (e.g., 25 times a second).
Windows (.NET and WPF)
Use a C++/CLI wrapper to create an EGL context and to call the C++ rendering code that is used directly in the MFC implementation. The C++ code creates a thread that redraws the graphics at a suitable rate (e.g., 25 times a second).
Windows (UWP)
Create the EGL context in the UWP app code and call the C++ rendering code via the a a C++/CXX wrapper. You will need to use a SwapChainPanel and create your own render loop running in a different thread. See the GLUWP project for sample code.
Qt on Windows, Linux and Mac OS
Use a QOpenGLWidget as your windows. Use the Qt OpenGL ES wrapper to create the EGL context, then call the C++ rendering code in your paintGL() function.
Android
Create a renderer class implementing android.opengl.GLSurfaceView.Renderer. Create a JNI wrapper for the C++ rendering object. Create the C++ rendering object in your onSurfaceCreated() function. Call the C++ rendering object's drawing function in your onDrawFrame() function. You will need to import the following libraries for your renderer class:
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
Create a view class derived from GLSurfaceView. In your view class's constructor first set up your EGL configuration:
setEGLContextClientVersion(2); // use OpenGL ES 2.0
setEGLConfigChooser(8,8,8,8,24,0);
then create an instance of your renderer class and call setRenderer to install it.
iOS
Use the METALAngle library, not GLKit, which Apple has deprecated and will eventually no longer support.
Create an Objective C++ renderer class to call your C++ OpenGL ES drawing logic.
Create a view class derived from MGLKView. In your view class's drawRect() function, create a renderer object if it doesn't yet exist, then call its drawing function. That is, your drawRect function should be something like:
-(void)drawRect:(CGRect)rect
{
if (m_renderer == nil && m_my_other_data != nil)
m_renderer = [[MyRenderer alloc] init:m_my_other_data];
if (m_renderer)
[m_renderer draw];
}
In your app you'll need a view controller class that creates the OpenGL context and sets it up, using code like this:
MGLContext* opengl_context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES2];
m_view = [[MyView alloc] initWithFrame:aBounds context:opengl_context];
m_view.drawableDepthFormat = MGLDrawableDepthFormat24;
self.view = m_view;
self.preferredFramesPerSecond = 30;
Linux
It is easiest to to use Qt on Linux (see above) but it's also possible to use the GLFW framework. In your app class's constructor, call glfwCreateWindow to create a window and store it as a data member. Call glfwMakeContextCurrent to make the EGL context current, then create a data member holding an instance of your renderer class; something like this:
m_window = glfwCreateWindow(1024,1024,"My Window Title",nullptr,nullptr);
glfwMakeContextCurrent(m_window);
m_renderer = std::make_unique<CMyRenderer>();
Add a Draw function to your app class:
bool MapWindow::Draw()
{
if (glfwWindowShouldClose(m_window))
return false;
m_renderer->Draw();
/* Swap front and back buffers */
glfwSwapBuffers(m_window);
return true;
}
Your main() function will then be:
int main(void)
{
/* Initialize the library */
if (!glfwInit())
return -1;
// Create the app.
MyApp app;
/* Draw continuously until the user closes the window */
while (app.Draw())
{
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Shader incompatibilities
There are incompatibilities in the shader language accepted by the various OpenGL ES 2.0 implementations. I overcome these in the C++ code using the following conditionally compiled code in my CompileShader function:
const char* preamble = "";
#if defined(_POSIX_VERSION) && !defined(ANDROID) && !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
// for Ubuntu using Qt or GLFW
preamble = "#version 100\n";
#elif defined(USING_QT) && defined(__APPLE__)
// On the Mac #version doesn't work so the precision qualifiers are suppressed.
preamble = "#define lowp\n#define mediump\n#define highp\n";
#endif
The preamble is then prefixed to the shader code.

OpenGL with Visual C++

I created a Visual C++ Project as win32 console setting, and I made a triangle successfully.
I'm using Visual studio 2010.
I wonder why there is no glOrthof function but only glOrtho function.
Is that an OpenGL version matter?
I used to use glOrthof function when I developed a game on the Android platform.
In OpenGL you only have the one version of glOrtho, the one taking floating point values. In Open GL ES there are two versions, one taking floats (glOrthof / GLfloat) and one taking fixeds (glOrthox / GLfixed).
One might argu that glOrtho in OpenGL should have the possibility to also use GLdouble, but since glOrtho orgins from back in time when only floats where used and today its depricated/removed there I see no reason to implement that.