Kivy,GLSL:为什么我会看到同一着色器的不同显示?

时间:2018-07-31 14:42:10

标签: python glsl kivy shader

这是一个说明我问题实质的例子。

main.py

from kivy.app import App
from kivy.clock import Clock
from kivy.factory import Factory
from kivy.graphics import RenderContext
from kivy.properties import StringProperty
from kivy.uix.widget import Widget

import kivy.core.window

shader = '''
$HEADER$

uniform vec2 resolution;

void main(void)
{
    vec2 position = (gl_FragCoord.xy / resolution.xy);

    float color = 0.0;
    color += position.y / position.x;
    if(color < 0.2) { color = 0.2; }
    vec3 output_color = vec3(color * 1.5, color, color * 2.0);

    gl_FragColor = vec4(output_color, 1.0);
}

'''

class ShaderWidget(Widget):
    fs = StringProperty(None)

    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_projection=True)
        super(ShaderWidget, self).__init__(**kwargs)
        self.canvas['time'] = Clock.get_boottime()
        Clock.schedule_interval(self.update_glsl, 1 / 60.)

    def update_glsl(self, *largs):
        self.canvas['time'] = Clock.get_boottime()
        self.canvas['resolution'] = [float(v) for v in self.size]

    def on_fs(self, instance, value):
        shader = self.canvas.shader
        shader.fs = value

class TestApp(App):
    def build(self):
        main_widget = Factory.MainWidget()
        main_widget.mini.fs = shader
        main_widget.mini2.fs = shader
        return main_widget

TestApp().run()

test.kv:

<MiniShaderWidget@ShaderWidget>:
    canvas:
        Color:
            rgb: 1.0, 1.0, 1.0
        Rectangle:
            pos: self.pos
            size: self.size


<MainWidget@ShaderWidget+FloatLayout>:
    mini: mini
    mini2: mini2

    BoxLayout
        MiniShaderWidget
            id: mini

        Label
            text: 'label'

        MiniShaderWidget
            id: mini2

在此应用程序中,我有一个包含三个相等部分的窗口。

同一来源的着色器(变量 shader )绘制在左侧和右侧。

着色器看起来像是从白色到紫色的过渡。

在中间,我添加了一个名为“标签”的标签,目的是为了更轻松地区分左着色器和右着色器。

我拿了这个例子,并从examples / shader / rotated.py(kivy github)做了一些修改

问题是: 我希望左右看到相同的图片,但是我看到同一着色器的不同图像。 为什么会这样?

是否可以在左右两侧制作相同的图片?

2 个答案:

答案 0 :(得分:1)

有趣的问题!

您实际上确实在左右两侧有两个不同的“图片”,看起来就像同一着色器分布在整个窗口中,标签小部件“浮动在顶部”居中。但这是一种幻想。

您确实有三个不同的小部件,每个小部件都不同。但是产生这种错觉是因为您的着色器功能正在使用屏幕空间的x,y位置来确定颜色。

为了更清楚地说明这一点,我添加了第二个着色器,并调整了配色方案:

gdb

我认为您的下一个问题是,如何将位置坐标传递给小部件的着色器,而不是屏幕空间?

答案 1 :(得分:1)

道歉的延迟:

查看您的.kv文件,看看如何设置MiniShaderWidgets?

<MiniShaderWidget@ShaderWidget>:
    canvas:
        Color:
            rgb: 1.0, 1.0, 1.0
        Rectangle:
            pos: self.pos
            size: self.size

只需更改您的:

 pos: self.pos
 size: self.size

这就是获取位置和大小信息的地方-只需将self.size和self.pos更改为您喜欢的任何内容即可。您可以使用(100,100)这样的绝对数字,也可以使用大小和位置提示,或者可以使用

这样的数学运算。
size: (self.width / 3, self.height)

基本上,您所需要做的就是查看任何其他小部件的大小和位置,然后使用它来获得所需的内容。

具有位置逻辑:gl_FragCoord.xy的着色器代码会分散注意力。

编写的着色器代码使用 widgets 的大小和位置-绝对正确。

您要做的是不要让小部件从主小部件继承其大小和位置。

这样想:您有两个紫色着色器小部件在相同位置绘制相同的纹理着色逻辑,然后在中心下方有一个标签框。

您需要将紫色着色器小部件放置在所需的位置,并且着色器位置逻辑将正常工作。

请告诉我这是否合理。