def init(self, width, height, render_samples=16): if not self._initialized: self.ctx = ContextManager.get_offscreen_context() self._scene = Scene(self.ctx) self._scene.init() # A fullscreen quad just for rendering one pass to offscreen textures self.quad_fs = QuadFS(self.ctx) self.quad_fs.m_model.write( Matrix44.identity().astype('f4').tobytes()) self.quad_fs.m_view.write( Matrix44.identity().astype('f4').tobytes()) self.quad_fs.m_proj.write( Matrix44.orthogonal_projection(-1, 1, 1, -1, 1, 10).astype('f4').tobytes()) self.quad_fs.flip_v.value = 0 # aa sampler self.setRenderSamples(render_samples) self._initialized = True print("Workbench initialized") if (self._width, self._height) != (width, height): self.resize(width, height)
def update_projection(self): """ https://stackoverflow.com/a/35817409/1705970 """ bbox = self.bbox bbox_ar = bbox[2] / bbox[3] viewport = self.wnd.viewport viewport_ar = viewport[2] / viewport[3] if viewport_ar >= bbox_ar: # wide viewport, use full height proj_width = (viewport_ar / bbox_ar) * bbox[2] proj_height = bbox[3] else: # tall viewport, use full width proj_width = bbox[2] proj_height = (bbox_ar / viewport_ar) * bbox[3] bbox_center = bbox[0] + bbox[2] / 2, bbox[1] + bbox[3] / 2 proj_left = bbox_center[0] - proj_width / 2 proj_right = proj_left + proj_width proj_top = bbox_center[1] - proj_height / 2 proj_bottom = proj_top + proj_height proj_matrix = Matrix44.orthogonal_projection( left=proj_left, right=proj_right, top=proj_bottom, bottom=proj_top, # opengl has y-axis aiming up near=0.5, far=-0.5, dtype="f4") self.line_prog["projection"].write(proj_matrix) self.point_prog["projection"].write(proj_matrix)
def transform(self): return Matrix44.orthogonal_projection(self.__left, self.__right, self.__bottom, self.__top, -1, 1, dtype='f4')
def resize(self, width, height): """Recalculate projection""" self.proj = Matrix44.orthogonal_projection(0, width * self.zoom_level, 0, height * self.zoom_level, -1.0, 1.0, dtype='f4')
def render(self, time, frametime): self.ctx.enable_only(moderngl.DEPTH_TEST | moderngl.CULL_FACE) self.lightpos = Vector3((math.sin(time) * 20, 5, math.cos(time) * 20), dtype='f4') scene_pos = Vector3((0, -5, -32), dtype='f4') # --- PASS 1: Render shadow map self.offscreen.clear() self.offscreen.use() depth_projection = Matrix44.orthogonal_projection(-20, 20, -20, 20, -20, 40, dtype='f4') depth_view = Matrix44.look_at(self.lightpos, (0, 0, 0), (0, 1, 0), dtype='f4') depth_mvp = depth_projection * depth_view self.shadowmap_program['mvp'].write(depth_mvp) self.floor.render(self.shadowmap_program) self.wall.render(self.shadowmap_program) self.sphere.render(self.shadowmap_program) # --- PASS 2: Render scene to screen self.wnd.use() self.basic_light['m_proj'].write(self.camera.projection.matrix) self.basic_light['m_camera'].write(self.camera.matrix) self.basic_light['m_model'].write( Matrix44.from_translation(scene_pos, dtype='f4')) bias_matrix = Matrix44( [[0.5, 0.0, 0.0, 0.0], [0.0, 0.5, 0.0, 0.0], [0.0, 0.0, 0.5, 0.0], [0.5, 0.5, 0.5, 1.0]], dtype='f4', ) self.basic_light['m_shadow_bias'].write( matrix44.multiply(depth_mvp, bias_matrix)) self.basic_light['lightDir'].write(self.lightpos) self.offscreen_depth.use(location=0) self.floor.render(self.basic_light) self.wall.render(self.basic_light) self.sphere.render(self.basic_light) # Render the sun position self.sun_prog['m_proj'].write(self.camera.projection.matrix) self.sun_prog['m_camera'].write(self.camera.matrix) self.sun_prog['m_model'].write( Matrix44.from_translation(self.lightpos + scene_pos, dtype='f4')) self.sun.render(self.sun_prog) # --- PASS 3: Debug --- # self.ctx.enable_only(moderngl.NOTHING) self.offscreen_depth.use(location=0) self.offscreen_quad.render(self.raw_depth_prog)
def __init__(self, ctx): super().__init__(ctx) self.prog = self.ctx.program( vertex_shader=''' #version 330 uniform mat4 model; uniform mat4 view; uniform mat4 projection; in vec3 in_vert; in vec3 in_color; out vec3 v_color; // Goes to the fragment shader void main() { gl_Position = projection * view * model * vec4(in_vert, 1.0); v_color = in_color; } ''', fragment_shader=''' #version 330 in vec3 v_color; out vec4 f_color; void main() { f_color = vec4(v_color, 1.0); } ''', ) self.model = self.prog['model'] self.view = self.prog['view'] self.projection = self.prog['projection'] origin_data = np.array([ # x,y,z,r,g,b [-1, -1, -1], [0.39, 0.50, 0.55], [1, -1, -1], [0.39, 0.50, 0.55], [1, 1, -1], [0.75, 0.78, 0.78], [-1, 1, -1], [0.75, 0.78, 0.78] ]) self.m_projection = Matrix44.orthogonal_projection(-1, 1, 1, -1, 1, 10) self.vbo = self.ctx.buffer(origin_data.astype('f4').tobytes()) self.model.write(self.m_identity.astype('f4').tobytes()) self.view.write(self.m_identity.astype('f4').tobytes()) self.projection.write(self.m_projection.astype('f4').tobytes())
def render(self, time, frame_time): self.ctx.clear() self.ctx.enable(moderngl.BLEND) num_sprites = 16 # We'll just generate some sprite data on the fly here. # This should only be necessary every time the sprite data changes (in a prefect wold) # Grab the size of the screen or current render target width, height = self.ctx.fbo.size # We just create a generator function instead of def gen_sprites(time): rot_step = math.pi * 2 / num_sprites for i in range(num_sprites): # Position yield width / 2 + math.sin(time + rot_step * i) * 300 yield height / 2 + math.cos(time + rot_step * i) * 300 # size yield 100 yield 100 # rotation yield math.sin(time + i) * 200 self.sprite_data.write(array("f", gen_sprites(time))) # calculate scroll offsets. We truncate to intergers here. # This depends what "look" you want for your game. scroll_x, scroll_y = int(math.sin(time) * 100), int( math.cos(time) * 100) # Create a orthogonal projection matrix # Let's also modify the projection to scroll the entire screen. projection = Matrix44.orthogonal_projection( scroll_x, # left width + scroll_x, # right height + scroll_y, # top scroll_y, # bottom 1, # near -1, # far dtype="f4", # ensure we create 32 bit value (64 bit is default) ) # Update the projection uniform self.program["projection"].write(projection) # Configure the sprite_texture uniform to read from texture channel 0 self.program["sprite_texture"] = 0 # Bind the texture to channel 0 self.ball_texture.use(0) # Since we have overallocated the buffer (room for 1000 sprites) we # need to specify how many we actually want to render passing number of vertices. # Also the mode needs to be the same as the geometry shader input type (points!) self.vao.render(mode=moderngl.POINTS, vertices=num_sprites)
def resize(self, width, height): self.release() # release framebuffers allocated for the old size self.width = width self.height = height self.dims = (width, height) hw = self.width * 0.5 hh = self.height * 0.5 self._proj = Matrix44.orthogonal_projection(left=-hw, right=hw, top=hh, bottom=-hh, near=-1000, far=1000).astype('f4')
def inner(scene): scene.camera_position = args.camera_position scene.camera_target = args.camera_target scene.up_vector = args.up scene.light = args.light or scene.camera_position if args.depth: H, W = args.orthographic_bounds scene.camera_matrix = Matrix44.orthogonal_projection( left=-W/2, right=W/2, bottom=H/2, top=-H/2, near=args.orthographic_near, far=args.orthographic_far ) if args.show_axes: scene.add(Lines.axes())
def getProjection(self, jittered=False, point=None): if self.is_perspective: viewportRadius = self.near_plane * math.tan( self.fov_degrees / 2.0 / 180.0 * math.pi) else: viewportRadius = self.ortogrphic_width * 0.5 if self.viewportWidthInPixels < self.viewportHeightInPixels: viewportWidth = 2.0 * viewportRadius viewportHeight = viewportWidth * self.viewportHeightInPixels / float( self.viewportWidthInPixels) else: viewportHeight = 2.0 * viewportRadius viewportWidth = viewportHeight * self.viewportWidthInPixels / float( self.viewportHeightInPixels) left = 0.5 * viewportWidth right = -0.5 * viewportWidth bottom = -0.5 * viewportHeight top = 0.5 * viewportHeight if jittered: if not point: x_j = random.uniform( -.75, .75) * viewportWidth / self.viewportWidthInPixels y_j = random.uniform( -.75, .75) * viewportHeight / self.viewportHeightInPixels else: x_j = (point[0] - 0.5) * 1.0 * viewportWidth / self.viewportWidthInPixels y_j = (point[1] - 0.5 ) * 1.0 * viewportHeight / self.viewportHeightInPixels left += x_j right += x_j top += y_j bottom += y_j if self.is_perspective: return Matrix44.perspective_projection_bounds( left, right, top, bottom, self.near_plane, self.far_plane) else: return Matrix44.orthogonal_projection(left, right, top, bottom, self.near_plane, self.far_plane)
def __init__(self, ctx, width, height): self.ctx = ctx self.width = width self.height = height hw = self.width * 0.5 hh = self.height * 0.5 self._proj = Matrix44.orthogonal_projection(left=-hw, right=hw, top=hh, bottom=-hh, near=-1000, far=1000).astype('f4') self._xform = np.identity(4, dtype='f4') self._cam_offset = np.zeros(2, dtype='f4') self._cam_vel = np.zeros(2, dtype='f4') self._pos = np.zeros(2, dtype='f4') self._fbs = {} self.pos = hw, hh
def on_draw(dt): if slowmo: dt *= 1 / 3 # Update graphical things for a in level.actors: a.update(dt) for w in Water.insts: w.update(dt) hud.update(dt) window.clear() with offscreen.bind_buffer() as fbuf: fbuf.clear(0.13, 0.1, 0.1) gl.glLoadIdentity() gl.glScalef(PIXEL_SCALE, PIXEL_SCALE, 1) level.background.draw() RockPoly.batch.draw() actor_sprites.draw() level.fg_batch.draw() mgl.screen.clear() offscreen.draw() mvp = Matrix44.orthogonal_projection(0, WIDTH * SPACE_SCALE, 0, HEIGHT * SPACE_SCALE, -1, 1, dtype='f4') with offscreen.bind_texture(location=0): water_batch.tex_uniform.value = 0 water_batch.render(dt, mvp) gl.glUseProgram(0) gl.glBindVertexArray(0) hud.draw()
def __init__(self, **kwargs): super().__init__(**kwargs) self.line_prog = self.load_program("rich_lines.glsl") lines = [ star(n=5) * 300 + (400, 400), star(n=8) * 150 + (900, 200), rect(900, 600, 150, 50), [(1200, 100), (1400, 200), (1300, 100)], ] vertex, index = build_buffers(lines) vbo = self.ctx.buffer(vertex) ibo = self.ctx.buffer(index) self.vao = self.ctx.simple_vertex_array(self.line_prog, vbo, "position", index_buffer=ibo) # Set the desired properties for the lines. # Note: # - round cap/ends are used if miter_limit < 0 # - antialias value is in model space and should probably be scaled to be ~1.5px in # screen space self.line_prog["linewidth"].value = 15 self.line_prog["antialias"].value = 1.5 self.line_prog["miter_limit"].value = -1 self.line_prog["color"].value = 0, 0, 1, 1 self.line_prog["projection"].write( Matrix44.orthogonal_projection(0, 1600, 800, 0, 0.5, -0.5, dtype="f4"))
def __init__(self, **kwargs): super().__init__(**kwargs) self.buffer_size = 320, 256 # Textures self.background_texture = self.load_texture_array( 'textures/animated_sprites/giphy.gif') self.background_texture.repeat_x = False self.background_texture.repeat_y = False self.caveman_texture = self.load_texture_array( 'textures/animated_sprites/player_2.gif', layers=35) self.caveman_texture.repeat_x = False self.caveman_texture.repeat_y = False self.caveman_texture.filter = moderngl.NEAREST, moderngl.NEAREST # Geometry # One pixel quad 0, 0 -> 1.0, 1.0 self.sprite_geometry = geometry.quad_2d(size=(1.0, 1.0), pos=(0.5, 0.5)) self.quad_fs = geometry.quad_fs() # Programs self.sprite_program = self.load_program( 'programs/animated_sprites/sprite_array.glsl') self.texture_program = self.load_program('programs/texture.glsl') # Offscreen buffer self.offscreen_texture = self.ctx.texture(self.buffer_size, 4) self.offscreen_texture.filter = moderngl.NEAREST, moderngl.NEAREST self.offscreen = self.ctx.framebuffer( color_attachments=[self.offscreen_texture]) self.projection = Matrix44.orthogonal_projection(0, 320, 0, 256, -1.0, 1.0, dtype='f4') self.sprite_program['projection'].write(self.projection)
def init(self): if not self._init_done: self.makeCurrent() self.ctx.point_size = 2.0 self.scope = None self.buildOffscreen(self.ctx.viewport[2], self.ctx.viewport[3]) self.scene_manager.init() # A fullscreen quad just for rendering one pass to offscreen textures self.quad_fs = QuadFS(self) self.quad_fs.program['m_model'].write( Matrix44.identity().astype('f4').tobytes()) self.quad_fs.program['m_view'].write( Matrix44.identity().astype('f4').tobytes()) self.quad_fs.program['m_proj'].write( Matrix44.orthogonal_projection(-1, 1, 1, -1, 1, 10).astype('f4').tobytes()) # init renderer self.renderer = WorkbenchIPR(scene=None, camera=self.activeCamera) self.renderer.setImageUpdateHandler(self.handleRenderedSample) self._init_done = True
def render(self, time, frametime): self.ctx.enable_only(moderngl.DEPTH_TEST | moderngl.CULL_FACE) scene_pos = Vector3((0, -5, -32), dtype="f4") all_poses = myDriver.get_pose() # hmd, cntl1, cntl2 = all_poses # --- PASS 1: Render shadow map self.offscreen.clear() self.offscreen.use() depth_projection = Matrix44.orthogonal_projection(-20, 20, -20, 20, -20, 40, dtype="f4") depth_view = Matrix44.look_at(self.lightpos, (0, 0, 0), (0, 1, 0), dtype="f4") depth_mvp = depth_projection * depth_view self.shadowmap_program["mvp"].write(depth_mvp) for i in range(len(myDriver.device_order)): self.device_list[i][0].render(self.shadowmap_program) self.device_list[i][1].render(self.shadowmap_program) self.floor.render(self.shadowmap_program) # --- PASS 2: Render scene to screen self.wnd.use() # self.basic_light['m_proj'].write(self.camera.projection.matrix) # self.basic_light['m_camera'].write(self.camera.matrix) # self.basic_light['m_model'].write(Matrix44.from_translation(scene_pos, dtype='f4') * Matrix44.from_y_rotation(time, dtype='f4')) bias_matrix = Matrix44( [ [0.5, 0.0, 0.0, 0.0], [0.0, 0.5, 0.0, 0.0], [0.0, 0.0, 0.5, 0.0], [0.5, 0.5, 0.5, 1.0], ], dtype="f4", ) # self.basic_light['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) # self.basic_light['lightDir'].write(self.lightpos) self.offscreen_depth.use(location=0) for i in range(len(myDriver.device_order)): self.device_list[i][0].write_bl( all_poses[i], self.camera, matrix44.multiply(depth_mvp, bias_matrix), self.lightpos, ) self.device_list[i][1].write_bl( all_poses[i], self.camera, matrix44.multiply(depth_mvp, bias_matrix), self.lightpos, ) for i in range(len(myDriver.device_order)): self.device_list[i][0].render( self.device_list[i][0].basic_light_prog) self.device_list[i][1].render( self.device_list[i][1].basic_light_prog) # floor self.basic_lightFloor["m_model"].write( Matrix44.from_translation((0, 0, 0), dtype="f4")) self.basic_lightFloor["m_proj"].write(self.camera.projection.matrix) self.basic_lightFloor["m_camera"].write(self.camera.matrix) self.basic_lightFloor["m_shadow_bias"].write( matrix44.multiply(depth_mvp, bias_matrix)) self.basic_lightFloor["lightDir"].write(self.lightpos) self.floor.render(self.basic_lightFloor) # # Render the sun position # self.sun_prog['m_proj'].write(self.camera.projection.matrix) # self.sun_prog['m_camera'].write(self.camera.matrix) # self.sun_prog['m_model'].write(Matrix44.from_translation(self.lightpos + scene_pos, dtype='f4')) # self.sun.render(self.sun_prog) # --- PASS 3: Debug --- # self.ctx.enable_only(moderngl.NOTHING) self.offscreen_depth.use(location=0) self.offscreen_quad.render(self.raw_depth_prog)
def load (self: 'GLQuadRenderer') -> None: self.make_current () GL.glDisable (GL.GL_CULL_FACE) self.program = GL.glCreateProgram () self.vertex_shader = GL.glCreateShader (GL.GL_VERTEX_SHADER) self.fragment_shader = GL.glCreateShader (GL.GL_FRAGMENT_SHADER) vs_file = open ("color_harmonization/gui/glsl/vertex_shader.vsh", 'r') vs_code = vs_file.read () vs_file.close () fs_file = open ("color_harmonization/gui/glsl/fragment_shader.fsh", 'r') fs_code = fs_file.read () fs_file.close () GL.glShaderSource (self.vertex_shader, vs_code) GL.glShaderSource (self.fragment_shader, fs_code) GL.glCompileShader (self.vertex_shader) if DEBUG: error_log = GL.glGetShaderInfoLog (self.vertex_shader) print ("Vertex shader: {}".format (error_log.decode ())) GL.glCompileShader (self.fragment_shader) if DEBUG: error_log = GL.glGetShaderInfoLog (self.fragment_shader) print ("Fragment shader: {}".format (error_log.decode ())) GL.glAttachShader (self.program, self.vertex_shader) GL.glAttachShader (self.program, self.fragment_shader) GL.glLinkProgram (self.program) if DEBUG: error_log = GL.glGetProgramInfoLog (self.program) print ("Program link: {}".format (error_log.decode ())) self.array_buffer = GL.glGenBuffers (1) self.vertex_array = GL.glGenVertexArrays (1) data = numpy.array ([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0], dtype = numpy.float32) GL.glBindVertexArray (self.vertex_array) GL.glBindBuffer (GL.GL_ARRAY_BUFFER, self.array_buffer) GL.glBufferData (GL.GL_ARRAY_BUFFER, data.nbytes, data, GL.GL_STATIC_DRAW) GL.glEnableVertexAttribArray (0) GL.glVertexAttribPointer (0, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p (0)) GL.glEnableVertexAttribArray (1) GL.glVertexAttribPointer (1, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p (8)) GL.glEnableVertexAttribArray (2) GL.glVertexAttribPointer (2, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p (16)) GL.glUseProgram (self.program) self.__uniform_world = GL.glGetUniformLocation (self.program, "WorldMatrix") self.__uniform_projection = GL.glGetUniformLocation (self.program, "ProjectionMatrix") self.__uniform_texture = GL.glGetUniformLocation (self.program, "Texture") self.__uniform_data_texture = GL.glGetUniformLocation (self.program, "DataTexture") self.__uniform_do_harmonization = GL.glGetUniformLocation (self.program, "DoHarmonization") self.__texture = 0 self.__data_texture = 0 GL.glUniformMatrix4fv (self.__uniform_projection, 1, False, Matrix44.orthogonal_projection (0, 1, 0, 1, 0, 1)) GL.glUniform1i (self.__uniform_do_harmonization, self.__do_harmonization)
def start(self): if not glfw.init(): print("Could not initialize OpenGL context") exit(1) glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) #glfw.window_hint(glfw.RESIZABLE, self.resizable) glfw.window_hint(glfw.DOUBLEBUFFER, True) glfw.window_hint(glfw.DEPTH_BITS, 24) #glfw.window_hint(glfw.SAMPLES, 1) glfw.window_hint(glfw.DECORATED, False) monitor = None ''' if self.fullscreen: # Use the primary monitors current resolution monitor = glfw.get_primary_monitor() self.width, self.height = mode.size.width, mode.size.height mode = glfw.get_video_mode(monitor) ''' self.window = glfw.create_window(self.width, self.height, self.window_name, monitor, None) if not self.window: glfw.terminate() raise ValueError("Failed to create window") ''' if not self.cursor: glfw.set_input_mode(self.window, glfw.CURSOR, glfw.CURSOR_DISABLED) ''' glfw.set_window_pos(self.window, 40, 40) # Get the actual buffer size of the window # This is important for some displays like Apple's Retina as reported window sizes are virtual self.buffer_width, self.buffer_height = glfw.get_framebuffer_size(self.window) #print("Frame buffer size:", self.buffer_width, self.buffer_height) #print("Actual window size:", glfw.get_window_size(self.window)) glfw.make_context_current(self.window) # The number of screen updates to wait from the time glfwSwapBuffers # was called before swapping the buffers and returning if self.bVsync: glfw.swap_interval(1) glfw.set_key_callback(self.window, self.key_event_callback) #glfw.set_cursor_pos_callback(self.window, self.mouse_event_callback) #glfw.set_window_size_callback(self.window, self.window_resize_callback) # Create mederngl context from existing context self.ctx = moderngl.create_context(require=330) self.fbo = self.ctx.screen #self.ctx.viewport = self.window.viewport #self.set_default_viewport() #print("Wow ! GL_SHADING_LANGUAGE_VERSION :", gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION)) ''' self.proj = Matrix44.perspective_projection(45.0, float(self.width)/float(self.height), 0.1, 1000.0) self.lookat = Matrix44.look_at( (0.0, 0.0, 10.0), (0.0, 0.0, 0.0), (0.0, -1.0, 0.0), ) ''' left = 0 #-float(self.width) right = float(self.width) top = 0 #float(self.height) bottom = -float(self.height) near = 1.0 far = 1000.0 self.proj = Matrix44.orthogonal_projection(left, right, bottom, top, near, far) self.lookat = Matrix44.look_at( (0.0, 0.0, -10.0), (0.0, 0.0, 0.0), (0.0, -1.0, 0.0), ) self.prog = self.ctx.program( vertex_shader=''' #version 330 uniform mat4 MVP; //in vec3 in_vert; in vec2 in_vert; in vec2 in_text; out vec2 v_text; void main() { //gl_Position = MVP * vec4(in_vert, 1.0); gl_Position = MVP * vec4(in_vert, 0.0, 1.0); v_text = in_text; } ''', fragment_shader=''' #version 330 uniform sampler2D Texture; in vec2 v_text; out vec4 f_color; void main() { //f_color = vec4(0.3, 0.5, 1.0, 1.0); f_color = vec4(texture(Texture, v_text).rgb, 1.0); } ''', ) self.mvp = self.prog['MVP'] img_left = Image.open(local('assets', 'l.png')).convert('RGB') self.texture_left = self.ctx.texture(img_left.size, 3, img_left.tobytes()) #self.texture_left.build_mipmaps() #img_right = Image.open(local('assets', 'r.png')).convert('RGB') #self.texture_right = self.ctx.texture(img_right.size, 3, img_right.tobytes()) #self.texture_right.build_mipmaps() texSize = (1024,1024) self.texture_left = self.ctx.texture((1024,1024), 3) depth_attachment_left = self.ctx.depth_renderbuffer(texSize) self.fbo_left = self.ctx.framebuffer(self.texture_left, depth_attachment_left) self.texture_right = self.ctx.texture((1024,1024), 3) depth_attachment_right = self.ctx.depth_renderbuffer(texSize) self.fbo_right = self.ctx.framebuffer(self.texture_right, depth_attachment_right) vertices_left_quad = np.array([ 0.0, 0.0, 0.0,1.0, 0.0, self.height, 0.0,0.0, self.width/2, 0.0, 1.0,1.0, self.width/2, self.height, 1.0,0.0 ]) self.vbo_left_quad = self.ctx.buffer(vertices_left_quad.astype('f4').tobytes()) self.vao_left_quad = self.ctx.simple_vertex_array(self.prog, self.vbo_left_quad, 'in_vert', 'in_text') vertices_right_quad = np.array([ self.width/2, 0.0, 0.0,1.0, self.width/2, self.height, 0.0,0.0, self.width, 0.0, 1.0,1.0, self.width, self.height, 1.0,0.0 ]) self.vbo_right_quad = self.ctx.buffer(vertices_right_quad.astype('f4').tobytes()) self.vao_right_quad = self.ctx.simple_vertex_array(self.prog, self.vbo_right_quad, 'in_vert', 'in_text') ##### # Persp scene self.proj_sample = Matrix44.perspective_projection(45.0, self.width / self.height, 0.1, 1000.0) self.proj_sample_stereo = Matrix44.perspective_projection(45.0, (self.width/2) / self.height, 0.1, 1000.0) self.lookat_sample = Matrix44.look_at( (50.0, 20.0, 30.0), (0.0, 0.0, 10.0), (0.0, 0.0, 1.0), ) self.prog_sample = self.ctx.program( 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; } ''', 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.objects = {} for name in ['ground', 'grass', 'billboard', 'billboard-holder', 'billboard-image']: obj = Obj.open(local('assets', '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_sample, vbo, 'in_vert', 'in_norm', 'in_text') self.objects[name] = vao img = Image.open(local('assets', 'infographic-1.jpg')).transpose(Image.FLIP_TOP_BOTTOM).convert('RGB') self.texture_sample = self.ctx.texture(img.size, 3, img.tobytes()) self.texture_sample.build_mipmaps() self.mvp_sample = self.prog_sample['MVP'] self.bUseTexture_sample = self.prog_sample['UseTexture'] self.light_sample = self.prog_sample['Light'] self.color_sample = self.prog_sample['Color']
def get_view_proj_matrix(self): proj = Matrix44.orthogonal_projection(-100, 100, -100, 100, 1, 1000) view = Matrix44.look_at(self.inv_direction, (0, 0, 0), (0, 1, 0)) return proj * view
def setViewPort(self, x0, y0, x1, y1): near = 1 far = 0 matrix = Matrix44.orthogonal_projection(x0, x1, y1, y0, near, far, dtype="f4") self._program["projection"].write(matrix)
def __init__(self, eyes, eyepos, resolution, projection): if (eyepos == "V"): # 頂点からレンダリングする場合 self.n_views = eyes.n_vert self.views = eyes.vert elif (eyepos == "F"): # 面の重心からレンダリングする場合 self.n_views = eyes.n_face self.views = eyes.calc_face_gravity_center() norms = np.linalg.norm(self.views, axis=1) max_norm = np.max(norms) self.views = self.views * (1.0 / max_norm) else: print("error: invalid camera position : " + camera) quit() self.resolution = resolution # contextを生成 self.ctx = moderngl.create_standalone_context() # シェーダプログラムを生成 self.prog_light = self.ctx.program( vertex_shader=vertex_shader_light, fragment_shader=fragment_shader_light) self.prog_depth = self.ctx.program( vertex_shader=vertex_shader_depth, fragment_shader=fragment_shader_depth) self.prog_normal = self.ctx.program( vertex_shader=vertex_shader_normal, fragment_shader=fragment_shader_normal) # Framebuffers self.fbo = self.ctx.framebuffer( self.ctx.renderbuffer((self.resolution, self.resolution)), self.ctx.depth_renderbuffer((self.resolution, self.resolution))) # input buffer self.buffer = self.ctx.buffer(data=None, reserve=350000000, dynamic=True) # 350MByteのバッファを確保 (ModelNet40 train setにこのくらいのバッファが必要な3Dモデルがある) # vertex arrays self.vao_light = self.ctx.simple_vertex_array(self.prog_light, self.buffer, 'in_vert', 'in_norm') self.vao_depth = self.ctx.simple_vertex_array(self.prog_depth, self.buffer, 'in_vert', 'in_norm') self.vao_normal = self.ctx.simple_vertex_array(self.prog_normal, self.buffer, 'in_vert', 'in_norm') if (projection == "O"): # 平行投影の場合 self.projection = Matrix44.orthogonal_projection( 1.0, # left -1.0, # right -1.0, # top 1.0, # bottom 0.0, # near 2.0) # far elif (projection == "P"): # 透視投影の場合 self.projection = Matrix44.perspective_projection( 90.0, # fovy 1.0, # aspect 0.01, # near 2.0) # far else: print("error: invalid projection setting : " + projection) quit() self.count = 0
def proj(self): if self.perspective == True: return Matrix44.perspective_projection(self.fovY, self.aspect_ratio, 0.1, 1000.0) else: length = math.tan(math.radians(self.fovY / 2)) * math.fabs(self.dist) return Matrix44.orthogonal_projection(-length, length, -length, length, 0.1, 1000.0)
def __init__(self, **kwargs): super().__init__(**kwargs) self.ball_texture = self.load_texture_2d("ball.png") # Sprite shader using geometry shader self.program = self.ctx.program( vertex_shader=""" #version 330 // The per sprite input data in vec2 in_position; in vec2 in_size; in float in_rotation; out vec2 size; out float rotation; void main() { // We just pass the values unmodified to the geometry shader gl_Position = vec4(in_position, 0, 1); size = in_size; rotation = in_rotation; } """, geometry_shader=""" #version 330 // We are taking single points form the vertex shader // and emitting 4 new vertices creating a quad/sprites layout (points) in; layout (triangle_strip, max_vertices = 4) out; uniform mat4 projection; // Since geometry shader can take multiple values from a vertex // shader we need to define the inputs from it as arrays. // In our instance we just take single values (points) in vec2 size[]; in float rotation[]; out vec2 uv; void main() { // We grab the position value from the vertex shader vec2 center = gl_in[0].gl_Position.xy; // Calculate the half size of the sprites for easier calculations vec2 hsize = size[0] / 2.0; // Convert the rotation to radians float angle = radians(rotation[0]); // Create a 2d rotation matrix mat2 rot = mat2( cos(angle), sin(angle), -sin(angle), cos(angle) ); // Emit a triangle strip creating a quad (4 vertices). // Here we need to make sure the rotation is applied before we position the sprite. // We just use hardcoded texture coordinates here. If an atlas is used we // can pass an additional vec4 for specific texture coordinates. // Each EmitVertex() emits values down the shader pipeline just like a single // run of a vertex shader, but in geomtry shaders we can do it multiple times! // Upper left gl_Position = projection * vec4(rot * vec2(-hsize.x, hsize.y) + center, 0.0, 1.0); uv = vec2(0, 1); EmitVertex(); // lower left gl_Position = projection * vec4(rot * vec2(-hsize.x, -hsize.y) + center, 0.0, 1.0); uv = vec2(0, 0); EmitVertex(); // upper right gl_Position = projection * vec4(rot * vec2(hsize.x, hsize.y) + center, 0.0, 1.0); uv = vec2(1, 1); EmitVertex(); // lower right gl_Position = projection * vec4(rot * vec2(hsize.x, -hsize.y) + center, 0.0, 1.0); uv = vec2(1, 0); EmitVertex(); // We are done with this triangle strip now EndPrimitive(); } """, fragment_shader=""" #version 330 uniform sampler2D sprite_texture; in vec2 uv; out vec4 fragColor; void main() { fragColor = texture(sprite_texture, uv); } """, ) self.sprite_data_size = 5 * 4 # 5 32 bit floats self.sprite_data = self.ctx.buffer( reserve=1000 * self.sprite_data_size) # Capacity for 1000 sprites self.vao = self.ctx.vertex_array(self.program, [ (self.sprite_data, "2f 2f 1f", "in_position", "in_size", "in_rotation"), ]) w, h = self.ctx.screen.size self.projection = Matrix44.orthogonal_projection(0, w, h, 0, 1, 0, dtype="f4")
def render(self, time, frametime): self.ctx.enable_only(moderngl.DEPTH_TEST | moderngl.CULL_FACE) scene_pos = Vector3((0, -5, -32), dtype='f4') data = myDriver.get_pose() hmd = data[:13] cntl1 = data[13:13+22] cntl2 = data[13+22:13+22+22] # --- PASS 1: Render shadow map self.offscreen.clear() self.offscreen.use() depth_projection = Matrix44.orthogonal_projection(-20, 20, -20, 20, -20, 40, dtype='f4') depth_view = Matrix44.look_at(self.lightpos, (0, 0, 0), (0, 1, 0), dtype='f4') depth_mvp = depth_projection * depth_view self.shadowmap_program['mvp'].write(depth_mvp) self.handL.render(self.shadowmap_program) self.handL2.render(self.shadowmap_program) self.handL3.render(self.shadowmap_program) self.handR.render(self.shadowmap_program) self.handR2.render(self.shadowmap_program) self.handR3.render(self.shadowmap_program) self.hmd.render(self.shadowmap_program) self.hmd2.render(self.shadowmap_program) self.floor.render(self.shadowmap_program) # --- PASS 2: Render scene to screen self.wnd.use() # self.basic_light['m_proj'].write(self.camera.projection.matrix) # self.basic_light['m_camera'].write(self.camera.matrix) # self.basic_light['m_model'].write(Matrix44.from_translation(scene_pos, dtype='f4') * Matrix44.from_y_rotation(time, dtype='f4')) bias_matrix = Matrix44( [[0.5, 0.0, 0.0, 0.0], [0.0, 0.5, 0.0, 0.0], [0.0, 0.0, 0.5, 0.0], [0.5, 0.5, 0.5, 1.0]], dtype='f4', ) # self.basic_light['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) # self.basic_light['lightDir'].write(self.lightpos) self.offscreen_depth.use(location=0) x, y, z, w, rx, ry, rz = cntl2[:7] # y = -y ry = -ry rx = -rx rz = -rz rotz = Matrix44.from_quaternion([rx, ry, rz, w], dtype='f4') mat1 = Matrix44.from_translation([x*10, y*10, z*10], dtype='f4') self.basic_lightL['m_model'].write(mat1*rotz) self.basic_lightL['m_proj'].write(self.camera.projection.matrix) self.basic_lightL['m_camera'].write(self.camera.matrix) self.basic_lightL['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) self.basic_lightL['lightDir'].write(self.lightpos) x, y, z, w, rx, ry, rz = cntl1[:7] # y = -y ry = -ry rx = -rx rz = -rz rotz = Matrix44.from_quaternion([rx, ry, rz, w], dtype='f4') mat1 = Matrix44.from_translation([x*10, y*10, z*10], dtype='f4') self.basic_lightR['m_model'].write(mat1*rotz) self.basic_lightR['m_proj'].write(self.camera.projection.matrix) self.basic_lightR['m_camera'].write(self.camera.matrix) self.basic_lightR['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) self.basic_lightR['lightDir'].write(self.lightpos) x, y, z, w, rx, ry, rz = hmd[:7] # y = -y ry = -ry rx = -rx rz = -rz rotz = Matrix44.from_quaternion([rx, ry, rz, w], dtype='f4') mat1 = Matrix44.from_translation([x*10, y*10, z*10], dtype='f4') self.basic_lightHmd['m_model'].write(mat1*rotz) self.basic_lightHmd['m_proj'].write(self.camera.projection.matrix) self.basic_lightHmd['m_camera'].write(self.camera.matrix) self.basic_lightHmd['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) self.basic_lightHmd['lightDir'].write(self.lightpos) self.handL.render(self.basic_lightL) self.handL2.render(self.basic_lightL) self.handL3.render(self.basic_lightL) self.handR.render(self.basic_lightR) self.handR2.render(self.basic_lightR) self.handR3.render(self.basic_lightR) self.hmd.render(self.basic_lightHmd) self.hmd2.render(self.basic_lightHmd) self.basic_lightFloor['m_model'].write(Matrix44.from_translation((0, 0, 0), dtype='f4')) self.basic_lightFloor['m_proj'].write(self.camera.projection.matrix) self.basic_lightFloor['m_camera'].write(self.camera.matrix) self.basic_lightFloor['m_shadow_bias'].write(matrix44.multiply(depth_mvp, bias_matrix)) self.basic_lightFloor['lightDir'].write(self.lightpos) self.floor.render(self.basic_lightFloor) # # Render the sun position # self.sun_prog['m_proj'].write(self.camera.projection.matrix) # self.sun_prog['m_camera'].write(self.camera.matrix) # self.sun_prog['m_model'].write(Matrix44.from_translation(self.lightpos + scene_pos, dtype='f4')) # self.sun.render(self.sun_prog) # --- PASS 3: Debug --- # self.ctx.enable_only(moderngl.NOTHING) self.offscreen_depth.use(location=0) self.offscreen_quad.render(self.raw_depth_prog)
def load(self: 'GLQuadRenderer') -> None: self.make_current() GL.glDisable(GL.GL_CULL_FACE) self.program = GL.glCreateProgram() self.vertex_shader = GL.glCreateShader(GL.GL_VERTEX_SHADER) self.fragment_shader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) vs_file = open("color_harmonization/gui/glsl/vertex_shader.vsh", 'r') vs_code = vs_file.read() vs_file.close() fs_file = open("color_harmonization/gui/glsl/fragment_shader.fsh", 'r') fs_code = fs_file.read() fs_file.close() GL.glShaderSource(self.vertex_shader, vs_code) GL.glShaderSource(self.fragment_shader, fs_code) GL.glCompileShader(self.vertex_shader) if DEBUG: error_log = GL.glGetShaderInfoLog(self.vertex_shader) print("Vertex shader: {}".format(error_log.decode())) GL.glCompileShader(self.fragment_shader) if DEBUG: error_log = GL.glGetShaderInfoLog(self.fragment_shader) print("Fragment shader: {}".format(error_log.decode())) GL.glAttachShader(self.program, self.vertex_shader) GL.glAttachShader(self.program, self.fragment_shader) GL.glLinkProgram(self.program) if DEBUG: error_log = GL.glGetProgramInfoLog(self.program) print("Program link: {}".format(error_log.decode())) self.array_buffer = GL.glGenBuffers(1) self.vertex_array = GL.glGenVertexArrays(1) data = numpy.array([ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 ], dtype=numpy.float32) GL.glBindVertexArray(self.vertex_array) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.array_buffer) GL.glBufferData(GL.GL_ARRAY_BUFFER, data.nbytes, data, GL.GL_STATIC_DRAW) GL.glEnableVertexAttribArray(0) GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p(0)) GL.glEnableVertexAttribArray(1) GL.glVertexAttribPointer(1, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p(8)) GL.glEnableVertexAttribArray(2) GL.glVertexAttribPointer(2, 2, GL.GL_FLOAT, False, 24, GL.ctypes.c_void_p(16)) GL.glUseProgram(self.program) self.__uniform_world = GL.glGetUniformLocation(self.program, "WorldMatrix") self.__uniform_projection = GL.glGetUniformLocation( self.program, "ProjectionMatrix") self.__uniform_texture = GL.glGetUniformLocation( self.program, "Texture") self.__uniform_data_texture = GL.glGetUniformLocation( self.program, "DataTexture") self.__uniform_do_harmonization = GL.glGetUniformLocation( self.program, "DoHarmonization") self.__texture = 0 self.__data_texture = 0 GL.glUniformMatrix4fv(self.__uniform_projection, 1, False, Matrix44.orthogonal_projection(0, 1, 0, 1, 0, 1)) GL.glUniform1i(self.__uniform_do_harmonization, self.__do_harmonization)