예제 #1
0
    def __init__(self, width, height, gbuffer=None, lightbuffer=None):
        self.ctx = context.ctx()

        self.width = width
        self.height = height
        self.size = (width, height)
        self.depth_sampler = samplers.create(texture_compare_mode=False,
                                             min_filter=moderngl.LINEAR,
                                             mag_filter=moderngl.LINEAR)

        # FBOs
        self.gbuffer = gbuffer
        self.lightbuffer = lightbuffer

        # Light Info
        self.point_lights = []

        # Create geometry buffer if not supplied
        depth_buffer = DepthTexture(self.size)

        if not self.gbuffer:
            self.gbuffer = FBO.create_from_textures(
                [
                    Texture2D.create(self.size, 4, dtype='f1'),
                    Texture2D.create(self.size, 3, dtype='f2'),
                ],
                depth_buffer=depth_buffer,
            )

        if not self.lightbuffer:
            self.lightbuffer = FBO.create_from_textures(
                [Texture2D.create(self.size, 4)],
                # depth_buffer=depth_buffer,
            )

        # Unit cube for point lights (cube with radius 1.0)
        self.unit_cube = geometry.cube(width=2, height=2, depth=2)
        self.point_light_shader = resources.shaders.get(
            "deferred/light_point.glsl", create=True)

        # Debug draw lights
        self.debug_shader = resources.shaders.get("deferred/debug.glsl",
                                                  create=True)

        # Combine shader
        self.combine_shader = resources.shaders.get("deferred/combine.glsl",
                                                    create=True)
        self.quad = geometry.quad_fs()
예제 #2
0
파일: glfw.py 프로젝트: binaryf/demosys-py
    def __init__(self):
        super().__init__()

        if not glfw.init():
            raise ValueError("Failed to initialize glfw")

        self.check_glfw_version()

        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, self.gl_version.major)
        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, self.gl_version.minor)
        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
        glfw.window_hint(glfw.RESIZABLE, self.resizable)
        glfw.window_hint(glfw.DOUBLEBUFFER, True)
        glfw.window_hint(glfw.DEPTH_BITS, 24)

        monitor = None
        if self.fullscreen:
            # Use the primary monitors current resolution
            monitor = glfw.get_primary_monitor()
            mode = glfw.get_video_mode(monitor)

            self.width, self.height = mode.size.width, mode.size.height
            print("picked fullscreen mode:", mode)

        print("Window size:", self.width, self.height)
        self.window = glfw.create_window(self.width, self.height, self.title, 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)

        # 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.vsync:
            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()
        self.fbo = FBO()
        self.fbo.ctx = self.ctx
        self.fbo.fbo = self.ctx.screen
        self.fbo.default_framebuffer = True
        context.WINDOW = self
        self.set_default_viewport()
예제 #3
0
 def test_create_from_textures(self):
     fbo = FBO.create_from_textures(
         [
             Texture2D.create((256, 256)),
             Texture2D.create((256, 256)),
         ],
         DepthTexture.create(((256, 256))),
     )
예제 #4
0
    def test_read(self):
        fbo = FBO.create((256, 256), depth=True, layers=1)

        data = fbo.read(components=4)
        assert len(data) == 256 * 256 * 4

        buffer = bytearray([0] * 256 * 256 * 4)
        fbo.read_into(buffer)
예제 #5
0
    def _post_load(self):
        super()._post_load()
        self._texture_width = int(
            round(
                self._meta.char_aspect_wh * self._texture_height *
                self.area[0] / self.area[1], 0))

        self.aspect_ratio = self._texture_width / self._texture_height
        self._fbo = FBO.create((self._texture_width, self._texture_height))
예제 #6
0
    def __init__(self):
        self.cube_shader1 = self.get_shader('geocubes/cube_multi_fade.glsl')
        self.cube_shader2 = self.get_shader('geocubes/cube_texture_light.glsl')
        self.quad_shader = self.get_shader('geocubes/quad_fs_uvscale.glsl')

        self.texture1 = self.get_texture('geocubes/texture.png')
        self.texture2 = self.get_texture('geocubes/GreenFabric.png')

        self.cube = geometry.cube(4.0, 4.0, 4.0)

        v = 100.0
        r = (-v, v)

        self.points = geometry.points_random_3d(50_000,
                                                range_x=r,
                                                range_y=r,
                                                range_z=r,
                                                seed=7656456)
        self.quad = geometry.quad_fs()
        self.fbo = FBO.create((512, 512), depth=True)
예제 #7
0
 def test_create(self):
     fbo = FBO.create((256, 256), depth=True, layers=1)
     self.assertGeneral(fbo)
예제 #8
0
 def test_stuff(self):
     FBO.create((10, 10), depth=True)
예제 #9
0
    def __init__(self, width, height, gbuffer=None, lightbuffer=None):
        self.width = width
        self.height = height
        # FBOs
        self.gbuffer = gbuffer
        self.lightbuffer = lightbuffer
        # Light Info
        self.point_lights = []

        # FIXME: We might want double buffering here as well
        # Create geometry buffer if not supplied
        if not self.gbuffer:
            self.gbuffer = FBO()
            # RGBA color attachment
            self.gbuffer.add_color_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_RGBA8,
                                  format=GL.GL_RGBA,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # 16 bit RGB float buffer for normals
            self.gbuffer.add_color_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  format=GL.GL_RGB,
                                  internal_format=GL.GL_RGB16F,
                                  type=GL.GL_FLOAT,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # 24 bit depth, 8 bit stencil
            self.gbuffer.set_depth_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_DEPTH24_STENCIL8,
                                  format=GL.GL_DEPTH_COMPONENT,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE,
                                  wrap_r=GL.GL_CLAMP_TO_EDGE))
        if not self.lightbuffer:
            self.lightbuffer = FBO()
            # 8 bit light accumulation buffer
            self.lightbuffer.add_color_attachment(
                # Texture.create_2d(width=width, height=height,
                #                   internal_format=GL.GL_RED, format=GL.GL_RED, type=GL.GL_UNSIGNED_BYTE,
                #                   min_filter=GL.GL_NEAREST, mag_filter=GL.GL_NEAREST,
                #                   wrap_s=GL.GL_CLAMP_TO_EDGE, wrap_t=GL.GL_CLAMP_TO_EDGE)
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_RGBA8,
                                  format=GL.GL_RGBA,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # Attach the same depth buffer as the geometry buffer
            self.lightbuffer.set_depth_attachment(self.gbuffer.depth_buffer)

        # Unit cube for point lights (cube with radius 1.0)
        self.unit_cube = geometry.cube(width=2, height=2, depth=2)
        self.point_light_shader = resources.shaders.get(
            "deferred/light_point.glsl", create=True)

        # Debug draw lights
        self.debug_shader = resources.shaders.get("deferred/debug.glsl",
                                                  create=True)

        # Combine shader
        self.combine_shader = resources.shaders.get("deferred/combine.glsl",
                                                    create=True)
        self.quad = geometry.quad_fs()
예제 #10
0
class DeferredRenderer:
    def __init__(self, width, height, gbuffer=None, lightbuffer=None):
        self.width = width
        self.height = height
        # FBOs
        self.gbuffer = gbuffer
        self.lightbuffer = lightbuffer
        # Light Info
        self.point_lights = []

        # FIXME: We might want double buffering here as well
        # Create geometry buffer if not supplied
        if not self.gbuffer:
            self.gbuffer = FBO()
            # RGBA color attachment
            self.gbuffer.add_color_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_RGBA8,
                                  format=GL.GL_RGBA,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # 16 bit RGB float buffer for normals
            self.gbuffer.add_color_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  format=GL.GL_RGB,
                                  internal_format=GL.GL_RGB16F,
                                  type=GL.GL_FLOAT,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # 24 bit depth, 8 bit stencil
            self.gbuffer.set_depth_attachment(
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_DEPTH24_STENCIL8,
                                  format=GL.GL_DEPTH_COMPONENT,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE,
                                  wrap_r=GL.GL_CLAMP_TO_EDGE))
        if not self.lightbuffer:
            self.lightbuffer = FBO()
            # 8 bit light accumulation buffer
            self.lightbuffer.add_color_attachment(
                # Texture.create_2d(width=width, height=height,
                #                   internal_format=GL.GL_RED, format=GL.GL_RED, type=GL.GL_UNSIGNED_BYTE,
                #                   min_filter=GL.GL_NEAREST, mag_filter=GL.GL_NEAREST,
                #                   wrap_s=GL.GL_CLAMP_TO_EDGE, wrap_t=GL.GL_CLAMP_TO_EDGE)
                Texture.create_2d(width=width,
                                  height=height,
                                  internal_format=GL.GL_RGBA8,
                                  format=GL.GL_RGBA,
                                  min_filter=GL.GL_NEAREST,
                                  mag_filter=GL.GL_NEAREST,
                                  wrap_s=GL.GL_CLAMP_TO_EDGE,
                                  wrap_t=GL.GL_CLAMP_TO_EDGE))
            # Attach the same depth buffer as the geometry buffer
            self.lightbuffer.set_depth_attachment(self.gbuffer.depth_buffer)

        # Unit cube for point lights (cube with radius 1.0)
        self.unit_cube = geometry.cube(width=2, height=2, depth=2)
        self.point_light_shader = resources.shaders.get(
            "deferred/light_point.glsl", create=True)

        # Debug draw lights
        self.debug_shader = resources.shaders.get("deferred/debug.glsl",
                                                  create=True)

        # Combine shader
        self.combine_shader = resources.shaders.get("deferred/combine.glsl",
                                                    create=True)
        self.quad = geometry.quad_fs()

    def draw_buffers(self, near, far):
        """
        Draw framebuffers for debug purposes.
        We need to supply near and far plane so the depth buffer can be linearized when visualizing.

        :param near: Projection near value
        :param far: Projection far value
        """
        self.gbuffer.draw_color_layer(layer=0,
                                      pos=(0.0, 0.0),
                                      scale=(0.25, 0.25))
        self.gbuffer.draw_color_layer(layer=1,
                                      pos=(0.5, 0.0),
                                      scale=(0.25, 0.25))
        self.gbuffer.draw_depth(near, far, pos=(1.0, 0.0), scale=(0.25, 0.25))
        self.lightbuffer.draw_color_layer(layer=0,
                                          pos=(1.5, 0.0),
                                          scale=(0.25, 0.25))

    def add_point_light(self, position, radius):
        """Add point light"""
        self.point_lights.append(PointLight(position, radius))

    def render_lights(self, camera_matrix, projection):
        """Render light volumes"""
        # Disable culling so lights can be rendered when inside volumes
        GL.glEnable(GL.GL_CULL_FACE)
        GL.glFrontFace(GL.GL_CW)
        # No depth testing
        GL.glDisable(GL.GL_DEPTH_TEST)
        # Enable additive blending
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_ONE, GL.GL_ONE)

        with self.lightbuffer:
            for light in self.point_lights:
                # Calc light properties
                light_size = light.radius
                m_light = matrix44.multiply(light.matrix, camera_matrix)
                # Draw the light volume
                with self.unit_cube.bind(self.point_light_shader) as s:
                    s.uniform_mat4("m_proj", projection.matrix)
                    s.uniform_mat4("m_light", m_light)
                    s.uniform_sampler_2d(0, "g_normal",
                                         self.gbuffer.color_buffers[1])
                    s.uniform_sampler_2d(1, "g_depth",
                                         self.gbuffer.depth_buffer)
                    s.uniform_2f("screensize", self.width, self.height)
                    s.uniform_2f("proj_const",
                                 *projection.projection_constants)
                    s.uniform_1f("radius", light_size)
                self.unit_cube.draw()

        GL.glDisable(GL.GL_BLEND)
        GL.glDisable(GL.GL_CULL_FACE)

    def render_lights_debug(self, camera_matrix, projection):
        """Render outlines of light volumes"""
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)

        for light in self.point_lights:
            m_mv = matrix44.multiply(light.matrix, camera_matrix)
            light_size = light.radius
            with self.unit_cube.bind(self.debug_shader) as s:
                s.uniform_mat4("m_proj", projection.matrix)
                s.uniform_mat4("m_mv", m_mv)
                s.uniform_1f("size", light_size)
            self.unit_cube.draw(GL.GL_LINE_STRIP)

        GL.glDisable(GL.GL_BLEND)

    def render_geometry(self, cam_matrix, projection):
        raise NotImplementedError("render_geometry() not implemented")

    def combine(self):
        """Combine diffuse and light buffer"""
        with self.quad.bind(self.combine_shader) as s:
            s.uniform_sampler_2d(0, "diffuse_buffer",
                                 self.gbuffer.color_buffers[0])
            s.uniform_sampler_2d(1, "light_buffer",
                                 self.lightbuffer.color_buffers[0])
        self.quad.draw()

    def clear(self):
        """clear all buffers"""
        self.gbuffer.clear()
        self.lightbuffer.clear()