Problems with glDrawPixels and numpy arrays with pyOpenGl

I’m trying to visualize mandelbrot set using numpy and OpenGL. However I have problems in drawing code, that is glDrawPixels.

When I draw using glDrawPixels I get something black and all messed up, but when using slower method of glBegin & glEnd I get the correct result. Code:


#!/usr/bin/env python3  

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

from pylab import *
from numpy import *
from time import clock

w,h = 800,600
eps = 2
max_iter = 16
u = (-1.5, 0.5)
v = (-1,1)

colorsMap = array([0x8B0000FF, 0xA52A2AFF, 0xB22222FF, 0xDC143CFF, 0xFF0000FF, 0xFF6347FF, 0xFF7F50FF, 0xCD5C5CFF, 0xF08080FF, 0xE9967AFF, 0xFA8072FF, 0xFFA07AFF, 0xFF4500FF, 0xFF8C00FF, 0xFFA500FF, 0xFFD700FF, 0xB8860BFF, 0xDAA520FF, 0xEEE8AAFF, 0xBDB76BFF, 0xF0E68CFF, 0x808000FF, 0xFFFF00FF, 0x9ACD32FF, 0x556B2FFF, 0x6B8E23FF, 0x7CFC00FF, 0x7FFF00FF, 0xADFF2FFF, 0x006400FF, 0x008000FF, 0x228B22FF, 0x00FF00FF, 0x32CD32FF, 0x90EE90FF, 0x98FB98FF, 0x8FBC8FFF, 0x00FA9AFF, 0x00FF7FFF, 0x2E8B57FF, 0x66CDAAFF, 0x3CB371FF, 0x20B2AAFF, 0x2F4F4FFF, 0x008080FF, 0x008B8BFF, 0x00FFFFFF, 0x00FFFFFF, 0xE0FFFFFF, 0x00CED1FF, 0x40E0D0FF, 0x48D1CCFF, 0xAFEEEEFF, 0x7FFFD4FF, 0xB0E0E6FF, 0x5F9EA0FF, 0x4682B4FF, 0x6495EDFF, 0x00BFFFFF, 0x1E90FFFF, 0xADD8E6FF, 0x87CEEBFF, 0x87CEFAFF, 0x191970FF, 0x000080FF, 0x00008BFF, 0x0000CDFF, 0x0000FFFF, 0x4169E1FF, 0x8A2BE2FF, 0x4B0082FF, 0x483D8BFF, 0x6A5ACDFF, 0x7B68EEFF, 0x9370DBFF, 0x8B008BFF, 0x9400D3FF, 0x9932CCFF, 0xBA55D3FF, 0x800080FF, 0xD8BFD8FF, 0xDDA0DDFF, 0xEE82EEFF, 0xFF00FFFF, 0xDA70D6FF, 0xC71585FF, 0xDB7093FF, 0xFF1493FF, 0xFF69B4FF, 0xFFB6C1FF, 0xFFC0CBFF, 0xFAEBD7FF, 0xF5F5DCFF, 0xFFE4C4FF, 0xFFEBCDFF, 0xF5DEB3FF, 0xFFF8DCFF, 0xFFFACDFF, 0xFAFAD2FF, 0xFFFFE0FF, 0x8B4513FF, 0xA0522DFF, 0xD2691EFF, 0xCD853FFF, 0xF4A460FF, 0xDEB887FF, 0xD2B48CFF, 0xBC8F8FFF, 0xFFE4B5FF, 0xFFDEADFF, 0xFFDAB9FF, 0xFFE4E1FF, 0xFFF0F5FF, 0xFAF0E6FF, 0xFDF5E6FF, 0xFFEFD5FF, 0xFFF5EEFF, 0xF5FFFAFF, 0x708090FF, 0x778899FF, 0xB0C4DEFF, 0xE6E6FAFF, 0xFFFAF0FF, 0xF0F8FFFF, 0xF8F8FFFF, 0xF0FFF0FF, 0xFFFFF0FF, 0xF0FFFFFF, 0xFFFAFAFF], dtype=uint32)

def draw():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    t = clock()
    print("Being calculation")

    x = linspace(u[0], u[1], w)
    y = linspace(v[0], v[1], h)
    a, b = meshgrid(x,y)
    M = (a + 1j*b).T
    Alive = ones((w,h), dtype=bool)

    ### Mandelbrot | Julia picker
    ## Mandelbrot
    # C = M.copy()

    ## Julia
    C = (0.32 + 0.043j) * ones(M.shape, dtype=complex128) 

    ### End picker

    esc = max_iter * ones((w,h), dtype=int32)

    for k in range(max_iter):
        M[Alive] = square(M[Alive]) + C[Alive]
        MD = real(M)**2 + imag(M)**2
        esc[logical_and(Alive, MD > eps*eps)] = k
        Alive = MD <= eps*eps


    cmap = zeros((w,h), dtype=uint32)

    for k in range(max_iter):
        cmap[esc == k] = colorsMap[k]
    

    print("Finish Calculation: {:.2f}".format(clock() - t))
    t = clock()
    print("Begin Drawing")

    if False: #Change for effect
        glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cmap.data)
    else:
        #Primite drawing numpy array
        def transform(cl):
            r = ((cl >> 24) & 0xFF) / 256.0
            b = ((cl >> 16) & 0xFF) / 256.0
            g = ((cl >>  8) & 0xFF) / 256.0
            return (r,b,g)

        glBegin(GL_POINTS)
        for y in range(0,h):
            for x in range(0,w):
                glColor3f(*transform(cmap[x,y]))
                glVertex2i(x,y)
        glEnd()
        glFlush()
    print("Finish drawing:     {:.2f}".format(clock() - t))

def idle():
    glutPostRedisplay()

def reshape(width, height):
    global w,h
    w,h =width, height

    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0, width, height, 0)
    glClearColor( 1., 1., 1., 0.)
    glClear( GL_COLOR_BUFFER_BIT )
    glPointSize(1.0)
    glColor3f(0., 0., 0.)

glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(w,h)
glutInitWindowPosition(100,100)

glutCreateWindow("Fraktali")
glutReshapeFunc(reshape)
glutDisplayFunc(draw)

glutMainLoop()

There are two issues with your code. First, the glDrawPixels() version doesn’t call glFlush(), which may result in the call not executing. Second, glDrawPixels() expects the data in row-major (“raster scan”) order, whereas your array is in column-major order. Use np.ascontiguousarray(cmap.transpose()) instead of just cmap (or, preferably, change the shape of cmap from (w,h) to (h,w)).

Thank you, this solved the problem.