def load_object(self, object, obj_idx=None, smooth=False, wireframe=False): vertex_data = None if isinstance(object, str): object = ShapeModel(fname=object) elif isinstance(object, Obj): vertex_data = object assert not smooth, 'not supported' if isinstance(object, ShapeModel): if smooth: verts, tex, norms, faces = object.export_smooth_faces() else: verts, tex, norms, faces = object.export_angular_faces() vertex_data = Obj(verts, tex, norms, faces) texture_data = object.load_texture() assert vertex_data is not None, 'wrong object type' if wireframe: w_vbo = self._ctx.buffer(vertex_data.pack('vx vy vz')) w_obj = self._ctx.simple_vertex_array(self._wireframe_prog, w_vbo, 'vertexPosition_modelFrame') else: texture = None if texture_data is not None: texture = self._ctx.texture(texture_data.T.shape, 1, np.flipud(texture_data).tobytes()) texture.build_mipmaps() vbo = self._ctx.buffer(vertex_data.pack('vx vy vz nx ny nz tx ty')) obj = self._ctx.simple_vertex_array(self._prog, vbo, 'vertexPosition_modelFrame', 'vertexNormal_modelFrame', 'aTexCoords') s_vbo = self._ctx.buffer(vertex_data.pack('vx vy vz')) s_obj = self._ctx.simple_vertex_array(self._shadow_prog, s_vbo, 'vertexPosition_modelFrame') if obj_idx is None: if wireframe: self._w_objs.append(w_obj) else: self._objs.append(obj) self._s_objs.append(s_obj) self._raw_objs.append(vertex_data) self._textures.append(texture) else: if wireframe: self._w_objs[obj_idx] = w_obj else: self._objs[obj_idx] = obj self._s_objs[obj_idx] = s_obj self._raw_objs[obj_idx] = vertex_data self._textures[obj_idx] = texture return len(self._w_objs if wireframe else self._objs)-1
def load_meshes_and_textures(self, path): meshes = {} mesh_attributes = {} try: with open(os.path.join(path, "config.yaml"), "r") as config: try: mesh_attributes = yaml.safe_load(config) except yaml.YAMLError as exc: raise Exception(exc) except EnvironmentError as e: print("[!] Could not load mesh attributes file:\ {}".format(os.path.join(path, "config.yaml"))) raise EnvironmentError(e) for file in os.listdir(path): if os.path.isfile(os.path.join(path, file)): if file.endswith('_frame.obj'): file_name = os.path.split(file)[-1] try: obj_file = Obj.open(os.path.join(path, file_name)) contour_obj_front_file = Obj.open( os.path.join(path, mesh_attributes[file_name]['contour_front'])) contour_obj_back_file = Obj.open( os.path.join(path, mesh_attributes[file_name]['contour_back'])) contour_png = Image.open( os.path.join( path, mesh_attributes[file_name]['texture']) ).transpose(Image.FLIP_LEFT_RIGHT).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') contour_texture = self.context.texture( contour_png.size, 3, contour_png.tobytes()) contour_texture.build_mipmaps() except Exception as e: raise Exception(e) meshes[file_name] = { 'center': Vector3(mesh_attributes[file_name]['center']), 'width': mesh_attributes[file_name]['width'], 'height': mesh_attributes[file_name]['height'], 'contour_obj_front': contour_obj_front_file, 'contour_obj_back': contour_obj_back_file, 'contour_texture': contour_texture, 'obj': obj_file } if len(meshes.items()) is 0: raise Exception("Meshes not loaded!") return meshes
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { gl_Position = Mvp * vec4(in_vert, 1.0); v_vert = in_vert; v_norm = in_norm; v_text = in_text; } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; f_color = vec4(texture(Texture, v_text).rgb * lum, 1.0); } '''), ]) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] obj = Obj.open(local('data', 'crate.obj')) img = Image.open(local('data', 'crate.png')).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') self.texture = self.ctx.texture(img.size, 3, img.tobytes()) self.texture.use() self.vbo = self.ctx.buffer(obj.pack('vx vy vz nx ny nz tx ty')) self.vao = self.ctx.simple_vertex_array( self.prog, self.vbo, ['in_vert', 'in_norm', 'in_text'])
def load_obj(self, filename): if not os.path.isfile(filename): print('{} is not an existing regular file!'.format(filename)) return obj = Obj.open(filename) # TODO: not very efficient, consider using an element index array later self.vao = self.ctx.simple_vertex_array( self.prog, self.ctx.buffer(obj.pack('vx vy vz tx ty')), ['in_vert', 'in_text'] )
import moderngl as ModernGL from ModernGL.ext.obj import Obj from PIL import Image from pyrr import Matrix44 # Data files vertex_data = Obj.open('data/sitting.obj').pack() texture_image = Image.open('data/wood.jpg') vertex_shader_source = open('data/shader.vert').read() fragment_shader_source = open('data/shader.frag').read() # Context creation ctx = ModernGL.create_standalone_context() # Shaders prog = ctx.program(vertex_shader=vertex_shader_source, fragment_shader=fragment_shader_source) # Matrices and Uniforms perspective = Matrix44.perspective_projection(45.0, 1.0, 0.1, 1000.0) lookat = Matrix44.look_at( (-85, -180, 140), (0.0, 0.0, 65.0), (0.0, 0.0, 1.0), ) mvp = perspective * lookat
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { gl_Position = Mvp * vec4(in_vert, 1.0); v_vert = in_vert; v_norm = in_norm; v_text = in_text; } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform vec3 Color; uniform bool UseTexture; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; if (UseTexture) { f_color = vec4(texture(Texture, v_text).rgb * lum, 1.0); } else { f_color = vec4(Color * lum, 1.0); } } '''), ]) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] self.color = self.prog.uniforms['Color'] self.use_texture = self.prog.uniforms['UseTexture'] self.objects = {} for name in [ 'ground', 'grass', 'billboard', 'billboard-holder', 'billboard-image' ]: obj = Obj.open(local('data', 'scene-1-%s.obj' % name)) vbo = self.ctx.buffer(obj.pack('vx vy vz nx ny nz tx ty')) vao = self.ctx.simple_vertex_array( self.prog, vbo, ['in_vert', 'in_norm', 'in_text']) self.objects[name] = vao img = Image.open(local('data', 'infographic-1.jpg')).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') self.texture1 = self.ctx.texture(img.size, 3, img.tobytes()) self.texture1.build_mipmaps() self.texture2 = self.ctx.texture(self.wnd.size, 3) depth_attachment = self.ctx.depth_renderbuffer(self.wnd.size) self.fbo = self.ctx.framebuffer(self.texture2, depth_attachment)
def initializeModernGL(self): """Initialize all things related to running modernGL """ self.ctx = mgl.create_context() self.prog = self.ctx.program( vertex_shader=''' #version 330 uniform mat4 Mvp; // Per vertex in vec3 in_vert_c; //in vec3 in_norm_c; in vec2 in_text_c; in vec3 in_vert_s; //in vec3 in_norm_s; in vec2 in_text_s; // Per object in vec3 in_pos; in mat3 in_rotMat; in vec3 in_size; in float texindex; in int shape; out vec3 v_vert; flat out int out_texindex; //out vec3 v_norm; out vec2 v_text; vec3 in_vert; vec2 in_text; //vec3 in_norm; void main() { // if shape is 0, it's a cube; if it's 1, it's a sphere if (shape==1) { in_vert = in_vert_s; v_text = in_text_s; //in_norm = in_norm_s; } else { in_vert = in_vert_c; v_text = in_text_c; //in_norm = in_norm_c; } v_vert = (in_vert * in_size) * in_rotMat + in_pos; //v_norm = (in_norm * in_size) * in_rotMat + in_pos; gl_Position = Mvp * vec4(v_vert, 1.0); out_texindex = int(texindex); } ''', fragment_shader=''' #version 330 uniform sampler2D textures[2]; //uniform vec3 Light; flat in int out_texindex; in vec3 v_vert; //in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { //float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; //vec3 base = vec3(0.5, 0.5, 0.5) * lum; //vec3 spec = vec3(1.0, 1.0, 1.0) * pow(lum, 6); vec4 tex = texture(textures[out_texindex], v_text); //f_color = vec4(base * 0.1 + tex.rgb * lum + spec, tex.a); f_color = vec4(tex.rgb, tex.a); } ''', ) # Assign self.mvp to the uniform Mvp in the modernGL program self.mvp = self.prog['Mvp'] # This should be programmatically determined, but basically I'm telling # the program that I've loaded two textures which can be accessed with # either a 0 or a 1 in the fragment shader. self.prog['textures'].value = [0, 1] # Haven't totally figured out how to use this stuff yet # self.light = self.prog.uniforms['Light'] # self.light.value = (0,0,0) #-140.0, -300.0, 350.0 # Uses an .obj file for vertex, texture, and surface normal information self.cubeobj = Obj.open(objDirectory + '\\cube\\cube.obj') self.sphereobj = Obj.open(objDirectory + '\\sphere\\Sphere.obj') # Each of these buffers provides the vertex and texture position info # to the vertex shader. Note that I should really be using a separate # program for cubes and spheres, but I've found a way to make this # work for now. # Only one gets used when rendering each entity. cubeVertBuffer = self.ctx.buffer(self.cubeobj.pack('vx vy vz tx ty')) sphereVertBuffer = self.ctx.buffer( self.sphereobj.pack('vx vy vz tx ty')) # entityBuffer is set up to provide the position, orientation, size, # texture index (each texture is loaded in Level), and shape type # (cube or sphere). self.entityBuffer = self.ctx.buffer(reserve=1024 * 1024) # Connect all of the buffers to a vertex array object which will be in # charge of rendering. vao_content = [ (cubeVertBuffer, '3f 2f', 'in_vert_c', 'in_text_c'), (sphereVertBuffer, '3f 2f', 'in_vert_s', 'in_text_s'), (self.entityBuffer, '3f 9f 3f 1f 1i/i', 'in_pos', 'in_rotMat', 'in_size', 'texindex', 'shape'), ] self.vao = self.ctx.vertex_array(self.prog, vao_content)
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec3 in_color; in vec3 in_origin; in mat3 in_basis; out vec3 v_vert; out vec3 v_norm; out vec3 v_color; void main() { v_vert = in_origin + in_basis * in_vert; v_norm = in_basis * in_norm; v_color = in_color; gl_Position = Mvp * vec4(v_vert, 1.0); } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec3 v_color; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; f_color = vec4(v_color * lum, 1.0); } '''), ]) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] obj = Obj.open(local('data', 'lowpoly_toy_car.obj')) self.vbo1 = self.ctx.buffer(obj.pack('vx vy vz nx ny nz')) self.vbo2 = self.ctx.buffer( struct.pack( '15f', 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, ) * len(cars)) self.vao = self.ctx.vertex_array(self.prog, [ (self.vbo1, '3f3f', ['in_vert', 'in_norm']), (self.vbo2, '3f3f9f/i', ['in_color', 'in_origin', 'in_basis']), ])
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_move; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { gl_Position = Mvp * vec4(in_vert + in_move, 1.0); v_vert = in_vert + in_move; v_norm = in_norm; v_text = in_text; } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; f_color = vec4(texture(Texture, v_text).rgb * lum, 1.0); } '''), ]) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] obj = Obj.open(local('data', 'crate.obj')) img = Image.open(local('data', 'crate.png')).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') self.texture = self.ctx.texture(img.size, 3, img.tobytes()) self.texture.build_mipmaps() self.texture.use() self.vbo1 = self.ctx.buffer(obj.pack('vx vy vz nx ny nz tx ty')) self.vbo2 = self.ctx.buffer(reserve=12 * 1024) self.vao = self.ctx.vertex_array(self.prog, [ (self.vbo1, '3f3f2f', ['in_vert', 'in_norm', 'in_text']), (self.vbo2, '3f/i', ['in_move']), ]) self.crate_a = np.random.uniform(0.7, 0.8, 32 * 32) self.crate_b = np.random.uniform(0.0, 6.3, 32 * 32) self.crate_x = (np.tile(np.arange(32), 32) - 16) * 1.5 self.crate_y = (np.repeat(np.arange(32), 32) - 16) * 1.5 self.crate_x += np.random.uniform(-0.2, 0.2, 32 * 32) self.crate_y += np.random.uniform(-0.2, 0.2, 32 * 32)
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.canvas_prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 in vec2 in_vert; out vec2 v_vert; void main() { gl_Position = vec4(in_vert * 2.0 - 1.0, 0.0, 1.0); v_vert = in_vert; } '''), self.ctx.fragment_shader(''' #version 330 uniform sampler2D Texture; in vec2 v_vert; out vec4 f_color; void main() { f_color = texture(Texture, v_vert); } '''), ]) self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { gl_Position = Mvp * vec4(in_vert, 1.0); v_vert = in_vert; v_norm = in_norm; v_text = in_text; } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; vec3 base = vec3(0.5, 0.5, 0.5) * lum; vec3 spec = vec3(1.0, 1.0, 1.0) * pow(lum, 5.7); vec4 tex = texture(Texture, v_text); f_color = vec4(base * 0.1 + tex.rgb * lum + spec, tex.a); } '''), ]) self.canvas_vbo = self.ctx.buffer( np.array([0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0], dtype='f4').tobytes()) self.canvas_vao = self.ctx.simple_vertex_array(self.canvas_prog, self.canvas_vbo, ['in_vert']) bg_img = Image.open(local('data', 'mug-background.jpg')).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') self.bg_texture = self.ctx.texture(bg_img.size, 3, bg_img.tobytes()) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] sticker_img = Image.open(local( 'data', 'mug-pymet-logo.png')).transpose( Image.FLIP_TOP_BOTTOM).convert('RGBA') self.sticker_texture = self.ctx.texture(sticker_img.size, 4, sticker_img.tobytes()) self.sticker_texture.build_mipmaps(0, 2) self.mug_texture = self.ctx.texture((1, 1), 3) self.mug_texture.write(struct.pack('3B', 10, 10, 10)) obj = Obj.open(local('data', 'mug.obj')) self.mug_vbo = self.ctx.buffer(obj.pack('vx vy vz nx ny nz tx ty')) self.mug_vao = self.ctx.simple_vertex_array( self.prog, self.mug_vbo, ['in_vert', 'in_norm', 'in_text']) segs = 32 radius = 29.94 bottom = 6.601 top = 57.856 left = -163.12 * np.pi / 180.0 right = 11.25 * np.pi / 180.0 lin = np.linspace(left, right, segs) sticker_vertices = np.array([ np.repeat(np.cos(lin) * radius, 2), np.repeat(np.sin(lin) * radius, 2), np.tile([bottom, top], segs), np.repeat(np.cos(lin), 2), np.repeat(np.sin(lin), 2), np.tile([0.0, 0.0], segs), np.repeat(np.linspace(0.0, 1.0, segs), 2), np.tile([0.0, 1.0], segs), ]) self.sticker_vbo = self.ctx.buffer( sticker_vertices.T.astype('f4').tobytes()) self.sticker_vao = self.ctx.simple_vertex_array( self.prog, self.sticker_vbo, ['in_vert', 'in_norm', 'in_text'])
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.obj = Obj.open( os.path.join(os.path.dirname(__file__), 'data', 'sitting_dummy.obj')) self.wood = Image.open( os.path.join(os.path.dirname(__file__), 'data', 'wood.jpg')) self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { v_vert = in_vert; v_norm = in_norm; v_text = in_text; gl_Position = Mvp * vec4(v_vert, 1.0); } '''), self.ctx.fragment_shader(''' #version 330 uniform sampler2D Texture; uniform vec4 Color; uniform vec3 Light; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = dot(normalize(v_norm), normalize(v_vert - Light)); lum = acos(lum) / 3.14159265; lum = clamp(lum, 0.0, 1.0); lum = lum * lum; lum = smoothstep(0.0, 1.0, lum); lum *= smoothstep(0.0, 80.0, v_vert.z) * 0.3 + 0.7; lum = lum * 0.8 + 0.2; vec3 color = texture(Texture, v_text).rgb; color = color * (1.0 - Color.a) + Color.rgb * Color.a; f_color = vec4(color * lum, 1.0); } '''), ]) self.light = self.prog.uniforms['Light'] self.color = self.prog.uniforms['Color'] self.mvp = self.prog.uniforms['Mvp'] self.texture = self.ctx.texture(self.wood.size, 3, self.wood.tobytes()) self.texture.build_mipmaps() self.vbo = self.ctx.buffer(self.obj.pack('vx vy vz nx ny nz tx ty')) self.vao = self.ctx.simple_vertex_array( self.prog, self.vbo, ['in_vert', 'in_norm', 'in_text'])
def __init__(self, wnd): self.wnd = wnd self.ctx = ModernGL.create_context() self.prog = self.ctx.program([ self.ctx.vertex_shader(''' #version 330 uniform mat4 Mvp; in vec3 in_vert; in vec3 in_norm; in vec2 in_text; out vec3 v_vert; out vec3 v_norm; out vec2 v_text; void main() { gl_Position = Mvp * vec4(in_vert, 1.0); v_vert = in_vert; v_norm = in_norm; v_text = in_text; } '''), self.ctx.fragment_shader(''' #version 330 uniform vec3 Light; uniform vec3 Color; uniform bool UseTexture; uniform sampler2D Texture; in vec3 v_vert; in vec3 v_norm; in vec2 v_text; out vec4 f_color; void main() { float lum = clamp(dot(normalize(Light - v_vert), normalize(v_norm)), 0.0, 1.0) * 0.8 + 0.2; if (UseTexture) { f_color = vec4(texture(Texture, v_text).rgb * lum, 1.0); } else { f_color = vec4(Color * lum, 1.0); } } '''), ]) self.mvp = self.prog.uniforms['Mvp'] self.light = self.prog.uniforms['Light'] self.color = self.prog.uniforms['Color'] self.use_texture = self.prog.uniforms['UseTexture'] self.objects = {} for name in [ 'ground', 'grass', 'billboard', 'billboard-holder', 'billboard-image' ]: obj = Obj.open(local('data', 'scene-1-%s.obj' % name)) vbo = self.ctx.buffer(obj.pack('vx vy vz nx ny nz tx ty')) vao = self.ctx.simple_vertex_array( self.prog, vbo, ['in_vert', 'in_norm', 'in_text']) self.objects[name] = vao figure_size = (640, 360) temp = io.BytesIO() plt.figure(0, figsize=(figure_size[0] / 72, figure_size[1] / 72)) mu, sigma = 100, 15 x = mu + sigma * np.random.randn(10000) n, bins, patches = plt.hist(x, 50, normed=1, facecolor='r', alpha=0.75) plt.axis([40, 160, 0, 0.03]) plt.grid(True) plt.show() plt.savefig(temp, format='raw', dpi=72) temp.seek(0) img = Image.frombytes('RGBA', figure_size, temp.read()).transpose( Image.FLIP_TOP_BOTTOM).convert('RGB') self.texture = self.ctx.texture(img.size, 3, img.tobytes()) self.texture.build_mipmaps()
def main(): # Data files vertex_data = Obj.open('data/sitting.obj').pack() texture_image = Image.open('data/wood.jpg') vertex_shader_source = open('data/shader.vert').read() fragment_shader_source = open('data/shader.frag').read() # Context creation ctx = ModernGL.create_standalone_context() # Shaders prog = ctx.program(vertex_shader=vertex_shader_source, fragment_shader=fragment_shader_source) # Matrices and Uniforms perspective = Matrix44.perspective_projection(45.0, 1.0, 0.1, 1000.0) lookat = Matrix44.look_at( (-85, -180, 140), (0.0, 0.0, 65.0), (0.0, 0.0, 1.0), ) mvp = perspective * lookat prog['Light'].value = (-140.0, -300.0, 350.0) prog['Color'].value = (1.0, 1.0, 1.0, 0.25) prog['Mvp'].write(mvp.astype('f4').tobytes()) # Texture texture = ctx.texture(texture_image.size, 3, texture_image.tobytes()) texture.build_mipmaps() # Vertex Buffer and Vertex Array vbo = ctx.buffer(vertex_data) vao = ctx.simple_vertex_array(prog, vbo, *['in_vert', 'in_text', 'in_norm']) # Framebuffers fbo = ctx.framebuffer( ctx.renderbuffer((512, 512)), ctx.depth_renderbuffer((512, 512)), ) # Rendering fbo.use() ctx.enable(ModernGL.DEPTH_TEST) ctx.clear(0.9, 0.9, 0.9) texture.use() vao.render() # Loading the image using Pillow data = fbo.read(components=3, alignment=1) img = Image.frombytes('RGB', fbo.size, data, 'raw', 'RGB', 0, -1) img.save('output.png')
def load_data(ctx, data_path=None, vertex_path=None, fragment_path=None, object_path=None, texture_path=None): """Loads texture data, vertex and fragment shaders and object data. Args: ctx (ModernGL.context.Context): the OpenGL context vertex_path (str, optional): Path to vertex shader fragment_path (str, optional): Path to fragment shader object_path (str, optional): Path to model's vertex data texture_path (str, optional): Path to texture file Updates: background_color texture_image model_data program texture model color Returns: tuple: opengl program, texture, vertex_data """ global foreground_color global background_color global texture_image global texture_data global model_data global program global texture global model global color data_path = data_path or _find_data_folder() # Build file lists files = os.listdir(data_path) colors = list(itertools.product( [0, 1], repeat=3)) # (0, 0, 0), (0, 0, 1), ... (1, 1, 1) models = [ Obj.open(os.path.join(data_path, filename)).pack() for filename in files if filename.endswith('.obj') ] textures = [ Image.open(os.path.join(data_path, filename)) for filename in files if filename.endswith('.jpg') ] textures = [t for t in textures if t.mode == 'RGB'] # Setup global generators color = _eternal_generator(colors) texture = _eternal_generator(textures) model = _eternal_generator(models) # Setup keyboard control parameters background_color = next(color) foreground_color = next(color) texture_image = next(texture) model_data = next(model) texture_data = ctx.texture(texture_image.size, 3, texture_image.tobytes()) texture_data.build_mipmaps() # Setup files vertex_path = vertex_path or f'{data_path}/glfw-simple-window.vert' fragment_path = fragment_path or f'{data_path}/glfw-simple-window.frag' object_path = object_path or f'{data_path}/mug.obj' program = _load_shaders(ctx, vertex_path, fragment_path)