The Problem Generally
I need to create a circular gradient of arbitrary radius and map it to the current mouse position. The project is primarily using OpenGL & PySDL2, but, for legacy reasons, also uses aggdraw (with Pillow wrapping PIL). Broadly, SDL2 runs interactions with OpenGL & most UI stuff, but aggdraw does, predictably, the drawing.
I've written a very rudimentary function. It works except that the latency between mouse motion and the gradient draw grows dramatically with gradient radius (see my code; it's obvious why).
The code below uses aggdraw; aggdraw objects are elsewhere converted into byte arrays with numpy to pass to OpenGL.
I'm open to solutions that use the SDL2 drawing library, but I've never used it and would appreciate being treated like the nub I am for such solutions. ;)
Notes for the Specific Context
Since the code I've provided is so sparse, as a courtesy I should mention that this interfaces with a large module I've been writing for ~1yr (KLIBS). Said module primarily does a lot that's impertinent here, but, the below function does plug into lot of in-house code. Alas, I've yet to write documentation for the module because it's (currently) for a local context.
This function is, verbatim, my code however; and the rest of the library has been well tested; the overhead is <10ms from anything else going on.
I think it must be possible to do this faster than the screen refresh rate, there is a latency tolerance of ~30ms (project's context is graduate work in the cognitive science of vision). I know this also depends on hardware; generally, we're talking iMacs no older than 3 years.
I'm sure this can be done much better, but I am waaay out of my depth; I usually work with with web languages (javascript/PHP/html/css)!
def mouse_gradient(radius):
mp = mouse_pos() # custom function, just wraps fetching mouse coords from sdl2
mouse_grad = None
mouse_grad = aggdraw.Draw('RGBA', (radius, radius), (0, 0, 0, 0))
for n in range(radius):
n = float(n)
r = float(radius - n)
opacity = int(( 0.25 * n / radius) * 100)
brush = aggdraw.Brush((255, 0, 0), int(opacity))
tl = (radius - r) // 2 # ie. top-left
br = (radius - r) // 2 + r # ie. bottom-right
mouse_grad.ellipse((tl, tl, br, br), brush)
return mouse_grad # where it is subsequently blit to the screen