Rendering textures in GLSL using python

I would have thought that dealing with textures in OpenGL would be simple, and that stacks of documentation would be available on the web to tell me how I should do it. Ok, so taking it to the next stage of doing something with that texture using GLSL might be a bit more involved, but it should be basically plain sailing. I assumed that using python would make no difference at all to what was actually involved.

I don’t know if its my incompetence or just the flaky pyside bindings for the Qt GLSL stuff, but it seemed to be much more difficult than it ought to have been. A small test example I hacked up builds on the previous post. The intention was to draw a 2D image over the top of the 3D Qt logo. Other than that, the code is identical.

There is stacks of documentation out there, including lots on the pyside website. Unfortunately, it seems the documentation often doesn’t actually represent reality. The doc page for QtOpenGL.QGLShaderProgram has a chunk of python that is not even valid (closer inspection reveals its a partial transliteration from the C++ docs), and I had no end of fun calling various functions from PyOpenGL that were documented but didn’t actually do as expected.

Part of the frustration with the OpenGL (and possibly a legacy of its state machine nature) is a deeply annoying failure mode in which nothing appears on the screen, but no errors occur. As often as not when you think you’ve followed some tutorial or documentation to the letter!

In the end, I adopted a hybrid approach of using parts of the Qt library, including QGLShaderProgram along with management of the texture using direct OpenGL calls. As a learned friend of mine declared,“writing OpenGL is about hacking until it works”. It now works (and isn’t wholly unclean).

As with the previous post, there was the necessity to combine my OpenGL scene with a QML overlay, which came with similar problems of context management as discussed. In particular, it is necessary to update the texture parameters on every update to the scene (as opposed to at initialisation as with more usual implementations). The modifications to the drawBackground() method of OpenGLScene amount to the inclusion of initialisation code (which is run once), which sets up the shaders (loading and linking etc), and then the following which is run on every redraw:

self.program.bind()

GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE)

GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
GL.glVertexPointer(3, GL.GL_FLOAT, 0, triangle_vertices)
GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(triangle_vertices)/3)
GL.glDisableClientState(GL.GL_VERTEX_ARRAY)

self.program.release()

Note that this code is run outside of the viewport modifications that are performed for the rendering of the Qt logo. The consequence of this is that the image scales with the window. It would be trivial to change but it didn’t seem necessary for this example.

The shaders themselves are at the top of the source code. Full functioning code can be found here.

One problem I had that’s worth noting was when I’d failed to make my texture a power of 2 (although it is documented, its not obviously necessary).

Finally, if anyone can work out how to pass attribute arrays to a GLSL program using python, please let me know!

Advertisements

About Henry Gomersall

I'm a engineer wanting to make things actually useful. I'm someone that wants to drive technology and ideas to be helpful for everyone. I'm someone that realises the disconnect between technology and utility and I hope to correct that...
This entry was posted in Programming. Bookmark the permalink.

5 Responses to Rendering textures in GLSL using python

  1. Pingback: Combining QML (QtQuick) with OpenGL using python | Engineering the world

  2. Mark says:

    Tremendously useful example. thanks for this.
    Struggling through the pyside – opengl is hard work…

  3. buck says:

    I’d be interested to know if pyglet gives you the same headaches as pyopengl. By default, pyglet double-checks for opengl errors, to avoid the “deeply annoying failure mode in which nothing appears on the screen, but no errors occur.” I’ve also not found anything in pyglet to not function as documented. http://www.pyglet.org/

  4. PySide-QML integration is perfect 🙂 Python has many rich modules and QML is a beautiful UI and can be published to pc, android, meego, blackberry..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s