这是一个说明我问题实质的例子。
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)做了一些修改
问题是: 我希望左右看到相同的图片,但是我看到同一着色器的不同图像。 为什么会这样?
是否可以在左右两侧制作相同的图片?
答案 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 的大小和位置-绝对正确。
您要做的是不要让小部件从主小部件继承其大小和位置。
这样想:您有两个紫色着色器小部件在相同位置绘制相同的纹理着色逻辑,然后在中心下方有一个标签框。
您需要将紫色着色器小部件放置在所需的位置,并且着色器位置逻辑将正常工作。
请告诉我这是否合理。