如何在Kivy中更改3D网格的颜色?

0 投票
1 回答
1382 浏览
提问于 2025-04-18 15:45

我想用Kivy来显示3D网格,这样我就可以移动、旋转它们,还能改变颜色。我成功地简化并修改了Niko Skrypnik的魔方项目,现在我有了这段代码,可以显示一个可以旋转的红色方块:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.resources import resource_find
from kivy.graphics.transformation import Matrix
from kivy.graphics import *

class Renderer(Widget):
    def __init__(self, **kw):
        self.vertices = [[ -1,-1, 0,
                            1,-1, 0,
                            1, 1,-0,
                           -1, 1, 0]]

        kw['shader_file'] = 'shaders.glsl'
        self.canvas = RenderContext(compute_normal_mat=True)
        shader_file = kw.pop('shader_file')
        self.canvas.shader.source = resource_find(shader_file)

        with self.canvas:
            Translate(0, 0, -4.5)
            self.rot = Rotate(0, 1, 1, 1)
            ChangeState(Kd=(1.0, 0.0, 0.0),
                        Ka=(1.0, 0.0, 0.0),
                        Ks=(.3, .3, .3),
                        Tr=1.,
                        Ns=1.,
                        intensity=1.)
            for i in xrange(len(self.vertices)):
                Mesh(   vertices=self.vertices[i],
                        indices=[0, 1, 2, 3, 0, 2],
                        fmt=[('v_pos', 3, 'float')],
                        mode='triangles')

        asp = float(Window.width) / Window.height / 2.0
        proj = Matrix().view_clip(-asp, asp, -0.5, 0.5, 1, 100, 1)
        self.canvas['projection_mat'] = proj

        Window.request_keyboard(None, self).bind(on_key_down = self.on_keyboard_down)

    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == "left": self.rot.angle -= 10
        elif keycode[1] == "right": self.rot.angle += 10

class MyApp(App):
     def build(self):
         return Renderer()

if __name__ == '__main__':
     MyApp().run()

注意:我使用了来自Github上魔方项目的shaders.glsl文件。

按照同样的原则,我可以移动或缩放这个方块,但我还没弄明白怎么改变它的颜色。现在唯一有效的方法就是清空画布再重新绘制,但我觉得应该有更好的方法。
有没有人能帮帮我呢?

1 个回答

0

你可以通过RenderContext的__setitem__方法来传递统一变量给着色器。在这个例子中,颜色(包括本身的颜色和光照的颜色)是通过Kd和Ka这两个变量来设置的,所以你可以这样做:

self.canvas['Kd'] = [0., 1., 0.]
self.canvas['Ka'] = [0., 1., 0.]

这样做应该会让所有东西变成绿色。

当然,你也可以用类似的方法来设置着色器中的其他统一变量。

撰写回答