I am trying to render 3 points with different colours, using a single VBO and shaders. I am passing the location and colour values to a single VBO:
vertices = np.array([[0, 0.1, 0.6, 1, 1, 0], [0.3, 0.1, 0, 0, 1, 1], [0.8, 0.5, 0, 0, 1, 0]], dtype='f')
which I'm then trying to read into my shaders. I add alpha in the fragment shader. I'm using glVertexAttribPointer
to differentiate between my x,y,z and my r,g,b,a. I am able to render my x,y,z:
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "position"))
glVertexAttribPointer(glGetAttribLocation(shader_program, "position"), 3, GL_FLOAT, False, 6*4, None)
I am unable to load my r,g,b,a by using glVertexAttribPointer
as I understand it from the docs:
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "color"))
glVertexAttribPointer(glGetAttribLocation(shader_program, "color"), 3, GL_FLOAT, False, 6*4, 3*4)
This does not render any visible points. My shaders are definitely working, as when I change the byte offset of my Pointer to None:
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "color")) glVertexAttribPointer(glGetAttribLocation(shader_program, "color"), 3, GL_FLOAT, False, 6*4, None)
my points are coloured according to my normalized x,y,z coordinates (i.e glVertexAttribPointer
interprets my x coordinate as r, y coordinate as g, z coordinate as b), which makes sense as the byte offset is 0. Surely the byte offset should be 3*4? My two thoughts were that I've either
glVertexAttribPointer
or but I've tried changing the ordering of my colours, adding alpha to the original dataset etc with no success. Any help appreciated.
Full code:
from OpenGL.arrays import vbo
import pygame
import numpy as np
from OpenGL.GL import *
from OpenGL.GL.shaders import *
def getFileContent(file):
content = open(file, 'r').read()
return content
def run():
pygame.init()
screen = pygame.display.set_mode((800,600), pygame.OPENGL | pygame.DOUBLEBUF)
vertices = np.array([[0, 0.1, 0.6, 1, 1, 0], [0.3, 0.1, 0, 0, 1, 1], [0.8, 0.5, 0, 0, 1, 0]], dtype='f')
vertexPositions = vbo.VBO(vertices)
indices = np.array([[0,1,2]], dtype=np.int32)
indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)
shader_program = glCreateProgram()
vertex_source = compileShader(getFileContent("testing_vert_shader.vert"), GL_VERTEX_SHADER)
fragment_source = compileShader(getFileContent("testing_frag_shader.frag"), GL_FRAGMENT_SHADER)
glAttachShader(shader_program, vertex_source)
glAttachShader(shader_program, fragment_source)
glBindAttribLocation(shader_program, 0, "position")
glBindAttribLocation(shader_program, 1, "color")
glLinkProgram(shader_program)
print(glGetProgramiv(shader_program, GL_LINK_STATUS)) # shader linked == 1
while True:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(shader_program)
indexPositions.bind()
vertexPositions.bind()
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "position"))
glVertexAttribPointer(glGetAttribLocation(shader_program, "position"), 3, GL_FLOAT, False, 6*4, None)
# red vertices rendered if these two lines are commented out
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "color"))
glVertexAttribPointer(glGetAttribLocation(shader_program, "color"), 3, GL_FLOAT, False, 6*4, None) # changing last argument of glVertexAttribPointer to None results in x,y,z being read as colours
glDrawElements(GL_POINTS, 3, GL_UNSIGNED_INT, None)
# Show the screen
pygame.display.flip()
run()
Vertex shader:
#version 330 core
in vec3 position;
in vec3 color;
out vec3 vColor;
void main()
{
gl_Position = vec4(position, 1.0);
vColor = vec3(color);
}
Fragment shader:
#version 330 core
in vec3 vColor;
out vec4 outcolor;
void main()
{
outcolor = vec4(vColor, 1.0f);
}
If a named buffer object is bound, then the 5th parameter of glVertexAttribPointer
is treated as a byte offset into the buffer object's data store. However, the type of the parameter is still a pointer (c_void_p
).
Hence the offset must be cast with c_void_p
. If the offset is 0, the 5th parameter can either be None
or c_void_p(0)
:
loc_col = glGetAttribLocation(shader_program, "color")
glVertexAttribPointer(loc_col, 3, GL_FLOAT, False, 6*4, ctypes.c_void_p(3*4))