Update examples to OpenGL 3.

Create issue
Issue #50 resolved
David Williams created an issue

We should really modernise the examples. In particular, the BasicExample should be easy to port, and if we could use shaders then we could compute the surface normal in the shader and get rid of the whole CubicSurfaceExtractorWithNormals class (which basically exists just to support this sample!).

Comments (26)

  1. Matt Williams

    I'm happy to take a look at converting the BasicExample to VBOs/OpenGL3. I don't have much experience with shaders to know how to do the vertex calculation but I might be able to work it out based on the stuff you wrote for the manual. Otherwise I'll just use the CubicSurfaceExtractorWithNormals until I've got the shaders working.

  2. David Williams reporter

    Sure, I was hoping you might volunteer :-) The shader stuff should be too difficult - the Wikipedia page on GLSL has simple pass-through examples and I can help with the part which computes the normal. It should also be possible to tackle the shaders and VBOs separately (probably VBOs first). Just let me know if you have questions.

  3. Matt Williams

    I've did a basic shader already for the Python example which looked like

    #version 130
    
    in vec4 position;
    in vec4 normal;
    
    uniform mat4 cameraToClipMatrix;
    uniform mat4 worldToCameraMatrix;
    uniform mat4 modelToWorldMatrix;
    
    flat out float theColor;
    
    void main()
    {
        vec4 temp = modelToWorldMatrix * position;
        temp = worldToCameraMatrix * temp;
        gl_Position = cameraToClipMatrix * temp;
    
        theColor = clamp(abs(dot(normalize(normal.xyz), normalize(vec3(0.9,0.1,0.5)))), 0, 1);
    }
    

    and a fragment shader like:

    #version 130
    
    flat in float theColor;
    
    out vec4 outputColor;
    void main()
    {
        outputColor = vec4(1.0, 0.5, theColor, 1.0);
    }
    

    so I guess it would need to replace the in vec4 normal; with a calculation inside main(). I'll do the VBO bit first using CubicSurfaceExtractor (without normals) and just set the colour to something arbitrary in the shader and then do the normal bit afterwards.

  4. David Williams reporter

    Yes, your understanding is correct. The normal calculation is not obvious so I'll help out once you get that far.

  5. Matt Williams

    I've got a fully working version of the BasicExample using OpenGL 3, VBOs, VAOs and calculating the normals in the shader. I will commit it once I've added plenty of comments to the code. To make things easier, I've used some of the new Qt 5 OpenGL classes since they have a nice API (compared to raw OpenGL). I've used Qt classes to handle the compilation of the shaders as well as doing the matrix calculations. There are some more Qt OpenGL classes I can use (for handling buffers etc.) but I wanted to make sure it was clear how the OpenGL interface works to access the output of PolyVox.

    Since I was using Qt for these things, I found it was possible to use it to basically replace the use of GLEW for the BasicExample. Qt provides a set of classes, each giving access to the OpenGL API for a given version. I'm using QOpenGLFunctions_3_1. The main disadvantage here is that it means that any call to, e.g., glGenBuffers must be done via the class as gl->glGenBuffers() but perhaps it is worth it to avoid having to use GLEW?

  6. David Williams reporter

    Excellent stuff, glad to hear you got it working! I think if you want to replace the GLEW stuff with Qt then that's fine by me... it was rather messy having four copies of that file anyway (as I recall?). I'll let you decide what's best as you're the one doing the work :-)

    I haven't actually tested the Qt 5 stuff on my machine yet but I'm not expecting it to cause any problems.

  7. Matt Williams

    One other thing crosses my mind. Currently PositionMaterial and PositionMaterialNormal have a material member which is a float. If I remember correctly, the reason this is a float is because OpenGL/D3D didn't support integer vertex attributes. As far as I know, both OpenGL3 and D3D10 both allow this now so perhaps it would be worth changing this? Since the vertex types can be seen as just examples anyway, it shouldn't hurt backwards-compatibility. The material is used in the OpenGLExample so it would have to wait for that one to be updated to OpenGL 3 however.

  8. Matt Williams

    Also, I'm going to need to update the tutorial, particularly the OpenGL bits of it since it's essentially the BasicExample and it makes sense to keep them in sync.

  9. David Williams reporter

    The material type issue is the main difference between the develop version of PolyVox and the 'cubiquity-version' branch. In 'cubiquity-version' the vertex types are templatised with a material type for basically the reasons you say. The main aim of the 'extractor-refactor' branch is to implement this properly and merge it into develop so that eventually we don't need the separate branch just for Cubiquity. And the unclassing of the extractors is a step in this direction because it allows some automatic detection of template parameters to take place.

    So basically you are right :-)

    That said, I don't think the material needs to be a simple number regardless of the type that is used. In Cubiquity's smooth terrain it is actually a set of materials (with weights) and with the coloured cubes volume the 'material' is actually a colour. I have a feeling that a nice design would be for a vertex to have a position, possibly a normal, and then an instance of 'VoxelType' which would be the interpolated volume data at the vertice's position in space. This VoxelType will include the material and possibly other properties which may or may not be useful to the shader.

    But we should take small steps at a time here, and your cleaning up of the OpenGL examples allows us to eliminate the CubicSurfaceExtractorWithNormals which is then less code to refactor.

  10. David Williams reporter

    Hey Matt,

    I just got the latest version of PolyVox and unfortunatly I'm having a lot of problems. The update to Qt5 causes some issues on Windows, as does the switch to using QOpenGLFunctions_3_1. I'm not sure yet about the switch to shaders as I haven't managed to get the latest version of PolyVox to build yet.

    I think we're going to need to address these issues one at a time, ensuring everything works as it should on Windows before moving on. Perhaps we can revert your latest commit (ac16dfd) and get the Qt 5.0 stuff working first? Then the shader stuff but without QOpenGLFunctions_3_1 (which I think is the main problem I'm having)? And then switch to QOpenGLFunctions_3_1 after that?

    Sorry I didn't test this sooner!

  11. Matt Williams

    We shouldn't need to revert anything. Not yet anyway. You should be able to checkout 868fbb8 (being the Qt5 commit) and see if you can get that working. At that point, nothing had changed in the example's C++ files, only CMake stuff. You'll need CMake 2.8.6 but getting the latest one can't hurt. From Qt you'll need QtCore, QtGui and QtWidgets (though CMake should detect if they're missing and ignore them).

    What exact errors are you getting?

  12. David Williams reporter

    You're right, reverting is probably over the top... I'm just looking for a way to test issues in isolation. But I can just make some local changes/reverts. I'll post the Qt 5 issues in the dedicated issue we had for that, and I'll get back to you here about the QOpenGLFunctions_3_1 problem.

  13. David Williams reporter

    I've now got this building :-) Unfortunately it was quite a painful experience which is basically a result of the messy state of OpenGL on Windows. I can't say I fully understand it yet but it's related to the issues discussed here:

    http://qt-project.org/wiki/Qt-5-on-Windows-ANGLE-and-OpenGL

    In short it seems Qt can be built with 'desktop' OpenGL or ANGLE OpenGL. The Qt QOpenGLFunctions_X_Y functions are wrapped in #ifdefs like the following:

    #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
    

    My current belief is that this means it doesn't work with ANGLE and that 'desktop' OpenGL is required. I haven't seen this in the 'QOpenGLFunctions' documentation though but I guess it's a Windows only issue (as ANGLE is a Windows-only solution).

    The Qt project only seems to provide a limited set of binaries for the Windows platform - for VS2012 the options are the following:

    • Qt 5.2.1 for Windows 32-bit (VS 2012, 541 MB) (Info)
    • Qt 5.2.1 for Windows 64-bit (VS 2012, 556 MB) (Info)
    • Qt 5.2.1 for Windows 64-bit (VS 2012, OpenGL, 553 MB) (Info)

    Note that 32-bit does not include an 'OpenGL' version but 64-bit does. I assume that 'OpenGL' in this context means 'desktop OpenGL' rather than ANGLE. Due to the lack of a 32-bit OpenGL version for VS2012 I compiled it myself, though this was quite some work.

    I'm not sure how we should proceed. The OpenGL on Qt5/Windows is clearly quite complex, and might take some time to properly work out. Perhaps we shouldn't use the 'QOpenGLFunctions_X_Y' classes and should stick to GLEW, though I'm not sure if that also has problem with ANGLE (I think I saw some error messages on my other machine). Perhaps the examples should instead use OpenGLES... maybe we don't need extensions then? Or maybe Qt is the wrong solution here and we shold just use SDL/GLUT/GLEW for the examples.

    Overall I think my gut feeling is that we sholdn't use the 'QOpenGLFunctions_X_Y' functions and should return to GLEW. We'll stick with Qt 5 for now and get it working on 'desktop' OpenGL. Once that is all good we can test whether it works with ANGLE. If that fails then we can either roll with it anyway (following our new approach of doing what is good for us, as I have it compiling now), or we can look to move away from Qt (as we'll be using GLEW again so the actual OpenGL code needn't change too much).

    It's a complex situation so we can also discuss it next weekend if that's easier :-)

  14. Matt Williams

    Ok, it is simple enough to move back to using GLEW instead of QOpenGLFunctions_X_Y so I'll put in a commit to do that now. I didn't expect OpenGL to be such a problem on Windows I guess. For now I'll stick with using QOpenGLShaderProgram to compile the shaders but if necessary I can remove that and just do raw OpenGL for that too.

  15. Matt Williams

    In general though, I think that using Qt should be a sensible approach. Given that it provides us with OpenGL context, input, rendering and OpenGL API it makes sense to use it if we can. The reason that Qt5 is using ANGLE for the OpenGL stuff is because all GUI stuff in Qt5 is now rendered using OpenGL and they found that doing OpenGL→ANGLE→Direct3D was faster than doing OpenGL directly to the less than stellar OpenGL drivers in Windows. GLEW shouldn't use ANGLE unless told to do so as it should be a Qt implementation detail which we can circumvent.

    The problem with OpenGL ES 2.0 is that it is based on OpenGL 2 which is what we were trying to move away from. I think it's likely to need more extensions if anything. Using OpenGL 3 we don't technically need any extensions as it's all provided by the core API but it seems that in order to select a specific OpenGL profile, it's technically done via glext.h (something which GLEW and Qt5 hide away).

  16. David Williams reporter

    Yeah, I also didn't know it was going to be such a pain, Microsoft really know how to make things difficult for the competition. But at least it's working now :-)

    The problem with OpenGL ES 2.0 is that it is based on OpenGL 2 which is what we were trying to move away from. I think it's likely to need more extensions if anything.

    I'm not sure this is true... I believe OpenGL 2 provides both Vertex Buffer Objects and also shaders. The main driving force here was to move towards shaders so that the 'CubicSurfaceExtractorWithNormals' could be eliminated, and using VBOs is a bonus because immediate mode is so out of date. OpenGL 3 is nice because it is a clean slate and forces you to only use modern features, but I don't think we don't actually need that (we can voluntarily only use modern features)?

    But I'm not quite clear on what ANGLE provides... does it mean we have a complete OpenGL(ES?) 2 system on Windows? I have the 'desktop OpenGL' version of Qt here at home but the ANGLE version at work, so perhaps next week I'll get a chance to do some testing. It would be nice to know what the capabilities of ANGLE are and then we can make an informed decision.

    But in general I still think these changes are sensible, and once we work out exactly what we want to do with the BasicExample we can look at updating the other examples in a similar way.

  17. David Williams reporter

    Ok, I've done some further research. In addition to the 'QOpenGLFunctions_X_Y' classes, Qt also provides just 'QOpenGLFunctions' (without any particular numbers on the end):

    http://qt-project.org/doc/qt-5/qopenglfunctions.html

    From those docs:

    QOpenGLFunctions provides a guaranteed API that is available on all OpenGL systems and takes care of function resolution on systems that need it.

    In other words, it appears this is what is supported on all platforms including through ANGLE on Windows. After some tests it does seem to elimiate the need for GLEW and still provides the functionality we need (vertex buffer arrays and shaders). So if we code to this interface then I think we are covered.

    I haven't got it working yet. One of the limitations is that I think it only exposes stuff which is also in OpenGL ES - this includes Vertex Buffer Object but does not include Vertex Arrays. The difference is slightly unclear to me but I believe VBOs are stored in GPU memory whereas VAs are stored in CPU memory, so actually we want to use VBOs anyway. But actually our code seems to reference both... I'm not sure this is correct and have seen some confusion about this in online tutorials.

    I think we also need to change the shader to the OpenGL ES version of GLSL, but I need to test this more. At least it didn't seem to like the 'in' and 'out' keywords but it accepts 'attribute' and 'varying'. Perhaps this is just an older version of desktop GLSL, but I need to check.

    The alternative is that we can stick with what we had before and continue to use GLEW, but it seems to be causing problems with ANGLE as they both define some common constants. I don't know if this can be fixed.

    There are other minor issues such as the use of 'R' raw string literals and empty initializers '{}' which prevent compilation on VS2012 but work on VS2013. We can fix these later though.

    I think I need to make the above changes myself and a bit at a time, to find out what is actually working on Windows. I assume it will probably be fine on Linux but maybe you can check occasionally as I make commits.

    Sorry it turned out to be so difficult, I didn't see these Windows problems coming. But I did see it running on my home PC with the 'desktop OpenGL' version of Qt, so at least I know your shader works and we can soon eliminate the CubicSurfaceExtractorWithNormsls :-)

  18. Ezequiel Pozzo

    I'm also having an error related to QOpenGLFunctions_3_1 but under Ubuntu 12.04. I installed qt5 from the runner (only qt 5.0.2 is available as a package). I then linked /usr/lib/qt5 and /usr/include/qt5 to the respective installed folders and compiled.

    cmake passed correctly. But then when doing make install I get:

    In file included from ~/Documents/polyvox/examples/Basic/main.cpp:24:0:
    ~/Documents/polyvox/examples/Basic/OpenGLWidget.h:29:32: fatal error: QOpenGLFunctions_3_1: No such file or directory
    compilation terminated.
    make[2]: *** [examples/Basic/CMakeFiles/BasicExample.dir/main.cpp.o] Error 1
    make[1]: *** [examples/Basic/CMakeFiles/BasicExample.dir/all] Error 2
    make: *** [all] Error 2
    
  19. David Williams reporter

    @pozzoe - Do you have 'QOpenGLFunctions' (i.e. without the _3_1 extension)? Perhaps your system wasn't able to built the _3_1 version due to hardware or driver constraints?

    @milliams - I'm starting to get my head around it. I was probably wrong about vertex array objects, it seems they serve a different purpose from vertex buffer objects and they can indeed be used together. Though I'm still not certain. They are not used in the Qt example though and don't seem to work without _3_1, but if I just remove them then the code compiles and runs OK. It seems they can save and restore state... perhaps the code works because we have only one mesh anyway.

    I think I will reinstate your use of QOpenGLFunctions but without the _3_1. It is kind of tidier, avoids the need for GLEW, and it seems it should work across all platforms. Then I'll make whatever changes I have to get it running on my difficult Windows machine. I'll do this on a separate branch though in case I end up going round in circles!

    I'm sorry to take over your feature but I'm assuming you can't practically test this stuff yourself as it's Windows-specific. When we find a setup that works your welcome to apply it to the other examples and/or unify some of the code. I think really we should have one OpenGLWidget which all the examples use.

  20. David Williams reporter

    @pozzoe - So you have the header... perhaps the #include needs to include the 'QtGui' part:

    #include <QtGui/QOpenGLFunctions_3_1>
    
  21. David Williams reporter

    @milliams

    Hey Matt,

    You've probably seen that I started an OpenGL branch to try and get my head around some of the issues we've been encountering recently. Unfortunately I'm kind of going round in circles - or at least struggling between the two separate directions of porting the shader code, etc to OpenGL ES so that it runs on all version of Qt 5 vs. trying to get the real OpenGL 3.1 version working on all machines when I'm lacking prebuilt SDKs for all platforms and am hitting VS2012 compile errors.

    I haven't yet managed to get everything configuring/building/running on any of my machines, and to be honest it's a bit too much as I'm also pushing hard on Cubiquity at the moment. So I've taken a step back to think about what we are really trying to achieve here.

    Your update to OpenGL 3.1 (VBOs plus shaders) is a really useful step forward, because it modernizes the code and let's us eliminate the CubicSurfaceExtractorWithNormals. This in turn will simplify some refactoring and eventually help merge in the 'cubiquity' branch.

    But I'm not convinced we're really getting any benefit from Qt 5 at the moment. It's causing a few issues with CMake on Windows, and the OpenGL situation (ANGLE vs. 'desktop') is really messy.

    So now to my question - given that you have already switched develop back to using GLEW for the BasicExample, how hard is it to switch back to Qt 4? Are all the required classes (QVertexBuffer, QShader, etc) still present? We should stick with OpenGL 3.1 as that is useful, but I assume it can be used together with Qt 4?

    I would still like to move to Qt 5 in the future, but at a point when I have more time to properly address the issues which come up. Maybe a couple of months after Cubiquity is out? I just didn't see the Qt5/OpenGL/Windows combination being so tricky.

    Anyway, don't make any changes yet... just give it some thought and we can discuss it when I see you at the weekend. I can try and explain the full set of complications over a beer (might take more than one!).

  22. Ezequiel Pozzo

    @DavidWilliams Adding QtGui/ didn't work. Adding Qt5/QtGui/ works but it breaks just a few lines after that, since QOpenGLFunctions_3_1 makes reference to other headers without the Qt5/QtGui part. So, that made me think I was doing something wrong when installing Qt5. So, I downloaded it from git, compiled it and installed it with make. Now cmake finds Qt5, but still having the same issue when compiling. I'll report this on the forum so I don't spam this ticket.

  23. David Williams reporter

    From the Qt 5.4 Alpha announcement: http://blog.qt.digia.com/blog/2014/09/08/qt-5-4-alpha-available/

    "On Windows it is now possible to dynamically select during the application startup whether to use ANGLE or OpenGL. It is possible to use either opengl32.dll or ANGLE’s OpenGL ES 2.0 implementation in Qt applications without the need for two separate builds of the binaries."

    Don't think we actually need that, but thought it was worth making a note of given the previous problems..

    More news regarding this: http://blog.qt.digia.com/blog/2014/11/27/qt-weekly-21-dynamic-opengl-implementation-loading-in-qt-5-4/

  24. David Williams reporter

    This has been merged into develop. It also worth noting that I went with @milliams original solution of using Qt5 to manage extensions, rather than using GLEW. The latest Qt5 versions do indeed seem to have improved things further on Windows.

  25. Log in to comment