I'm working on a project that has a simple OpenGL scene (two primitive triangles forming a quad, then shaded with a GLSL shader). Despite the simplicity of the project, I still need to relay uniform values to the GPU at runtime and some of those values are updated by the kivy MotionEvents 'on_touch_down', 'on_touch_move' and 'on_touch_up'. When the events are fired, I'm experiencing significant FPS drops (both on PC and Android). What might be the cause of this declination in performance, in such a simple situation and how can I work around it?
Here is the code:
from kivy.config import Config
Config.set('modules', 'monitor', '')
from kivy.app import App
from kivy.core.window import Window
from kivy.clock import mainthread
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scatterlayout import ScatterLayout
from kivy.vector import Vector
from kivy.clock import Clock
from kivy.graphics.instructions import RenderContext, Callback
from kivy.graphics import Mesh
class MainWidget(Widget):
def __init__(self, **kwargs):
super(MainWidget, self).__init__()
self.cardinalVector = Vector((0, 1))
self.canvas = RenderContext(use_parent_projection=True)
self.canvas.shader.source = 'Shaders/fan.glsl'
self.iTouch = (0, 0)
Clock.schedule_interval(self.updateShaderUniforms, 1/60)
self.canvas["iTouch"] = (0, 0)
self.vfmt = (
(b'vPosition', 2, 'float'),
(b'vCardinalUv', 2, 'float')
)
self.nextDraw()
def on_touch_down(self, touch):
v = Vector(touch.x, touch.y) - Vector(*self.center)
self.iTouch = (v.x, v.y)
return True
def on_touch_move(self, touch):
v = Vector(touch.x, touch.y) - Vector(*self.center)
self.iTouch = (v.x, v.y)
return True
def on_touch_up(self, touch):
self.iTouch = (0, 0)
return True
@mainthread
def updateShaderUniforms(self, delta):
self.canvas["iResolution"] = (float(self.size[0]), float(self.size[1]))
self.canvas["iTouch"] = (self.iTouch[0]/self.size[0], self.iTouch[1]/self.size[1])
@mainthread
def nextDraw(self):
with self.canvas:
self.mesh = self.build_mesh()
self.bind(pos=self.syncValues, size=self.syncValues)
def build_mesh(self):
vertices = [
self.pos[0], self.pos[1], 0, 0,
self.pos[0]+self.size[0], self.pos[1], 0, 1,
self.pos[0]+self.size[0], self.size[1]+self.pos[1], 1, 1,
self.pos[0], self.size[1]+self.pos[1], 1, 0
]
indices = [0, 1, 2, 3]
return Mesh(vertices=vertices, indices=indices, mode='triangle_fan', fmt=self.vfmt)
def syncValues(self, *args):
self.mesh.vertices = [
self.pos[0], self.pos[1], 0, 0,
self.pos[0]+self.size[0], self.pos[1], 0, 1,
self.pos[0]+self.size[0], self.size[1]+self.pos[1], 1, 1,
self.pos[0], self.size[1]+self.pos[1], 1, 0
]
class GLTestApplication(App):
def build(self):
self.root = BoxLayout(orientation="vertical")
self.root.add_widget(MainWidget())
return self.root
if __name__ == '__main__':
GLTestApplication().run()