Python Forum
PyGlet Trouble Drawing Cube.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PyGlet Trouble Drawing Cube.
#1
I missing something. Just can't get that cube to draw.
Using numpy and modern Opengl. My graphic card support upto 4.6.
import pyglet
from pyglet.gl import *
from pyglet.graphics.vertexbuffer import create_buffer
from random import randrange
import numpy as np
import ctypes
import math

#           base on gl3n row major
def perspective(width, height, fov, near, far):
    array = np.array([0 for i in range(16)], dtype=float).reshape(4,4)
    mat = np.matrix(array)
    aspect = width/height
    top = near * math.tan(fov * (math.pi/360.0))
    bottom = -top
    right = top * aspect
    left = -right

    mat[0,0] = (2 * near) / (right - left)
    mat[0,2] = (right + left) / (right - left)
    mat[1,1] = (2 * near) / (top - bottom)
    mat[1,2] = (top + bottom) / (top - bottom)
    mat[2,2] = -(far + near) / (far - near)
    mat[2,3] = -(2 * far + near)  / (far - near)
    mat[3,2] = -1
    return mat

def normalized(array):
    if np.linalg.norm(array) != 0:
        return array / np.linalg.norm(array)
    return array

def matrix_idenity():
    return np.matrix(np.identity(4, dtype=float))

def look_at(eye, target, up):
    look_dir = normalized(target - eye)
    up_dir = normalized(up)
    right_dir = normalized(np.cross(look_dir, up_dir))
    perp_up_dir = np.cross(right_dir, look_dir)

    mat = matrix_idenity()
    mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)])
    mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)])
    mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)])

    return mat

class Face:
    FRONT = 1     # counter clockwise
    BACK = 2
    LEFT = 4     # counter clockwise
    RIGHT = 8
    TOP = 16     # counter clockwise
    BOTTOM = 32
    ALL = 63

def create_cube(size, face=Face.ALL, element=True):
    array = np.array([
    size, size, size,       #0  + + +
    -size, -size, -size,    #1  - - -
    size, -size, -size,     #2  + - -
    size, size, -size,      #3  + + -
    -size, size, -size,     #4  - + -
    -size, size, size,      #5  - + +
    -size, -size, size,     #6  - - +
    size, -size, size       #7  + - +
    ], GLfloat)

    elements = np.array([], GLuint)
    if face & Face.BACK:
        elements = np.append(elements, [1,3,2,3,1,4])
    if face & Face.FRONT:
        elements = np.append(elements, [1,7,0,0,5,6])
    if face & Face.LEFT:
        elements = np.append(elements, [5,4,1,1,6,5])
    if face & Face.RIGHT:
        elements = np.append(elements, [0,2,3,2,0,7])
    if face & Face.TOP:
        elements = np.append(elements, [4,0,3,0,4,5])
    if face & Face.BOTTOM:
        elements = np.append(elements, [1,2,7,7,6,1])

    if element:
        return array, elements

    pylist = []
    for i in elements:
        n = i * 3
        pylist.extend(array[n:n + 3])

    return np.array(pylist, GLfloat)

class Shader:
    def __init__(self):
        self.program = GLuint(glCreateProgram())

        vbuffer = open('vshader.glsl', 'r')
        vshader = glCreateShader(GL_VERTEX_SHADER)
        vbuff = ctypes.create_string_buffer(vbuffer.read().encode())
        vtext = ctypes.cast(ctypes.pointer(ctypes.pointer(vbuff)), ctypes.POINTER(ctypes.POINTER(GLchar)))
        glShaderSource(vshader, 1, vtext, None)
        glCompileShader(vshader)

        success = GLint()
        infoLog = ctypes.create_string_buffer(512)
        glGetShaderiv(vshader, GL_COMPILE_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(vshader, 512, None, infoLog)
            print("Error: Vertex Shader ", infoLog.value)

        fbuffer = open('fshader.glsl', 'r')
        fshader = glCreateShader(GL_FRAGMENT_SHADER)
        fbuff = ctypes.create_string_buffer(fbuffer.read().encode())
        ftext = ctypes.cast(ctypes.pointer(ctypes.pointer(fbuff)), ctypes.POINTER(ctypes.POINTER(GLchar)))
        glShaderSource(fshader, 1, ftext, None)
        glCompileShader(fshader)

        glGetShaderiv(fshader, GL_COMPILE_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(fshader, 512, None, infoLog)
            print("Error: Fragment Shader ", infoLog.value)

        glAttachShader(self.program, vshader)
        glAttachShader(self.program, fshader)
        glLinkProgram(self.program)

        glGetProgramiv(self.program, GL_LINK_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(fshader, 512, None, infoLog)
            print("Error: Program ", infoLog.value)

        # clean up
        glDeleteShader(vshader)
        glDeleteShader(fshader)
        vbuffer.close()
        fbuffer.close()

    def uniformMatrix4fv(self, key, count, transpose, value):
        buff = ctypes.create_string_buffer(key.encode())
        location = glGetUniformLocation(self.program, buff)
        nvalue = np.array(value, GLfloat) # .flatten()
        nref = nvalue.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
        glUniformMatrix4fv(location, count, transpose, nref)

    def use(self):
        glUseProgram(self.program)

    def destroy(self):
        glDeleteProgram(self.program)

class Window(pyglet.window.Window):
    def __init__(self):
        pyglet.window.Window.__init__(self)
        self.context.config.alpha_size = 8
        self.context.config.buffer_size = 32
        self.context.config.sample_buffers = 1
        self.context.config.samples = 4

        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LESS)
        glClearColor(0.1, 0.0, 0.0, 1.0)
        glViewport(0, 0, self.width, self.height)
        print(self.width, self.height)

        self.model = matrix_idenity()
        eye = np.array([0,0,4], dtype=float)
        self.view = look_at(eye,
            eye + np.array([0,0,4], dtype=float),
            np.array([0,0,4], dtype=float))

        self.projection = perspective(self.width, self.height, 45.0, 1.0, 100.0)

        self.vertices = create_cube(0.4, element=False)
        self.vertices[2::3] -= 8
        print(self.vertices[:6])
        colors = []
        for i in range(6):
            color = [randrange(20, 256), randrange(20, 256), randrange(20, 256)]
            colors.extend(color + color + color + color + color + color)

        #self.cube = pyglet.graphics.vertex_list(36, ('v3f', verticies), ('c3B/static', colors))
        self.vao = GLuint()
        glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        self.vbo = create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW)
        self.vbo.bind()
        self.vbo.set_data(self.vertices.ctypes.data)


        #glGenBuffers(1, pointer(self.VBO))
        #glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, self.vertices, GL_STATIC_DRAW)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, self.vertices.nbytes, 0);
        glEnableVertexAttribArray(0);
        glBindVertexArray(0);

        self.shader = Shader()

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.shader.use()
        self.shader.uniformMatrix4fv('view', 1, GL_TRUE, self.view)
        self.shader.uniformMatrix4fv('model', 1, GL_TRUE, self.model)
        self.shader.uniformMatrix4fv('proj', 1, GL_TRUE, self.projection)

        glBindVertexArray(self.vao);
        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))
        glBindVertexArray(0)

if __name__ == '__main__':
    window = Window()
    pyglet.app.run()
Shaders
#version 330 core

layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main()
{
	gl_Position = proj * view * model * vec4(position, 1.0f);
}
#version 330 core

void main()
{
	gl_FragColor = vec4(0.0, 0.0, 0.6, 1.0);
}
99 percent of computer problems exists between chair and keyboard.
Reply
#2
I have the cube drawing but the color is off. Color is to be on 1 side.
import pyglet
from pyglet.gl import *
from pyglet.graphics.vertexbuffer import create_buffer
from random import randrange
import numpy as np
import ctypes
import math
import os

#           base on gl3n row major
def perspective(width, height, fov, near, far):
    array = np.array([0 for i in range(16)], dtype=GLfloat).reshape(4,4)
    mat = np.matrix(array)
    aspect = width/height
    top = near * math.tan(fov * (math.pi/360.0))
    bottom = -top
    right = top * aspect
    left = -right

    mat[0,0] = (2 * near) / (right - left)
    mat[0,2] = (right + left) / (right - left)
    mat[1,1] = (2 * near) / (top - bottom)
    mat[1,2] = (top + bottom) / (top - bottom)
    mat[2,2] = -(far + near) / (far - near)
    mat[2,3] = -(2 * far + near)  / (far - near)
    mat[3,2] = -1
    return mat

def normalized(array):
    if np.linalg.norm(array) != 0:
        return array / np.linalg.norm(array)
    return array

def matrix_idenity():
    return np.matrix(np.identity(4, GLfloat))

def look_at(eye, target, up):
    look_dir = normalized(target - eye)
    up_dir = normalized(up)
    right_dir = normalized(np.cross(look_dir, up_dir))
    perp_up_dir = np.cross(right_dir, look_dir)

    mat = matrix_idenity()
    mat[0] = np.append(right_dir, [-np.dot(eye, right_dir)])
    mat[1] = np.append(perp_up_dir, [-np.dot(eye, perp_up_dir)])
    mat[2] = np.append(-look_dir, [np.dot(eye, look_dir)])

    return mat

def unit_vector(data):
    data = np.array(data, dtype=GLfloat, copy=True)
    if data.ndim == 1:
        data /= math.sqrt(np.dot(data, data))
        return data

def rotation(alpha, axis):
    cosa = math.cos(alpha)
    sina = math.sin(alpha)
    axis = unit_vector(axis)
    R = np.diag([cosa, cosa, cosa])
    R += np.outer(axis, axis) * (1.0 - cosa)
    axis *= sina
    R += np.array([[0.0, -axis[2], axis[1]],
                   [axis[2], 0.0, -axis[0]],
                   [-axis[1], axis[0], 0.0]], GLfloat)
    M = np.identity(4)
    M[:3, :3] = R
    return M

class Face:
    FRONT = 1     # counter clockwise
    BACK = 2
    LEFT = 4     # counter clockwise
    RIGHT = 8
    TOP = 16     # counter clockwise
    BOTTOM = 32
    ALL = 63

def create_cube(size, face=Face.ALL, element=True):
    array = np.array([
    size, size, size,       #0  + + + right   top      front
    -size, -size, -size,    #1  - - - left    bottom   back
    size, -size, -size,     #2  + - - right   bottom   back
    size, size, -size,      #3  + + - right   top      back
    -size, size, -size,     #4  - + - left    top      back
    -size, size, size,      #5  - + + left    top      front
    -size, -size, size,     #6  - - + left    bottom   front
    size, -size, size       #7  + - + right   bottom   front
    ], GLfloat)

    elements = np.array([], GLuint)
    if face & Face.BACK:
        elements = np.append(elements, [1,3,2,3,1,4])
    if face & Face.FRONT:
        elements = np.append(elements, [6,7,0,0,5,6])
    if face & Face.LEFT:
        elements = np.append(elements, [5,4,1,1,6,5])
    if face & Face.RIGHT:
        elements = np.append(elements, [0,2,3,2,0,7])
    if face & Face.TOP:
        elements = np.append(elements, [4,0,3,0,4,5])
    if face & Face.BOTTOM:
        elements = np.append(elements, [1,2,7,7,6,1])

    if element:
        return array, elements

    pylist = []
    for i in elements:
        n = i * 3
        pylist.extend(array[n:n + 3])

    return np.array(pylist, GLfloat)

class Shader:
    def __init__(self, vstring, fstring):
        self.program = GLuint(glCreateProgram())

        if not os.path.exists(vstring):
            print(vstring, "doesn't exists")
            return

        if not os.path.exists(fstring):
            print(fstring, "doesn't exists")
            return

        vbuffer = open(vstring, 'r')
        vshader = glCreateShader(GL_VERTEX_SHADER)
        vbuff = ctypes.create_string_buffer(vbuffer.read().encode())
        vtext = ctypes.cast(ctypes.pointer(ctypes.pointer(vbuff)), ctypes.POINTER(ctypes.POINTER(GLchar)))
        glShaderSource(vshader, 1, vtext, None)
        glCompileShader(vshader)

        success = GLint()
        infoLog = ctypes.create_string_buffer(512)
        glGetShaderiv(vshader, GL_COMPILE_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(vshader, 512, None, infoLog)
            print("Error: Vertex Shader ", infoLog.value)

        fbuffer = open(fstring, 'r')
        fshader = glCreateShader(GL_FRAGMENT_SHADER)
        fbuff = ctypes.create_string_buffer(fbuffer.read().encode())
        ftext = ctypes.cast(ctypes.pointer(ctypes.pointer(fbuff)), ctypes.POINTER(ctypes.POINTER(GLchar)))
        glShaderSource(fshader, 1, ftext, None)
        glCompileShader(fshader)

        glGetShaderiv(fshader, GL_COMPILE_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(fshader, 512, None, infoLog)
            print("Error: Fragment Shader ", infoLog.value)

        glAttachShader(self.program, vshader)
        glAttachShader(self.program, fshader)
        glLinkProgram(self.program)

        glGetProgramiv(self.program, GL_LINK_STATUS, ctypes.byref(success))
        if not success:
            glGetShaderInfoLog(fshader, 512, None, infoLog)
            print("Error: Program ", infoLog.value)

        # clean up
        glDeleteShader(vshader)
        glDeleteShader(fshader)
        vbuffer.close()
        fbuffer.close()

    def uniformMatrix4fv(self, key, count, transpose, value):
        buff = ctypes.create_string_buffer(key.encode())
        location = glGetUniformLocation(self.program, buff)
        nvalue = np.array(value, GLfloat) # .flatten()
        nref = nvalue.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
        glUniformMatrix4fv(location, count, transpose, nref)

    def use(self):
        glUseProgram(self.program)

    def destroy(self):
        glDeleteProgram(self.program)

class Window(pyglet.window.Window):
    def __init__(self):
        pyglet.window.Window.__init__(self)
        self.context.config.alpha_size = 8
        self.context.config.buffer_size = 32
        self.context.config.sample_buffers = 1
        self.context.config.samples = 4

        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LESS)
        glClearColor(0.1, 0.0, 0.0, 1.0)
        glViewport(0, 0, self.width, self.height)

        self.model = matrix_idenity()
        self.view = look_at(
            np.array([4,3,3], dtype=GLfloat),
            np.array([0,0,0], dtype=GLfloat),
            np.array([0,1,0], dtype=GLfloat))

        self.projection = perspective(self.width, self.height, 45.0, 1.0, 100.0)
        self.mvp = self.projection * self.view * self.model

        self.vertices = create_cube(0.6, element=False)
        print("How many vertices.", len(self.vertices) / 3)
        color_choice = [[1.0,0.0,0.0], [0.0,1.0,0.0], [0.0,0.0,1.0],
            [1.0,0.0,1.0], [1.0,1.0,0.0], [0.0,0.5,1.0]]
        colors = []
        for i in range(6):
            color = color_choice[i]
            colors.extend(color + color + color + color + color + color)
        self.colors = np.array(colors, GLfloat)
        print("How many colors.", len(self.colors) / 3)

        self.vao = GLuint()
        glGenVertexArrays(1, self.vao)
        glBindVertexArray(self.vao)

        self.vbo = create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW)
        self.vbo.set_data(self.vertices.ctypes.data)
        self.vbo.bind()

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(0);

        self.color_vbo = create_buffer(self.colors.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW)
        self.color_vbo.set_data(self.colors.ctypes.data)
        self.color_vbo.bind()

        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(1);
        glBindVertexArray(0);

        self.tick = 0.0
        self.shader = Shader('vshader.glsl', 'fshader.glsl')
        pyglet.clock.schedule_interval(self.tick_update, 1.0 / 60.0)

    def tick_update(self, dt):
        self.tick += dt
        self.model = rotation(self.tick, np.array([0.1, 0.2, 0.3], GLfloat))
        self.mvp = self.projection * self.view * self.model

    def on_draw(self):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.shader.use()
        self.shader.uniformMatrix4fv('mvp', 1, GL_TRUE, self.mvp)

        glBindVertexArray(self.vao);
        glDrawArrays(GL_TRIANGLES, 0, len(self.vertices))
        glBindVertexArray(0)

    def clean_up(self):
        self.vbo.delete()
        self.color_vbo.delete()
        glDeleteVertexArrays(1, self.vao)

if __name__ == '__main__':
    window = Window()
    pyglet.app.run()
    window.clean_up()
shaders : edit replace duplicate fragment shader with vertex shader
#version 330 core

layout (location = 0) in vec3 position;
layout (location = 0) in vec3 color;

out vec3 fragColor;
uniform mat4 mvp;

void main()
{
	gl_Position = mvp * vec4(position, 1.0f);
    fragColor = color;
}
#version 330 core

in vec3 fragColor;
out vec3 color;

void main()
{
	color = fragColor;
}

Okay all figure out. Replace duplicate fragment shader above.
Color mistake was because I forgot to change layout location to 1.
layout (location = 0) in vec3 color;
to
layout (location = 1) in vec3 color;
99 percent of computer problems exists between chair and keyboard.
Reply
#3
Thanks for sharing what the solution was :)

Also, thanks for sharing some code, I was recently wondering if python could use shaders easily, and it doesn't look that difficult at all.
Reply
#4
Shaders has nothing to do with python. Shaders are all opengl.
I was pulling my hair out. Dealing with pyglet and ctypes for the first time.
Doing this in D with opengl was simple. No ctypes.

Wish PyGlet wrap the cytpes. For I don't have to deal with them.
Need another option for opengl in python with no ctypes.
99 percent of computer problems exists between chair and keyboard.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Drawing a net of a cube freethrownucleus 26 4,703 May-05-2023, 10:23 PM
Last Post: freethrownucleus
  Cube drawing freethrownucleus 51 9,198 Apr-12-2023, 08:04 AM
Last Post: ClaytonMorrison
  2D-Cube-Tic-Tac-Toe freethrownucleus 0 1,109 Mar-10-2023, 07:07 PM
Last Post: freethrownucleus
  Pygame or Pyglet luke83 4 4,023 Nov-20-2020, 09:15 PM
Last Post: luke83
  [Pyglet] pyglet freezing pfaber11 1 2,828 Jun-06-2019, 04:31 PM
Last Post: Windspar
  problems with pyglet error catching jotes 1 2,575 Jul-24-2018, 11:34 AM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020