Kivy,Mask Widget Canvas

时间:2016-03-24 09:42:04

标签: python kivy

我发现自己经常使用ScatterLayout(Scatter内部的Scatter等等)。逃避我的一个功能是将某种alpha蒙版应用于Scatter画布。想法是执行对应于背景图像或其他简单深度技巧的简单形状敲除。

我觉得这对于一些基本的OpenGL或者 kivy.graphics.stencil_instructions 是可行的。我对使用繁重的OpenGL命令并不是特别熟悉(我不知道如何调试它们),但将一些简单的命令包装到Widget类中就可以了。

所以这是我从其他来源得到的,但我想把它超越原始实体(如Rectangle):

使用基于纹理的方向更新(代码未经测试!)

    with self.canvas:

        # Hopefully I can build my "transparency mask" manually with a Texture
        texture = Texture.create(size=(64, 64))
        size = 64 * 64 * 3
        buf = [int(x * 255 / size) for x in range(size)]
        buf = b''.join(map(chr, buf))
        texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')

        StencilPush()

        Rectangle(texture=texture, pos=self.pos, size=(64, 64))

        #use mask
        StencilUse()

        """
        Will we get an image based mask on all drawing commands placed here?
        """

        StencilPop()

1 个答案:

答案 0 :(得分:1)

MultiTexture Canvas正是答案。尝试使用您自己的自定义PNG,您将看到,使它们变得如您所愿,并且它的工作非常精美。我将包含使其工作的重要代码片段,并考虑回答的问题,但如果我遇到渲染顺序问题,我可能会重新打开(因为我没有为我的应用程序使用静态PNG。

你需要将非常简单的着色器定义作为文档字符串包含在内(它将被自动加载,如果我已经剥离了太多,请参阅上面的链接:

fs_multitexture = '''
$HEADER$

// New uniform that will receive texture at index 1
uniform sampler2D texture1;

void main(void) {

    // multiple current color with both texture (0 and 1).
    // currently, both will use exactly the same texture coordinates.
    gl_FragColor = frag_color * \
        texture2D(texture0, tex_coord0) * \
        texture2D(texture1, tex_coord0);
}
'''

最基本的Widget类,它演示了创建这个简单魔法的纹理过滤过程:

class MultitextureWidget(Widget):
    def __init__(self, **kwargs):
        self.canvas = RenderContext()
        self.canvas.shader.fs = fs_multitexture
        with self.canvas:
            Color(1, 1, 1)
            BindTexture(source='mtexture2.png', index=1)
            Rectangle(size=(150, 150), source='mtexture1.png', pos=(500, 200))

        self.canvas['texture1'] = 1
        super(MultitextureWidget, self).__init__(**kwargs)
        Clock.schedule_interval(self.update_glsl, 0)

    def update_glsl(self, *largs):
        self.canvas['projection_mat'] = Window.render_context['projection_mat']
        self.canvas['modelview_mat'] = Window.render_context['modelview_mat']