I am trying to make sphere with OpenGL in Python but only single red dot appears in the center of screen. My code is as follow
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
try:
glUseProgram(self.shader)
glBindVertexArray(self.vao)
glDrawArrays(GL_POINTS, 0, int(self.buff_size/3))
finally:
glBindVertexArray(0)
glUseProgram(0)
def geometry(self):
self.vao = glGenVertexArrays(1)
self.vbo = glGenBuffers(1)
lats = 180
longs = 360
r = 0.5
data = []
for i in range(lats):
lat0 = np.pi * (-0.5 + (i - 1) / lats)
z0 = np.sin(lat0)
zr0 = np.cos(lat0)
lat1 = np.pi * (-0.5 + i / lats)
z1 = np.sin(lat1)
zr1 = np.cos(lat1)
for j in range(longs):
lng = 2 * np.pi * (j - 1) / longs
x_cord = np.cos(lng)
y = np.sin(lng)
data.extend([x_cord * zr0, y * zr0, z0])
data.extend([r * x_cord * zr0, r * y * zr0, r * z0])
data.extend([x_cord * zr1, y * zr1, z1])
data.extend([r * x_cord * zr1, r * y * zr1, r * z1])
data_input = np.array(data, dtype=np.float32)
self.buff_size = len(data_input)
vertex_size = int(data_input.nbytes / self.buff_size) * 3
glUseProgram(self.shader)
glBindVertexArray(self.vao)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, data_input.nbytes, data_input, GL_DYNAMIC_DRAW)
self.vertex_position = glGetAttribLocation(self.shader, 'position')
glVertexAttribPointer(self.vertex_position, 3, GL_FLOAT, GL_FALSE, vertex_size, None)
glEnableVertexAttribArray(self.vertex_position)
glDisableVertexAttribArray(self.vertex_position)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
glUseProgram(0)
Shader for my program is:
self.vertex_shader = shaders.compileShader(
"""
#version 330
in vec3 pos;
uniform mat4 movement;
void main()
{
gl_Position = movement * vec4(pos, 1.0);
}
"""
, GL_VERTEX_SHADER
)
self.fragment_shader = shaders.compileShader(
"""
#version 330
out vec4 gl_FragColor;
void main()
{
gl_FragColor = vec4(1.0,0.0,0.5,1.0);
}
"""
, GL_FRAGMENT_SHADER
)
self.shader = shaders.compileProgram(self.vertex_shader, self.fragment_shader)
I don't know where I'm having issue. I also tried using indices with GL_ELEMENT_ARRAY_BUFFER
and glDrawElements
as GL_QUAD_STRIP
but no success. If you know how I can fix this then please share. Thanks
The name of the vertex attribute is pos
:
in vec3 pos;
So the argument to glGetAttribLocation
has to be 'pos' rather than 'position':
self.vertex_position = glGetAttribLocation(self.shader, 'position')
self.vertex_position = glGetAttribLocation(self.shader, 'pos')
If the specification and enable state is stored in the Vertex Array Object. If you glDisableVertexAttribArray(self.vertex_position)
, this state is stored to the self.vao
. Remove it:
glBindVertexArray(self.vao)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, data_input.nbytes, data_input, GL_DYNAMIC_DRAW)
self.vertex_position = glGetAttribLocation(self.shader, 'pos')
glVertexAttribPointer(self.vertex_position, 3, GL_FLOAT, GL_FALSE, vertex_size, None)
glEnableVertexAttribArray(self.vertex_position)
#glDisableVertexAttribArray(self.vertex_position) # <--- DELETE
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
A matrix unfiorm be default is initialized with all fields 0.
uniform mat4 movement;
If you do not need the uniform, then remove it. Or initialize it by the Identity matrix.
glUseProgram(self.shader)
ident4x4 = np.identity(4, np.float32)
self.movement_loc = glGetUniformLocation(self.shader, 'movement')
glUniformMatrix4fv(self.movement_loc, 1, GL_FALSE, ident4x4)
Alternatively you can use a view and perspective projection matrix (self.width
and self.height
are the width and height of the window):
# projection matrix
aspect, ta, near, far = self.width/self.height, np.tan(np.radians(90.0) / 2), 0.1, 10
proj = np.matrix(((1/ta/aspect, 0, 0, 0), (0, 1/ta, 0, 0), (0, 0, -(far+near)/(far-near), -1), (0, 0, -2*far*near/(far-near), 0)), np.float32)
# view matrix
view = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, -3, 1)), np.float32)
glUniformMatrix4fv(self.movement_loc, 1, GL_FALSE, view * proj)