Esempio n. 1
0
 def fbo_create(self, size, tex=None):
     if tex is None:
         tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
         tex.mag_filter = 'nearest'
         tex.min_filter = 'nearest'
     if self.fbo is None:
         self.fbo = Fbo(size=size, texture=tex)
         self.fbo.texture.mag_filter = 'nearest'
         self.fbo.texture.min_filter = 'nearest'
     else:
         self.fbo = Fbo(size=size, texture=tex)
         self.fbo.texture.mag_filter = 'nearest'
         self.fbo.texture.min_filter = 'nearest'
     tool_tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
     tool_tex.mag_filter = 'nearest'
     tool_tex.min_filter = 'nearest'
     if self.tool_fbo is None:
         self.tool_fbo = Fbo(size=size, texture=tool_tex)
         self.tool_fbo.texture.mag_filter = 'nearest'
         self.tool_fbo.texture.min_filter = 'nearest'
     else:
         self.tool_fbo = Fbo(size=size, texture=tool_tex)
         self.tool_fbo.texture.mag_filter = 'nearest'
         self.tool_fbo.texture.min_filter = 'nearest'
     return self.fbo
Esempio n. 2
0
class Renderer(Widget):

    def __init__(self, **kw):
        self.shader_file = kw.pop("shader_file", None)
        self.canvas = Canvas()
        super(Renderer, self).__init__(**kw)

        with self.canvas:
            self._viewport = Rectangle(size=self.size, pos=self.pos)
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True, compute_normal_mat=True)
        self._config_fbo()
        self.texture = self.fbo.texture
        self.camera = None
        self.scene = None

    def _config_fbo(self):
        # set shader file here
        self.fbo.shader.source = self.shader_file or \
                                os.path.join(kivy3_path, "default.glsl")
        with self.fbo:
            Callback(self._setup_gl_context)
            PushMatrix()
            # instructions set for all instructions
            self._instructions = InstructionGroup()
            PopMatrix()
            Callback(self._reset_gl_context)

    def _setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()

    def _reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def render(self, scene, camera):
        self.scene = scene
        self.camera = camera
        self.camera.bind_to(self)
        self._instructions.add(scene.as_instructions())
        Clock.schedule_once(self._update_matrices, -1)

    def on_size(self, instance, value):
        self.fbo.size = value
        self._viewport.texture = self.fbo.texture
        self._viewport.size = value
        self._update_matrices()

    def on_texture(self, instance, value):
        self._viewport.texture = value

    def _update_matrices(self, dt=None):
        if self.camera:
            self.fbo['projection_mat'] = self.camera.projection_matrix
            self.fbo['modelview_mat'] = self.camera.modelview_matrix
        else:
            raise RendererError("Camera is not defined for renderer")

    def set_clear_color(self, color):
        self.fbo.clear_color = color
Esempio n. 3
0
    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas.before:
            Callback(self._set_blend_func)

        self.fbo_texture = Texture.create(size=self.size,
                                                  colorfmt='rgba',)
        self.fbo_texture.mag_filter='nearest'

        with self.canvas:
            #self.cbs = Callback(self.prepare_canvas)
            self.fbo = Fbo(size=self.size, texture=self.fbo_texture)
            #Color(1, 1, 1, 0)
            #self.fbo_rect = Rectangle()


        with self.fbo:
            ClearColor(0.0, 0.0, 0.0, 0.0)
            ClearBuffers()
            self.fbo_rect = Rectangle(size=self.size)


        #self.fbo.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/invert.glsl')
        #with self.fbo.after:
        #    self.cbr = Callback(self.reset_gl_context)
        #    PopMatrix()

        with self.canvas.before:
            Callback(self._set_blend_func)

        # wait that all the instructions are in the canvas to set texture

        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)
Esempio n. 4
0
 def refbo(self):
     tex = Texture.create(size=self.fbo.texture.size, colorfmt='rgba', bufferfmt='ubyte')
     self.fbo = Fbo(size=tex.size, texture=tex)
     self.fbo.texture.mag_filter = 'nearest'
     self.fbo.texture.min_filter = 'nearest'
     self.fbo.draw()
     self.canvas.ask_update()
Esempio n. 5
0
    def __init__(self, **kwargs):

        # self.canvas = RenderContext(compute_normal_mat=True)
        # self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))

        self.meshes = []

        with self.canvas:
            self.fbo = Fbo(
                size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0.0, 0.0, 0.0, 0.0)
            )
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find("simple.glsl")
        # self.texture = self.fbo.texture

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            # ClearBuffers(clear_depth=True)

            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        Clock.schedule_interval(self.update_scene, 1 / 60.0)

        self._touches = []
Esempio n. 6
0
def texture_get_data(texture):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    return data
Esempio n. 7
0
def texture_to_pil_image(texture):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    im = PILImage.fromstring('RGBA', size, data)
    return im
 def on_parent(self, *args):
     if not self.canvas:
         Clock.schedule_once(self.on_parent, 0)
         return
     if not hasattr(self, '_fbo'):
         with self.canvas:
             self._fbo = Fbo(size=self.size)
             self._fbo.add_reload_observer(self.redraw)
             self._translate = Translate(x=self.x, y=self.y)
             self._rectangle = Rectangle(texture=self._fbo.texture, size=self.size)
     self.rebind_children()
Esempio n. 9
0
def merged_texture_from_zip(filename):
    textures_list = textures_list_from_zip(filename)
    fbo = Fbo(size=textures_list[0].size)
    fbo.bind()
    with fbo:
        for texture in textures_list:
            Rectangle(texture=texture)
    fbo.release()
    fbo.draw()
    return fbo.texture
Esempio n. 10
0
    def _redraw(self, *args):
        if not self._ffplayer:
            return
        next_frame = self._next_frame
        if not next_frame:
            return

        img, pts = next_frame
        if img.get_size() != self._size or self._texture is None:
            self._size = w, h = img.get_size()

            if self._out_fmt == 'yuv420p':
                w2 = int(w / 2)
                h2 = int(h / 2)
                self._tex_y = Texture.create(size=(w, h), colorfmt='luminance')
                self._tex_u = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                self._tex_v = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                self._fbo = fbo = Fbo(size=self._size)
                with fbo:
                    BindTexture(texture=self._tex_u, index=1)
                    BindTexture(texture=self._tex_v, index=2)
                    Rectangle(size=fbo.size, texture=self._tex_y)
                fbo.shader.fs = VideoFFPy.YUV_RGB_FS
                fbo['tex_y'] = 0
                fbo['tex_u'] = 1
                fbo['tex_v'] = 2
                self._texture = fbo.texture
            else:
                self._texture = Texture.create(size=self._size,
                                               colorfmt='rgba')

            # XXX FIXME
            # self.texture.add_reload_observer(self.reload_buffer)
            self._texture.flip_vertical()
            self.dispatch('on_load')

        if self._texture:
            if self._out_fmt == 'yuv420p':
                dy, du, dv, _ = img.to_memoryview()
                if dy and du and dv:
                    self._tex_y.blit_buffer(dy, colorfmt='luminance')
                    self._tex_u.blit_buffer(du, colorfmt='luminance')
                    self._tex_v.blit_buffer(dv, colorfmt='luminance')
                    self._fbo.ask_update()
                    self._fbo.draw()
            else:
                self._texture.blit_buffer(img.to_memoryview()[0],
                                          colorfmt='rgba')

            self.dispatch('on_frame')
Esempio n. 11
0
def widget_save_canvas(widget, filename, format):
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)
    size = (int(widget.size[0]), int(widget.size[1]))
    texture = Texture.create(size=widget.size, colorfmt='rgba')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)
    fbo.draw()
    fbo.bind()
    data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    im = PILImage.fromstring('RGBA', size, data)
    im = im.transpose(PILImage.FLIP_TOP_BOTTOM)
    im.save(filename, format)
    if parent:
        parent.add_widget(widget)
    return True
Esempio n. 12
0
    def __init__(self, **kwargs):
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("brain.obj"))

        self.meshes = []

        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=(0, -150))
        self.fbo.shader.source = resource_find('simple.glsl')

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)
Esempio n. 13
0
class Graph(Image):
    def __init__(self, colors=(Color(1, 0, 1)), *args, **kwargs):
        if 'height' not in kwargs:
            kwargs['height'] = 32
        self.fbo = Fbo()
        with self.fbo:
            Color(1, 1, 1)
            self.fboscrollrect = Rectangle(pos=(-1, 0))
            Color(0, 0, 0)
            self.fboclearrect = Rectangle()
            self.points = []
            self.colors = []
            for color in colors:
                self.colors.append(Color(*color.rgba))
                self.points.append(Point(points=(), pointsize=0.5))
        super().__init__(*args, **kwargs)

    @staticmethod
    def to2pow(x):
        return 1 << (int(x) - 1).bit_length()

    def on_size(self, instance, size):
        self.fbo.size = (*(self.to2pow(v) for v in size), )
        self.fboscrollrect.size = self.fbo.size
        self.fboclearrect.pos = (self.fbo.size[0] - 1, 0)
        self.fboclearrect.size = (1, self.fbo.size[1])
        # this quick call to draw while the old texture is still attached stretches the old image instead of
        # preserving it at the proper scale, but at least it keeps the old data visible in some manner
        self.fbo.draw()
        self.fboscrollrect.texture = self.fbo.texture
        self.fboscrollrect.tex_coords = self.fbo.texture.tex_coords
        self.texture = self.fbo.texture

    def add(self, *values):
        for point, value in zip(self.points, values):
            point.points = (self.fbo.size[0] - 0.5,
                            (value + 1) / 2 * self.fbo.size[1])
        self.fbo.draw()
        self.canvas.ask_update()
    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0., 0., 0., 0.))

            self.viewport = Rectangle(size=self.size, pos=self.pos)

        self.fbo.shader.source = resource_find(
            join(dirname(__file__), 'simple.glsl'))
        super(ObjectRenderer, self).__init__(**kwargs)
Esempio n. 15
0
	def render_widget(self, widget):

		# create an FBO to render the widget to
		self.tmp_fbo = Fbo(size = self.size)
		self.tmp_fbo.add(ClearColor(0,0,0,0))
		self.tmp_fbo.add(ClearBuffers())
		self.tmp_fbo.add(widget.canvas)
		self.tmp_fbo.draw()

		# render a rectangle in the main fbo containing the content from the widget
		with self.fbo:
			Color(1,1,1,1)
			Rectangle(texture=self.tmp_fbo.texture, size=self.tmp_fbo.size)
Esempio n. 16
0
    def __init__(self, mc: "MpfMc", name: str, config: dict) -> None:
        """Initialise DMD."""

        self.mc = mc
        self.name = name

        self.mc.log.info('Initializing DMD')

        self.config = self._get_validated_config(config)

        self.source = self.mc.displays[self.config['source_display']]
        self.prev_data = None

        # put the widget canvas on a Fbo
        texture = Texture.create(size=self.source.size, colorfmt='rgb')
        self.fbo = Fbo(size=self.source.size, texture=texture)

        self.effect_widget = EffectWidget()

        effect_list = list()
        effect_list.append(FlipVerticalEffect())

        if self.config['brightness'] != 1.0:
            if not 0.0 <= self.config['brightness'] <= 1.0:
                raise ValueError("DMD brightness value should be between 0.0 "
                                 "and 1.0. Yours is {}".format(
                                     self.config['brightness']))

            effect_list.append(GainEffect(gain=self.config['brightness']))

        if self.config['gamma'] != 1.0:
            effect_list.append(GammaEffect(gamma=self.config['gamma']))

        self.effect_widget.effects = effect_list
        self.effect_widget.size = self.source.size

        self.fbo.add(self.effect_widget.canvas)

        self._set_dmd_fps()
Esempio n. 17
0
    def _setup_fbo(self, element, settings):
        """Setup FBO for a display."""
        if element not in self.machine.displays:
            raise AssertionError(
                "Display {} not found. Please create it to use display_light_player."
                .format(element))
        source = self.machine.displays[element]

        # put the widget canvas on a Fbo
        texture = Texture.create(size=source.size, colorfmt='rgb')
        fbo = Fbo(size=source.size, texture=texture)

        effect_widget = EffectWidget()

        effect_list = list()

        effect_widget.effects = effect_list
        effect_widget.size = source.size

        fbo.add(effect_widget.canvas)

        return [fbo, effect_widget, source, settings, True]
Esempio n. 18
0
    def __init__(self, **kw):
        self.shader_file = kw.pop("shader_file", None)
        self.canvas = Canvas()
        super(Renderer, self).__init__(**kw)

        with self.canvas:
            self._viewport = Rectangle(size=self.size, pos=self.pos)
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True, compute_normal_mat=True)
        self._config_fbo()
        self.texture = self.fbo.texture
        self.camera = None
        self.scene = None
Esempio n. 19
0
def texture_add_to_zip(texture, zip_object, entry_name):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    if format == 'BMP':
        data = glReadPixels(0, 0, size[0], size[1], GL_RGB, GL_UNSIGNED_BYTE)
    else:
        data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    zip_object.writestr(entry_name, data)
Esempio n. 20
0
    def export(self, wid, *largs):

        fbo = Fbo(size=wid.size, with_stencilbuffer=True)

        with fbo:
            ClearColor(1, 1, 1, 1)
            ClearBuffers()
            #Scale(1, -1, 1)
            #Translate(-self.x, -self.y - self.height, 0)

        fbo.add(wid.canvas)
        fbo.draw()
        img = fbo.texture
        img.save('test.png')
        fbo.remove(wid.canvas)
Esempio n. 21
0
    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas:
            self.fbo = Fbo(size=self.size)
            self.fbo_color = Color(1, 1, 1, 1)
            self.fbo_rect = Rectangle()

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()

        # wait that all the instructions are in the canvas to set texture
        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)
Esempio n. 22
0
    def _setup_fbo(self, element, settings, context):
        """Setup FBO for a display."""
        if element not in self.machine.displays:
            raise AssertionError(
                "Display {} not found. Please create it to use display_light_player."
                .format(element))
        source = self.machine.displays[element]

        # put the widget canvas on a Fbo
        texture = Texture.create(size=source.size, colorfmt='rgba')
        fbo = Fbo(size=source.size, texture=texture)

        effect_widget = RelativeLayout()

        effect_widget.size = source.size

        fbo.add(effect_widget.canvas)
        with source.canvas:
            callback = Callback(partial(self._trigger_render, context,
                                        element))

        return [
            fbo, effect_widget, source, settings, True, True, True, callback
        ]
Esempio n. 23
0
    def __init__(self,
                 filename=None,
                 onload=None,
                 maxtexsize=(1024, 1024),
                 **kwargs):

        if maxtexsize == None:
            maxtexsize = (1024, 1024)

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=maxtexsize)
            self.fbo.add_reload_observer(self.updateFbo)

        self.border_image = CoreImage('data/shadow32.png')
        self.img_texture = Texture.create(size=(16, 16), colorfmt="rgba")

        self.alpha = 0
        self.fbo_texture = self.fbo.texture

        super(Picture, self).__init__(**kwargs)

        self.loadImage(filename, onload)
Esempio n. 24
0
    def __init__(self, **kwargs):

        LOP, dm = initFiles()

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        self.LOP = LOP
        self.dm = dm
        
        self.meshes = []

        self.panCamera = False # KEITH EDIT
        self.pause = True # KEITH EDIT
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        # Keith: This allows keyboard interaction
        # http://stackoverflow.com/questions/22137786/
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        
        super(NSpect, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene(self.LOP, dm)
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []
Esempio n. 25
0
def texture_save(texture, filename, format=None):
    size = texture.size
    fbo = Fbo(size=texture.size, texture=texture)
    fbo.draw()
    fbo.bind()
    if format == 'BMP':
        data = glReadPixels(0, 0, size[0], size[1], GL_RGB, GL_UNSIGNED_BYTE)
    else:
        data = glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()
    if format == 'BMP':
        im = PILImage.fromstring('RGB', size, data)
    else:
        im = PILImage.fromstring('RGBA', size, data)
    im = im.transpose(PILImage.FLIP_TOP_BOTTOM)
    im.save(filename)
Esempio n. 26
0
 def create_image(self):
     parent = self.parent
     if parent:
         canvas_parent_index = parent.canvas.indexof(self.canvas)
         if canvas_parent_index > -1:
             parent.canvas.remove(self.canvas)
     fbo = Fbo(size=self.size, with_stencilbuffer=True)
     with fbo:
         ClearColor(0, 0, 0, 0)
         ClearBuffers()
         Scale(1, -1, 1)
         Translate(-self.x, -self.y - self.height, 0)
     fbo.add(self.canvas)
     fbo.draw()
     image = Image.frombytes('RGBA', list(map(int, self.size)),
                             fbo.texture.pixels, 'raw', 'RGBA', 0, 1)
     fbo.remove(self.canvas)
     if parent is not None and canvas_parent_index > -1:
         parent.canvas.insert(canvas_parent_index, self.canvas)
     return image
Esempio n. 27
0
def screenshot(widget, filename='output.png', region=None):
    if widget.parent is not None:
        canvas_parent_index = widget.parent.canvas.indexof(widget.canvas)
        widget.parent.canvas.remove(widget.canvas)

    fbo = Fbo(size=widget.size)

    with fbo:
        ClearColor(0, 0, 0, 0)
        ClearBuffers()
        Translate(-widget.x, -widget.y, 0)

    fbo.add(widget.canvas)
    fbo.draw()
    fbo.texture.save(filename)
    fbo.remove(widget.canvas)

    if widget.parent is not None:
        widget.parent.canvas.insert(canvas_parent_index, widget.canvas)

    return True
Esempio n. 28
0
    def __init__(self, filename=None, onload=None, maxtexsize=(1024, 1024), **kwargs):

        if maxtexsize == None:
            maxtexsize = (1024, 1024)

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=maxtexsize)
            self.fbo.add_reload_observer(self.updateFbo)

        self.border_image = CoreImage("data/shadow32.png")
        self.img_texture = Texture.create(size=(16, 16), colorfmt="rgba")

        self.alpha = 0
        self.fbo_texture = self.fbo.texture

        super(Picture, self).__init__(**kwargs)

        self.loadImage(filename, onload)
Esempio n. 29
0
    def __init__(self, **kwargs):
        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(
                size=self.size,
                with_depthbuffer=True,
            )
            self.fbo_color = Color(1, 1, 1, 1)
            self.viewport = Rectangle(
                pos=self.pos,
                size=self.size,
            )

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()

        self.texture = self.fbo.texture

        super(TransparentLayout, self).__init__(**kwargs)
Esempio n. 30
0
def screenshot_texture(widget, factory_func):
    if widget.parent is not None:
        canvas_parent_index = widget.parent.canvas.indexof(widget.canvas)
        widget.parent.canvas.remove(widget.canvas)

    fbo = Fbo(size=widget.size)

    with fbo:
        ClearColor(0, 0, 0, 0)
        ClearBuffers()
        Translate(-widget.x, -widget.y, 0)

    fbo.add(widget.canvas)
    fbo.draw()

    result = factory_func(fbo.texture)

    fbo.remove(widget.canvas)

    if widget.parent is not None:
        widget.parent.canvas.insert(canvas_parent_index, widget.canvas)

    return result
Esempio n. 31
0
    def update_img(self, img, force=False):
        ''' Updates the screen with a new image.

        :Parameters:

            `img`: :class:`~ffpyplayer.pic.Image` instance
                The image to be displayed.
        '''
        from ffpyplayer.tools import get_best_pix_fmt
        from ffpyplayer.pic import SWScale
        if img is None:
            return

        img_fmt = img.get_pixel_format()
        self.image_size = img_w, img_h = img.get_size()

        update = force
        if self._iw != img_w or self._ih != img_h:
            update = True

        if img_fmt not in ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'):
            swscale = self._swscale
            if img_fmt != self._sw_src_fmt or swscale is None or update:
                ofmt = get_best_pix_fmt(
                    img_fmt, (
                        'yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'))
                self._swscale = swscale = SWScale(
                    iw=img_w, ih=img_h, ifmt=img_fmt, ow=0, oh=0, ofmt=ofmt)
                self._sw_src_fmt = img_fmt
            img = swscale.scale(img)
            img_fmt = img.get_pixel_format()

        w, h = self.available_size or self.size
        if (not w) or not h:
            self.img = img
            return

        if self._fmt != img_fmt:
            self._fmt = img_fmt
            self._kivy_ofmt = {
                'yuv420p': 'yuv420p', 'rgba': 'rgba', 'rgb24': 'rgb',
                'gray': 'luminance', 'bgr24': 'bgr', 'bgra': 'bgra'}[img_fmt]
            update = True

        if update or w != self._last_w or h != self._last_h or \
                self.rotation != self._last_rotation:
            if self.scale_to_image:
                rotation = self.rotation
                rot = self.rotation * math.pi / 180
                rot_w = abs(img_w * math.cos(rot)) + abs(img_h * math.sin(rot))
                rot_h = abs(img_h * math.cos(rot)) + abs(img_w * math.sin(rot))
                scalew, scaleh = w / rot_w, h / rot_h
                scale = min(min(scalew, scaleh), 1)
                self.transform = Matrix()
                self.rotation = rotation
                self.apply_transform(Matrix().scale(scale, scale, 1),
                                     post_multiply=True)
                self.pos = 0, 0
            self._iw, self._ih = img_w, img_h
            self._last_h = h
            self._last_w = w
            self._last_rotation = self.rotation

        self.img = img
        kivy_ofmt = self._kivy_ofmt

        if update:
            self.canvas.remove_group(str(self) + 'image_display')
            if kivy_ofmt == 'yuv420p':
                w2 = int(img_w / 2)
                h2 = int(img_h / 2)
                self._tex_y = Texture.create(size=(img_w, img_h),
                                             colorfmt='luminance')
                self._tex_u = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                self._tex_v = Texture.create(size=(w2, h2),
                                             colorfmt='luminance')
                with self.canvas:
                    self._fbo = fbo = Fbo(size=(img_w, img_h),
                                          group=str(self) + 'image_display')
                with fbo:
                    BindTexture(texture=self._tex_u, index=1)
                    BindTexture(texture=self._tex_v, index=2)
                    Rectangle(size=fbo.size, texture=self._tex_y)
                fbo.shader.fs = BufferImage._YUV_RGB_FS
                fbo['tex_y'] = 0
                fbo['tex_u'] = 1
                fbo['tex_v'] = 2
                tex = self.img_texture = fbo.texture
                fbo.add_reload_observer(self.reload_buffer)
            else:
                tex = self.img_texture = Texture.create(
                    size=(img_w, img_h), colorfmt=kivy_ofmt)
                tex.add_reload_observer(self.reload_buffer)

            tex.flip_vertical()
            if self.flip:
                tex.flip_horizontal()
            self.texture_size = img_w, img_h

        if kivy_ofmt == 'yuv420p':
            dy, du, dv, _ = img.to_memoryview()
            self._tex_y.blit_buffer(dy, colorfmt='luminance')
            self._tex_u.blit_buffer(du, colorfmt='luminance')
            self._tex_v.blit_buffer(dv, colorfmt='luminance')
            self._fbo.ask_update()
            self._fbo.draw()
        else:
            self.img_texture.blit_buffer(img.to_memoryview()[0],
                                         colorfmt=kivy_ofmt)
            self.canvas.ask_update()
Esempio n. 32
0
class TextureStackBatchWidget(Widget):
    """Widget for efficiently drawing many TextureStacks

    Only add TextureStack or ImageStack widgets to this. Avoid adding
    any that are to be changed frequently.

    """
    critical_props = ['texs', 'offxs', 'offys', 'pos']
    """Properties that, when changed on my children, force a redraw."""

    def __init__(self, **kwargs):
        self._trigger_redraw = Clock.create_trigger(self.redraw)
        self._trigger_rebind_children = Clock.create_trigger(self.rebind_children)
        super(TextureStackBatchWidget, self).__init__(**kwargs)

    def on_parent(self, *args):
        if not self.canvas:
            Clock.schedule_once(self.on_parent, 0)
            return
        if not hasattr(self, '_fbo'):
            with self.canvas:
                self._fbo = Fbo(size=self.size)
                self._fbo.add_reload_observer(self.redraw)
                self._translate = Translate(x=self.x, y=self.y)
                self._rectangle = Rectangle(texture=self._fbo.texture, size=self.size)
        self.rebind_children()

    def rebind_children(self, *args):
        child_by_uid = {}
        binds = {prop: self._trigger_redraw for prop in self.critical_props}
        for child in self.children:
            child_by_uid[child.uid] = child
            child.bind(**binds)
        if hasattr(self, '_old_children'):
            old_children = self._old_children
            for uid in set(old_children).difference(child_by_uid):
                old_children[uid].unbind(**binds)
        self.redraw()
        self._old_children = child_by_uid

    def redraw(self, *args):
        fbo = self._fbo
        fbo.bind()
        fbo.clear()
        fbo.clear_buffer()
        fbo.release()
        for child in self.children:
            assert child.canvas not in fbo.children
            fbo.add(child.canvas)

    def on_pos(self, *args):
        if not hasattr(self, '_translate'):
            return
        self._translate.x, self._translate.y = self.pos

    def on_size(self, *args):
        if not hasattr(self, '_rectangle'):
            return
        self._rectangle.size = self._fbo.size = self.size
        self.redraw()

    def add_widget(self, widget, index=0, canvas=None):
        if not isinstance(widget, TextureStack):
            raise TypeError("TextureStackBatch is only for TextureStack")
        if index == 0 or len(self.children) == 0:
            self.children.insert(0, widget)
        else:
            children = self.children
            if index >= len(children):
                index = len(children)

            children.insert(index, widget)
        widget.parent = self
        if hasattr(self, '_fbo'):
            self.rebind_children()

    def remove_widget(self, widget):
        if widget not in self.children:
            return
        self.children.remove(widget)
        widget.parent = None
        if hasattr(self, '_fbo'):
            self.rebind_children()
Esempio n. 33
0
    def __init__(self, **kwargs):
        self.canvas = Canvas()

        window_width = Window.width
        window_height = Window.height

        aspect = window_width / float(window_height)

        center_x = window_width / 2.
        center_y = window_height / 2.

        element_size = window_width

        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True)
            self.fbo_color = Color(1, 1, 1, 1)
            self.fbo_rects = (
                StencilPush(),
                Triangle(points=(
                    0,
                    0,
                    center_x * 1.5,
                    window_height,
                    0,
                    window_height,
                )),
                StencilUse(),
                Rotate(angle=-90,
                       axis=(0, 0, 1),
                       origin=(center_x, window_height * 2 / 3.)),
                Rectangle(pos=(center_x - element_size / 2., -5),
                          size=(element_size, element_size / aspect),
                          texture=self.texture),
                Rotate(angle=90,
                       axis=(0, 0, 1),
                       origin=(center_x, window_height * 2 / 3.)),
                StencilUnUse(),
                Triangle(points=(
                    0,
                    0,
                    center_x * 1.5,
                    window_height,
                    0,
                    window_height,
                )),
                StencilPop(),
                StencilPush(),
                Triangle(points=(
                    window_width,
                    0,
                    center_x * .5,
                    window_height,
                    window_width,
                    window_height,
                )),
                StencilUse(),
                Rotate(angle=90,
                       axis=(0, 0, 1),
                       origin=(center_x, window_height * 2 / 3.)),
                Rectangle(pos=(center_x - element_size / 2., -5),
                          size=(element_size, element_size / aspect),
                          texture=self.texture),
            )

            Rotate(angle=-90,
                   axis=(0, 0, 1),
                   origin=(center_x, window_height * 2 / 3.))

            StencilUnUse()
            Triangle(points=(
                window_width,
                0,
                center_x * .5,
                window_height,
                window_width,
                window_height,
            ))
            StencilPop()

            StencilPush()
            Triangle(points=(
                0,
                0,
                window_width,
                0,
                center_x,
                window_height * 2 / 3.,
            ))
            StencilUse()

            if self.texture:
                self.texture.flip_horizontal()
            self.mirrored_rect = Rectangle(pos=(center_x - element_size / 2.,
                                                0),
                                           size=(element_size,
                                                 element_size / aspect),
                                           texture=self.texture)

            StencilUnUse()
            Triangle(points=(
                0,
                0,
                window_width,
                0,
                center_x,
                window_height * 2 / 3.,
            ))
            StencilPop()

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()

        self.texture = self.fbo.texture
        super(HoloStandLayout, self).__init__(**kwargs)
Esempio n. 34
0
        def count_it(num):
            if num == 0:
                fbo = Fbo(size=self.stencil.size, with_stencilbuffer=True)

                with fbo:
                    ClearColor(1, 1, 1, 0)
                    ClearBuffers()
                    img2 = self.paintscreen.bg.texture
                    fbo.add(self.stencil.canvas)
                    fbo.draw()
                    img = fbo.texture
                    fbo.remove(self.stencil.canvas)
                    self.remove_widget(self.paintscreen)
                    im = np.frombuffer(img.pixels, np.uint8)
                    data = np.reshape(im, (im.shape[0], 1)).tostring()

                    data2 = str(data)
                    data2 = str.encode(data2)

                    pix = np.frombuffer(data, np.uint8)
                    a = np.empty_like(pix)
                    a[:] = pix
                    texture = Texture.create(size=self.stencil.size)

                    texture.blit_buffer(a, colorfmt='rgba', bufferfmt='ubyte')
                    self.imge = Image(pos=(0, 0),
                                      size=self.paintscreen.stencil.size,
                                      texture=texture)
                    #self.paintscreen.stencil.add_widget(self.imge)

                    #img2 = self.paintscreen.grid_layout.bg.texture
                    im2 = np.frombuffer(img2.pixels, np.uint8)
                    data = np.reshape(im2, (im2.shape[0], 1)).tostring()

                    data2 = str(data)
                    data2 = str.encode(data2)

                    pix = np.frombuffer(data, np.uint8)
                    a2 = np.empty_like(pix)
                    a2[:] = pix

                    img2 = a2
                    print(img2.shape)

                    print(img2)
                    img1 = a
                    print(img1.shape)

                    import cv2
                    #setting alpha=1, beta=1, gamma=0 gives direct overlay of two images
                    # in theory this would give a direct overlay...
                    #img3 = cv2.addWeighted(img1, 1, img2, 1, 0)
                    #print(img3.shape)

                    im = img1.reshape(1200, 1200, 4)
                    # for i in range(0, 1200):
                    #     for j in range(0,1200):
                    #         points = im[i,j,:]
                    #         if (points[3] == 0):#points[0] == 255 & points[1] == 255 & points[2] == 255):
                    #             im[i,j,:] = [255,255,255,0]
                    img_2 = img2.reshape((1200, 1200, 4))
                    for i in range(0, 1200):
                        for j in range(0, 1200):
                            points1 = im[i, j, :]
                            if (points1[3] != 0):
                                img_2[i, j, :] = im[i, j, :]

                    socket_client.send(img_2)

                    while MESSAGE is None:
                        pass
                    if MESSAGE is not None:
                        new_img = MESSAGE
                    else:
                        new_img = img_2

                    texture = Texture.create(size=(1200, 1200))

                    texture.blit_buffer(np.reshape(new_img,
                                                   (1200 * 1200 * 4, )),
                                        colorfmt='rgba',
                                        bufferfmt='ubyte')

                    self.paintscreen = PaintScreen()
                    self.add_widget(self.paintscreen)
                    self.paintscreen.bg.texture = texture
                return
            num -= 1
            self.count.text = str(num)
            Clock.schedule_once(lambda dt: count_it(num), 1)
Esempio n. 35
0
class FboFloatLayout(FloatLayout):

    texture = ObjectProperty(None, allownone=True)

    alpha_blending = BooleanProperty(False)

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas.before:
            Callback(self._set_blend_func)
        #self.size
        self.fbo_texture = Texture.create(size=self.size, colorfmt='rgba')

        self.fbo_texture.mag_filter = 'linear'
        self.fbo_texture.min_filter = 'linear'

        with self.canvas:
            #self.cbs = Callback(self.prepare_canvas)
            self.fbo = Fbo(size=self.size, texture=self.fbo_texture)
            #Color(1, 1, 1, 0)
            #self.fbo_rect = Rectangle()

        with self.fbo:
            ClearColor(0.0, 0.0, 0.0, 0.0)
            ClearBuffers()
            self.fbo_rect = Rectangle(size=self.size)

        #self.fbo.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/invert.glsl')
        #with self.fbo.after:
        #    self.cbr = Callback(self.reset_gl_context)
        #    PopMatrix()

        with self.canvas.before:
            Callback(self._set_blend_func)

        # wait that all the instructions are in the canvas to set texture

        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)

    def prepare_canvas(self, *args):
        glEnable(GL_BLEND)
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
                            GL_ONE)
        glEnable(GL_DEPTH_TEST)

    def _set_blend_func(self, instruction):
        # clobber the blend mode
        if self.alpha_blending:
            glBlendFunc(GL_ONE, GL_ZERO)
        else:
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        glDisable(GL_CULL_FACE)
        self.fbo.draw()

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def setup_gl_context(self, *args):
        glEnable(GL_BLEND)
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_DEPTH_TEST)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def add_widget(self, *largs):
        # trick to attach kivy3dgui instructino to fbo instead of canvas
        canvas = self.canvas
        self.canvas = self.fbo
        ret = super(FboFloatLayout, self).add_widget(*largs)
        self.canvas = canvas
        return ret

    def remove_widget(self, *largs):
        canvas = self.canvas
        self.canvas = self.fbo
        super(FboFloatLayout, self).remove_widget(*largs)
        self.canvas = canvas

    def on_size(self, instance, value):
        self.fbo.size = value
        self.texture = self.fbo_texture
        self.fbo_rect.size = value

    def on_pos(self, instance, value):
        self.fbo_rect.pos = value

    def on_texture(self, instance, value):
        self.fbo_rect.texture = value

    def on_touch_down(self, touch):
        return super(FboFloatLayout, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        return super(FboFloatLayout, self).on_touch_move(touch)

    """def on_touch_up(self, touch):
        return super(FboFloatLayout, self).on_touch_up(touch)"""

    def on_touch_up(self, touch):
        for e in self.children:
            if e.collide_point(touch.x, touch.y):
                return e.on_touch_up(touch)
Esempio n. 36
0
def widgetshot(widget, filename='output.png'): 
# detach the widget from the parent 
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)

    # put the widget canvas on a Fbo
    texture = Texture.create(size=widget.size, colorfmt='rgb')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)

    # clear the fbo background
    fbo.bind()
    fbo.clear_buffer()
    fbo.release()

    # draw!
    fbo.draw()

    # get the fbo data
    fbo.bind()
    data = glReadPixels(0, 0, widget.size[0], widget.size[1], GL_RGBA, GL_UNSIGNED_BYTE)
    fbo.release()

    # save to a file
    surf = pygame.image.fromstring(data, widget.size, 'RGBA', True)
    pygame.image.save(surf, filename)

    # reattach to the parent
    if parent:
        parent.add_widget(widget)

    return True
class ObjectRenderer(Widget):
    scene = StringProperty('')
    obj_id = StringProperty('')
    obj_translation = ListProperty([0, 0, 0])
    obj_rotation = ListProperty([0, 0, 0])
    obj_scale = NumericProperty(1)
    obj_texture = StringProperty('')
    texture = ObjectProperty(None, allownone=True)
    cam_translation = ListProperty([0, 0, 0])
    cam_rotation = ListProperty([0, 0, 0])
    display_all = BooleanProperty(False)
    light_sources = DictProperty()
    ambiant = NumericProperty(.5)
    diffuse = NumericProperty(.5)
    specular = NumericProperty(.5)
    mode = StringProperty('triangles')

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0., 0., 0., 0.))

            self.viewport = Rectangle(size=self.size, pos=self.pos)

        self.fbo.shader.source = resource_find(
            join(dirname(__file__), 'simple.glsl'))
        super(ObjectRenderer, self).__init__(**kwargs)

    def on_obj_rotation(self, *args):
        self.obj_rot_x.angle = self.obj_rotation[0]
        self.obj_rot_y.angle = self.obj_rotation[1]
        self.obj_rot_z.angle = self.obj_rotation[2]

    def on_cam_rotation(self, *args):
        self.cam_rot_x.angle = self.cam_rotation[0]
        self.cam_rot_y.angle = self.cam_rotation[1]
        self.cam_rot_z.angle = self.cam_rotation[2]

    def on_obj_translation(self, *args):
        self.obj_translate.xyz = self.cam_translation

    def on_cam_translation(self, *args):
        self.cam_translate.xyz = self.cam_translation

    def on_obj_scale(self, *args):
        self.scale.xyz = [self.obj_scale, ] * 3

    def on_display_all(self, *args):
        self.setup_canvas()

    def on_light_sources(self, *args):
        self.fbo['light_sources'] = [
            ls[:] for ls in list(self.light_sources.values())]
        self.fbo['nb_lights'] = len(self.light_sources)

    def on_ambiant(self, *args):
        self.fbo['ambiant'] = self.ambiant

    def on_diffuse(self, *args):
        self.fbo['diffuse'] = self.diffuse

    def on_specular(self, *args):
        self.fbo['specular'] = self.specular

    def on_mode(self, *args):
        self.setup_canvas()

    def setup_canvas(self, *args):
        if not (self.scene and self.obj_id or self.display_all):
            return

        print('setting up the scene')
        with self.fbo:
            self.fbo['ambiant'] = self.ambiant
            self.fbo['diffuse'] = self.diffuse
            self.fbo['specular'] = self.specular
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

    def on_scene(self, instance, value):
        print("loading scene %s" % value)
        self._scene = ObjFileLoader(resource_find(value))
        self.setup_canvas()

    def on_obj_id(self, *args):
        self.setup_canvas()

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value

    def setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def update_glsl(self, *args):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        self.cam_translate = Translate(self.cam_translation)
        # Rotate(0, 1, 0, 0)
        self.cam_rot_x = Rotate(self.cam_rotation[0], 1, 0, 0)
        self.cam_rot_y = Rotate(self.cam_rotation[1], 0, 1, 0)
        self.cam_rot_z = Rotate(self.cam_rotation[2], 0, 0, 1)
        self.scale = Scale(self.obj_scale)
        UpdateNormalMatrix()
        if self.display_all:
            for i in self._scene.objects:
                self.draw_object(i)
        else:
            self.draw_object(self.obj_id)
        PopMatrix()

    def draw_object(self, obj_id):
        m = self._scene.objects[obj_id]
        self.obj_rot_x = Rotate(self.obj_rotation[0], 1, 0, 0)
        self.obj_rot_y = Rotate(self.obj_rotation[1], 0, 1, 0)
        self.obj_rot_z = Rotate(self.obj_rotation[2], 0, 0, 1)
        self.obj_translate = Translate(xyz=self.obj_translation)

        if len(m.indices) > 2 ** 16:
            print('%s too big! %s indices' % (obj_id, len(m.indices)))

        if m.texture:
            print("loading texture %s " % m.texture)
            img = Image(source=resource_find(
                join(dirname(self.scene), m.texture)))
            texture = img.texture
            if texture:
                texture.wrap = 'repeat'
        else:
            texture = None

        vertex_lenght = sum(x[1] for x in m.vertex_format)
        if len(m.vertices) % vertex_lenght:
            print((
                (
                    'warning: vertices lenght (%s)'
                    'is not a multiple of vertex_format lenght(%s)'
                )
                % (len(m.vertices), vertex_lenght)))
        Mesh(
            vertices=m.vertices,
            indices=m.indices,
            fmt=m.vertex_format,
            texture=texture,
            mode=self.mode)
Esempio n. 38
0
class Renderer(Widget):
    texture = ObjectProperty(None, allownone=True)

    def load(self, *l):
        self.button.disabled = True

        if os.path.isdir(meshdir):
            rep = meshdir
            self.fl = FileChooserListView(path=rep,
                                          rootpath=rep,
                                          filters=["*.mesh.ascii"],
                                          dirselect=False,
                                          size=(400, 400),
                                          center_x=250,
                                          center_y=250)
        else:
            rep = os.getcwd()
            self.fl = FileChooserListView(path=rep,
                                          filters=["*.mesh.ascii"],
                                          dirselect=False,
                                          size=(400, 400),
                                          center_x=250,
                                          center_y=250)
        '''if platform == 'android':
            rep = "."
        else:
            rep = "../../Mesh"'''

        self.fl.bind(selection=self.on_selected)
        super(Renderer, self).add_widget(self.fl)

    def on_selected(self, filechooser, selection):
        self.button.disabled = False

        print 'load', selection
        super(Renderer, self).remove_widget(self.fl)

        scale = 3
        self.fbo.remove_group('truc')

        self.scene = MeshAsciiLoader(selection[0], scale)

        with self.fbo:
            #ClearBuffers(clear_depth=True)

            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

    def change_shader(self, *l):
        print 'change_shader'
        if self.shader == 0:
            self.fbo.shader.source = resource_find('simple.glsl')
            self.shader = 1
        else:
            #self.fbo.shader.source = resource_find('flat.glsl')
            self.fbo.shader.source = resource_find('normalmap.glsl')
            self.shader = 0

    def __init__(self, **kwargs):
        self.model = 0
        self.shader = 0
        self.canvas = Canvas()
        #self.scene = ObjFileLoader(resource_find("testnurbs.obj"))

        Logger.debug('******************************************************')
        scale = 3
        #dir = "Duke Nukem Forever_Dr_Valencia" # error index out of range
        #dir = "Duke Nukem Forever_Kitty Pussoix"
        dir = "Duke_Nukem_by_Ventrue"
        #dir = "DOA5U_Rachel_Nurse/Model" #pb uv

        if not os.path.isdir(meshdir):
            self.scene = MeshAsciiLoader(
                resource_find(dir + "/Generic_Item.mesh.ascii"), scale)
        else:
            self.scene = MeshAsciiLoader(
                resource_find(meshdir + dir + "/Generic_Item.mesh.ascii"),
                scale)

        #scale = .03
        #self.texturename = 'Batman_Rabbit_Head_Posed/Batman_V3_Body_D.PNG'
        #self.scene = PSKFileLoader(resource_find("Batman_Rabbit_Head_Posed/Batman_Rabbit_Head_Posed.psk"), scale)
        #self.texturename = 'Gray/Gray_C1.tga'
        #self.scene = PSKFileLoader(resource_find("Gray/Mike_TPP.psk"), scale) #too many indices, good for split test
        #self.texturename = 'CV_Talia/Talia_Body_D.tga'
        #self.texturename = 'CV_Talia/Talia_Legs_D.tga')
        #self.scene = PSKFileLoader(resource_find("CV_Talia/Talia_posed.psk"), scale) #too many indices, good for split test
        Logger.debug('******************************************************')

        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0, 0, 0, 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        #self.fbo.shader.source = resource_find('simple.glsl')
        self.fbo.shader.source = resource_find('normalmap.glsl')

        super(Renderer, self).__init__(**kwargs)

        self.fbo['texture1'] = 1
        self.fbo['toggletexture'] = 1

        with self.fbo:
            #ClearBuffers(clear_depth=True)

            self.cb = Callback(self.setup_gl_context)

            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        Clock.schedule_interval(self.update_scene, 1 / 60.)

        self._touches = []

        self.button = Button(text='load')
        self.button.bind(on_release=self.load)
        super(Renderer, self).add_widget(self.button)

        button1 = Button(text='shader', center_x=150)
        button1.bind(on_release=self.change_shader)
        super(Renderer, self).add_widget(button1)

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value

    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 500, 1)
        self.fbo['projection_mat'] = proj
        self.fbo['diffuse_light'] = (1.0, 0.0, 0.0)
        self.fbo['ambient_light'] = (0.1, 0.1, 0.1)
        self.fbo['glLightSource0_position'] = (1.0, 1.0, 1.0, 0.0)
        self.fbo['glLightSource0_spotCutoff'] = 360
        self.fbo['glLightModel_ambient'] = (0.2, 0.2, 0.2, 1.0)
        self.fbo['glLightSource0_diffuse'] = (0.7, 0.7, 0.7, 1.0)
        self.fbo['glLightSource0_specular'] = (.1, .1, .1, 1.0)
        self.fbo['glFrontMaterial_specular'] = (.10, .10, .10, 1.0)
        self.fbo['glFrontMaterial_shininess'] = 0.1

    def setup_scene(self):
        Color(.5, .5, .5, 0)

        PushMatrix()
        Translate(0, -3, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        # here just rotate scene for best view
        self.roty = Rotate(180, 0, 1, 0)
        self.scale = Scale(1)

        UpdateNormalMatrix()

        self.draw_elements()

        PopMatrix()

    def draw_elements(self):
        #Draw separately all meshes on the scene
        def _draw_element(m, texture='', texture1=''):
            #bind the texture BEFORE the draw (Mesh)
            if texture1:
                # here, we are binding a custom texture at index 1
                # this will be used as texture1 in shader.
                tex1 = Image(texture1).texture
                tex1.wrap = 'repeat'  #enable of uv support >1 or <0
                BindTexture(texture=tex1, index=1)
            #clear the texture if none
            else:
                BindTexture(source="", index=1)

            mesh = Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
                group='truc',
            )

            if texture:
                try:
                    texture = Image(texture).texture
                    texture.wrap = 'repeat'  #enable of uv support >1 or <0
                    mesh.texture = texture
                except:  #no texture if not found or not supported
                    pass

        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                Kd=color,
                Ka=color,
                Ks=(.3, .3, .3),
                Tr=1.,
                Ns=1.,
                intensity=1.,
                id_color=[i / 255. for i in id_color],
            )

        for meshid in range(0, len(self.scene.objects)):
            # Draw each element
            mesh = self.scene.objects[meshid]
            #_set_color(0.7, 0.7, 0., id_color=(255, 255, 0))
            if (mesh.diffuse != ""):
                _draw_element(mesh, mesh.diffuse, mesh.normal)
                #_draw_element(mesh, mesh.diffuse)
                #_draw_element(mesh, mesh.normal)
            else:
                _draw_element(mesh, self.texturename)

    def update_scene(self, *largs):
        pass

    # ============= All stuff after is for trackball implementation ===========

    def define_rotate_angle(self, touch):
        x_angle = (touch.dx / self.width) * 360
        y_angle = -1 * (touch.dy / self.height) * 360
        return x_angle, y_angle

    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        return super(Renderer, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        touch.ungrab(self)
        self._touches.remove(touch)
        return super(Renderer, self).on_touch_up(touch)

    def on_touch_move(self, touch):
        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation
                ax, ay = self.define_rotate_angle(touch)

                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2:  # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)

                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]

                old_distance = (old_dx * old_dx + old_dy * old_dy)
                #Logger.debug('Old distance: %s' % old_distance)

                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y

                new_distance = (new_dx * new_dx + new_dy * new_dy)

                #Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01

                if new_distance > old_distance:
                    scale = SCALE_FACTOR
                    #Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1 * SCALE_FACTOR
                    #Logger.debug('Scale down')

                xyz = self.scale.xyz

                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 39
0
class Paint(StencilView):
    scale = NumericProperty()

    def __init__(self, app, **kwargs):
        StencilView.__init__(self, **kwargs)
        self.app = app
        self.xx = 0
        self.scale = 1.0
        self.size_hint = (None, None)
        self.cursor_pos = (0, 0)
        self.fbo_size = DEFAULT_IMAGE_SIZE
        self.fbo = None
        self.fbo_rect = None
        self.tool_fbo = None
        self.tool_fbo_rect = None
        self.bg_rect = None
        self.rect = None
        self.fbo_clear_color = (1, 1, 1, 1)
        self.layer_undo_stack = []
        self.undo_layer_index = 0
        self.layer_rect = []
        self.fbo_create_on_canvas()
        self.touches = []
        self.move_image = False
        self.active_layer = None
        self.tool_buffer_enabled = True
        self.px = None
        self.py = None
        self.grid_texture = None
        self.active_layer_last_texture = None

    def grid_create(self, size):
        self.grid_texture = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
        tex = improc.texture_draw_grid(self.grid_texture, 255, 4)
        return tex

    def fbo_create(self, size, tex=None):
        if tex is None:
            tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
            tex.mag_filter = 'nearest'
            tex.min_filter = 'nearest'
        if self.fbo is None:
            self.fbo = Fbo(size=size, texture=tex)
            self.fbo.texture.mag_filter = 'nearest'
            self.fbo.texture.min_filter = 'nearest'
        else:
            self.fbo = Fbo(size=size, texture=tex)
            self.fbo.texture.mag_filter = 'nearest'
            self.fbo.texture.min_filter = 'nearest'
        tool_tex = Texture.create(size=size, colorfmt='rgba', bufferfmt='ubyte')
        tool_tex.mag_filter = 'nearest'
        tool_tex.min_filter = 'nearest'
        if self.tool_fbo is None:
            self.tool_fbo = Fbo(size=size, texture=tool_tex)
            self.tool_fbo.texture.mag_filter = 'nearest'
            self.tool_fbo.texture.min_filter = 'nearest'
        else:
            self.tool_fbo = Fbo(size=size, texture=tool_tex)
            self.tool_fbo.texture.mag_filter = 'nearest'
            self.tool_fbo.texture.min_filter = 'nearest'
        return self.fbo

    def refbo(self):
        tex = Texture.create(size=self.fbo.texture.size, colorfmt='rgba', bufferfmt='ubyte')
        self.fbo = Fbo(size=tex.size, texture=tex)
        self.fbo.texture.mag_filter = 'nearest'
        self.fbo.texture.min_filter = 'nearest'
        self.fbo.draw()
        self.canvas.ask_update()

    def canvas_put_drawarea(self, texture=None):
        self.canvas.clear()
        if texture:
            self.fbo_size = texture.size
            self.fbo_create(texture.size, tex=texture)
        self.bg_rect = layer.Layer.layer_bg_rect
        with self.canvas:
            self.canvas.add(self.bg_rect)
            Color(1, 1, 1, 1)
            for laybox in layer.LayerBox.boxlist:
                if laybox.layer:
                    if laybox.layer.texture and laybox.layer.visible:
                        self.canvas.add(laybox.layer.rect)
                        laybox.layer.rect.pos = self.fbo_rect.pos

                if self.tool_buffer_enabled:
                    self.tool_fbo_rect = Rectangle(pos=self.fbo_rect.pos, size=self.tool_fbo.texture.size,
                                                   texture=self.tool_fbo.texture)
        self.fbo_update_pos()
        self.fbo.draw()
        self.canvas.ask_update()

    def fbo_create_on_canvas(self, size=None, pos=(0, 0)):
        self.canvas.clear()
        if size is None:
            size = self.fbo_size
        else:
            self.fbo_size = size
        self.fbo_create(size)
        with self.canvas:
            Color(1, 1, 1, 1)
            self.fbo_rect = Rectangle(texture=self.fbo.texture, pos=pos, size=self.fbo.texture.size)
            self.tool_fbo_rect = Rectangle(texture=self.tool_fbo.texture, pos=pos, size=self.tool_fbo.texture.size)
        self.fbo.draw()
        self.canvas.ask_update()


    def fbo_clear(self):
        self.fbo.bind()
        self.fbo.clear()
        self.fbo.clear_color = self.fbo_clear_color
        self.fbo.clear_buffer()
        self.fbo.release()
        self.fbo.draw()

    def fbo_update_pos(self):
        x = self.app.aPaintLayout.size[0] / self.scale / 2 - self.fbo.size[0] / 2
        y = self.app.aPaintLayout.size[1] / self.scale / 2 - self.fbo.size[1] / 2
        self.fbo_rect.pos = (x, y)
        self.tool_fbo_rect.pos = (x, y)
        if self.bg_rect:
            self.bg_rect.pos = (x, y)
        if self.app.layer_ribbon:
            for lb in layer.LayerBox.boxlist:
                if lb.layer.rect:
                    lb.layer.rect.pos = self.fbo_rect.pos

    def fbo_move_by_offset(self, offset):
        if self.bg_rect:
            self.bg_rect.pos = self.bg_rect.pos[0] + offset[0], self.bg_rect.pos[1] + offset[1]
            self.fbo_rect.pos = self.bg_rect.pos
            self.tool_fbo_rect.pos = self.bg_rect.pos
        if self.app.layer_ribbon:
            for lb in layer.LayerBox.boxlist:
                if lb.layer.rect:
                    lb.layer.rect.pos = self.fbo_rect.pos
        # self.ox, self.oy = self.bg_rect.pos
    #
    def fbo_render(self, touch, width):
        self.fbo.bind()
        if touch and touch.ud.has_key('line'):
            with self.fbo:
                self.fbo.add(self.app.aColor)
                d = width
                self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                   (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                touch.ud['line'].points += self.cursor_pos
        self.fbo.release()
        self.fbo.draw()
        self.canvas.ask_update()

    def fbo_get_texture(self):
        return self.fbo.texture

    def fbo_get_pixel_color(self, touch, format='1'):
        self.fbo.bind()
        x = touch.x / self.scale - self.fbo_rect.pos[0]
        y = touch.y / self.scale - self.fbo_rect.pos[1]
        data = glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE)
        self.fbo.release()
        if format == '1':
            c = [ord(a) / 255.0 for a in data]
        else:
            c = [ord(a) for a in data]
        return c

    def fbo_fill_region(self, touch):
        x = int(touch.x / self.scale - self.fbo_rect.pos[0])
        y = int(touch.y / self.scale - self.fbo_rect.pos[1])
        improc.fillimage(self.fbo, (x, y), [int(255 * c) for c in self.app.aColor.rgba])
        self.canvas.ask_update()

    def fbo_replace_color(self, touch, width):
        cx = int(touch.x / self.scale - self.fbo_rect.pos[0])
        cy = int(touch.y / self.scale - self.fbo_rect.pos[1])
        if self.px is None:
            self.px = cx
        if self.py is None:
            self.py = cy
        if (cx - self.px) > 0:
            tg_alpha = float((cy - self.py)) / (cx - self.px)
            step = int(math.copysign(1, tg_alpha))
            if abs(cx - self.px) > abs(cy - self.py):
                coords = [(x, self.py + (x - self.px) * tg_alpha) for x in xrange(int(self.px), int(cx))]
            else:
                coords = [(self.px + (y - self.py) / tg_alpha, y) for y in xrange(int(self.py), int(cy), step)]
        elif (cx - self.px) < 0:
            tg_alpha = float((cy - self.py)) / (cx - self.px)
            step = int(math.copysign(1, tg_alpha))
            if abs(cx - self.px) > abs(cy - self.py):
                coords = [(x, self.py + (x - self.px) * tg_alpha) for x in xrange(int(cx), int(self.px))]
            else:
                coords = [(self.px + (y - self.py) / tg_alpha, y) for y in xrange(int(cy), int(self.py), step)]
        elif (cx - self.px) == 0:
            if (cy - self.py) > 0:
                coords = [(cx, y) for y in xrange(int(self.py), int(cy))]
            elif (cy - self.py) < 0:
                coords = [(cx, y) for y in xrange(int(cy), int(self.py))]
            else:
                coords = [(cx, cy), ]
        self.fbo.bind()
        for (x, y) in coords:
            improc.texture_replace_color(tex=self.fbo.texture, pos=(x, y), color=0, size=(width, width))
        self.fbo.release()
        self.fbo.clear()
        self.fbo.draw()
        self.canvas.ask_update()
        self.px = cx
        self.py = cy

    def pos_to_widget(self, touch):
        return self.to_widget(touch.x, touch.y)

    def scale_canvas(self, zoom):
        with self.canvas.before:
            PushMatrix()
            self.scale *= zoom
            context_instructions.Scale(zoom)
        with self.canvas.after:
            PopMatrix()
        self.fbo_update_pos()

    def on_scale(self, instance, scale):
        ToolBehavior.scale()

    def scale_pos(self, pos):
        return [pos[0] / self.scale - self.fbo_rect.pos[0],
                pos[1] / self.scale - self.fbo_rect.pos[1]]

    def scaled_pos(self):
        return [self.fbo_rect.pos[0] * self.scale,
                self.fbo_rect.pos[1] * self.scale]

    def scaled_size(self):
        return [self.fbo_rect.texture.size[0] * self.scale,
                self.fbo_rect.texture.size[1] * self.scale]

    def add_touch(self, touch):
        if touch and len(self.touches) < 2:
            self.touches.append(touch)
        if len(self.touches) >= 2:
            self.touch_dist = self.touches[0].distance(self.touches[1])
            self.touch_dist_const = self.touch_dist
            self.first_touch = self.touches[0]

    def double_touch(self):
        if len(self.touches) > 1:
            return True

    # def double_touch_distance(self):
    #     return Vector(self.touches[0].pos).distance(self.touches[1].pos)

    def touch_responce(self):
        result = False
        if len(self.touches) >= 2:
            pos1 = self.pos_to_widget(self.touches[0])
            pos2 = self.touches[1].pos
            dist = distance(pos1, pos2)
            if dist > self.touch_dist + 10:
                self.touch_dist = dist
                result = 2
            elif dist <= self.touch_dist - 10:
                self.touch_dist = dist
                result = 1
            if abs(self.touch_dist_const - dist) < 10:
                result = 3
            return result
        return False

    def on_touch_down(self, touch):
        self.tool_buffer.on_touch_down(touch)

        if self.collide_point(*touch.pos):
            if self.app.config.getint('toolbars', 'toolbar_autohide'):
                self.app.toolbar.animate_hide()
            if self.app.config.getint('toolbars', 'palette_autohide'):
                self.app.palette.animate_hide()
            if self.app.config.getint('toolbars', 'layer_ribbon_autohide'):
                self.app.layer_ribbon.animate_hide()

        if not self.collide_point(*touch.pos):
            if self.app.active_tool == TOOL_LINE:
                self.tool_line._render_and_reset_state(self.fbo, self.tool_fbo)
                self.fbo.draw()
                self.canvas.ask_update()

            return False

        touch.grab(self)

        self.add_touch(touch)

        if len(self.touches) == 1:
            self.active_layer_backup_texture()

        if self.double_touch():
            self.active_layer_set_last_backup_texture()
            return

        if not self.app.layer_ribbon.get_active_layer().visible:
            dialog.PopupMessage("Notification", "The current layer is hidden, make it visible for edit")
            return
        if self.app.layer_ribbon.get_active_layer().texture_locked:
            dialog.PopupMessage("Notification", "The current layer is locked, make it unlock for edit")
            return

        if self.app.active_tool == TOOL_PENCIL1:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 1.
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PENCIL2:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 2.1
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d / 2.0)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PENCIL3:
            self.fbo.bind()
            if touch:
                with self.fbo:
                    self.fbo.add(self.app.aColor)
                    d = 3.
                    self.cursor_pos = ((touch.x - d / 2) / self.scale - self.fbo_rect.pos[0],
                                       (touch.y - d / 2) / self.scale - self.fbo_rect.pos[1])
                    Ellipse(pos=self.cursor_pos, size=(d, d))
                    touch.ud['line'] = Line(points=self.cursor_pos, width=d / 2)
            self.fbo.release()
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_PICKER:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    c = self.fbo_get_pixel_color(touch)
                    self.app.aColor = Color(c[0], c[1], c[2], c[3])
                    self.app.toolbar.tools_select(self.app.prev_tool)
        elif self.app.active_tool == TOOL_FILL:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_fill_region(touch)
        elif self.app.active_tool == TOOL_ERASE1:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=1)
        elif self.app.active_tool == TOOL_ERASE2:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=2)
        elif self.app.active_tool == TOOL_ERASE3:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=3)
        elif self.app.active_tool == TOOL_SELECT:
            if touch:
                if not self.tool_buffer.enabled:
                    self.tool_select.on_touch_down(touch, self.fbo, self.tool_fbo)
                else:
                    pass
        elif self.app.active_tool == TOOL_LINE:
            if touch:
                self.tool_line.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_RECT:
            if touch:
                self.tool_rect.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_ELLIPSE:
            if touch:
                self.tool_ellipse.on_touch_down(touch, self.fbo, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_MOVE:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.move_image = True
                    self.ox, self.oy = touch.pos
        return True

    def on_touch_move(self, touch):
        result = self.touch_responce()
        if result == 2:
            self.scale_canvas(1.02)
            return
        elif result == 1:
            self.scale_canvas(0.98)
            return
        elif result == 3:
            dist = self.touches[0].distance(self.first_touch)
            self.fbo_move_by_offset((dist / self.scale, dist / self.scale))

        if self.app.active_tool == TOOL_PENCIL1:
            self.fbo_render(touch, width=1.)
        elif self.app.active_tool == TOOL_PENCIL2:
            self.fbo_render(touch, width=2.)
        elif self.app.active_tool == TOOL_PENCIL3:
            self.fbo_render(touch, width=3.)
        elif self.app.active_tool == TOOL_PICKER:
            c = self.fbo_get_pixel_color(touch)
            self.app.aColor = Color(c[0], c[1], c[2])
        elif self.app.active_tool == TOOL_ERASE1:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=1)
        elif self.app.active_tool == TOOL_ERASE2:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=2)
        elif self.app.active_tool == TOOL_ERASE3:
            if touch:
                if self.collide_point(touch.x, touch.y):
                    self.fbo_replace_color(touch, width=3)
        elif self.app.active_tool == TOOL_SELECT:
            if touch:
                if not self.tool_buffer.enabled:
                    self.tool_select.on_touch_move(touch, self.tool_fbo)
                    self.fbo.draw()
                    self.canvas.ask_update()
                else:
                    pass

        elif self.app.active_tool == TOOL_LINE:
            if touch:
                self.tool_line.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_RECT:
            if touch:
                self.tool_rect.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_ELLIPSE:
            if touch:
                self.tool_ellipse.on_touch_move(touch, self.tool_fbo)
            self.fbo.draw()
            self.canvas.ask_update()
        elif self.app.active_tool == TOOL_MOVE:
            if self.move_image:
                self.fbo_move_by_offset((touch.dx / self.scale, touch.dy / self.scale))
        self.tool_buffer.on_touch_move(touch, self.fbo)

    def on_touch_up(self, touch):
        self.tool_buffer.on_touch_up(touch)
        if touch.grab_current is not self:
            return False
        if not self.collide_point(*touch.pos):
            return False
        touch.ungrab(self)

        if self.double_touch():
            _not_add_too_undo = True
        else:
            _not_add_too_undo = False

        if touch:
            try:
                self.touches.remove(touch)
            except:
                pass
            if self.app.active_tool == TOOL_SELECT:
                if touch:
                    self.tool_select.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_LINE:
                if touch:
                    self.tool_line.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_RECT:
                if touch:
                    self.tool_rect.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_ELLIPSE:
                if touch:
                    self.tool_ellipse.on_touch_up(touch)
                self.fbo.draw()
                self.canvas.ask_update()
            elif self.app.active_tool == TOOL_MOVE:
                if touch:
                    self.move_image = False
            elif self.app.active_tool == TOOL_ERASE1 or self.app.active_tool == TOOL_ERASE2 or self.app.active_tool == TOOL_ERASE3:
                if touch:
                    self.px = None
                    self.py = None
            if self.app.active_tool == TOOL_PENCIL1 or self.app.active_tool == TOOL_ERASE1 \
                    or self.app.active_tool == TOOL_PENCIL2 or self.app.active_tool == TOOL_ERASE2 \
                    or self.app.active_tool == TOOL_PENCIL3 or self.app.active_tool == TOOL_ERASE3 \
                    or self.app.active_tool == TOOL_FILL:
                rect = self.app.layer_ribbon.get_active_layer().rect
                pos = rect.pos[0] * self.scale, rect.pos[1] * self.scale
                size = rect.size[0] * self.scale, rect.size[1] * self.scale
                if not _not_add_too_undo:
                    if pos[0] <= touch.x <= pos[0] + size[0] and pos[1] <= touch.y <= pos[1] + size[1]:
                        self.add_undo_stack()
        return True

    def add_redo_stack(self):
        pass

    def add_undo_stack(self):
        _active_layer = self.app.layer_ribbon.get_active_layer()
        _active_layer.backup_texture()
        self.layer_undo_stack = self.layer_undo_stack[:self.undo_layer_index + 1]
        self.layer_undo_stack.append(_active_layer)
        self.undo_layer_index = len(self.layer_undo_stack) - 1

    def do_undo(self, *args):
        if self.layer_undo_stack:
            if self.undo_layer_index > 0:
                _layer = self.layer_undo_stack[self.undo_layer_index]
                _layer.texture_from_backup(direction=-1)
                _active_layer = self.app.layer_ribbon.get_active_layer()
                if _layer is _active_layer:
                    self.fbo_create(_active_layer.texture.size, _active_layer.texture)
                self.undo_layer_index -= 1
                self.canvas_put_drawarea()
            self.fbo_update_pos()

    def active_layer_backup_texture(self):
        active_layer = self.app.layer_ribbon.get_active_layer()
        self.active_layer_last_texture = improc.texture_copy(active_layer.texture)

    def active_layer_set_last_backup_texture(self):
        active_layer = self.app.layer_ribbon.get_active_layer()
        # texture = active_layer.textures_array[-1]
        active_layer.replace_texture(self.active_layer_last_texture)

        self.fbo_create(active_layer.texture.size, active_layer.texture)

        self.canvas_put_drawarea()
        self.fbo_update_pos()
        self.canvas.ask_update()

    def do_redo(self, *args):
        if self.layer_undo_stack:
            if self.undo_layer_index < len(self.layer_undo_stack) - 1:
                self.undo_layer_index += 1
                _layer = self.layer_undo_stack[self.undo_layer_index]
                _layer.texture_from_backup(direction=1)
                _active_layer = self.app.layer_ribbon.get_active_layer()
                if _layer is _active_layer:
                    self.fbo_create(_active_layer.texture.size, _active_layer.texture)
                self.canvas_put_drawarea()
            self.fbo_update_pos()
Esempio n. 40
0
    def __init__(self, **kwargs):
        self.model = 0
        self.shader = 0
        self.canvas = Canvas()
        #self.scene = ObjFileLoader(resource_find("testnurbs.obj"))

        Logger.debug('******************************************************')
        scale = 3
        #dir = "Duke Nukem Forever_Dr_Valencia" # error index out of range
        #dir = "Duke Nukem Forever_Kitty Pussoix"
        dir = "Duke_Nukem_by_Ventrue"
        #dir = "DOA5U_Rachel_Nurse/Model" #pb uv

        if not os.path.isdir(meshdir):
            self.scene = MeshAsciiLoader(
                resource_find(dir + "/Generic_Item.mesh.ascii"), scale)
        else:
            self.scene = MeshAsciiLoader(
                resource_find(meshdir + dir + "/Generic_Item.mesh.ascii"),
                scale)

        #scale = .03
        #self.texturename = 'Batman_Rabbit_Head_Posed/Batman_V3_Body_D.PNG'
        #self.scene = PSKFileLoader(resource_find("Batman_Rabbit_Head_Posed/Batman_Rabbit_Head_Posed.psk"), scale)
        #self.texturename = 'Gray/Gray_C1.tga'
        #self.scene = PSKFileLoader(resource_find("Gray/Mike_TPP.psk"), scale) #too many indices, good for split test
        #self.texturename = 'CV_Talia/Talia_Body_D.tga'
        #self.texturename = 'CV_Talia/Talia_Legs_D.tga')
        #self.scene = PSKFileLoader(resource_find("CV_Talia/Talia_posed.psk"), scale) #too many indices, good for split test
        Logger.debug('******************************************************')

        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0, 0, 0, 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        #self.fbo.shader.source = resource_find('simple.glsl')
        self.fbo.shader.source = resource_find('normalmap.glsl')

        super(Renderer, self).__init__(**kwargs)

        self.fbo['texture1'] = 1
        self.fbo['toggletexture'] = 1

        with self.fbo:
            #ClearBuffers(clear_depth=True)

            self.cb = Callback(self.setup_gl_context)

            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        Clock.schedule_interval(self.update_scene, 1 / 60.)

        self._touches = []

        self.button = Button(text='load')
        self.button.bind(on_release=self.load)
        super(Renderer, self).add_widget(self.button)

        button1 = Button(text='shader', center_x=150)
        button1.bind(on_release=self.change_shader)
        super(Renderer, self).add_widget(button1)
Esempio n. 41
0
class ObjectRenderer(Widget):
    scene = StringProperty('')
    obj_id = StringProperty('')
    obj_translation = ListProperty([0, 0, 0])
    obj_rotation = ListProperty([0, 0, 0])
    obj_scale = NumericProperty(1)
    obj_texture = StringProperty('')
    texture = ObjectProperty(None, allownone=True)
    cam_translation = ListProperty([0, 0, 0])
    cam_rotation = ListProperty([0, 0, 0])
    display_all = BooleanProperty(False)
    light_sources = DictProperty()
    ambiant = NumericProperty(.5)
    diffuse = NumericProperty(.5)
    specular = NumericProperty(.5)
    mode = StringProperty('triangles')

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas:
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True,
                           compute_normal_mat=True,
                           clear_color=(0., 0., 0., 0.))

            self.viewport = Rectangle(size=self.size, pos=self.pos)

        self.fbo.shader.source = resource_find(
            join(dirname(__file__), 'simple.glsl'))
        super(ObjectRenderer, self).__init__(**kwargs)

    def on_obj_rotation(self, *args):
        self.obj_rot_x.angle = self.obj_rotation[0]
        self.obj_rot_y.angle = self.obj_rotation[1]
        self.obj_rot_z.angle = self.obj_rotation[2]

    def on_cam_rotation(self, *args):
        self.cam_rot_x.angle = self.cam_rotation[0]
        self.cam_rot_y.angle = self.cam_rotation[1]
        self.cam_rot_z.angle = self.cam_rotation[2]

    def on_obj_translation(self, *args):
        self.obj_translate.xyz = self.cam_translation

    def on_cam_translation(self, *args):
        self.cam_translate.xyz = self.cam_translation

    def on_obj_scale(self, *args):
        self.scale.xyz = [
            self.obj_scale,
        ] * 3

    def on_display_all(self, *args):
        self.setup_canvas()

    def on_light_sources(self, *args):
        self.fbo['light_sources'] = [
            ls[:] for ls in self.light_sources.values()
        ]
        self.fbo['nb_lights'] = len(self.light_sources)

    def on_ambiant(self, *args):
        self.fbo['ambiant'] = self.ambiant

    def on_diffuse(self, *args):
        self.fbo['diffuse'] = self.diffuse

    def on_specular(self, *args):
        self.fbo['specular'] = self.specular

    def on_mode(self, *args):
        self.setup_canvas()

    def setup_canvas(self, *args):
        if not (self.scene and self.obj_id or self.display_all):
            return

        print 'setting up the scene'
        with self.fbo:
            self.fbo['ambiant'] = self.ambiant
            self.fbo['diffuse'] = self.diffuse
            self.fbo['specular'] = self.specular
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

    def on_scene(self, instance, value):
        print "loading scene %s" % value
        self._scene = ObjFileLoader(resource_find(value))
        self.setup_canvas()

    def on_obj_id(self, *args):
        self.setup_canvas()

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value

    def setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def update_glsl(self, *args):
        asp = self.width / max(float(self.height), 1)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        self.cam_translate = Translate(self.cam_translation)
        # Rotate(0, 1, 0, 0)
        self.cam_rot_x = Rotate(self.cam_rotation[0], 1, 0, 0)
        self.cam_rot_y = Rotate(self.cam_rotation[1], 0, 1, 0)
        self.cam_rot_z = Rotate(self.cam_rotation[2], 0, 0, 1)
        self.scale = Scale(self.obj_scale)
        UpdateNormalMatrix()
        if self.display_all:
            for i in self._scene.objects:
                self.draw_object(i)
        else:
            self.draw_object(self.obj_id)
        PopMatrix()

    def draw_object(self, obj_id):
        m = self._scene.objects[obj_id]
        self.obj_rot_z = Rotate(self.obj_rotation[2], 0, 0, 1)
        self.obj_rot_y = Rotate(self.obj_rotation[1], 0, 1, 0)
        self.obj_rot_x = Rotate(self.obj_rotation[0], 1, 0, 0)
        self.obj_translate = Translate(xyz=self.obj_translation)

        if len(m.indices) > 2**16:
            print '%s too big! %s indices' % (obj_id, len(m.indices))

        if m.texture:
            print "loading texture %s " % m.texture
            img = Image(
                source=resource_find(join(dirname(self.scene), m.texture)))
            texture = img.texture
            if texture:
                texture.wrap = 'repeat'
        else:
            texture = None

        vertex_lenght = sum(x[1] for x in m.vertex_format)
        if len(m.vertices) % vertex_lenght:
            print(('warning: vertices lenght (%s)'
                   'is not a multiple of vertex_format lenght(%s)') %
                  (len(m.vertices), vertex_lenght))
        Mesh(vertices=m.vertices,
             indices=m.indices,
             fmt=m.vertex_format,
             texture=texture,
             mode=self.mode)
Esempio n. 42
0
class Renderer(Widget):

    texture = ObjectProperty(None, allownone=True)

    def __init__(self, **kwargs):

        # self.canvas = RenderContext(compute_normal_mat=True)
        # self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))

        self.meshes = []

        with self.canvas:
            self.fbo = Fbo(
                size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0.0, 0.0, 0.0, 0.0)
            )
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find("simple.glsl")
        # self.texture = self.fbo.texture

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            # ClearBuffers(clear_depth=True)

            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        Clock.schedule_interval(self.update_scene, 1 / 60.0)

        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value

    def setup_gl_context(self, *args):
        # clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        # glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo["projection_mat"] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -4.75)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0)  # here just rotate scene for best view
        self.scale = Scale(1)

        UpdateNormalMatrix()

        self.draw_elements()

        PopMatrix()

    def draw_elements(self):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """

        def _draw_element(m, texture=""):
            mesh = Mesh(vertices=m.vertices, indices=m.indices, fmt=m.vertex_format, mode="triangles")
            if texture:
                texture = Image(texture).texture
                mesh.texture = texture

        def _set_color(*color, **kw):
            id_color = kw.pop("id_color", (0, 0, 0))
            return ChangeState(
                Kd=color,
                Ka=color,
                Ks=(0.3, 0.3, 0.3),
                Tr=1.0,
                Ns=1.0,
                intensity=1.0,
                id_color=[i / 255.0 for i in id_color],
            )

        # Draw sphere in the center
        sphere = self.scene.objects["Sphere"]
        _set_color(0.7, 0.7, 0.0, id_color=(255, 255, 0))
        _draw_element(sphere, "rock.png")

        # Then draw other elements and totate it in different axis
        pyramid = self.scene.objects["Pyramid"]
        PushMatrix()
        self.pyramid_rot = Rotate(0, 0, 0, 1)
        _set_color(0.0, 0.0, 0.7, id_color=(0.0, 0.0, 255))
        _draw_element(pyramid, "rain.png")
        PopMatrix()

        box = self.scene.objects["Box"]
        PushMatrix()
        self.box_rot = Rotate(0, 0, 1, 0)
        _set_color(0.7, 0.0, 0.0, id_color=(255, 0.0, 0))
        _draw_element(box, "bricks.png")
        PopMatrix()

        cylinder = self.scene.objects["Cylinder"]
        PushMatrix()
        self.cylinder_rot = Rotate(0, 1, 0, 0)
        _set_color(0.0, 0.7, 0.0, id_color=(0.0, 255, 0))
        _draw_element(cylinder, "wood.png")
        PopMatrix()

    def update_scene(self, *largs):
        self.pyramid_rot.angle += 0.5
        self.box_rot.angle += 0.5
        self.cylinder_rot.angle += 0.5

    # =============== All stuff after is for trackball implementation =============

    def define_rotate_angle(self, touch):
        x_angle = (touch.dx / self.width) * 360
        y_angle = -1 * (touch.dy / self.height) * 360
        return x_angle, y_angle

    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)

    def on_touch_up(self, touch):
        touch.ungrab(self)
        self._touches.remove(touch)

    def on_touch_move(self, touch):
        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation
                ax, ay = self.define_rotate_angle(touch)

                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2:  # scaling here
                # use two touches to determine do we need scal
                touch1, touch2 = self._touches
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)

                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]

                old_distance = old_dx * old_dx + old_dy * old_dy
                Logger.debug("Old distance: %s" % old_distance)

                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y

                new_distance = new_dx * new_dx + new_dy * new_dy

                Logger.debug("New distance: %s" % new_distance)
                SCALE_FACTOR = 0.01

                if new_distance > old_distance:
                    scale = SCALE_FACTOR
                    Logger.debug("Scale up")
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1 * SCALE_FACTOR
                    Logger.debug("Scale down")

                xyz = self.scale.xyz

                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 43
0
class Picture(Scatter):

    img_texture = ObjectProperty()
    alpha = NumericProperty()
    onLoadCallback = None
    filename = None

    vertices = ListProperty([])

    fbo_texture = ObjectProperty(None)
    fbo = None

    border_image = None
    keep_aspect = True

    aspectRatio = 1.0

    # --
    def __init__(self,
                 filename=None,
                 onload=None,
                 maxtexsize=(1024, 1024),
                 **kwargs):

        if maxtexsize == None:
            maxtexsize = (1024, 1024)

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=maxtexsize)
            self.fbo.add_reload_observer(self.updateFbo)

        self.border_image = CoreImage('data/shadow32.png')
        self.img_texture = Texture.create(size=(16, 16), colorfmt="rgba")

        self.alpha = 0
        self.fbo_texture = self.fbo.texture

        super(Picture, self).__init__(**kwargs)

        self.loadImage(filename, onload)

    # --
    def updateFbo(self):

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            Color(1, 1, 1, 1)
            BorderImage(texture=self.border_image.texture,
                        border=(36, 36, 36, 36),
                        size=(self.fbo.size[0], self.fbo.size[1]),
                        pos=(0, 0))
            Rectangle(texture=self.img_texture,
                      size=(self.fbo.size[0] - 72, self.fbo.size[1] - 72),
                      pos=(36, 36))

        self.fbo_texture = self.fbo.texture

        pass

    # --
    def on_size(self, instance, value):

        # change the underlying size property
        newAspectRatio = float(value[1]) / float(value[0])

        if self.keep_aspect:
            value[1] = value[0] * self.aspectRatio
            newAspectRatio = self.aspectRatio

        self.size = value

        # setup simple quad mesh to be rendered
        # the quad is used for actual resizing
        self.vertices = []
        self.vertices.extend([0, 0, 0, 0])
        self.vertices.extend([0, self.height, 0, 1])
        self.vertices.extend([self.width, self.height, 1, 1])
        self.vertices.extend([self.width, 0, 1, 0])

        # if the aspect ratio of the underlying FBO is not the same as the aspect
        # ratio of the new size, then change the size of the FBO
        fboAspectRatio = float(self.fbo.size[1]) / float(self.fbo.size[0])

        if abs(fboAspectRatio - newAspectRatio) > 0.1:
            fboSize = (self.fbo.size[0], self.fbo.size[1] * newAspectRatio)
            self.fbo.size = fboSize
            self.updateFbo()

        pass

    # --
    def loadImage(self, filename, onload=None):
        self.filename = filename
        if filename != None:
            self.onLoadCallback = onload

            proxyImage = Loader.image(filename)

            # this is totally stupid behaviour of Kivy
            # the docs suggest to bind proxy image's on_load method to a callback
            # to indicate when image is loaded. However, when image is already
            # in the cache the callback won't be called. My first thought was
            # that it was a threading issue, because the bindind might have happened
            # after the callback was initiated, but it seems that indeed the method is just not called.
            if proxyImage.loaded == False:
                proxyImage.bind(on_load=self._image_loaded)
            else:
                self._image_loaded(proxyImage)

    # --
    # All used memory except of the FBO texture is released. The image
    # can still be used, however, properties could not be changed
    def releaseMemory(self):

        self.img_texture = False
        self.border_image = False
        self.fbo_texture = Texture.create(size=(2, 2), colorfmt="rgba")

        # clear up cache
        Cache.remove('kv.image')
        Cache.remove('kv.texture')
        Cache.remove('kv.loader')

        pass

    # --
    def _image_loaded(self, proxyImage):

        if proxyImage.image.texture:
            self.img_texture = proxyImage.image.texture
            self.aspectRatio = float(proxyImage.image.height) / float(
                proxyImage.image.width)
            self.updateFbo()

            anim = Animation(alpha=1, duration=0.2)
            anim.start(self)

            if self.onLoadCallback != None:
                self.onLoadCallback(self)
Esempio n. 44
0
class Picture(Scatter):

    img_texture = ObjectProperty()
    alpha = NumericProperty()
    onLoadCallback = None
    filename = None

    vertices = ListProperty([])

    fbo_texture = ObjectProperty(None)
    fbo = None

    border_image = None
    keep_aspect = True

    aspectRatio = 1.0

    # --
    def __init__(self, filename=None, onload=None, maxtexsize=(1024, 1024), **kwargs):

        if maxtexsize == None:
            maxtexsize = (1024, 1024)

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=maxtexsize)
            self.fbo.add_reload_observer(self.updateFbo)

        self.border_image = CoreImage("data/shadow32.png")
        self.img_texture = Texture.create(size=(16, 16), colorfmt="rgba")

        self.alpha = 0
        self.fbo_texture = self.fbo.texture

        super(Picture, self).__init__(**kwargs)

        self.loadImage(filename, onload)

    # --
    def updateFbo(self):

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            Color(1, 1, 1, 1)
            BorderImage(
                texture=self.border_image.texture,
                border=(36, 36, 36, 36),
                size=(self.fbo.size[0], self.fbo.size[1]),
                pos=(0, 0),
            )
            Rectangle(texture=self.img_texture, size=(self.fbo.size[0] - 72, self.fbo.size[1] - 72), pos=(36, 36))

        self.fbo_texture = self.fbo.texture

        pass

    # --
    def on_size(self, instance, value):

        # change the underlying size property
        newAspectRatio = float(value[1]) / float(value[0])

        if self.keep_aspect:
            value[1] = value[0] * self.aspectRatio
            newAspectRatio = self.aspectRatio

        self.size = value

        # setup simple quad mesh to be rendered
        # the quad is used for actual resizing
        self.vertices = []
        self.vertices.extend([0, 0, 0, 0])
        self.vertices.extend([0, self.height, 0, 1])
        self.vertices.extend([self.width, self.height, 1, 1])
        self.vertices.extend([self.width, 0, 1, 0])

        # if the aspect ratio of the underlying FBO is not the same as the aspect
        # ratio of the new size, then change the size of the FBO
        fboAspectRatio = float(self.fbo.size[1]) / float(self.fbo.size[0])

        if abs(fboAspectRatio - newAspectRatio) > 0.1:
            fboSize = (self.fbo.size[0], self.fbo.size[1] * newAspectRatio)
            self.fbo.size = fboSize
            self.updateFbo()

        pass

    # --
    def loadImage(self, filename, onload=None):
        self.filename = filename
        if filename != None:
            self.onLoadCallback = onload

            proxyImage = Loader.image(filename)

            # this is totally stupid behaviour of Kivy
            # the docs suggest to bind proxy image's on_load method to a callback
            # to indicate when image is loaded. However, when image is already
            # in the cache the callback won't be called. My first thought was
            # that it was a threading issue, because the bindind might have happened
            # after the callback was initiated, but it seems that indeed the method is just not called.
            if proxyImage.loaded == False:
                proxyImage.bind(on_load=self._image_loaded)
            else:
                self._image_loaded(proxyImage)

    # --
    # All used memory except of the FBO texture is released. The image
    # can still be used, however, properties could not be changed
    def releaseMemory(self):

        self.img_texture = False
        self.border_image = False
        self.fbo_texture = Texture.create(size=(2, 2), colorfmt="rgba")

        # clear up cache
        Cache.remove("kv.image")
        Cache.remove("kv.texture")
        Cache.remove("kv.loader")

        pass

    # --
    def _image_loaded(self, proxyImage):

        if proxyImage.image.texture:
            self.img_texture = proxyImage.image.texture
            self.aspectRatio = float(proxyImage.image.height) / float(proxyImage.image.width)
            self.updateFbo()

            anim = Animation(alpha=1, duration=0.2)
            anim.start(self)

            if self.onLoadCallback != None:
                self.onLoadCallback(self)
Esempio n. 45
0
    def _show_image(config,
                    img,
                    scale=None,
                    translation=None,
                    rotation=None,
                    transform_matrix=None):
        from kivy.graphics.texture import Texture
        from kivy.graphics.fbo import Fbo
        from kivy.graphics import (Mesh, StencilPush, StencilUse, StencilUnUse,
                                   StencilPop, Rectangle, Color)
        from kivy.graphics.context_instructions import (PushMatrix, PopMatrix,
                                                        Rotate, Translate,
                                                        Scale,
                                                        MatrixInstruction,
                                                        BindTexture)
        from kivy.graphics.transformation import Matrix
        img_fmt = img.get_pixel_format()
        img_w, img_h = img.get_size()
        size = config['orig_size']
        pos = config['pos']
        canvas = config['canvas']

        if img_fmt not in ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24',
                           'bgra'):
            ofmt = get_best_pix_fmt(
                img_fmt, ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'))
            swscale = SWScale(iw=img_w,
                              ih=img_h,
                              ifmt=img_fmt,
                              ow=0,
                              oh=0,
                              ofmt=ofmt)
            img = swscale.scale(img)
            img_fmt = img.get_pixel_format()

        kivy_ofmt = {
            'yuv420p': 'yuv420p',
            'rgba': 'rgba',
            'rgb24': 'rgb',
            'gray': 'luminance',
            'bgr24': 'bgr',
            'bgra': 'bgra'
        }[img_fmt]

        if kivy_ofmt == 'yuv420p':
            w2 = int(img_w / 2)
            h2 = int(img_h / 2)
            tex_y = Texture.create(size=(img_w, img_h), colorfmt='luminance')
            tex_u = Texture.create(size=(w2, h2), colorfmt='luminance')
            tex_v = Texture.create(size=(w2, h2), colorfmt='luminance')

            with canvas:
                fbo = Fbo(size=(img_w, img_h))
            with fbo:
                BindTexture(texture=tex_u, index=1)
                BindTexture(texture=tex_v, index=2)
                Rectangle(size=fbo.size, texture=tex_y)
            fbo.shader.fs = CeedDataReader._YUV_RGB_FS
            fbo['tex_y'] = 0
            fbo['tex_u'] = 1
            fbo['tex_v'] = 2

            tex = fbo.texture
            dy, du, dv, _ = img.to_memoryview()
            tex_y.blit_buffer(dy, colorfmt='luminance')
            tex_u.blit_buffer(du, colorfmt='luminance')
            tex_v.blit_buffer(dv, colorfmt='luminance')
        else:
            tex = Texture.create(size=(img_w, img_h), colorfmt=kivy_ofmt)
            tex.blit_buffer(img.to_memoryview()[0], colorfmt=kivy_ofmt)
        tex.flip_vertical()

        with canvas:
            StencilPush()
            Rectangle(pos=pos, size=size)
            StencilUse()

            PushMatrix()
            center = pos[0] + size[0] / 2, pos[1] + size[1] / 2
            if rotation:
                Rotate(angle=rotation, axis=(0, 0, 1), origin=center)
            if scale:
                Scale(scale, scale, 1, origin=center)
            if translation:
                Translate(*translation)
            if transform_matrix is not None:
                mat = Matrix()
                mat.set(array=transform_matrix)
                m = MatrixInstruction()
                m.matrix = mat
            Rectangle(size=(img_w, img_h), texture=tex, pos=pos)
            PopMatrix()

            StencilUnUse()
            Rectangle(pos=pos, size=size)
            StencilPop()
Esempio n. 46
0
def widgetshot(widget, filename='output.png'):
    # detach the widget from the parent
    parent = widget.parent
    if parent:
        parent.remove_widget(widget)

    # put the widget canvas on a Fbo
    texture = Texture.create(size=widget.size, colorfmt='rgb')
    fbo = Fbo(size=widget.size, texture=texture)
    fbo.add(widget.canvas)

    # clear the fbo background
    fbo.bind()
    fbo.clear_buffer()
    fbo.release()

    # draw!
    fbo.draw()

    # get the fbo data
    fbo.bind()
    data = glReadPixels(0, 0, widget.size[0], widget.size[1], GL_RGBA,
                        GL_UNSIGNED_BYTE)
    fbo.release()

    # save to a file
    surf = pygame.image.fromstring(data, widget.size, 'RGBA', True)
    pygame.image.save(surf, filename)

    # reattach to the parent
    if parent:
        parent.add_widget(widget)

    return True
Esempio n. 47
0
    def generate_movie(self,
                       filename,
                       out_fmt='yuv420p',
                       codec='libx264',
                       lib_opts={'crf': '0'},
                       video_fmt='mp4',
                       start=None,
                       end=None,
                       canvas_size=(0, 0),
                       canvas_size_hint=(1, 1),
                       projector_pos=(0, 0),
                       projector_pos_hint=(None, None),
                       paint_funcs=(),
                       stimulation_transparency=1.,
                       lum=1.,
                       speed=1.,
                       hidden_shapes=None):
        from kivy.graphics import (Canvas, Translate, Fbo, ClearColor,
                                   ClearBuffers, Scale)
        from kivy.core.window import Window

        rate = float(self.view_controller.frame_rate)
        rate_int = int(rate)
        if rate != rate_int:
            raise ValueError('Frame rate should be integer')
        orig_w, orig_h = (self.view_controller.screen_width,
                          self.view_controller.screen_height)

        canvas_w, canvas_h = canvas_size
        cv_hint_w, cv_hint_h = canvas_size_hint
        w = int(canvas_w if cv_hint_w is None else orig_w * cv_hint_w)
        h = int(canvas_h if cv_hint_h is None else orig_h * cv_hint_h)

        projector_x, projector_y = projector_pos
        projector_hint_x, projector_hint_y = projector_pos_hint
        x = int(projector_x if projector_hint_x is None else orig_w *
                projector_hint_x)
        y = int(projector_y if projector_hint_y is None else orig_h *
                projector_hint_y)

        Window.size = w, h
        intensities = self.shapes_intensity

        n = len(intensities[next(iter(intensities.keys()))])
        if start is not None:
            start = int(start * rate)
            if start >= n:
                raise Exception('Start time is after the end of the data')
        else:
            start = 0

        if end is not None:
            end = int(math.ceil(end * rate)) + 1
            if end <= start:
                raise Exception('End time is before or at the start time')
        else:
            end = n

        stream = {
            'pix_fmt_in': 'rgba',
            'pix_fmt_out': out_fmt,
            'width_in': w,
            'height_in': h,
            'width_out': w,
            'height_out': h,
            'codec': codec,
            'frame_rate': (int(speed * rate_int), 1)
        }
        writer = MediaWriter(filename, [stream],
                             fmt=video_fmt,
                             lib_opts=lib_opts)

        fbo = Fbo(size=(w, h), with_stencilbuffer=True)
        with fbo:
            ClearColor(0, 0, 0, 1)
            ClearBuffers()
            Scale(1, -1, 1)
            Translate(0, -h, 0)

        config = {
            'canvas': fbo,
            'pos': (x, y),
            'size': (w, h),
            'orig_size': (orig_w, orig_h),
            'rate': rate
        }
        paint_funcs = [func(config) for func in paint_funcs]
        paint_funcs = [func for func in paint_funcs if func is not None]

        fbo.draw()
        img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h))
        writer.write_frame(img, 0.)

        fbo.add(Translate(x, y))
        shape_views = self.stage_factory.get_shapes_gl_color_instructions(
            fbo, 'stage_replay')
        fbo.add(Translate(-x, -y))

        pbar = tqdm(total=(end - 1 - start) / rate,
                    file=sys.stdout,
                    unit='second',
                    unit_scale=1)

        # all shapes listed in intensities must be in shape_views. However,
        # we don't want to show shapes not given values in intensities or if
        # they are to be hidden
        unused_shapes = set(shape_views) - set(intensities)
        unused_shapes.update(set(hidden_shapes or []))
        for name in unused_shapes:
            if name in shape_views:
                shape_views[name].rgba = 0, 0, 0, 0

        for i in range(start, end):
            pbar.update(1 / rate)
            for name, intensity in intensities.items():
                r, g, b, a = intensity[i]
                if name in unused_shapes:
                    a = 0
                shape_views[name].rgba = \
                    r * lum, g * lum, b * lum, a * stimulation_transparency

            try:
                for func in paint_funcs:
                    func(i)
            except EndOfDataException:
                break

            fbo.draw()
            img = Image(plane_buffers=[fbo.pixels],
                        pix_fmt='rgba',
                        size=(w, h))
            writer.write_frame(img, (i - start + 1) / (rate * speed))
        pbar.close()
Esempio n. 48
0
class FboFloatLayout(Widget):

    texture = ObjectProperty(None, allownone=True)
    vertices = ListProperty([])

    fbo = None
    tmp_fbo = None

    def __init__(self, **kwargs):

        self.canvas = Canvas()

        with self.canvas:
            self.fbo = Fbo(size=self.size)

        super(FboFloatLayout, self).__init__(**kwargs)

    # --
    # preload FBO with background texture
    def initFbo(self):

        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            #Rectangle(source = 'data/background.jpg', size=self.size, pos=self.pos)

        self.texture = self.fbo.texture

    # --
    # add the content of the widget to the FBO
    # this will literally render the widget into the texture
    def render_widget(self, widget):

        # create an FBO to render the widget to
        self.tmp_fbo = Fbo(size=self.size)
        self.tmp_fbo.add(ClearColor(0, 0, 0, 0))
        self.tmp_fbo.add(ClearBuffers())
        self.tmp_fbo.add(widget.canvas)
        self.tmp_fbo.draw()

        # render a rectangle in the main fbo containing the content from the widget
        with self.fbo:
            Color(1, 1, 1, 1)
            Rectangle(texture=self.tmp_fbo.texture, size=self.tmp_fbo.size)

    #def add_widget(self, *largs):
    # trick to attach graphics instruction to fbo instead of canvas
    #	canvas = self.canvas
    #	self.canvas = self.fbo
    #	ret = super(FboFloatLayout, self).add_widget(*largs)
    #	self.canvas = canvas

    # remove widget after next frame, this makes sure that
    # we do not use the widget for more than one frame
    #Clock.schedule_once(lambda dt: self.remove_widget(*largs))

    #	return ret

    #def remove_widget(self, *largs):
    #	canvas = self.canvas
    #	self.canvas = self.fbo
    #	super(FboFloatLayout, self).remove_widget(*largs)
    #	self.canvas = canvas

    def on_size(self, instance, value):
        self.size = value

        self.fbo.size = value

        #self.fbo_rect.size = value
        #self.fbo_background.size = value
        #self.fbo_rect.texture = self.fbo.texture

        # setup simple quad mesh to be rendered
        # the quad is used for actual resizing
        self.vertices = []
        self.vertices.extend([0, 0, 0, 0])
        self.vertices.extend([0, self.height, 0, 1])
        self.vertices.extend([self.width, self.height, 1, 1])
        self.vertices.extend([self.width, 0, 1, 0])

        #self.updateFbo()
        self.initFbo()
Esempio n. 49
0
class FboFloatLayout(FloatLayout):

    texture = ObjectProperty(None, allownone=True)

    alpha_blending = BooleanProperty(False)

    def __init__(self, **kwargs):
        self.canvas = Canvas()
        with self.canvas.before:
            Callback(self._set_blend_func)

        self.fbo_texture = Texture.create(size=self.size,
                                                  colorfmt='rgba',)
        self.fbo_texture.mag_filter='nearest'

        with self.canvas:
            #self.cbs = Callback(self.prepare_canvas)
            self.fbo = Fbo(size=self.size, texture=self.fbo_texture)
            #Color(1, 1, 1, 0)
            #self.fbo_rect = Rectangle()


        with self.fbo:
            ClearColor(0.0, 0.0, 0.0, 0.0)
            ClearBuffers()
            self.fbo_rect = Rectangle(size=self.size)


        #self.fbo.shader.source = resource_find('./kivy3dgui/gles2.0/shaders/invert.glsl')
        #with self.fbo.after:
        #    self.cbr = Callback(self.reset_gl_context)
        #    PopMatrix()

        with self.canvas.before:
            Callback(self._set_blend_func)

        # wait that all the instructions are in the canvas to set texture

        self.texture = self.fbo.texture
        super(FboFloatLayout, self).__init__(**kwargs)

    def prepare_canvas(self, *args):
        glEnable(GL_BLEND)
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)
        glEnable(GL_DEPTH_TEST)

    def _set_blend_func(self, instruction):
        # clobber the blend mode
        if self.alpha_blending:
            glBlendFunc(GL_ONE,
                        GL_ZERO)
        else:

        #glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA)
            #glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)
            #glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
            glBlendFunc(GL_SRC_ALPHA,
                    GL_ONE_MINUS_SRC_ALPHA)


        # draw the buffer, not the whole freakin canvas
        glDisable(GL_CULL_FACE)
        self.fbo.draw()
        # unclobber the buffer
        glBlendFunc(GL_SRC_ALPHA,
                    GL_ONE_MINUS_SRC_ALPHA)

    def setup_gl_context(self, *args):
        glEnable(GL_BLEND)
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_DEPTH_TEST)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)


    def add_widget(self, *largs):
        # trick to attach kivy3dgui instructino to fbo instead of canvas
        canvas = self.canvas
        self.canvas = self.fbo
        ret = super(FboFloatLayout, self).add_widget(*largs)
        self.canvas = canvas
        return ret

    def remove_widget(self, *largs):
        canvas = self.canvas
        self.canvas = self.fbo
        super(FboFloatLayout, self).remove_widget(*largs)
        self.canvas = canvas

    def on_size(self, instance, value):
        self.fbo.size = value
        self.texture = self.fbo_texture
        self.fbo_rect.size = value

    def on_pos(self, instance, value):
        self.fbo_rect.pos = value

    def on_texture(self, instance, value):
        self.fbo_rect.texture = value

    def on_touch_down(self, touch):
        return super(FboFloatLayout, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        return super(FboFloatLayout, self).on_touch_move(touch)

    def on_touch_up(self, touch):
        return super(FboFloatLayout, self).on_touch_up(touch)
Esempio n. 50
0
class FboFloatLayout(Widget):

	texture = ObjectProperty(None, allownone=True)
	vertices = ListProperty([])
	
	fbo = None
	tmp_fbo = None 
	
	def __init__(self, **kwargs):
		
		self.canvas = Canvas()
		
		with self.canvas:
			self.fbo = Fbo(size=self.size)
			
		super(FboFloatLayout, self).__init__(**kwargs)

	# --
	# preload FBO with background texture
	def initFbo(self):
		
		with self.fbo:
			ClearColor(0,0,0,0)
			ClearBuffers()
			#Rectangle(source = 'data/background.jpg', size=self.size, pos=self.pos)

		self.texture = self.fbo.texture
				
	# --
	# add the content of the widget to the FBO
	# this will literally render the widget into the texture
	def render_widget(self, widget):

		# create an FBO to render the widget to
		self.tmp_fbo = Fbo(size = self.size)
		self.tmp_fbo.add(ClearColor(0,0,0,0))
		self.tmp_fbo.add(ClearBuffers())
		self.tmp_fbo.add(widget.canvas)
		self.tmp_fbo.draw()

		# render a rectangle in the main fbo containing the content from the widget
		with self.fbo:
			Color(1,1,1,1)
			Rectangle(texture=self.tmp_fbo.texture, size=self.tmp_fbo.size)
					
	#def add_widget(self, *largs):
		# trick to attach graphics instruction to fbo instead of canvas
	#	canvas = self.canvas
	#	self.canvas = self.fbo
	#	ret = super(FboFloatLayout, self).add_widget(*largs)
	#	self.canvas = canvas
		
		# remove widget after next frame, this makes sure that 
		# we do not use the widget for more than one frame
		#Clock.schedule_once(lambda dt: self.remove_widget(*largs))

	#	return ret

	#def remove_widget(self, *largs):
	#	canvas = self.canvas
	#	self.canvas = self.fbo
	#	super(FboFloatLayout, self).remove_widget(*largs)
	#	self.canvas = canvas

	def on_size(self, instance, value):
		self.size = value 
		
		self.fbo.size = value
		
		#self.fbo_rect.size = value
		#self.fbo_background.size = value
		#self.fbo_rect.texture = self.fbo.texture
		
		# setup simple quad mesh to be rendered
		# the quad is used for actual resizing
		self.vertices = []
		self.vertices.extend([0,0,0,0])
		self.vertices.extend([0,self.height,0,1])
		self.vertices.extend([self.width,self.height,1,1])
		self.vertices.extend([self.width,0,1,0])

		#self.updateFbo()		
		self.initFbo()
Esempio n. 51
0
class Renderer(Widget):
    
    texture = ObjectProperty(None, allownone=True)    
    
    def __init__(self, **kwargs):

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        
        self.meshes = []
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        

        super(Renderer, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value


    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0) # here just rotate scene for best view
        self.scale = Scale(1)
                
        UpdateNormalMatrix()
        
        self.draw_elements()
        
        PopMatrix()

    def draw_elements(self):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """
        def _draw_element(m):
            Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
            )
            
        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                        Kd=color,
                        Ka=color,
                        Ks=(.3, .3, .3),
                        Tr=1., Ns=1.,
                        intensity=1.,
                        id_color=[i / 255. for i in id_color],
                    )
            
        # Draw sphere in the center
        sphere = self.scene.objects['Sphere']
        _set_color(0.7, 0.7, 0., id_color=(255, 255, 0))
        _draw_element(sphere)
        
        # Then draw other elements and totate it in different axis
        pyramid = self.scene.objects['Pyramid']
        PushMatrix()
        self.pyramid_rot = Rotate(0, 0, 0, 1)
        _set_color(0., 0., .7, id_color=(0., 0., 255))
        _draw_element(pyramid)
        PopMatrix()
        
        box = self.scene.objects['Box']
        PushMatrix()
        self.box_rot = Rotate(0, 0, 1, 0)
        _set_color(.7, 0., 0., id_color=(255, 0., 0))
        _draw_element(box)
        PopMatrix()

        cylinder = self.scene.objects['Cylinder']
        PushMatrix()
        self.cylinder_rot = Rotate(0, 1, 0, 0)
        _set_color(0.0, .7, 0., id_color=(0., 255, 0))
        _draw_element(cylinder)
        PopMatrix()
    

    def update_scene(self, *largs):
        self.pyramid_rot.angle += 0.5
        self.box_rot.angle += 0.5
        self.cylinder_rot.angle += 0.5
        
    
    # =============== All stuff after is for trackball implementation =============
        
    def define_rotate_angle(self, touch):
        x_angle = (touch.dx/self.width)*360
        y_angle = -1*(touch.dy/self.height)*360
        return x_angle, y_angle
    
    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        
    def on_touch_up(self, touch): 
        touch.ungrab(self)
        self._touches.remove(touch)
        self.fbo.shader.source = 'select_mode.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
        print(self.fbo.get_pixel_color(touch.x, touch.y))
        self.fbo.shader.source = 'simple.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
    
    def on_touch_move(self, touch): 

        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation        
                ax, ay = self.define_rotate_angle(touch)
                
                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2: # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches 
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)
                
                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]
                
                old_distance = (old_dx*old_dx + old_dy*old_dy)
                Logger.debug('Old distance: %s' % old_distance)
                
                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y
                
                new_distance = (new_dx*new_dx + new_dy*new_dy)
                
                Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01
                
                if new_distance > old_distance: 
                    scale = SCALE_FACTOR
                    Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1*SCALE_FACTOR
                    Logger.debug('Scale down')
                    
                xyz = self.scale.xyz
                
                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 52
0
class NSpect(Widget):
    
    texture = ObjectProperty(None, allownone=True)    
    
    def __init__(self, **kwargs):

        LOP, dm = initFiles()

        #self.canvas = RenderContext(compute_normal_mat=True)
        #self.canvas.shader.source = resource_find('simple.glsl')
        self.canvas = Canvas()
        self.scene = ObjFileLoader(resource_find("testnurbs.obj"))
        self.LOP = LOP
        self.dm = dm
        
        self.meshes = []

        self.panCamera = False # KEITH EDIT
        self.pause = True # KEITH EDIT
        
        with self.canvas:
            self.fbo = Fbo(size=self.size, with_depthbuffer=True, compute_normal_mat=True, clear_color=(0., 0., 0., 0.))
            self.viewport = Rectangle(size=self.size, pos=self.pos)
        self.fbo.shader.source = resource_find('simple.glsl')
        #self.texture = self.fbo.texture
        
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        # Keith: This allows keyboard interaction
        # http://stackoverflow.com/questions/22137786/
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        # *&Y*&Y*&YH*&Y*&Y*&Y*Y&*
        
        super(NSpect, self).__init__(**kwargs)

        with self.fbo:
            #ClearBuffers(clear_depth=True)
            
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene(self.LOP, dm)
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        
        Clock.schedule_interval(self.update_scene, 1 / 60.)
        
        self._touches = []

    def on_size(self, instance, value):
        self.fbo.size = value
        self.viewport.texture = self.fbo.texture
        self.viewport.size = value
        self.update_glsl()

    def on_pos(self, instance, value):
        self.viewport.pos = value

    def on_texture(self, instance, value):
        self.viewport.texture = value


    def setup_gl_context(self, *args):
        #clear_buffer
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()
        #glDepthMask(GL_FALSE);

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        

    def update_glsl(self, *largs):
        asp = self.width / float(self.height)
        proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1)
        self.fbo['projection_mat'] = proj

    def setup_scene(self, LOP, dm):
        Color(1, 1, 1, 0)

        PushMatrix()
        Translate(0, 0, -5)
        # This Kivy native Rotation is used just for
        # enabling rotation scene like trackball
        self.rotx = Rotate(0, 1, 0, 0)
        self.roty = Rotate(-120, 0, 1, 0) # here just rotate scene for best view
        self.scale = Scale(1)
                
        UpdateNormalMatrix()
        
        self.draw_elements(LOP, dm)
        
        PopMatrix()

    def draw_elements(self, LOP, dm):
        """ Draw separately all objects on the scene
            to setup separate rotation for each object
        """
        def _draw_element(m):
            Mesh(
                vertices=m.vertices,
                indices=m.indices,
                fmt=m.vertex_format,
                mode='triangles',
            )
            
        def _set_color(*color, **kw):
            id_color = kw.pop('id_color', (0, 0, 0))
            return ChangeState(
                        Kd=color,
                        Ka=color,
                        Ks=(.3, .3, .3),
                        Tr=1., Ns=1.,
                        intensity=1.,
                        id_color=[i / 255. for i in id_color],
                    )
            
        def drawPoints():
            print self.scene.objects
            for i in range(len(self.LOP)):
                PushMatrix()
                point = self.LOP[i]
                point.shape = self.scene.objects['Sphere']
                point.color = _set_color(i/10., (i+1)/10., 0., id_color=(int(255/(1+i)), int(255/(1+i)), 255))
                point.shape.scale = Scale((i+1)/10.0,(i+1)/10.0,(i+1)/10.0)
                self.LOP[i] = point
                print point.shape
                _draw_element(point.shape)
                point.shape.scale.origin =  (point.loc[0],point.loc[1],point.loc[2])
                PopMatrix()
                
        drawPoints()

    def update_scene(self, *largs):
        def randLoc(point):
            newLoc = (0.1*random.random(),0.1*random.random(),0.1*random.random())
            oldLoc = point.shape.scale.origin
            newLoc = ( newLoc[0]-0.05+oldLoc[0], newLoc[1]-0.05+oldLoc[1], newLoc[2]-0.05+oldLoc[2] )
            return newLoc 
        def updateLocs(self):        
            for i in range(len(self.LOP)):
                point = self.LOP[i]
                point.shape.scale.origin = randLoc(point) 
           
        if not self.pause:
            updateLocs(self)        
        pass

        
    
    # =============== All stuff after is for trackball implementation =============
    def moveA(self):
        

        pass
    def moveB(self):
        pass
    def define_rotate_angle(self, touch):
        x_angle = (touch.dx/self.width)*360
        y_angle = -1*(touch.dy/self.height)*360
        return x_angle, y_angle
    
    def on_touch_down(self, touch):
        self._touch = touch
        touch.grab(self)
        self._touches.append(touch)
        
    def on_touch_up(self, touch): 
        touch.ungrab(self)
        self._touches.remove(touch)
        self.fbo.shader.source = 'select_mode.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
        print self.fbo.get_pixel_color(touch.x, touch.y)
        self.fbo.shader.source = 'simple.glsl'
        self.fbo.ask_update()
        self.fbo.draw()
    
    # *O(U(U())(*U(*(******************
    # Keith: This allows keyboard interaction
    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'left':
            if self.panCamera == True:
                self.x -= 10
            else: 
                self.roty.angle += 10
        elif keycode[1] == 'right':
            if self.panCamera == True:
                self.x += 10
            else: 
                self.roty.angle -= 10
        if keycode[1] == 'up':
            if self.panCamera == True:
                self.y += 10
            else: 
                self.rotx.angle += 10
        elif keycode[1] == 'down':
            if self.panCamera == True:
                self.y -= 10
            else: 
                self.rotx.angle -= 10

        elif keycode[1] == 'i':
            self.update_glsl()                             
            SCALE_FACTOR = 0.01             
            scale = SCALE_FACTOR
            Logger.debug('Scale up')                  
            xyz = self.scale.xyz                
            if scale:
                self.scale.xyz = tuple(p + scale for p in xyz)
        elif keycode[1] == 'o':
            self.update_glsl()                             
            SCALE_FACTOR = 0.01             
            scale = SCALE_FACTOR
            Logger.debug('Scale up')                  
            xyz = self.scale.xyz  
            if scale:
                temp = tuple(p - scale for p in xyz)
                # Prevent the collection from having a negative size
                if temp[0] > 0:
                    self.scale.xyz = temp
        elif keycode[1] == 't':
            self.panCamera = not self.panCamera    
        elif keycode[1] == 'p':
            self.pause = not self.pause    
            if not self.pause:
                print "Playing"
            else:
                print "Paused"
    
    
    
    def on_touch_move(self, touch): 

        self.update_glsl()
        if touch in self._touches and touch.grab_current == self:
            if len(self._touches) == 1:
                # here do just rotation        
                ax, ay = self.define_rotate_angle(touch)
                
                self.roty.angle += ax
                self.rotx.angle += ay

            elif len(self._touches) == 2: # scaling here
                #use two touches to determine do we need scal
                touch1, touch2 = self._touches 
                old_pos1 = (touch1.x - touch1.dx, touch1.y - touch1.dy)
                old_pos2 = (touch2.x - touch2.dx, touch2.y - touch2.dy)
                
                old_dx = old_pos1[0] - old_pos2[0]
                old_dy = old_pos1[1] - old_pos2[1]
                
                old_distance = (old_dx*old_dx + old_dy*old_dy)
                Logger.debug('Old distance: %s' % old_distance)
                
                new_dx = touch1.x - touch2.x
                new_dy = touch1.y - touch2.y
                
                new_distance = (new_dx*new_dx + new_dy*new_dy)
                
                Logger.debug('New distance: %s' % new_distance)
                SCALE_FACTOR = 0.01
                
                if new_distance > old_distance: 
                    scale = SCALE_FACTOR
                    Logger.debug('Scale up')
                elif new_distance == old_distance:
                    scale = 0
                else:
                    scale = -1*SCALE_FACTOR
                    Logger.debug('Scale down')
                    
                xyz = self.scale.xyz
                
                if scale:
                    self.scale.xyz = tuple(p + scale for p in xyz)
Esempio n. 53
0
class Renderer(Widget):

    def __init__(self, **kw):
        self.shader_file = kw.pop("shader_file", None)
        self.canvas = Canvas()
        super(Renderer, self).__init__(**kw)

        with self.canvas:
            self._viewport = Rectangle(size=self.size, pos=self.pos)
            self.fbo = Fbo(size=self.size,
                           with_depthbuffer=True, compute_normal_mat=True,
                           clear_color=(0., 0., 0., 0.))
        self._config_fbo()
        self.texture = self.fbo.texture
        self.camera = None
        self.scene = None

    def _config_fbo(self):
        # set shader file here
        self.fbo.shader.source = self.shader_file or \
            os.path.join(kivy3_path, "default.glsl")
        with self.fbo:
            Callback(self._setup_gl_context)
            PushMatrix()
            # instructions set for all instructions
            self._instructions = InstructionGroup()
            PopMatrix()
            Callback(self._reset_gl_context)

    def _setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)
        self.fbo.clear_buffer()

    def _reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)

    def render(self, scene, camera):
        self.scene = scene
        self.camera = camera
        self.camera.bind_to(self)
        self._instructions.add(scene.as_instructions())
        Clock.schedule_once(self._update_matrices, -1)

    def add(self, obj):
        self._instructions.add(obj.as_instructions())

    def on_size(self, instance, value):
        self.fbo.size = value
        self._viewport.texture = self.fbo.texture
        self._viewport.size = value
        self._viewport.pos = self.pos
        self._update_matrices()

    def on_pos(self, instance, value):
        self._viewport.pos = self.pos
        self._update_matrices()

    def on_texture(self, instance, value):
        self._viewport.texture = value

    def _update_matrices(self, dt=None):
        if self.camera:
            self.fbo['projection_mat'] = self.camera.projection_matrix
            self.fbo['modelview_mat'] = self.camera.modelview_matrix
        else:
            raise RendererError("Camera is not defined for renderer")

    def set_clear_color(self, color):
        self.fbo.clear_color = color
Esempio n. 54
0
class DmdBase(object):
    """Base class for DMD devices."""

    dmd_name_string = 'DMD'

    def __init__(self, mc: "MpfMc", name: str, config: dict) -> None:
        """Initialise DMD."""

        self.mc = mc
        self.name = name

        self.mc.log.info('Initializing DMD')

        self.config = self._get_validated_config(config)

        self.source = self.mc.displays[self.config['source_display']]
        self.prev_data = None

        # put the widget canvas on a Fbo
        texture = Texture.create(size=self.source.size, colorfmt='rgb')
        self.fbo = Fbo(size=self.source.size, texture=texture)

        self.effect_widget = EffectWidget()

        effect_list = list()
        effect_list.append(FlipVerticalEffect())

        if self.config['brightness'] != 1.0:
            if not 0.0 <= self.config['brightness'] <= 1.0:
                raise ValueError("DMD brightness value should be between 0.0 "
                                 "and 1.0. Yours is {}".format(
                                     self.config['brightness']))

            effect_list.append(GainEffect(gain=self.config['brightness']))

        if self.config['gamma'] != 1.0:
            effect_list.append(GammaEffect(gamma=self.config['gamma']))

        self.effect_widget.effects = effect_list
        self.effect_widget.size = self.source.size

        self.fbo.add(self.effect_widget.canvas)

        self._set_dmd_fps()

    def _get_validated_config(self, config: dict) -> dict:
        raise NotImplementedError

    def _set_dmd_fps(self) -> None:
        # fps is the rate that the connected client requested. We'll use the
        # lower of the two

        mc_fps = self.config['fps']

        if mc_fps == 0:
            # pylint: disable-msg=protected-access
            mc_fps = Clock._max_fps

        # pylint: disable-msg=protected-access
        if mc_fps > Clock._max_fps:
            self.mc.log.warning(
                "%s fps is higher than mpf-mc fps. "
                "Will use mpf-mc fps setting for the DMD.",
                DmdBase.dmd_name_string)
            # pylint: disable-msg=protected-access
            fps = Clock._max_fps
            update = 0
        # pylint: disable-msg=protected-access
        elif Clock._max_fps > mc_fps > 0:
            fps = mc_fps
            update = 1 / fps
        else:
            # pylint: disable-msg=protected-access
            fps = Clock._max_fps
            update = 0

        Clock.schedule_interval(self.tick, update)
        self.mc.log.info("Setting %s to %sfps", DmdBase.dmd_name_string, fps)

    def tick(self, dt) -> None:
        """Draw image for DMD and send it."""
        del dt
        widget = self.source
        fbo = self.fbo

        # detach the widget from the parent
        parent = widget.parent
        if parent:
            parent.remove_widget(widget)

        self.effect_widget.add_widget(widget)

        # clear the fbo background
        fbo.bind()
        fbo.clear_buffer()
        fbo.release()

        fbo.draw()

        fbo.bind()
        data = glReadPixels(0, 0, widget.native_size[0], widget.native_size[1],
                            GL_RGB, GL_UNSIGNED_BYTE)
        fbo.release()

        # reattach to the parent
        if parent:
            self.effect_widget.remove_widget(widget)
            parent.add_widget(widget)

        if not self.config['only_send_changes'] or self.prev_data != data:
            self.prev_data = data
            self.send(data)

    def send(self, data: bytes) -> None:
        """Send data to DMD via BCP."""
        raise NotImplementedError
Esempio n. 55
0
class EffectWidget(RelativeLayout):
    '''
    Widget with the ability to apply a series of graphical effects to
    its children. See the module documentation for more information on
    setting effects and creating your own.
    '''

    background_color = ListProperty((0, 0, 0, 0))
    '''This defines the background color to be used for the fbo in the
    EffectWidget.

    :attr:`background_color` is a :class:`ListProperty` defaults to
    (0, 0, 0, 0)
    '''

    texture = ObjectProperty(None)
    '''The output texture of the final :class:`~kivy.graphics.Fbo` after
    all effects have been applied.

    texture is an :class:`~kivy.properties.ObjectProperty` and defaults
    to None.
    '''

    effects = ListProperty([])
    '''List of all the effects to be applied. These should all be
    instances or subclasses of :class:`EffectBase`.

    effects is a :class:`ListProperty` and defaults to [].
    '''

    fbo_list = ListProperty([])
    '''(internal) List of all the fbos that are being used to apply
    the effects.

    fbo_list is a :class:`ListProperty` and defaults to [].
    '''

    _bound_effects = ListProperty([])
    '''(internal) List of effect classes that have been given an fbo to
    manage. This is necessary so that the fbo can be removed if the
    effect is no longer in use.

    _bound_effects is a :class:`ListProperty` and defaults to [].
    '''
    def __init__(self, **kwargs):
        # Make sure opengl context exists
        EventLoop.ensure_window()

        self.canvas = RenderContext(use_parent_projection=True,
                                    use_parent_modelview=True)
        self._callbacks = {}

        with self.canvas:
            self.fbo = Fbo(size=self.size)

        with self.fbo.before:  # noqa
            PushMatrix()
        with self.fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()
            self._background_color = Color(*self.background_color)
            self.fbo_rectangle = Rectangle(size=self.size)
        with self.fbo.after:  # noqa
            PopMatrix()

        super(EffectWidget, self).__init__(**kwargs)

        fbind = self.fbind
        fbo_setup = self.refresh_fbo_setup
        fbind('size', fbo_setup)
        fbind('effects', fbo_setup)
        fbind('background_color', self._refresh_background_color)

        self.refresh_fbo_setup()
        self._refresh_background_color()  # In case thi was changed in kwargs

    def _refresh_background_color(self, *args):  # noqa
        self._background_color.rgba = self.background_color

    def _propagate_updates(self, *largs):
        """Propagate updates from widgets."""
        del largs
        for fbo in self.fbo_list:
            fbo.ask_update()

    def refresh_fbo_setup(self, *args):  # noqa
        '''(internal) Creates and assigns one :class:`~kivy.graphics.Fbo`
        per effect, and makes sure all sizes etc. are correct and
        consistent.
        '''
        # Add/remove fbos until there is one per effect
        while len(self.fbo_list) < len(self.effects):
            with self.canvas:
                new_fbo = EffectFbo(size=self.size)
            with new_fbo:
                ClearColor(0, 0, 0, 0)
                ClearBuffers()
                Color(1, 1, 1, 1)
                new_fbo.texture_rectangle = Rectangle(size=self.size)

                new_fbo.texture_rectangle.size = self.size
            self.fbo_list.append(new_fbo)
        while len(self.fbo_list) > len(self.effects):
            old_fbo = self.fbo_list.pop()
            self.canvas.remove(old_fbo)

        # Remove fbos from unused effects
        for effect in self._bound_effects:
            if effect not in self.effects:
                effect.fbo = None
        self._bound_effects = self.effects

        # Do resizing etc.
        self.fbo.size = self.size
        self.fbo_rectangle.size = self.size
        for i in range(len(self.fbo_list)):
            self.fbo_list[i].size = self.size
            self.fbo_list[i].texture_rectangle.size = self.size

        # If there are no effects, just draw our main fbo
        if len(self.fbo_list) == 0:  # noqa
            self.texture = self.fbo.texture
            return

        for i in range(1, len(self.fbo_list)):
            fbo = self.fbo_list[i]
            fbo.texture_rectangle.texture = self.fbo_list[i - 1].texture

        # Build effect shaders
        for effect, fbo in zip(self.effects, self.fbo_list):
            effect.fbo = fbo

        self.fbo_list[0].texture_rectangle.texture = self.fbo.texture
        self.texture = self.fbo_list[-1].texture

        for fbo in self.fbo_list:
            fbo.draw()
        self.fbo.draw()

    def add_widget(self, widget):  # noqa
        # Add the widget to our Fbo instead of the normal canvas
        c = self.canvas
        self.canvas = self.fbo
        with widget.canvas:
            self._callbacks[widget.canvas] = Callback(self._propagate_updates)
        super(EffectWidget, self).add_widget(widget)
        self.canvas = c

    def remove_widget(self, widget):
        # Remove the widget from our Fbo instead of the normal canvas
        c = self.canvas
        widget.canvas.remove(self._callbacks[widget.canvas])
        del self._callbacks[widget.canvas]
        self.canvas = self.fbo
        super(EffectWidget, self).remove_widget(widget)
        self.canvas = c

    def clear_widgets(self, children=None):
        # Clear widgets from our Fbo instead of the normal canvas
        c = self.canvas
        self.canvas = self.fbo
        for canvas, callback in self._callbacks.items():
            canvas.remove(callback)
        self._callbacks = {}

        super(EffectWidget, self).clear_widgets(children)
        self.canvas = c
Esempio n. 56
0
def texture_merge(texture1, texture2):
    fbo = Fbo(size=texture2.size, texture=texture2)
    fbo.add(Rectangle(pos=(0, 0), texture=texture1, size=texture1.size))
    fbo.draw()
    return fbo.texture
Esempio n. 57
0
    def init_smaa(self):
        curdir = dirname(__file__)

        # load shaders sources
        with open(join(curdir, "SMAA.h"), "r") as fd:
            smaa_h = fd.read()

        config = """
            #version 410 compatibility
            #define SMAA_PIXEL_SIZE vec2(1.0 / {width}, 1.0 / {height})
            #define SMAA_PRESET_{quality} 1
            #define SMAA_GLSL_4 1
        """.format(
            width=self.width, height=self.height, quality=self.quality.upper()
        )

        header_vs = (
            config
            + """
            #define SMAA_ONLY_COMPILE_VS 1

            in vec2 vPosition;
            in vec2 vTexCoords0;
            uniform mat4 modelview_mat;
            uniform mat4 projection_mat;
        """
            + smaa_h
        )

        header_fs = (
            config
            + """
            #define SMAA_ONLY_COMPILE_PS 1
        """
            + smaa_h
        )

        edge_vs = (
            header_vs
            + """
            out vec2 texcoord;
            out vec4 offset[3];
            out vec4 dummy2;
            void main()
            {
                texcoord = vTexCoords0;
                vec4 dummy1 = vec4(0);
                SMAAEdgeDetectionVS(dummy1, dummy2, texcoord, offset);
                gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0);
            }
        """
        )

        edge_fs = (
            header_fs
            + """
            uniform sampler2D albedo_tex;
            in vec2 texcoord;
            in vec4 offset[3];
            in vec4 dummy2;
            void main()
            {
                #if SMAA_PREDICATION == 1
                    gl_FragColor = SMAAColorEdgeDetectionPS(texcoord, offset, albedo_tex, depthTex);
                #else
                    gl_FragColor = SMAAColorEdgeDetectionPS(texcoord, offset, albedo_tex);
                #endif
            }
        """
        )

        blend_vs = (
            header_vs
            + """
            out vec2 texcoord;
            out vec2 pixcoord;
            out vec4 offset[3];
            out vec4 dummy2;
            void main()
            {
                texcoord = vTexCoords0;
                vec4 dummy1 = vec4(0);
                SMAABlendingWeightCalculationVS(dummy1, dummy2, texcoord, pixcoord, offset);
                gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0);
            }
        """
        )

        blend_fs = (
            header_fs
            + """
            uniform sampler2D edge_tex;
            uniform sampler2D area_tex;
            uniform sampler2D search_tex;
            in vec2 texcoord;
            in vec2 pixcoord;
            in vec4 offset[3];
            in vec4 dummy2;
            void main()
            {
                gl_FragColor = SMAABlendingWeightCalculationPS(texcoord, pixcoord, offset, edge_tex, area_tex, search_tex, ivec4(0));
            }
        """
        )

        neighborhood_vs = (
            header_vs
            + """
            out vec2 texcoord;
            out vec4 offset[2];
            out vec4 dummy2;
            void main()
            {
                texcoord = vTexCoords0;
                vec4 dummy1 = vec4(0);
                SMAANeighborhoodBlendingVS(dummy1, dummy2, texcoord, offset);
                gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0);
            }
        """
        )

        neighborhood_fs = (
            header_fs
            + """
            uniform sampler2D albedo_tex;
            uniform sampler2D blend_tex;
            in vec2 texcoord;
            in vec4 offset[2];
            in vec4 dummy2;
            void main()
            {
                gl_FragColor = SMAANeighborhoodBlendingPS(texcoord, offset, albedo_tex, blend_tex);
            }
        """
        )

        size = self.size
        self.albedo_tex = Texture.create(size=size, bufferfmt="float")
        self.albedo_fbo = Fbo(size=size, texture=self.albedo_tex)

        self.edge_tex = Texture.create(size=size, bufferfmt="float")
        self.edge_fbo = Fbo(size=size, vs=edge_vs, fs=edge_fs, texture=self.edge_tex)
        self.edge_fbo.bind()
        self.edge_fbo["albedo_tex"] = 0
        self.edge_fbo.release()

        self.blend_tex = Texture.create(size=size, bufferfmt="float")
        self.blend_fbo = Fbo(size=size, vs=blend_vs, fs=blend_fs, texture=self.blend_tex)
        self.blend_fbo.bind()
        self.blend_fbo["edge_tex"] = 0
        self.blend_fbo["area_tex"] = 1
        self.blend_fbo["search_tex"] = 2
        self.blend_fbo.release()

        self.neighborhood = RenderContext(
            use_parent_modelview=True, use_parent_projection=True, vs=neighborhood_vs, fs=neighborhood_fs
        )
        with self.neighborhood:
            self.neighborhood["albedo_tex"] = 0
            self.neighborhood["blend_tex"] = 1

        self.area_tex = Texture.create(size=(AREATEX_WIDTH, AREATEX_HEIGHT), colorfmt="rg", icolorfmt="rg8")

        with open(join(curdir, "smaa_area.raw"), "rb") as fd:
            self.area_tex.blit_buffer(fd.read(), colorfmt="rg")

        self.search_tex = Texture.create(size=(SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT), colorfmt="red", icolorfmt="r8")

        self.search_tex.min_filter = "nearest"
        self.search_tex.mag_filter = "nearest"

        with open(join(curdir, "smaa_search.raw"), "rb") as fd:
            self.search_tex.blit_buffer(fd.read(), colorfmt="red")

        with self.albedo_fbo:
            ClearColor(0, 0, 0, 0)
            ClearBuffers()

        with self.edge_fbo:
            Rectangle(size=self.size, texture=self.albedo_tex)

        with self.blend_fbo:
            BindTexture(index=1, texture=self.area_tex)
            BindTexture(index=2, texture=self.search_tex)
            Rectangle(size=self.size, texture=self.edge_tex)

        self.neighborhood.add(self.albedo_fbo)
        self.neighborhood.add(Callback(lambda *x: glDisable(GL_BLEND)))
        self.neighborhood.add(self.edge_fbo)
        self.neighborhood.add(self.blend_fbo)
        self.neighborhood.add(Callback(lambda *x: glEnable(GL_BLEND)))
        with self.neighborhood:
            BindTexture(index=1, texture=self.blend_tex)
            Rectangle(size=self.size, texture=self.albedo_tex)

        self.smaa_canvas = Canvas()
        with self.smaa_canvas.before:

            def do_stuff(*args):
                self.albedo_fbo.bind()
                self.albedo_fbo.clear_buffer()
                self.albedo_fbo.release()
                self.edge_fbo.bind()
                self.edge_fbo.clear_buffer()
                self.edge_fbo.release()
                self.blend_fbo.bind()
                self.blend_fbo.clear_buffer()
                self.blend_fbo.release()
                self.albedo_fbo.ask_update()
                self.edge_fbo.ask_update()
                self.blend_fbo.ask_update()
                self.neighborhood.ask_update()

            Callback(do_stuff)
        self.smaa_canvas.add(self.neighborhood)

        self._g_debug_added = False
        self._g_debug = [
            Callback(lambda *x: glDisable(GL_BLEND)),
            Color(0, 0, 0, 1),
            Rectangle(size=self.size),
            Color(1, 1, 1, 1),
            Rectangle(size=self.size),
            Callback(lambda *x: glEnable(GL_BLEND)),
        ]