Esempio n. 1
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()
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()
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()
Esempio n. 4
0
 def __init__(self):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.window.mouse_callback = self.mouse
     self.shader = ShaderProgram(vertex=vertex_shader,
                                 fragment=fragment_shader)
     self.shader.colormap = Texture1D(cm.spectral(linspace(0, 1, 256)),
                                      wrap_s="MIRRORED_REPEAT")
     self.shader.minval = (-2.5, -1.75)
     self.shader.maxval = (1.0, 1.75)
     self.vao = get_fullscreen_quad()
     self.history = []
Esempio n. 5
0
    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)
Esempio n. 6
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)
    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)))
Esempio n. 8
0
class MandelbrotRenderer(object):
    transition_time = 0.3  # seconds
    update_step = 10  # milliseconds

    def __init__(self):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.window.mouse_callback = self.mouse
        self.shader = ShaderProgram(vertex=vertex_shader,
                                    fragment=fragment_shader)
        self.shader.colormap = Texture1D(cm.spectral(linspace(0, 1, 256)),
                                         wrap_s="MIRRORED_REPEAT")
        self.shader.minval = (-2.5, -1.75)
        self.shader.maxval = (1.0, 1.75)
        self.vao = get_fullscreen_quad()
        self.history = []

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

    def timer(self):
        t = min(1.0, (get_elapsed_time() - self.transition_start) /
                self.transition_time)
        x = 0.5 - 0.5 * cos(pi * t)
        self.shader.minval = self.minstart * (1 - x) + self.minend * x
        self.shader.maxval = self.maxstart * (1 - x) + self.maxend * x
        if t < 1:
            self.window.add_timer(self.update_step, self.timer)
        self.window.post_redisplay()

    def start_transition(self, minval, maxval):
        self.minstart, self.maxstart = self.shader.minval, self.shader.maxval
        self.minend, self.maxend = minval, maxval
        self.transition_start = get_elapsed_time()
        self.timer()

    def mouse(self, button, state, x, y):
        if button == glut.GLUT_LEFT_BUTTON:
            pos = array(
                (x, self.window.shape[0] - y)) / array(self.window.shape[::-1],
                                                       dtype=float)
            pos = pos * (self.shader.maxval -
                         self.shader.minval) + self.shader.minval
            if state == glut.GLUT_DOWN:
                self.last_pos = pos
            elif state == glut.GLUT_UP and all(pos != self.last_pos):
                self.history.append((self.shader.minval, self.shader.maxval))
                self.start_transition(minimum(pos, self.last_pos),
                                      maximum(pos, self.last_pos))
        elif state == glut.GLUT_DOWN and button == glut.GLUT_RIGHT_BUTTON:
            if self.history:
                self.start_transition(*self.history.pop())

    def run(self):
        with self.shader:
            main_loop()
Esempio n. 9
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))
Esempio n. 10
0
 def __init__(self, images):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.window.keyboard_callback = self.keyboard
     self.window.special_callback = self.special
     self.images = images
     self.window.shape = self.images[0].shape[:2]
     self.render_pipeline = get_copy_pipeline_2d(
         context=self.window,
         sampler_type="isampler2D",
         maxval=255,
         yscale=-1,
         use_framebuffer=False,
         image=Texture2D(self._prepare_image(0)))
     self.current_index = 0
     self.fps = 25
     self.playing = False
Esempio n. 11
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)
    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)))
Esempio n. 13
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)))
Esempio n. 14
0
 def __init__(self):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.window.mouse_callback = self.mouse
     self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)
     self.shader.colormap = Texture1D(cm.spectral(linspace(0, 1, 256)), wrap_s="MIRRORED_REPEAT")
     self.shader.minval = (-2.5, -1.75)
     self.shader.maxval = (1.0, 1.75)
     self.vao = get_fullscreen_quad()
     self.history = []
Esempio n. 15
0
class MandelbrotRenderer(object):
    transition_time = 0.3 # seconds
    update_step = 10 # milliseconds

    def __init__(self):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.window.mouse_callback = self.mouse
        self.shader = ShaderProgram(vertex=vertex_shader, fragment=fragment_shader)
        self.shader.colormap = Texture1D(cm.spectral(linspace(0, 1, 256)), wrap_s="MIRRORED_REPEAT")
        self.shader.minval = (-2.5, -1.75)
        self.shader.maxval = (1.0, 1.75)
        self.vao = get_fullscreen_quad()
        self.history = []

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

    def timer(self):
        t = min(1.0, (get_elapsed_time() - self.transition_start) / self.transition_time)
        x = 0.5 - 0.5 * cos(pi * t)
        self.shader.minval = self.minstart * (1 - x) + self.minend * x
        self.shader.maxval = self.maxstart * (1 - x) + self.maxend * x
        if t < 1:
            self.window.add_timer(self.update_step, self.timer)
        self.window.post_redisplay()

    def start_transition(self, minval, maxval):
        self.minstart, self.maxstart = self.shader.minval, self.shader.maxval
        self.minend, self.maxend = minval, maxval
        self.transition_start = get_elapsed_time()
        self.timer()

    def mouse(self, button, state, x, y):
        if button == glut.GLUT_LEFT_BUTTON:
            pos = array((x, self.window.shape[0] - y)) / array(self.window.shape[::-1], dtype=float)
            pos = pos * (self.shader.maxval - self.shader.minval) + self.shader.minval
            if state == glut.GLUT_DOWN:
                self.last_pos = pos
            elif state == glut.GLUT_UP and all(pos != self.last_pos):
                self.history.append((self.shader.minval, self.shader.maxval))
                self.start_transition(minimum(pos, self.last_pos), maximum(pos, self.last_pos))
        elif state == glut.GLUT_DOWN and button == glut.GLUT_RIGHT_BUTTON:
            if self.history:
                self.start_transition(*self.history.pop())

    def run(self):
        with self.shader:
            main_loop()
Esempio n. 16
0
 def __init__(self, images):
     self.window = GlutWindow(double=True, multisample=True)
     self.window.display_callback = self.display
     self.window.keyboard_callback = self.keyboard
     self.window.special_callback = self.special
     self.images = images
     self.window.shape = self.images[0].shape[:2]
     self.render_pipeline = get_copy_pipeline_2d(context=self.window, sampler_type="isampler2D",
             maxval=255, yscale=-1, use_framebuffer=False, image=Texture2D(self._prepare_image(0)))
     self.current_index = 0
     self.fps = 25
     self.playing = False
Esempio n. 17
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

        # 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)
Esempio n. 18
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)
Esempio n. 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()
Esempio n. 20
0
    def create_default_context():
        """Create a default offscreen rendering context.

        @todo: This is window system dependent; create an appropriate context
        dynamically.
        @todo: When no context exists, create a raw offscreen context instead of a
        hidden GLUT window so that rendering is possible without an X connection.
        """

        try:
            from glitter.contexts.glx import GLXContext
            return GLXContext()
        except ImportError:
            from glitter.contexts.glut import GlutWindow
            return GlutWindow(shape=(1, 1), hide=True)
Esempio n. 21
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()
Esempio n. 22
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))
Esempio n. 23
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)
Esempio n. 24
0
def get_gl_context(option="g"):
    """Returns an OpenGL context. Options: g(lut), q(t)"""
    if "g" == option:
        print "Creating GLUT context."
        from glitter.contexts.glut import GlutWindow
        gl_context = GlutWindow(shape=(1, 1), hide=True)
    elif "q" == option:
        print "Creating QT context."
        from PySide import QtGui
        from glitter.contexts.qt import QtWidget
        app = QtGui.QApplication.instance()
        if app is None:
            app = QtGui.QApplication(sys.argv)
        gl_context = QtWidget(None)
    else:
        raise Exception("Unknown option: %s" % option)
    return gl_context
Esempio n. 25
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()
Esempio n. 26
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

        # 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)
Esempio n. 27
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()
Esempio n. 28
0
class IntroductionExample(object):
    fps_scale = 1.1

    def __init__(self, images):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard
        self.window.special_callback = self.special
        self.images = images
        self.window.shape = self.images[0].shape[:2]
        self.render_pipeline = get_copy_pipeline_2d(
            context=self.window,
            sampler_type="isampler2D",
            maxval=255,
            yscale=-1,
            use_framebuffer=False,
            image=Texture2D(self._prepare_image(0)))
        self.current_index = 0
        self.fps = 25
        self.playing = False

    def _prepare_image(self, idx):
        img = self.images[idx]
        while img.ndim < 3:
            img = img[..., None]
        return img

    def display(self):
        self.window.clear()
        self.render_pipeline.image.data = self._prepare_image(
            self.current_index)
        self.window.window_title = self.images.filenames[
            self.current_index].filename
        self.render_pipeline.draw()
        self.window.swap_buffers()

    def keyboard(self, key, x, y):
        key = chr(key)
        if key == "+":
            self.fps *= self.fps_scale
        elif key == "-":
            self.fps /= self.fps_scale
        elif key == " ":
            if self.playing:
                self.playing = False
            else:
                self.playing = True
                self.timer()
        elif key == chr(27):
            raise SystemExit

    def special(self, key, x, y):
        if key == _gl.GLUT_KEY_LEFT:
            self.current_index = (self.current_index - 1) % len(self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_RIGHT:
            self.current_index = (self.current_index + 1) % len(self.images)
            self.window.post_redisplay()
        if key == _gl.GLUT_KEY_PAGE_UP:
            self.current_index = (self.current_index - self.fps) % len(
                self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_PAGE_DOWN:
            self.current_index = (self.current_index + self.fps) % len(
                self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_HOME:
            self.current_index = 0
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_END:
            self.current_index = len(self.images) - 1
            self.window.post_redisplay()

    def timer(self):
        if self.playing:
            self.current_index = (self.current_index + 1) % len(self.images)
            self.window.add_timer(int(round(1000.0 / self.fps)), self.timer)
            self.window.post_redisplay()

    def run(self):
        self.timer()
        main_loop()
Esempio n. 29
0
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()
Esempio n. 30
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()
Esempio n. 31
0
    # clear the screen
    window.clear(color=True, depth=True)
    # display the backbuffer
    window.swap_buffers()


def keyboard(key, x, y):
    # if F1 or ALT-Enter is pressed, toggle fullscreen
    # TODO: key constants like GLUT_KEY_F1 should be available as an enum
    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="NeHe's OpenGL Framework", double=True)
    # set background color to black
    # TODO: it would be nice if window.color_clear_value = (0, 0, 0) would
    # implicitly set alpha to 1
    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
    # loops until SystemExit is raised or window is closed
    main_loop()
Esempio n. 32
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()
Esempio n. 33
0
class IntroductionExample(object):
    fps_scale = 1.1

    def __init__(self, images):
        self.window = GlutWindow(double=True, multisample=True)
        self.window.display_callback = self.display
        self.window.keyboard_callback = self.keyboard
        self.window.special_callback = self.special
        self.images = images
        self.window.shape = self.images[0].shape[:2]
        self.render_pipeline = get_copy_pipeline_2d(context=self.window, sampler_type="isampler2D",
                maxval=255, yscale=-1, use_framebuffer=False, image=Texture2D(self._prepare_image(0)))
        self.current_index = 0
        self.fps = 25
        self.playing = False

    def _prepare_image(self, idx):
        img = self.images[idx]
        while img.ndim < 3:
            img = img[..., None]
        return img

    def display(self):
        self.window.clear()
        self.render_pipeline.image.data = self._prepare_image(self.current_index)
        self.window.window_title = self.images.filenames[self.current_index].filename
        self.render_pipeline.draw()
        self.window.swap_buffers()

    def keyboard(self, key, x, y):
        key = chr(key)
        if key == "+":
            self.fps *= self.fps_scale
        elif key == "-":
            self.fps /= self.fps_scale
        elif key == " ":
            if self.playing:
                self.playing = False
            else:
                self.playing = True
                self.timer()
        elif key == chr(27):
            raise SystemExit

    def special(self, key, x, y):
        if key == _gl.GLUT_KEY_LEFT:
            self.current_index = (self.current_index - 1) % len(self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_RIGHT:
            self.current_index = (self.current_index + 1) % len(self.images)
            self.window.post_redisplay()
        if key == _gl.GLUT_KEY_PAGE_UP:
            self.current_index = (self.current_index - self.fps) % len(self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_PAGE_DOWN:
            self.current_index = (self.current_index + self.fps) % len(self.images)
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_HOME:
            self.current_index = 0
            self.window.post_redisplay()
        elif key == _gl.GLUT_KEY_END:
            self.current_index = len(self.images) - 1
            self.window.post_redisplay()

    def timer(self):
        if self.playing:
            self.current_index = (self.current_index + 1) % len(self.images)
            self.window.add_timer(int(round(1000.0 / self.fps)), self.timer)
            self.window.post_redisplay()

    def run(self):
        self.timer()
        main_loop()
Esempio n. 34
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()
Esempio n. 35
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()
Esempio n. 36
0
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()
Esempio n. 37
0
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()
Esempio n. 38
0
def display():
    # clear the screen
    window.clear(color=True, depth=True)
    # display the backbuffer
    window.swap_buffers()

def keyboard(key, x, y):
    # if F1 or ALT-Enter is pressed, toggle fullscreen
    # TODO: key constants like GLUT_KEY_F1 should be available as an enum
    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="NeHe's OpenGL Framework", double=True)
    # set background color to black
    # TODO: it would be nice if window.color_clear_value = (0, 0, 0) would
    # implicitly set alpha to 1
    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
    # loops until SystemExit is raised or window is closed
    main_loop()

Esempio n. 39
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()
Esempio n. 40
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)))
Esempio n. 41
0
        triangle.draw(primitive_types.TRIANGLES)
    # display the backbuffer
    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