Results 1 to 3 of 3

Thread: Need help passing array buffers to GLSL program (using PyOpenGL)??

  1. #1
    Newbie Newbie
    Join Date
    Apr 2017
    Posts
    5

    Need help passing array buffers to GLSL program (using PyOpenGL)??

    I am trying to create a first opengl project using Python but I am very new to OpenGL. I have created this simple example which dynamically sets the color, size and places vertices while updating the vertex position for each draw event.

    I did manage to get things working using Uniform inputs and it looked something like this:
    2GNWb.jpg

    Now I would like to attempt using attributes and data buffers. I have looked at an example on the web (cant post any urls..) and I have tried to modify my program according to them. However now all I get is a blank screen and I can't figure out what I'm doing wrong?

    Here is my the functional example, and I think there is possibly something wrong with the way I am using glGenBuffers and glBindBuffer but I am not very sure.

    Code :
    #!/bin/env python
     
    # file color_cube_actor.py
     
    import time
    from textwrap import dedent
    import numpy as np
     
    from OpenGL.GL import *
    from OpenGL.GL.shaders import compileShader, compileProgram
     
    import pygame
    from pygame.locals import *
     
    class ColorCubeActor(object):
     
        array_size = 100
     
        def __init__(self):
            self.program = 0
            self.scale = 0
     
            self.indices = np.arange(self.array_size)
            self.colors = np.tile(np.array([0.0,1.0,0.0]), (self.array_size,1)) #a bunch of green vertices
            self.sizes = np.ones(self.array_size)*10
        def init_gl(self):
            glEnable(GL_VERTEX_PROGRAM_POINT_SIZE) #allow the program to specify the point size
     
            vertex_shader = compileShader(dedent("""
                #version 450 core
     
                layout(location = 0) uniform mat4 Projection = mat4(1);
                layout(location = 4) uniform mat4 ModelView = mat4(1);
     
                in vec3 ptPosition;
                in float ptSize;
                in vec3 ptColor;
     
                out vec3 _color;
     
                void main()
                {
                    _color = ptColor; //vec3(0.2, 0.5, 1.0); //light blue
                    gl_Position = Projection * ModelView * vec4(ptPosition, 1.0);
     
                    //use normalized device coordinates to calculate the PointSize of a vertex based on it's distance from the perspective camera.
                    vec3 ndc = gl_Position.xyz / gl_Position.w ; // perspective divide.
                    float zDist = 1.0-ndc.z ; // 1 is close (right up in your face,)
                    // 0 is far (at the far plane)
                    gl_PointSize = ptSize*zDist ; // between 0 and 50 now.
     
                }
                """), GL_VERTEX_SHADER)
     
            fragment_shader = compileShader(dedent("""
                #version 450 core
     
                in vec3 _color;
                out vec4 FragColor;
     
                void main() {
                    FragColor = vec4(_color, 1.0); //just pass a color to the vertex (results in a rectangle pixel)
                }
                """), GL_FRAGMENT_SHADER)
     
            self.program = compileProgram(vertex_shader, fragment_shader)
     
            #setup the vao and bind buffers
            self.vao = glGenVertexArrays(1)
            glBindVertexArray(self.vao)
     
            self.ptSize = glGenBuffers(1) #bind buffer for point sizes
            glBindBuffer(GL_ARRAY_BUFFER, self.ptSize) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptSize_pointer = glGetAttribLocation(self.program, "ptSize") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, self.sizes.nbytes, self.sizes, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            glEnableVertexAttribArray(ptSize_pointer) #Enable the attribute at that location
            glVertexAttribPointer(ptSize_pointer, 1, GL_FLOAT, GL_FALSE, 0, 0) #Tell OpenGL what the array contains:
     
            self.ptColor = glGenBuffers(1) #bind buffer for point colors
            glBindBuffer(GL_ARRAY_BUFFER, self.ptColor) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptColor_pointer = glGetAttribLocation(self.program, "ptColor") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, self.colors.nbytes, self.colors, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            glEnableVertexAttribArray(ptColor_pointer) #Enable the attribute at that location
            glVertexAttribPointer(ptColor_pointer, 3, GL_FLOAT, GL_FALSE, 0, 0) #Tell OpenGL what the array contains:
     
        def setPoints(self, modelview, projection):
            self.scale += 0.0005
     
            #create dataset
            theta = np.linspace(-4 * np.pi, 4 * np.pi, self.array_size)
            z = np.linspace(-2, 2, self.array_size)
            r = z**2 + 1
            x = r * np.sin(theta)
            y = r * np.cos(theta)
            plot = np.dstack((x,y,z)) * self.scale
     
            self.ptPosition = glGenBuffers(1) #bind buffer for positions and copy data into buffer
            glBindBuffer(GL_ARRAY_BUFFER, self.ptPosition) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptPosition_pointer = glGetAttribLocation(self.program, "ptPosition") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, plot.nbytes, plot, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            glEnableVertexAttribArray(ptPosition_pointer) #Enable the attribute at that location
            glVertexAttribPointer(ptPosition_pointer, 3, GL_FLOAT, GL_FALSE, 0, 0)#Tell OpenGL what the array contains:
     
            glUniformMatrix4fv(0, 1, False, projection)
            glUniformMatrix4fv(4, 1, False, modelview)
     
            glDrawElements(GL_POINTS, self.array_size, GL_UNSIGNED_INT, self.indices)
     
        def display_gl(self, modelview, projection):
            glClear(GL_COLOR_BUFFER_BIT) #| GL_DEPTH_BUFFER_BIT)
            glUseProgram(self.program)
            self.setPoints(modelview, projection)
     
        def dispose_gl(self):
            glDeleteProgram(self.program)
            self.program = 0
     
        def main(self):
            pygame.init()
            pygame.display.set_mode((800, 600), HWSURFACE|OPENGL|DOUBLEBUF)
            self.init_gl()
     
            projection = np.array([#the matrix generated captured while using HTC Vive
                [ 0.75752085,  0.        ,  0.        ,  0.],
                [ 0.        ,  0.68160856,  0.        ,  0.],
                [ 0.05516453, -0.00299519, -1.00040019, -1.],
                [ 0.        ,  0.        , -0.20008004,  0.]
            ])
            modelview = np.array([#the matrix generated captured while using HTC Vive
                [ 0.99030989,  0.04490654,  0.13141415,  0.],
                [-0.01430531,  0.9742285 , -0.22510922,  0.],
                [-0.13813627,  0.22104797,  0.9654305 ,  0.],
                [-0.12975544, -0.9294402 , -1.06236947,  1.]
            ])
     
            start_time = time.time()
            while time.time() - start_time < 5: #5 second animation
                self.display_gl( modelview, projection)
                pygame.display.flip()
     
    if __name__ == '__main__':
        t = ColorCubeActor()
        t.main()

    I truly hope someone can help me with figuring this out. I need to render 2500 vertices (point cloud) and I have been trying to learn OpenGL for the last 3 days now but this is a part I have really gotten hung up on.

    Thanks so much!!

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,103
    Quote Originally Posted by logic1 View Post
    Code :
            self.sizes = np.ones(self.array_size)*10
    ...
            glBufferData(GL_ARRAY_BUFFER, self.sizes.nbytes, self.sizes, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            glEnableVertexAttribArray(ptSize_pointer) #Enable the attribute at that location
            glVertexAttribPointer(ptSize_pointer, 1, GL_FLOAT, GL_FALSE, 0, 0) #Tell OpenGL what the array contains:
    The glVertexAttribPointer() call tells OpenGL that the buffer contains floats, but it actually contains doubles (the default dtype for np.ones() is float64). You may run into similar issues with self.indices on 64-bit systems, as the default dtype for np.arange() will be int64 (it's whatever matches Python's "int" type, which is either 32-bit or 64-bit depending upon the build). The Python wrapper for glDrawElements() might convert the indices to the specified type, but glBufferData() cannot perform conversion because it doesn't know what you're going to do with the data.

    As a matter of course, you should use np.ascontiguousarray() with a specific dtype= parameter on any arrays which you're going to be passing to OpenGL. This will force them to the correct type, and will force views to be converted to arrays (the wrappers simply pass a pointer to the underlying buffer, so operations such as slicing and transposition will effectively be undone).

  3. #3
    Newbie Newbie
    Join Date
    Apr 2017
    Posts
    5
    Quote Originally Posted by GClements View Post
    As a matter of course, you should use np.ascontiguousarray() with a specific dtype= parameter on any arrays which you're going to be passing to OpenGL.
    I have made some changes and added np.ascontiguousarray() where I believe it should go. This didn't make much difference on my 64bit Win8.1 PC and the screen is still blank.

    However I have noticed that if I change my GLSL shader so that the point's color is static defined, for example:
    Code :
    void main()
    {
        _color = vec3(0.2, 0.5, 1.0); //light blue
        ...
    }

    Then I notice a small 1px dot in the center of the screen (and can only assume that all of the vertices are piled up in the same place).

    Feels like even though I am buffering data and not getting errors the attributes are always just zero valued and maybe

    Am I using glBindBuffer() correctly? I call it once for each pointer and continuously for the positions pointer?

    Code :
    #!/bin/env python
     
    # file color_cube_actor.py
     
    import time
    from textwrap import dedent
    import numpy as np
     
    from OpenGL.GL import * 
    from OpenGL.GL.shaders import compileShader, compileProgram
     
    import pygame
    from pygame.locals import *
     
    class ColorCubeActor(object):
     
        array_size = 100
     
        def __init__(self):
            self.program = 0
            self.scale = 0
     
            self.indices = np.ascontiguousarray( np.arange(self.array_size), dtype=np.int)
            self.colors = np.ascontiguousarray( np.tile(np.array([0.0,1.0,0.0]), (self.array_size,1)), dtype=np.float) #a bunch of green vertices
            self.sizes = np.ascontiguousarray( np.ones(self.array_size)*10, dtype=np.float)
     
        def init_gl(self):
            glEnable(GL_VERTEX_PROGRAM_POINT_SIZE) #allow the program to specify the point size
     
            vertex_shader = compileShader(dedent("""
                #version 450 core
     
                layout(location = 0) uniform mat4 Projection = mat4(1);
                layout(location = 4) uniform mat4 ModelView = mat4(1);
     
                in vec3 ptPosition;
                in float ptSize;
                in vec3 ptColor;
     
                out vec3 _color;
     
                void main()
                {
                    _color = vec3(0.2, 0.5, 1.0);//light blue     //ptColor;
                    gl_Position = Projection * ModelView * vec4(ptPosition, 1.0);
     
                    //use normalized device coordinates to calculate the PointSize of a vertex based on it's distance from the perspective camera.
     
                    vec3 ndc = gl_Position.xyz / gl_Position.w ; // perspective divide.
                    float zDist = 1.0-ndc.z ; // 1 is close (right up in your face,)
                    // 0 is far (at the far plane)
                    gl_PointSize = ptSize*zDist ; // between 0 and 50 now.
     
                }
                """), GL_VERTEX_SHADER)
     
            fragment_shader = compileShader(dedent("""
                #version 450 core
     
                in vec3 _color;
                out vec4 FragColor;
     
                void main() {
                    FragColor = vec4(_color, 1.0); //just pass a color to the vertex (results in a rectangle pixel)
                }
                """), GL_FRAGMENT_SHADER)
     
            self.program = compileProgram(vertex_shader, fragment_shader)
     
            #setup the vao and bind buffers 
            self.vao = glGenVertexArrays(1)
            glBindVertexArray(self.vao)
     
            self.ptSize = glGenBuffers(1) #bind buffer for point sizes
            glBindBuffer(GL_ARRAY_BUFFER, self.ptSize) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptSize_pointer = glGetAttribLocation(self.program, "ptSize") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, self.sizes.nbytes, self.sizes, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            ####glEnableVertexAttribArray(ptSize_pointer) #Enable the attribute at that location
            ####glVertexAttribPointer(ptSize_pointer, 1, GL_FLOAT, GL_FALSE, 0, 0) #Tell OpenGL what the array contains:
     
            self.ptColor = glGenBuffers(1) #bind buffer for point colors
            glBindBuffer(GL_ARRAY_BUFFER, self.ptColor) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptColor_pointer = glGetAttribLocation(self.program, "ptColor") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, self.colors.nbytes, self.colors, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            ####glEnableVertexAttribArray(ptColor_pointer) #Enable the attribute at that location
            ####glVertexAttribPointer(ptColor_pointer, 3, GL_FLOAT, GL_FALSE, 0, 0) #Tell OpenGL what the array contains:
     
        def setPoints(self, modelview, projection):
            self.scale += 0.0005
     
            #create dataset
            theta = np.linspace(-4 * np.pi, 4 * np.pi, self.array_size)
            z = np.linspace(-2, 2, self.array_size)
            r = z**2 + 1
            x = r * np.sin(theta)
            y = r * np.cos(theta)
            plot = np.ascontiguousarray(np.dstack((x,y,z)) * self.scale, dtype=np.float)
     
            self.ptPosition = glGenBuffers(1) #bind buffer for positions and copy data into buffer
            glBindBuffer(GL_ARRAY_BUFFER, self.ptPosition) #GL_ARRAY_BUFFER is the buffer type we use to feed attributes
            ptPosition_pointer = glGetAttribLocation(self.program, "ptPosition") #get the location of attribute "ptSize" from self.program
            glBufferData(GL_ARRAY_BUFFER, plot.nbytes, plot, GL_STREAM_DRAW) #feed the buffer, and let OpenGL know that we don't plan to
            glEnableVertexAttribArray(ptPosition_pointer) #Enable the attribute at that location
            glVertexAttribPointer(ptPosition_pointer, 3, GL_FLOAT, GL_FALSE, 0, 0)#Tell OpenGL what the array contains:
     
            glUniformMatrix4fv(0, 1, False, projection)
            glUniformMatrix4fv(4, 1, False, modelview)
     
            glDrawElements(GL_POINTS, self.array_size, GL_UNSIGNED_INT, self.indices)
     
        def display_gl(self, modelview, projection):
            glClear(GL_COLOR_BUFFER_BIT) #| GL_DEPTH_BUFFER_BIT)
            glUseProgram(self.program)
            self.setPoints(modelview, projection)
     
        def dispose_gl(self):
            glDeleteProgram(self.program)
            self.program = 0
     
        def main(self):
            pygame.init()
            pygame.display.set_mode((800, 600), HWSURFACE|OPENGL|DOUBLEBUF)
            self.init_gl()
     
            projection = np.array([#the matrix generated captured while using HTC Vive
                [ 0.75752085,  0.        ,  0.        ,  0.],
                [ 0.        ,  0.68160856,  0.        ,  0.],
                [ 0.05516453, -0.00299519, -1.00040019, -1.],
                [ 0.        ,  0.        , -0.20008004,  0.]
            ])
            modelview = np.array([#the matrix generated captured while using HTC Vive
                [ 0.99030989,  0.04490654,  0.13141415,  0.],
                [-0.01430531,  0.9742285 , -0.22510922,  0.],
                [-0.13813627,  0.22104797,  0.9654305 ,  0.],
                [-0.12975544, -0.9294402 , -1.06236947,  1.]
            ])
     
            start_time = time.time()
            while time.time() - start_time < 5: #5 second animation
                self.display_gl( modelview, projection)
                pygame.display.flip()
     
    if __name__ == '__main__':
        t = ColorCubeActor()
        t.main()

Similar Threads

  1. Passing an array of mat4's per instance
    By Septimra in forum OpenGL: Advanced Coding
    Replies: 3
    Last Post: 07-13-2015, 07:14 AM
  2. Replies: 1
    Last Post: 09-09-2013, 02:30 PM
  3. [C++] Passing array to opengl
    By imported_Silverlan in forum OpenGL: Basic Coding
    Replies: 3
    Last Post: 07-22-2013, 08:02 AM
  4. options for passing short array
    By noah_r in forum OpenCL
    Replies: 2
    Last Post: 10-22-2011, 06:15 PM
  5. Passing array of structures to GLSL
    By iris_raj in forum OpenGL: GLSL
    Replies: 4
    Last Post: 06-12-2007, 03:41 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean