DuckyShine
DuckyShine

Reputation: 11

OpenGL Cube w/ Python pyopengl

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

Answers (0)

Related Questions