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:
[ATTACH=CONFIG]1459[/ATTACH]
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.
#!/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!!