PyGlet Trouble Drawing Cube. - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: PyGlet Trouble Drawing Cube. (/thread-7126.html) |
PyGlet Trouble Drawing Cube. - Windspar - Dec-21-2017 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); } RE: PyGlet Trouble Drawing Cube. - Windspar - Dec-25-2017 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; RE: PyGlet Trouble Drawing Cube. - nilamo - Jan-02-2018 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. RE: PyGlet Trouble Drawing Cube. - Windspar - Jan-02-2018 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. |