Reputation: 11
I am writing a opengl application that renders a simple green colored cube, but unfortunately it does not. So far the project consists of a camera and obviously, the cube. I do not think the underlying problem is the camera as the projection does not affect the vertices of the cube in any way and I have tested my camera with glm's camera.
I think the underlying problem is how I have setup my vertices and vbo, but I do not know how to fix this.
Here is my code to retrieve a cube model:
import numpy
import ctypes
from OpenGL.GL import *
from OpenGL.GL import shaders
class Model:
def __init__(self, app):
self.app = app
self.vertex_data = self.get_vertex_data()
self.vbo = self.get_vbo()
self.program = self.get_shader_program()
self.vao = self.get_vao()
self.m_model = self.get_model_matrix()
self.locations = {}
self.initialize_uniforms()
def get_model_matrix(self):
return numpy.matrix(numpy.identity(4), copy = False, dtype = numpy.float32)
def SetUniformLocation(self, program, variable):
self.locations[variable] = glGetUniformLocation(program, variable)
def get_vertex_data(self):
vertices = [(-1, -1, 1), ( 1, -1, 1), ( 1, 1, 1), (-1, 1, 1),
(-1, 1, -1), (-1, -1, -1), ( 1, -1, -1), ( 1, 1, -1)]
indices = [(0, 2, 3), (0, 1, 2),
(1, 7, 2), (1, 6, 7),
(6, 5, 4), (4, 7, 6),
(3, 4, 5), (3, 5, 0),
(3, 7, 4), (3, 2, 7),
(0, 6, 1), (0, 5, 6)]
vertex_data = self.get_data(vertices, indices)
return vertex_data
@staticmethod
def get_data(vertices, indices):
data = [vertices[index] for triangle in indices for index in triangle]
return numpy.array(data, dtype = numpy.float32)
def get_shader_program(self, vertex_shader_filename = 'vertex', fragment_shader_filename = 'fragment'):
with open(f'shaders/{vertex_shader_filename}.glsl') as file:
vertex_shader = file.read()
with open(f'shaders/{fragment_shader_filename}.glsl') as file:
fragment_shader = file.read()
vertex_shader = shaders.compileShader(vertex_shader, GL_VERTEX_SHADER)
fragment_shader = shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER)
program = shaders.compileProgram(vertex_shader, fragment_shader)
return program
def get_vbo(self):
vertex_data = self.vertex_data
# Generate a buffer and bind it to the program
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, 24 * vertex_data.nbytes, vertex_data, GL_STATIC_DRAW)
return vbo
def get_vao(self):
vertex_data = self.vertex_data
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
glEnableVertexAttribArray(0)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
return vao
def initialize_uniforms(self):
program = self.program
# Make sure the program exists
glUseProgram(program)
# Matrix uniforms
self.SetUniformLocation(program, "m_perspective")
self.SetUniformLocation(program, "m_view")
self.SetUniformLocation(program, "m_model")
self.SetUniformLocation(program, "rotation")
def render(self):
locations = self.locations
glBindVertexArray(self.vao)
glUniformMatrix4fv(locations["m_perspective"], 1, GL_FALSE, self.app.camera.m_perspective)
glUniformMatrix4fv(locations["m_view"], 1, GL_FALSE, self.app.camera.m_view)
glUniformMatrix4fv(locations["m_model"], 1, GL_FALSE, self.m_model)
glDrawArrays(GL_TRIANGLES, 0, len(self.vertex_data))
I strongly believe the error lies in the vbo but I do not know how to fix it.
Also here is the code to the camera in case I am wrong about my judegment:
import numpy
import math
class Camera:
FAR = 0.1
NEAR = 100
FOV = 90
def __init__(self, app, position = (0, 0, 1), target = (0, 0, 0)):
self.app = app
self.aspect_ratio = self.app.WINDOWWIDTH / self.app.WINDOWHEIGHT
self.position = numpy.array(position)
self.target = numpy.array(target)
self.forward = numpy.array([ 0, 0, -1])
self.right = numpy.array([ 1, 0, 0])
self.up = numpy.array([ 0, 1, 0])
self.m_perspective = self.get_perspective_matrix()
self.m_view = self.get_view_matrix()
def Normalize(self, v):
return v / numpy.linalg.norm(v)
def Dot(self, a, b):
return numpy.dot(a, b)
def Cross(self, a, b):
return numpy.cross(a, b)
def get_perspective_matrix(self):
fn = self.FAR + self.NEAR
f_n = self.FAR - self.NEAR
r = self.aspect_ratio
t = 1 / math.tan(math.radians(self.FOV) / 2)
perspective_matrix = numpy.matrix([
[ t/r, 0, 0, 0],
[ 0, t, 0, 0],
[ 0, 0, -fn/f_n, -1],
[ 0, 0, -2 * self.FAR * self.NEAR / f_n, 0]], dtype = numpy.float32)
return perspective_matrix
def get_view_matrix(self):
f = self.Normalize(self.position - self.target)
l = self.Normalize(self.Cross(self.up, f))
u = self.Cross(f, l)
dl = -self.Dot(l, self.position)
du = -self.Dot(u, self.position)
df = -self.Dot(f, self.position)
view_matrix = numpy.matrix([
[l[0], l[1], l[2], dl],
[u[0], u[1], u[2], du],
[f[0], f[1], f[2], df],
[ 0, 0, 0, 1]], dtype = numpy.float32)
return view_matrix
And the two respective shaders:
Vert:
# version 330 core
layout (location = 0) in vec3 in_position;
uniform mat4 m_perspective;
uniform mat4 m_view;
uniform mat4 m_model;
void main () {
gl_Position = m_view * m_perspective * m_model * vec4(in_position.xy, in_position.z - 2.5, 1.0);
}
Frag:
# version 330 core
layout (location = 0) out vec4 fragColor;
void main() {
vec3 color = vec3(0.0, 1.0, 0.0);
fragColor = vec4(color, 1.0);
}
Upvotes: 1
Views: 194