Beispiel #1
0
class MainView:
    def __init__(self):
        fileConfig('log.conf')
        self.logger = logging.getLogger(type(self).__name__)

        self.resolution = np.array([800, 450])
        self.target_fps = 60
        self.frame_render_time = 1 / self.target_fps

        self.init_window()
        self.get_gl_info()
        self.init_shader()
        self.init_camera()
        self.main_loop()

    def get_gl_info(self):
        self.logger.info('Vendor    : {}'.format(
            glGetString(GL_VENDOR).decode()))
        self.logger.info('Renderer  : {}'.format(
            glGetString(GL_RENDERER).decode()))
        self.logger.info('Version   : {}'.format(
            glGetString(GL_VERSION).decode()))
        self.logger.info('SL Version: {}'.format(
            glGetString(GL_SHADING_LANGUAGE_VERSION).decode()))
        #self.logger.debug('Extensions: {}'.format(glGetString(GL_EXTENSIONS).decode()))

    def get_shader_time(self):
        return os.path.getmtime('shaders/shader.frag')

    def init_shader(self):
        self.shader = Shader({
            GL_VERTEX_SHADER: 'shaders/shader.vert',
            GL_GEOMETRY_SHADER: 'shaders/shader.geom',
            GL_FRAGMENT_SHADER: 'shaders/shader.frag'
        })
        self.shader.create()
        self.shader_time = self.get_shader_time()
        self.freeze_time = False
        self.time = 0.
        self.logger.debug('Shader program initialized')

    def init_camera(self):
        self.camera = Camera(self)

    def init_window(self):
        glfw.init()
        self.window = glfw.create_window(*self.resolution, 'PyGL', None, None)
        glfw.make_context_current(self.window)
        glfw.set_window_size_callback(self.window, self.resize)
        glfw.set_key_callback(self.window, self.keyboard_input)
        glfw.set_scroll_callback(self.window, self.scroll_input)
        glfw.set_cursor_pos_callback(self.window, self.mouse_position_input)
        glClearColor(0, 0, 0, 1)
        self.target_frame_time = 1 / self.target_fps

        self.ui = UI(self)
        self.logger.debug('Window initialized')

    def resize(self, win, width, height):
        #self.logger.debug('Window resized: {}x{}'.format(width, height))
        self.resolution = np.array([width, height])
        glViewport(0, 0, *self.resolution)

    def keyboard_input(self, win, key, scancode, action, mods):
        #self.logger.debug('key: {}, scancode: {}, action: {}, mods: {}'.format(key, scancode, action, mods))
        if (key == glfw.KEY_ESCAPE
            ) or (mods == glfw.MOD_ALT
                  and key == glfw.KEY_F4) and action == glfw.PRESS:
            glfw.set_window_should_close(self.window, True)
            self.logger.info('Exiting')
        if key == glfw.KEY_H and action == glfw.PRESS:
            self.ui.toggle_visibility()
            self.logger.debug('Toggle UI')
        if key == glfw.KEY_W and action != glfw.RELEASE:
            self.camera.move_forward()
        if key == glfw.KEY_A and action != glfw.RELEASE:
            self.camera.move_left()
        if key == glfw.KEY_S and action != glfw.RELEASE:
            self.camera.move_backward()
        if key == glfw.KEY_D and action != glfw.RELEASE:
            self.camera.move_right()
        if key == glfw.KEY_Q and action != glfw.RELEASE:
            self.camera.move_up()
        if key == glfw.KEY_E and action != glfw.RELEASE:
            self.camera.move_down()
        if key == glfw.KEY_R and action == glfw.PRESS:
            self.camera.reset()
        if key == glfw.KEY_P and action == glfw.PRESS:
            self.freeze_time = not self.freeze_time
            self.logger.info('Toggle time freeze')
        if key == glfw.KEY_F and action == glfw.PRESS:
            self.camera.toggle_look_mode()
            self.logger.info('Toggle camera look mode')
        if key == glfw.KEY_T and action == glfw.PRESS:
            self.ui.toggle_composition_overlay()
            self.logger.info('Toggle composition overlay')

    def scroll_input(self, win, x, y):
        if y > 0:
            self.camera.accelerate()
        elif y < 0:
            self.camera.decelerate()

    def mouse_position_input(self, win, x, y):
        if self.camera.look_mode:
            self.camera.look(x, y)

    def wait_for_frame_end(self, frame_start_time):
        frame_render_time = glfw.get_time() - frame_start_time
        #self.logger.debug('Frame render time: {:.1f} ms ({:.1f}%)'.format(1000*frame_render_time, frame_render_time/self.target_frame_time*100))
        self.frame_render_time = frame_render_time
        sleep_time = self.target_frame_time - frame_render_time
        if sleep_time > 0:
            time.sleep(sleep_time)

    def check_for_shader_change(self):
        current_time = self.get_shader_time()
        if current_time != self.shader_time:
            self.shader_time = current_time
            self.shader.create()

    def main_loop(self):
        while not glfw.window_should_close(self.window):
            self.check_for_shader_change()
            frame_start_time = glfw.get_time()
            if not self.freeze_time:
                self.time = frame_start_time

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            # Draw scene
            self.shader.bind()
            self.shader.set_uniforms({
                'resolution':
                self.resolution,
                'time':
                self.time,
                'camera_position':
                self.camera.position,
                'camera_rotation':
                self.camera.rotation.mat3()
            })
            glDrawArrays(GL_POINTS, 0, 1)  # dummy vbo
            self.shader.unbind()

            # Draw UI
            self.ui.draw({
                'fps_label':
                '{:4.0f}/{:2.0f} FPS, {:4.1f} ms ({:3.0f}%)'.format(
                    1 / self.frame_render_time, self.target_fps,
                    self.frame_render_time * 1000,
                    self.frame_render_time / self.target_frame_time * 100),
                'time_label':
                'Time: {:4.2f} s {}'.format(self.time,
                                            '[f]' if self.freeze_time else ''),
                'camera_label':
                'Camera: [{:5.2f}, {:5.2f}, {:5.2f}] ({:3.0f}%), [{:5.1f}, {:4.1f}]'
                .format(*self.camera.position, self.camera.speed * 100,
                        np.degrees(self.camera.yaw),
                        np.degrees(self.camera.pitch))
            })

            glfw.swap_buffers(self.window)
            self.wait_for_frame_end(frame_start_time)
            glfw.poll_events()

        glfw.terminate()
Beispiel #2
0
class UI:
	def __init__(self, view):
		self.logger = logging.getLogger(type(self).__name__)
		self.view = view

		self.enabled = True

		self.init_opengl()
		self.elements = {
			'time_label':Text((.01, .99)),
			'fps_label':Text((.71, .99)),
			'camera_label':Text((.01, .04))
		}

		self.composition_overlay_enabled = True
		self.overlay_shader = Shader({GL_VERTEX_SHADER:'shaders/shader.vert', GL_GEOMETRY_SHADER:'shaders/shader.geom', GL_FRAGMENT_SHADER:'shaders/composition.frag'})
		self.overlay_shader.create()
		self.logger.debug('Initialized UI')

	def init_opengl(self):
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
		glEnable(GL_BLEND)
		glEnable(GL_COLOR_MATERIAL)
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
		glEnable(GL_TEXTURE_2D)

	def toggle_visibility(self):
		self.enabled = not self.enabled

	def toggle_composition_overlay(self):
		self.composition_overlay_enabled = not self.composition_overlay_enabled

	def draw_composition_overlay(self):
		self.overlay_shader.bind()
		self.overlay_shader.set_uniforms(
			{
				'resolution':self.view.resolution,
				'time':0.,
			}
		)
		glDrawArrays(GL_POINTS, 0, 1) # dummy vbo
		self.overlay_shader.unbind()

	def draw(self, values_dict):
		if not self.enabled: return
		ar = self.view.resolution[0]/self.view.resolution[1]
		glPushMatrix()
		glTranslatef(-1,-1,0)
		glScale(2,2,1) # -> [0,1]x[0,1]

		for name, elem in self.elements.items():
			glPushMatrix()
			glTranslatef(*elem.position, 0)
			#glScale(1/self.view.resolution[0], 1/self.view.resolution[1], 1)
			glScale(1/2000, 1/2000*ar, 1)
			elem.draw(values_dict[name])
			glPopMatrix()

		if self.composition_overlay_enabled:
			self.draw_composition_overlay()

		glPopMatrix()