コード例 #1
0
class MinimalFramebufferExample(object):
    def __init__(self):
        self.window = GlutWindow(double=True,
                                 multisample=True,
                                 shape=(100, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)
        self.shader.dimy, self.shader.dimx = self.window.shape
        self.fbo = Framebuffer(
            RectangleTexture(shape=self.window.shape + (3, )))

        self.vao = VertexArray(
            ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)),
            elements=((0, 1, 2), (0, 2, 3)))

    def save(self, filename):
        self.fbo.clear()
        with self.shader:
            with self.fbo:
                self.vao.draw()
        imsave(filename, self.fbo[0].data)

    def display(self):
        self.window.clear()
        with self.shader:
            self.vao.draw()
        self.window.swap_buffers()

    def run(self):
        main_loop()
コード例 #2
0
class MinimalFramebufferExample(object):
    def __init__(self):
        self.window = GlutWindow(double=True, multisample=True, shape=(100, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)
        self.shader.dimy, self.shader.dimx = self.window.shape
        self.fbo = Framebuffer(RectangleTexture(shape=self.window.shape + (3,)))

        self.vao = VertexArray(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)), elements=((0, 1, 2), (0, 2, 3)))

    def save(self, filename):
        self.fbo.clear()
        with self.shader:
            with self.fbo:
                self.vao.draw()
        imsave(filename, self.fbo[0].data)

    def display(self):
        self.window.clear()
        with self.shader:
            self.vao.draw()
        self.window.swap_buffers()

    def run(self):
        main_loop()
コード例 #3
0
    def __init__(self, volume, **kwargs):
        assert isinstance(volume, Texture3D), "volume must be a 3D texture"

        # We need a vertex array to hold the faces of the cube:
        self.vao = VertexArray(cube_vertices, elements=cube_indices)

        # For rendering the back faces, we create a shader program and a
        # framebuffer with an attached texture:
        self.back_shader = ShaderProgram(vertex=vertex_code,
                                         fragment=back_fragment_code)
        self.back_fbo = Framebuffer(
            RectangleTexture(shape=volume.shape[:2] + (4, ), dtype=float32))

        # For the front faces, we do the same. Additionally, the shader
        # receives the texture containing the back face coordinates in a
        # uniform variable <code>back</code>, and the 3D texture containing the
        # volumetric data in a uniform variable <code>volume</code>.
        self.front_shader = ShaderProgram(vertex=vertex_code,
                                          fragment=front_fragment_code,
                                          back=self.back_fbo[0],
                                          volume=volume)
        self.front_fbo = Framebuffer(
            RectangleTexture(shape=volume.shape[:2] + (4, ), dtype=float32))

        # All other parameters are simply set as attributes (this might be
        # <code>modelview_matrix</code>, <code>intensity_scale</code>, or
        # <code>absorption</code>).
        for key, value in list(kwargs.items()):
            setattr(self, key, value)
コード例 #4
0
ファイル: meshview.py プロジェクト: adamlwgriffiths/glitter
    def __init__(self, filename):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # We open the HDF5 file specified on the command line for reading:
        if filename.endswith(".dat"):
            data = loadtxt(filename)
            assert data.ndim == 2 and data.shape[1] in (3, 6)

            vertices = data[:, :3]
            vertices -= vertices.min()
            vertices /= vertices.max()
            vertices -= 0.5
            
            colors = data[:, 3:] if data.shape[1] == 6 else None
            colors -= colors.min()
            colors /= colors.max()
            
            elements = None
        else:
            with h5py.File(filename, "r") as f:
                # The vertices, colors and indices of the mesh are read from the
                # corresponding datasets in the HDF5 file. Note that the names of the
                # datasets are mere convention. Colors and indices are allowed to be
                # undefined.
                vertices = f["vertices"]
                colors = f.get("colors", None)
                elements = f.get("indices", None)
                if vertices is not None:
                    vertices = vertices.value
                if colors is not None:
                    colors = colors.value
                if elements is not None:
                    elements = elements.value

        # If no colors were specified, we generate random ones so we can
        # distinguish the triangles without fancy shading.
        if colors is None:
            colors = random((len(vertices), 3))[:, None, :][:, [0] * vertices.shape[1], :]

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array. If <code>elements</code>
        # is <code>None</code>, the vertex array class will draw all vertices
        # in order.
        self.vao = VertexArray(vertices, colors, elements=elements)
コード例 #5
0
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, alpha=True, depth=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # Here, we generate numpy arrays to hold the positions, colors, and
        # velocities of the particles:
        num = 200000
        positions = numpy.empty((num, 4), dtype=numpy.float32)
        colors = numpy.empty((num, 4), dtype=numpy.float32)
        velocities = numpy.empty((num, 4), dtype=numpy.float32)

        # So far, the array contents are undefined. We have to initialize them with meaningful values:
        positions[:, 0] = numpy.sin(numpy.arange(0, num) * 2 * numpy.pi /
                                    num) * (numpy.random.random_sample(
                                        (num, )) / 3 + 0.2)
        positions[:, 1] = numpy.cos(numpy.arange(0, num) * 2 * numpy.pi /
                                    num) * (numpy.random.random_sample(
                                        (num, )) / 3 + 0.2)
        positions[:, 2:] = 0, 1
        colors[:] = 0, 1, 0, 1
        velocities[:, :2] = 2 * positions[:, :2]
        velocities[:, 2] = 3
        velocities[:, 3] = numpy.random.random_sample((num, ))

        # Instead of simply generating a vertex array from the position and color
        # data, we first generate array buffers for them:
        gl_positions = ArrayBuffer(data=positions, usage="DYNAMIC_DRAW")
        gl_colors = ArrayBuffer(data=colors, usage="DYNAMIC_DRAW")
        # These array buffers will later also be used by OpenCL. We do not need to
        # wrap <code>velocities</code> in this way, as it will only be used by
        # OpenCL and can be wrapped in an OpenCL buffer directly.

        # We now create a vertex array that will pass the position and color data
        # to the shader. The vertex array constructor accepts
        # <code>ArrayBuffer</code> instances:
        self.vao = VertexArray(gl_positions, gl_colors)

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create the <code>CLCode</code> object that manages OpenCL
        # interaction. It is passed the OpenGL buffer objects as well as a numpy
        # array of velocities.
        self.clcode = CLCode(gl_positions, gl_colors, velocities)
コード例 #6
0
    def __init__(self):
        self.window = GlutWindow(double=True,
                                 multisample=True,
                                 shape=(100, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)
        self.shader.dimy, self.shader.dimx = self.window.shape
        self.fbo = Framebuffer(
            RectangleTexture(shape=self.window.shape + (3, )))

        self.vao = VertexArray(
            ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)),
            elements=((0, 1, 2), (0, 2, 3)))
コード例 #7
0
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        n_points = 100000
        self.vao = VertexArray(randn(n_points, 3), randn(n_points, 3))
コード例 #8
0
 def __init__(self, filename):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.shader = get_default_program()
     self.fbo = Framebuffer(
         depth=Texture2D(shape=self.window.shape + (1, ), depth=True))
     self.copy_pipeline = get_copy_pipeline_2d(image=self.fbo.depth,
                                               use_framebuffer=False)
     with h5py.File(filename, "r") as f:
         vertices = f["vertices"]
         colors = f.get("colors", None)
         elements = f.get("indices", None)
         if colors is None:
             colors = random(
                 (len(vertices), 3))[:, None, :][:,
                                                 [0] * vertices.shape[1], :]
         self.vao = VertexArray(vertices, colors, elements=elements)
コード例 #9
0
class DepthViewer(object):
    def __init__(self, filename):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.shader = get_default_program()
        self.fbo = Framebuffer(
            depth=Texture2D(shape=self.window.shape + (1, ), depth=True))
        self.copy_pipeline = get_copy_pipeline_2d(image=self.fbo.depth,
                                                  use_framebuffer=False)
        with h5py.File(filename, "r") as f:
            vertices = f["vertices"]
            colors = f.get("colors", None)
            elements = f.get("indices", None)
            if colors is None:
                colors = random(
                    (len(vertices), 3))[:, None, :][:,
                                                    [0] * vertices.shape[1], :]
            self.vao = VertexArray(vertices, colors, elements=elements)

    def display(self):
        try:
            with self.fbo:
                self.fbo.clear()
                self.vao.draw()
            self.window.clear()
            self.copy_pipeline.draw()
            self.window.swap_buffers()
        except Exception as e:
            import traceback
            traceback.print_exc()
            raise SystemExit(e)

    def timer(self):
        phi = 2 * pi * get_elapsed_time() / 20.0
        self.shader.modelview_matrix = ((cos(phi), 0, sin(phi), 0),
                                        (0, 1, 0, 0), (-sin(phi), 0, cos(phi),
                                                       0), (0, 0, 0, 1))
        self.window.add_timer(10, self.timer)
        self.window.post_redisplay()

    def run(self):
        self.timer()
        with self.shader:
            with State(depth_test=True):
                main_loop()
コード例 #10
0
    def __init__(self):
        self.window = GlutWindow(double=True, multisample=True, shape=(100, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)
        self.shader.dimy, self.shader.dimx = self.window.shape
        self.fbo = Framebuffer(RectangleTexture(shape=self.window.shape + (3,)))

        self.vao = VertexArray(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)), elements=((0, 1, 2), (0, 2, 3)))
コード例 #11
0
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # A shader program is built from the previously defined vertex and
        # fragment codes:
        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)

        # This shader program is then used to build a pipeline. A pipeline is a
        # convenience object that encapsulates a vertex array for input, a
        # shader program for processing, and a framebuffer for output. The
        # framebuffer is optional (we could render directly to the screen if we
        # wanted), but we will render into a texture and copy the texture to
        # the screen for instructional purposes. The <code>Pipeline</code>
        # constructor automatically creates an empty vertex array and a
        # framebuffer with no attachments. Named constructor arguments are
        # interpreted as attributes of the vertex array and the framebuffer or
        # as named inputs and outputs of the shader. This means we can directly
        # pass in arrays of vertices and colors that will be bound to
        # <code>in_position</code> and <code>in_color</code>, respectivey, as
        # well as the array of element indices to draw and an empty texture to
        # bind to the framebuffer:
        self.render_pipeline = Pipeline(self.shader, in_position=vertices, in_color=colors,
                elements=indices, out_color=RectangleTexture(shape=(300, 300, 3)))

        # Shader uniform variables like textures can also be set directly on
        # the pipeline. Here we initialize two textures with random data:
        self.render_pipeline.texture_0 = Texture2D(random((30, 30, 4)))
        self.render_pipeline.texture_1 = RectangleTexture(random((30, 30, 4)))

        # Many properties, such as the filtering mode for textures, can
        # directly be set as attributes on the corresponding objects:
        self.render_pipeline.texture_0.min_filter = Texture2D.min_filters.NEAREST
        self.render_pipeline.texture_0.mag_filter = Texture2D.mag_filters.NEAREST

        # For copying the texture to the screen, we create another shader
        # program.
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader, fragment=copy_fragment_shader)

        # The input texture of this shader program is the output texture of the
        # previous pipeline. Since all textures and framebuffers are
        # automatically bound and unbound, we do not need to worry about
        # whether the framebuffer is still writing to the texture.
        self.copy_shader.image = self.render_pipeline.out_color

        # Instead of using a pipeline with named vertex shader inputs, we can
        # also create a vertex array object directly with a list of vertex
        # shader inputs to use. Here we use only a single vertex shader input:
        # the coordinates of a fullscreen quad. The <code>elements</code>
        # parameter defines two triangles that make up the quad.
        self.vao = VertexArray(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)), elements=((0, 1, 2), (0, 2, 3)))
コード例 #12
0
ファイル: simple.py プロジェクト: adamlwgriffiths/glitter
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined
        # later.
        self.window.display_callback = self.display

        # We also set mouse callbacks that will display the pixel color in the
        # title bar.
        self.window.mouse_callback = self.mouse
        self.window.motion_callback = self.motion

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        self.vao = VertexArray(vertices, colors, elements=indices)
コード例 #13
0
ファイル: minimal.py プロジェクト: adamlwgriffiths/glitter
class IntroductionExample(object):
    def __init__(self):
        self.window = GlutWindow(double=True, multisample=True, shape=(600, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader, fragment=copy_fragment_shader)
        
        self.copy_shader.image = RectangleTexture(shape=self.window.shape + (3,))
        self.fbo = Framebuffer(self.copy_shader.image)

        self.vao = VertexArray(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)), elements=((0, 1, 2), (0, 2, 3)))

    def display(self, use_texture=False):
        self.window.clear()

        if use_texture:
            self.fbo.clear()
            with self.fbo:
                with self.shader:
                    self.vao.draw()
            with self.copy_shader:
                self.vao.draw()
        else:
            with self.shader:
                self.vao.draw()
        
        self.window.swap_buffers()

    def run(self):
        main_loop()
コード例 #14
0
 def __init__(self, filename):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.shader = get_default_program()
     self.fbo = Framebuffer(depth=Texture2D(shape=self.window.shape + (1,), depth=True))
     self.copy_pipeline = get_copy_pipeline_2d(image=self.fbo.depth, use_framebuffer=False)
     with h5py.File(filename, "r") as f:
         vertices = f["vertices"]
         colors = f.get("colors", None)
         elements = f.get("indices", None)
         if colors is None:
             colors = random((len(vertices), 3))[:, None, :][:, [0] * vertices.shape[1], :]
         self.vao = VertexArray(vertices, colors, elements=elements)
コード例 #15
0
class DepthViewer(object):
    def __init__(self, filename):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.shader = get_default_program()
        self.fbo = Framebuffer(depth=Texture2D(shape=self.window.shape + (1,), depth=True))
        self.copy_pipeline = get_copy_pipeline_2d(image=self.fbo.depth, use_framebuffer=False)
        with h5py.File(filename, "r") as f:
            vertices = f["vertices"]
            colors = f.get("colors", None)
            elements = f.get("indices", None)
            if colors is None:
                colors = random((len(vertices), 3))[:, None, :][:, [0] * vertices.shape[1], :]
            self.vao = VertexArray(vertices, colors, elements=elements)

    def display(self):
        try:
            with self.fbo:
                self.fbo.clear()
                self.vao.draw()
            self.window.clear()
            self.copy_pipeline.draw()
            self.window.swap_buffers()
        except Exception as e:
            import traceback
            traceback.print_exc()
            raise SystemExit(e)

    def timer(self):
        phi = 2 * pi * get_elapsed_time() / 20.0
        self.shader.modelview_matrix = ((cos(phi), 0, sin(phi), 0), (0, 1, 0, 0), (-sin(phi), 0, cos(phi), 0), (0, 0, 0, 1))
        self.window.add_timer(10, self.timer)
        self.window.post_redisplay()
    
    def run(self):
        self.timer()
        with self.shader:
            with State(depth_test=True):
                main_loop()
コード例 #16
0
ファイル: pointcloud.py プロジェクト: adamlwgriffiths/glitter
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        n_points = 100000
        self.vao = VertexArray(randn(n_points, 3), randn(n_points, 3))
コード例 #17
0
ファイル: opencl.py プロジェクト: adamlwgriffiths/glitter
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, alpha=True, depth=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # Here, we generate numpy arrays to hold the positions, colors, and
        # velocities of the particles:
        num = 200000
        positions = numpy.empty((num, 4), dtype=numpy.float32)
        colors = numpy.empty((num, 4), dtype=numpy.float32)
        velocities = numpy.empty((num, 4), dtype=numpy.float32)

        # So far, the array contents are undefined. We have to initialize them with meaningful values:
        positions[:, 0] = numpy.sin(numpy.arange(0, num) * 2 * numpy.pi / num) * (numpy.random.random_sample((num,)) / 3 + 0.2)
        positions[:, 1] = numpy.cos(numpy.arange(0, num) * 2 * numpy.pi / num) * (numpy.random.random_sample((num,)) / 3 + 0.2)
        positions[:, 2:] = 0, 1
        colors[:] = 0, 1, 0, 1
        velocities[:, :2] = 2 * positions[:, :2]
        velocities[:, 2] = 3
        velocities[:, 3] = numpy.random.random_sample((num,))

        # Instead of simply generating a vertex array from the position and color
        # data, we first generate array buffers for them:
        gl_positions = ArrayBuffer(data=positions, usage="DYNAMIC_DRAW")
        gl_colors = ArrayBuffer(data=colors, usage="DYNAMIC_DRAW")
        # These array buffers will later also be used by OpenCL. We do not need to
        # wrap <code>velocities</code> in this way, as it will only be used by
        # OpenCL and can be wrapped in an OpenCL buffer directly.

        # We now create a vertex array that will pass the position and color data
        # to the shader. The vertex array constructor accepts
        # <code>ArrayBuffer</code> instances:
        self.vao = VertexArray(gl_positions, gl_colors)

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()
        
        # Here, we create the <code>CLCode</code> object that manages OpenCL
        # interaction. It is passed the OpenGL buffer objects as well as a numpy
        # array of velocities.
        self.clcode = CLCode(gl_positions, gl_colors, velocities)
コード例 #18
0
ファイル: simple.py プロジェクト: adamlwgriffiths/glitter
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined
        # later.
        self.window.display_callback = self.display

        # We also set mouse callbacks that will display the pixel color in the
        # title bar.
        self.window.mouse_callback = self.mouse
        self.window.motion_callback = self.motion

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        self.vao = VertexArray(vertices, colors, elements=indices)
コード例 #19
0
class IntroductionExample(object):
    def __init__(self):
        self.window = GlutWindow(double=True,
                                 multisample=True,
                                 shape=(600, 800))
        self.window.display_callback = self.display

        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader,
                                         fragment=copy_fragment_shader)

        self.copy_shader.image = RectangleTexture(shape=self.window.shape +
                                                  (3, ))
        self.fbo = Framebuffer(self.copy_shader.image)

        self.vao = VertexArray(
            ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)),
            elements=((0, 1, 2), (0, 2, 3)))

    def display(self, use_texture=False):
        self.window.clear()

        if use_texture:
            self.fbo.clear()
            with self.fbo:
                with self.shader:
                    self.vao.draw()
            with self.copy_shader:
                self.vao.draw()
        else:
            with self.shader:
                self.vao.draw()

        self.window.swap_buffers()

    def run(self):
        main_loop()
コード例 #20
0
class IntroductionExample(object):
    # <h3>Initialization</h3>

    # When an <code>IntroductionExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # A shader program is built from the previously defined vertex and
        # fragment codes:
        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)

        # This shader program is then used to build a pipeline. A pipeline is a
        # convenience object that encapsulates a vertex array for input, a
        # shader program for processing, and a framebuffer for output. The
        # framebuffer is optional (we could render directly to the screen if we
        # wanted), but we will render into a texture and copy the texture to
        # the screen for instructional purposes. The <code>Pipeline</code>
        # constructor automatically creates an empty vertex array and a
        # framebuffer with no attachments. Named constructor arguments are
        # interpreted as attributes of the vertex array and the framebuffer or
        # as named inputs and outputs of the shader. This means we can directly
        # pass in arrays of vertices and colors that will be bound to
        # <code>in_position</code> and <code>in_color</code>, respectivey, as
        # well as the array of element indices to draw and an empty texture to
        # bind to the framebuffer:
        self.render_pipeline = Pipeline(self.shader, in_position=vertices, in_color=colors,
                elements=indices, out_color=RectangleTexture(shape=(300, 300, 3)))

        # Shader uniform variables like textures can also be set directly on
        # the pipeline. Here we initialize two textures with random data:
        self.render_pipeline.texture_0 = Texture2D(random((30, 30, 4)))
        self.render_pipeline.texture_1 = RectangleTexture(random((30, 30, 4)))

        # Many properties, such as the filtering mode for textures, can
        # directly be set as attributes on the corresponding objects:
        self.render_pipeline.texture_0.min_filter = Texture2D.min_filters.NEAREST
        self.render_pipeline.texture_0.mag_filter = Texture2D.mag_filters.NEAREST

        # For copying the texture to the screen, we create another shader
        # program.
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader, fragment=copy_fragment_shader)

        # The input texture of this shader program is the output texture of the
        # previous pipeline. Since all textures and framebuffers are
        # automatically bound and unbound, we do not need to worry about
        # whether the framebuffer is still writing to the texture.
        self.copy_shader.image = self.render_pipeline.out_color

        # Instead of using a pipeline with named vertex shader inputs, we can
        # also create a vertex array object directly with a list of vertex
        # shader inputs to use. Here we use only a single vertex shader input:
        # the coordinates of a fullscreen quad. The <code>elements</code>
        # parameter defines two triangles that make up the quad.
        self.vao = VertexArray(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)), elements=((0, 1, 2), (0, 2, 3)))

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever
    # the screen has to be redrawn.
    def display(self):
        # We can simply clear the pipeline and render the vertices into the
        # framebuffer using the shader with the following two lines:
        self.render_pipeline.clear()
        self.render_pipeline.draw()

        # For output on the screen, we have created a GLUT window. It can be
        # cleared in very much the same way:
        self.window.clear()

        # To copy the results of the pipeline to the screen, we use the shader
        # that simply displays a texture. The shader can be bound by using a
        # <code>with</code> statement:
        with self.copy_shader:
            # All textures used by the shader are then bound automatically, and
            # everything is reset to its previous state when we leave the
            # <code>with</code> block.

            # With the shader bound, we simply draw a fullscreen quad that is
            # stored in a vertex array we will create in the initialization
            # section:
            self.vao.draw()

        # After all rendering commands have been issued, we swap the back
        # buffer to the front, making the rendered image visible all at once:
        self.window.swap_buffers()

        # Finally, we disable logging so that we only see the OpenGL calls of
        # the first run of the display function:
        add_logger(None)

    # <h4>Keyboard function</h4>

    # To further illustrate the concept of GLUT callbacks, here's a keyboard
    # handler that will simply make the program exit when any key is pressed:
    def keyboard(self, key, x, y):
        raise SystemExit

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes
    # the modelview matrix, schedules the next timer event, and causes a screen
    # redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using
        # <code>get_elapsed_time()</code>:
        t = get_elapsed_time()
        phi = 2 * pi * t / 4.0

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), sin(phi), 0, 0), (-sin(phi), cos(phi), 0, 0), (0, 0, 1, 0), (0, 0, 0, 1))

        # The following line schedules the next timer event to execute after
        # ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>
    
    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # Now that all the initialization is done, we add the default logger to
        # all OpenGL commands so that we can see what OpenGL the display
        # function issues, and in which order.
        add_logger()

        # Finally, to start rendering, we enter the GLUT main loop.
        main_loop()
コード例 #21
0
# an HDF5 output file. An optional third parameter specifies the size of the
# resulting volume.
if __name__ == "__main__":
    # We need to read a mesh filename from <code>sys.argv</code>, so import
    # <code>sys</code>.
    import sys

    # We assume the mesh is stored in a <a
    # href="http://www.hdfgroup.org/HDF5/">HDF5</a> file, so import <a
    # href="h5py.alfven.org"><code>h5py</code></a>.
    import h5py

    # We open the HDF5 file specified on the command line for reading, extract
    # the vertices and indices, and store them in a vertex array:
    with h5py.File(sys.argv[1]) as f:
        mesh = VertexArray(f["vertices"], elements=f["indices"])

    # Now the voxelization is performed and the result is returned as an array
    # of 2D integer textures.
    volume = voxelize(mesh, int(sys.argv[3]) if len(sys.argv) > 3 else 128)

    # Finally, we open the output file, download the data, and store it in a
    # dataset. The dataset can typically be compressed a lot, which is why we
    # enable LZF compression. However, this may take a long time, so you can
    # disable it if you are not short on disk space.
    with h5py.File(sys.argv[2], "w") as f:
        f.create_dataset("data", data=volume.data, compression="lzf")

    # Note how we did not need to create an OpenGL context explicitly. The
    # first object that needs an OpenGL context (in this case the
    # <code>VertexArray</code>) will create an invisible context as soon as it
コード例 #22
0
ファイル: opencl.py プロジェクト: adamlwgriffiths/glitter
class OpenCLExample(object):
    # <h3>Initialization</h3>

    # When a <code>OpenCLExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, alpha=True, depth=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # Here, we generate numpy arrays to hold the positions, colors, and
        # velocities of the particles:
        num = 200000
        positions = numpy.empty((num, 4), dtype=numpy.float32)
        colors = numpy.empty((num, 4), dtype=numpy.float32)
        velocities = numpy.empty((num, 4), dtype=numpy.float32)

        # So far, the array contents are undefined. We have to initialize them with meaningful values:
        positions[:, 0] = numpy.sin(numpy.arange(0, num) * 2 * numpy.pi / num) * (numpy.random.random_sample((num,)) / 3 + 0.2)
        positions[:, 1] = numpy.cos(numpy.arange(0, num) * 2 * numpy.pi / num) * (numpy.random.random_sample((num,)) / 3 + 0.2)
        positions[:, 2:] = 0, 1
        colors[:] = 0, 1, 0, 1
        velocities[:, :2] = 2 * positions[:, :2]
        velocities[:, 2] = 3
        velocities[:, 3] = numpy.random.random_sample((num,))

        # Instead of simply generating a vertex array from the position and color
        # data, we first generate array buffers for them:
        gl_positions = ArrayBuffer(data=positions, usage="DYNAMIC_DRAW")
        gl_colors = ArrayBuffer(data=colors, usage="DYNAMIC_DRAW")
        # These array buffers will later also be used by OpenCL. We do not need to
        # wrap <code>velocities</code> in this way, as it will only be used by
        # OpenCL and can be wrapped in an OpenCL buffer directly.

        # We now create a vertex array that will pass the position and color data
        # to the shader. The vertex array constructor accepts
        # <code>ArrayBuffer</code> instances:
        self.vao = VertexArray(gl_positions, gl_colors)

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()
        
        # Here, we create the <code>CLCode</code> object that manages OpenCL
        # interaction. It is passed the OpenGL buffer objects as well as a numpy
        # array of velocities.
        self.clcode = CLCode(gl_positions, gl_colors, velocities)

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()
        
        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback animates the
    # particle system, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first tell an instance of the <code>CLCode</code> class to execute the
        # OpenCL kernel:
        self.clcode.execute(10)

        # The following line schedules the next timer event to execute after one millisecond.
        self.window.add_timer(1, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h4>Keyboard function</h4>

    # To further illustrate the concept of GLUT callbacks, here's a keyboard
    # handler that will simply make the program exit when any key is pressed:
    def keyboard(self, key, x, y):
        raise SystemExit

    # <h3>Running</h3>
    
    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement. At
        # the same time, we can pass in additional uniform variables, such as the
        # modelview matrix:
        with self.shader(modelview_matrix=((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 2))):
            # With the shader bound, we enter the GLUT main loop.
            main_loop()
コード例 #23
0
ファイル: simple.py プロジェクト: adamlwgriffiths/glitter
class SimpleExample(object):
    # <h3>Initialization</h3>

    # When a <code>SimpleExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined
        # later.
        self.window.display_callback = self.display

        # We also set mouse callbacks that will display the pixel color in the
        # title bar.
        self.window.mouse_callback = self.mouse
        self.window.motion_callback = self.motion

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        self.vao = VertexArray(vertices, colors, elements=indices)

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()

        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Mouse functions</h4>

    # The motion callback is called when the mouse is moved while a button is
    # pressed. It reads the current color of the pixel under the cursor from
    # the front buffer and displays it in the window title.
    def motion(self, x, y):
        self.window.window_title = "%.2f, %.2f, %.2f, %.2f" % tuple(
            self.window.front_pixels[self.window.shape[0] - y, x])

    # The mouse callback is called whenever a mouse button is pressed. It
    # redirects to the functionality of the motion callback.
    def mouse(self, button, state, x, y):
        self.motion(x, y)

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes the
    # modelview matrix, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using <code>get_elapsed_time()</code>:
        phi = get_elapsed_time()

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), sin(phi), 0,
                                         0), (-sin(phi), cos(phi), 0, 0),
                                        (0, 0, 1, 0), (0, 0, 0, 2))

        # The following line schedules the next timer event to execute after ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>

    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement:
        with self.shader:
            # With the shader bound, we enter the GLUT main loop.
            main_loop()
コード例 #24
0
ファイル: meshview.py プロジェクト: adamlwgriffiths/glitter
class MeshViewer(object):
    # <h3>Initialization</h3>

    # When a <code>MeshViewer</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self, filename):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # We open the HDF5 file specified on the command line for reading:
        if filename.endswith(".dat"):
            data = loadtxt(filename)
            assert data.ndim == 2 and data.shape[1] in (3, 6)

            vertices = data[:, :3]
            vertices -= vertices.min()
            vertices /= vertices.max()
            vertices -= 0.5
            
            colors = data[:, 3:] if data.shape[1] == 6 else None
            colors -= colors.min()
            colors /= colors.max()
            
            elements = None
        else:
            with h5py.File(filename, "r") as f:
                # The vertices, colors and indices of the mesh are read from the
                # corresponding datasets in the HDF5 file. Note that the names of the
                # datasets are mere convention. Colors and indices are allowed to be
                # undefined.
                vertices = f["vertices"]
                colors = f.get("colors", None)
                elements = f.get("indices", None)
                if vertices is not None:
                    vertices = vertices.value
                if colors is not None:
                    colors = colors.value
                if elements is not None:
                    elements = elements.value

        # If no colors were specified, we generate random ones so we can
        # distinguish the triangles without fancy shading.
        if colors is None:
            colors = random((len(vertices), 3))[:, None, :][:, [0] * vertices.shape[1], :]

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array. If <code>elements</code>
        # is <code>None</code>, the vertex array class will draw all vertices
        # in order.
        self.vao = VertexArray(vertices, colors, elements=elements)

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()

        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes the
    # modelview matrix, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using <code>get_elapsed_time()</code>:
        phi = 2 * pi * get_elapsed_time() / 20.0

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader simply by setting an attribute:
        self.shader.modelview_matrix = ((cos(phi), 0, sin(phi), 0), (0, 1, 0, 0), (-sin(phi), 0, cos(phi), 0), (0, 0, 0, 1))

        # The following line schedules the next timer event to execute after ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>
    
    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The shader program is bound by using a <code>with</code> statement:
        with self.shader:
            # The <code>State</code> class encapsulates state changes in the
            # context. For example, to enable depth testing for the duration of the
            # following function call, we would write:
            with State(depth_test=True):
                # With the shader bound and depth testing enabled, we enter the
                # GLUT main loop.
                main_loop()
コード例 #25
0
ファイル: pointcloud.py プロジェクト: adamlwgriffiths/glitter
class PointcloudRenderer(object):
    # <h3>Initialization</h3>

    # When a <code>PointcloudRenderer</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        n_points = 100000
        self.vao = VertexArray(randn(n_points, 3), randn(n_points, 3))

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()
        
        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes the
    # modelview matrix, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using <code>get_elapsed_time()</code>:
        phi = 2 * pi * get_elapsed_time() / 20.0

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), 0, sin(phi), 0), (0, 1, 0, 0), (-sin(phi), 0, cos(phi), 0), (0, 0, 0, 5))

        # The following line schedules the next timer event to execute after ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>
    
    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement:
        with self.shader:
            # The <code>State</code> class encapsulates state changes in the
            # context. For example, to enable depth testing and set the point size
            # to three for the duration of the following function call, we would
            # write:
            with State(depth_test=True, point_size=3):
                # With the shader bound, depth testing enabled, and the point size
                # set, we enter the GLUT main loop.
                main_loop()
コード例 #26
0
ファイル: lesson_02.py プロジェクト: adamlwgriffiths/glitter
    window.swap_buffers()


def keyboard(key, x, y):
    # if F1 or ALT-Enter is pressed, toggle fullscreen
    if key == _gl.GLUT_KEY_F1 or (get_alt_state() and key == ord('\r')):
        window.toggle_full_screen()
    elif key == 27:  # escape key
        raise SystemExit  # makes program quit out of main_loop


if __name__ == "__main__":
    # create main window
    window = GlutWindow(name="My First Quad and Triangle", double=True)
    # set background color to black
    window.color_clear_value = (0, 0, 0, 1)
    # callback for rendering
    window.display_callback = display
    # callback for normal keys and special keys (like F1), both handled by same function here
    window.keyboard_callback = window.special_callback = keyboard
    # render all the time
    window.idle_callback = window.post_redisplay
    # shader program for rendering
    shader = get_default_program(modelview=False, color=False)
    quad = VertexArray(((-0.7, 0.3, 0.0, 1.0), (-0.1, 0.3, 0.0, 1.0),
                        (-0.7, -0.3, 0.0, 1.0), (-0.1, -0.3, 0.0, 1.0)))
    triangle = VertexArray(
        ((0.1, -0.2, 0.0, 1.0), (0.7, -0.2, 0.0, 1.0), (0.4, 0.2, 0.0, 1.0)))
    # loops until SystemExit is raised or window is closed
    main_loop()
コード例 #27
0
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # A shader program is built from the previously defined vertex and
        # fragment codes:
        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)

        # This shader program is then used to build a pipeline. A pipeline is a
        # convenience object that encapsulates a vertex array for input, a
        # shader program for processing, and a framebuffer for output. The
        # framebuffer is optional (we could render directly to the screen if we
        # wanted), but we will render into a texture and copy the texture to
        # the screen for instructional purposes. The <code>Pipeline</code>
        # constructor automatically creates an empty vertex array and a
        # framebuffer with no attachments. Named constructor arguments are
        # interpreted as attributes of the vertex array and the framebuffer or
        # as named inputs and outputs of the shader. This means we can directly
        # pass in arrays of vertices and colors that will be bound to
        # <code>in_position</code> and <code>in_color</code>, respectivey, as
        # well as the array of element indices to draw and an empty texture to
        # bind to the framebuffer:
        self.render_pipeline = Pipeline(self.shader,
                                        in_position=vertices,
                                        in_color=colors,
                                        elements=indices,
                                        out_color=RectangleTexture(shape=(300,
                                                                          300,
                                                                          3)))

        # Shader uniform variables like textures can also be set directly on
        # the pipeline. Here we initialize two textures with random data:
        self.render_pipeline.texture_0 = Texture2D(random((30, 30, 4)))
        self.render_pipeline.texture_1 = RectangleTexture(random((30, 30, 4)))

        # Many properties, such as the filtering mode for textures, can
        # directly be set as attributes on the corresponding objects:
        self.render_pipeline.texture_0.min_filter = Texture2D.min_filters.NEAREST
        self.render_pipeline.texture_0.mag_filter = Texture2D.mag_filters.NEAREST

        # For copying the texture to the screen, we create another shader
        # program.
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader,
                                         fragment=copy_fragment_shader)

        # The input texture of this shader program is the output texture of the
        # previous pipeline. Since all textures and framebuffers are
        # automatically bound and unbound, we do not need to worry about
        # whether the framebuffer is still writing to the texture.
        self.copy_shader.image = self.render_pipeline.out_color

        # Instead of using a pipeline with named vertex shader inputs, we can
        # also create a vertex array object directly with a list of vertex
        # shader inputs to use. Here we use only a single vertex shader input:
        # the coordinates of a fullscreen quad. The <code>elements</code>
        # parameter defines two triangles that make up the quad.
        self.vao = VertexArray(
            ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)),
            elements=((0, 1, 2), (0, 2, 3)))
コード例 #28
0
class IntroductionExample(object):
    # <h3>Initialization</h3>

    # When an <code>IntroductionExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # A shader program is built from the previously defined vertex and
        # fragment codes:
        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)

        # This shader program is then used to build a pipeline. A pipeline is a
        # convenience object that encapsulates a vertex array for input, a
        # shader program for processing, and a framebuffer for output. The
        # framebuffer is optional (we could render directly to the screen if we
        # wanted), but we will render into a texture and copy the texture to
        # the screen for instructional purposes. The <code>Pipeline</code>
        # constructor automatically creates an empty vertex array and a
        # framebuffer with no attachments. Named constructor arguments are
        # interpreted as attributes of the vertex array and the framebuffer or
        # as named inputs and outputs of the shader. This means we can directly
        # pass in arrays of vertices and colors that will be bound to
        # <code>in_position</code> and <code>in_color</code>, respectivey, as
        # well as the array of element indices to draw and an empty texture to
        # bind to the framebuffer:
        self.render_pipeline = Pipeline(self.shader,
                                        in_position=vertices,
                                        in_color=colors,
                                        elements=indices,
                                        out_color=RectangleTexture(shape=(300,
                                                                          300,
                                                                          3)))

        # Shader uniform variables like textures can also be set directly on
        # the pipeline. Here we initialize two textures with random data:
        self.render_pipeline.texture_0 = Texture2D(random((30, 30, 4)))
        self.render_pipeline.texture_1 = RectangleTexture(random((30, 30, 4)))

        # Many properties, such as the filtering mode for textures, can
        # directly be set as attributes on the corresponding objects:
        self.render_pipeline.texture_0.min_filter = Texture2D.min_filters.NEAREST
        self.render_pipeline.texture_0.mag_filter = Texture2D.mag_filters.NEAREST

        # For copying the texture to the screen, we create another shader
        # program.
        self.copy_shader = ShaderProgram(vertex=copy_vertex_shader,
                                         fragment=copy_fragment_shader)

        # The input texture of this shader program is the output texture of the
        # previous pipeline. Since all textures and framebuffers are
        # automatically bound and unbound, we do not need to worry about
        # whether the framebuffer is still writing to the texture.
        self.copy_shader.image = self.render_pipeline.out_color

        # Instead of using a pipeline with named vertex shader inputs, we can
        # also create a vertex array object directly with a list of vertex
        # shader inputs to use. Here we use only a single vertex shader input:
        # the coordinates of a fullscreen quad. The <code>elements</code>
        # parameter defines two triangles that make up the quad.
        self.vao = VertexArray(
            ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0)),
            elements=((0, 1, 2), (0, 2, 3)))

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever
    # the screen has to be redrawn.
    def display(self):
        # We can simply clear the pipeline and render the vertices into the
        # framebuffer using the shader with the following two lines:
        self.render_pipeline.clear()
        self.render_pipeline.draw()

        # For output on the screen, we have created a GLUT window. It can be
        # cleared in very much the same way:
        self.window.clear()

        # To copy the results of the pipeline to the screen, we use the shader
        # that simply displays a texture. The shader can be bound by using a
        # <code>with</code> statement:
        with self.copy_shader:
            # All textures used by the shader are then bound automatically, and
            # everything is reset to its previous state when we leave the
            # <code>with</code> block.

            # With the shader bound, we simply draw a fullscreen quad that is
            # stored in a vertex array we will create in the initialization
            # section:
            self.vao.draw()

        # After all rendering commands have been issued, we swap the back
        # buffer to the front, making the rendered image visible all at once:
        self.window.swap_buffers()

        # Finally, we disable logging so that we only see the OpenGL calls of
        # the first run of the display function:
        add_logger(None)

    # <h4>Keyboard function</h4>

    # To further illustrate the concept of GLUT callbacks, here's a keyboard
    # handler that will simply make the program exit when any key is pressed:
    def keyboard(self, key, x, y):
        raise SystemExit

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes
    # the modelview matrix, schedules the next timer event, and causes a screen
    # redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using
        # <code>get_elapsed_time()</code>:
        t = get_elapsed_time()
        phi = 2 * pi * t / 4.0

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), sin(phi), 0,
                                         0), (-sin(phi), cos(phi), 0, 0),
                                        (0, 0, 1, 0), (0, 0, 0, 1))

        # The following line schedules the next timer event to execute after
        # ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>

    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # Now that all the initialization is done, we add the default logger to
        # all OpenGL commands so that we can see what OpenGL the display
        # function issues, and in which order.
        add_logger()

        # Finally, to start rendering, we enter the GLUT main loop.
        main_loop()
コード例 #29
0
class PointcloudRenderer(object):
    # <h3>Initialization</h3>

    # When a <code>PointcloudRenderer</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined later.
        self.window.display_callback = self.display

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        n_points = 100000
        self.vao = VertexArray(randn(n_points, 3), randn(n_points, 3))

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()

        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes the
    # modelview matrix, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using <code>get_elapsed_time()</code>:
        phi = 2 * pi * get_elapsed_time() / 20.0

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), 0, sin(phi), 0),
                                        (0, 1, 0, 0), (-sin(phi), 0, cos(phi),
                                                       0), (0, 0, 0, 5))

        # The following line schedules the next timer event to execute after ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>

    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement:
        with self.shader:
            # The <code>State</code> class encapsulates state changes in the
            # context. For example, to enable depth testing and set the point size
            # to three for the duration of the following function call, we would
            # write:
            with State(depth_test=True, point_size=3):
                # With the shader bound, depth testing enabled, and the point size
                # set, we enter the GLUT main loop.
                main_loop()
コード例 #30
0
ファイル: simple.py プロジェクト: adamlwgriffiths/glitter
class SimpleExample(object):
    # <h3>Initialization</h3>

    # When a <code>SimpleExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, multisample=True)

        # Then, we set the GLUT display callback function which will be defined
        # later.
        self.window.display_callback = self.display

        # We also set mouse callbacks that will display the pixel color in the
        # title bar.
        self.window.mouse_callback = self.mouse
        self.window.motion_callback = self.motion

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create a vertex array that contains buffers for two vertex array
        # input variables as well as an index array:
        self.vao = VertexArray(vertices, colors, elements=indices)

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()
        
        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Mouse functions</h4>

    # The motion callback is called when the mouse is moved while a button is
    # pressed. It reads the current color of the pixel under the cursor from
    # the front buffer and displays it in the window title.
    def motion(self, x, y):
        self.window.window_title = "%.2f, %.2f, %.2f, %.2f" % tuple(self.window.front_pixels[self.window.shape[0] - y, x])

    # The mouse callback is called whenever a mouse button is pressed. It
    # redirects to the functionality of the motion callback.
    def mouse(self, button, state, x, y):
        self.motion(x, y)

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback changes the
    # modelview matrix, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first get the elapsed time from GLUT using <code>get_elapsed_time()</code>:
        phi = get_elapsed_time()

        # We then set the <code>modelview_matrix</code> uniform variable of the
        # shader created in the initialization section simply by setting an
        # attribute:
        self.shader.modelview_matrix = ((cos(phi), sin(phi), 0, 0), (-sin(phi), cos(phi), 0, 0), (0, 0, 1, 0), (0, 0, 0, 2))

        # The following line schedules the next timer event to execute after ten milliseconds.
        self.window.add_timer(10, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h3>Running</h3>
    
    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement:
        with self.shader:
            # With the shader bound, we enter the GLUT main loop.
            main_loop()
コード例 #31
0
class OpenCLExample(object):
    # <h3>Initialization</h3>

    # When a <code>OpenCLExample</code> instance is created, we need to
    # initialize a few OpenGL objects.
    def __init__(self):
        # First, we create a window; this also creates an OpenGL context.
        self.window = GlutWindow(double=True, alpha=True, depth=True)

        # Then, we set the GLUT display and keyboard callback functions which
        # will be defined later.
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard

        # Here, we generate numpy arrays to hold the positions, colors, and
        # velocities of the particles:
        num = 200000
        positions = numpy.empty((num, 4), dtype=numpy.float32)
        colors = numpy.empty((num, 4), dtype=numpy.float32)
        velocities = numpy.empty((num, 4), dtype=numpy.float32)

        # So far, the array contents are undefined. We have to initialize them with meaningful values:
        positions[:, 0] = numpy.sin(numpy.arange(0, num) * 2 * numpy.pi /
                                    num) * (numpy.random.random_sample(
                                        (num, )) / 3 + 0.2)
        positions[:, 1] = numpy.cos(numpy.arange(0, num) * 2 * numpy.pi /
                                    num) * (numpy.random.random_sample(
                                        (num, )) / 3 + 0.2)
        positions[:, 2:] = 0, 1
        colors[:] = 0, 1, 0, 1
        velocities[:, :2] = 2 * positions[:, :2]
        velocities[:, 2] = 3
        velocities[:, 3] = numpy.random.random_sample((num, ))

        # Instead of simply generating a vertex array from the position and color
        # data, we first generate array buffers for them:
        gl_positions = ArrayBuffer(data=positions, usage="DYNAMIC_DRAW")
        gl_colors = ArrayBuffer(data=colors, usage="DYNAMIC_DRAW")
        # These array buffers will later also be used by OpenCL. We do not need to
        # wrap <code>velocities</code> in this way, as it will only be used by
        # OpenCL and can be wrapped in an OpenCL buffer directly.

        # We now create a vertex array that will pass the position and color data
        # to the shader. The vertex array constructor accepts
        # <code>ArrayBuffer</code> instances:
        self.vao = VertexArray(gl_positions, gl_colors)

        # In the OpenGL core profile, there is no such thing as a "standard pipeline"
        # any more. We use the minimalistic <code>defaultpipeline</code> from the
        # <code>glitter.convenience</code> module to create a shader program instead:
        self.shader = get_default_program()

        # Here, we create the <code>CLCode</code> object that manages OpenCL
        # interaction. It is passed the OpenGL buffer objects as well as a numpy
        # array of velocities.
        self.clcode = CLCode(gl_positions, gl_colors, velocities)

    # <h3>Callback functions</h3>

    # <h4>Display function</h4>

    # Here we define the display function. It will be called by GLUT whenever the
    # screen has to be redrawn.
    def display(self):
        # First we clear the default framebuffer:
        self.window.clear()

        # To draw the vertex array, we use:
        self.vao.draw()

        # After all rendering commands have been issued, we swap the back buffer to
        # the front, making the rendered image visible all at once:
        self.window.swap_buffers()

    # <h4>Timer function</h4>

    # The animation is controlled by a GLUT timer. The timer callback animates the
    # particle system, schedules the next timer event, and causes a screen redraw:
    def timer(self):
        # We first tell an instance of the <code>CLCode</code> class to execute the
        # OpenCL kernel:
        self.clcode.execute(10)

        # The following line schedules the next timer event to execute after one millisecond.
        self.window.add_timer(1, self.timer)

        # Finally, we tell GLUT to redraw the screen.
        self.window.post_redisplay()

    # <h4>Keyboard function</h4>

    # To further illustrate the concept of GLUT callbacks, here's a keyboard
    # handler that will simply make the program exit when any key is pressed:
    def keyboard(self, key, x, y):
        raise SystemExit

    # <h3>Running</h3>

    # We will call the <code>run()</code> method later to run the OpenGL code.
    def run(self):
        # To start the animation, we call the timer once; all subsequent timer
        # calls will be scheduled by the timer function itself.
        self.timer()

        # The default program is bound by using a <code>with</code> statement. At
        # the same time, we can pass in additional uniform variables, such as the
        # modelview matrix:
        with self.shader(modelview_matrix=((1, 0, 0, 0), (0, 0, 1, 0),
                                           (0, 1, 0, 0), (0, 0, 0, 2))):
            # With the shader bound, we enter the GLUT main loop.
            main_loop()
コード例 #32
0
class VolumeRenderer(object):
    # Some default values for instance variables can be declared as class
    # variables (these values are all immutable, so no problem here):
    modelview_matrix = tuple(map(tuple, numpy.eye(4)))
    intensity_scale = 1.0
    absorption = False

    # <h3>Initialization</h3>
    def __init__(self, volume, **kwargs):
        assert isinstance(volume, Texture3D), "volume must be a 3D texture"

        # We need a vertex array to hold the faces of the cube:
        self.vao = VertexArray(cube_vertices, elements=cube_indices)

        # For rendering the back faces, we create a shader program and a
        # framebuffer with an attached texture:
        self.back_shader = ShaderProgram(vertex=vertex_code,
                                         fragment=back_fragment_code)
        self.back_fbo = Framebuffer(
            RectangleTexture(shape=volume.shape[:2] + (4, ), dtype=float32))

        # For the front faces, we do the same. Additionally, the shader
        # receives the texture containing the back face coordinates in a
        # uniform variable <code>back</code>, and the 3D texture containing the
        # volumetric data in a uniform variable <code>volume</code>.
        self.front_shader = ShaderProgram(vertex=vertex_code,
                                          fragment=front_fragment_code,
                                          back=self.back_fbo[0],
                                          volume=volume)
        self.front_fbo = Framebuffer(
            RectangleTexture(shape=volume.shape[:2] + (4, ), dtype=float32))

        # All other parameters are simply set as attributes (this might be
        # <code>modelview_matrix</code>, <code>intensity_scale</code>, or
        # <code>absorption</code>).
        for key, value in list(kwargs.items()):
            setattr(self, key, value)

    # <h3>Rendering</h3>
    def render(self):
        # We first draw the back faces, storing their coordinates into a
        # texture. This means we have to clear and bind the back framebuffer,
        # activate face culling with cull face mode "FRONT", bind the back face
        # shader with the current modelview matrix set, and render the vertex
        # array for the cube:
        self.back_fbo.clear()
        with State(cull_face=True, cull_face_mode="FRONT"):
            with self.back_shader(modelview_matrix=self.modelview_matrix):
                with self.back_fbo:
                    self.vao.draw()

        # We then draw the front faces, accumulating the intensity between
        # front and back face. The setup is very similar to the one stated
        # before, except that the additional uniform variables
        # <code>intensity_scale</code> and <code>absorption</code> are passed
        # to the shader:
        self.front_fbo.clear()
        with State(cull_face=True, cull_face_mode="BACK"):
            with self.front_shader(modelview_matrix=self.modelview_matrix,
                                   intensity_scale=self.intensity_scale,
                                   absorption=self.absorption):
                with self.front_fbo:
                    self.vao.draw()

        # Finally, we simply return the texture into which we just rendered.
        # The client code might want to display this directly, or to download
        # the data into a numpy array.
        return self.front_fbo[0]