# surface slow and buggy #892

Open
opened this Issue May 8, 2015 · 11 comments

Projects
None yet
5 participants

### SimonDanisch commented May 8, 2015

 Hi, I don't know much about python and vispy, but I'd like to have this go as fast as possible: ```# -*- coding: utf-8 -*- # vispy: gallery 30 # ----------------------------------------------------------------------------- # Copyright (c) 2014, Vispy Development Team. All Rights Reserved. # Distributed under the (new) BSD License. See LICENSE.txt for more info. # ----------------------------------------------------------------------------- """ This example demonstrates the use of the SurfacePlot visual. """ import sys import numpy as np from vispy import app, scene from vispy.util.filter import gaussian_filter canvas = scene.SceneCanvas(keys='interactive') view = canvas.central_widget.add_view() view.camera = scene.TurntableCamera(up='z') N = 50 def generate(i): #this seems to be the fastest way to create an array return np.fromfunction(lambda x, y: np.sin(np.sqrt((((x/N)-0.5)*i)*(((x/N)-0.5)*i) + (((y/N)-0.5)*i)*(((y/N)-0.5)*i)))/np.sqrt((((x/N)-0.5)*i)*(((x/N)-0.5)*i) + (((y/N)-0.5)*i)*(((y/N)-0.5)*i)), (N, N), dtype=np.float32) p1 = scene.visuals.SurfacePlot(z=generate(1.0), color=(0.9, 0.2, 0.5, 1), shading='smooth') p1.transform = scene.transforms.AffineTransform() p1.transform.scale([1/49., 1/49., 1.0]) p1.transform.translate([-0.5, -0.5, 0]) view.add(p1) # Add a 3D axis to keep us oriented axis = scene.visuals.XYZAxis(parent=view.scene) i = 1.0 def update(ev): global p1 global i i += 1.0 p1.set_data(z=generate(i)) timer = app.Timer() timer.connect(update) timer.start(0) if __name__ == '__main__': canvas.show() if sys.flags.interactive == 0: app.run()``` Normals seem to be missing, and the animation runs really slow. The camera stutters even without animation with a 20x20 surface. There was also a bug, when I updated the scalars after canvas.show(), where the surface got distorted depending on the camera angle. Best, Simon

### SimonDanisch commented May 8, 2015

 I also suspect #890 to be true... In my example I don't have any shading, so any depth testing issue couldn't be seen. But if I execute the original example, it does seem to look odd and indicates some depth testing issue. I'm not sure which version I'm running, but I installed it some days ago and I'm on windows 8.1.
Contributor

### inclement commented May 8, 2015

 Since you mentioned it, I'll note I've just updated my issue about depth testing, I don't think it actually applies to SurfacePlot (or at least I'm not experiencing it there). I'm wondering why you don't get shading though - is this a bug in set_data? The shading does appear if I move the camera directly above the surface. I've experienced some apparent shading bugs elsewhere where it appears or disappears depending on camera position, but never checked it out. Edit: Actually, the shading behaves the same even when the animation is disabled so I guess it isn't set_data, maybe I'm missing something simple about the example. Also, I experience a slowdown here only because of the animation (which is also consistent with my experience of far larger meshes, and with what should be expected from opengl), which makes me think the lag is just due to recalculating the vertices and uploading them to the gpu. But then, I don't know why you'd experience lag and slowdown even when the animation is disabled at your end.

### SimonDanisch commented May 8, 2015

 So you can't see anything else slowing this down, and I'm doing things in the correct way? The animation is just rather sluggish even for small N (like 100), and I bench marked the generate function alone and it seems to be as fast as it should (so not the culprit I guess)... Concerning the bug, it's not very stable...one time I had shading when I removed the transforms, one time when i changed generate back to the initial data generation from the example and one time some weird things in between....

### SimonDanisch commented May 8, 2015

 Concerning the depth test: it's hard to really pin it down, but when the shading was working, there was some shady thing going on (no pun intended)... It looked like fragments where randomly put to the front or back... But it could also be some shading issue, where the shaded part changes with the camera angle in an unnatural way.
Contributor

### inclement commented May 8, 2015

 @SimonDanisch I don't know if there's a better way to continuously update vertices from the cpu side, but I'm not a vispy dev or opengl expert. I'm sure one of the developers will point it out if there is one. It would be very fast to do it on the gpu with a vertex shader, but I'm not sure how best to do so in vispy. It might actually be really easy with a custom Transformation, which would be cool. What you mention does sound like depth test issues, so maybe it does affect the surface_plot after all. Given the sporadic shading problem, I guess it's quite possible. Maybe it'll be clear if I can work out the nature of the problem I originally noticed. Edit: Having understood the depth test bug I faced, it can't be affecting your example because it arises directly from Node and Mesh both calling `Visual.__init__`. You're using the surface visual directly, not the Node version in vispy.scene.visuals.
Member

### larsoner commented May 9, 2015

 It looks like not having the vertex normals forces them to get calculated. I ran your example with the `--vispy-cprofile` option and got this for the first few lines: `````` ncalls tottime percall cumtime percall filename:lineno(function) 4303/214 0.049 0.000 4.030 0.019 event.py:391(__call__) 3726/163 0.004 0.000 4.022 0.025 event.py:446(_invoke_callback) 16 0.000 0.000 4.009 0.251 _qt.py:611(paintGL) 16 0.000 0.000 3.974 0.248 canvas.py:152(on_draw) 16 0.000 0.000 3.974 0.248 canvas.py:194(_draw_scene) 16 0.003 0.000 3.970 0.248 canvas.py:202(draw_visual) 39/23 0.000 0.000 3.957 0.172 subscene.py:57(process_system) 64/16 0.000 0.000 3.950 0.247 subscene.py:40(draw) 128/16 0.003 0.000 3.950 0.247 systems.py:18(process) 16 0.001 0.000 3.948 0.247 viewbox.py:231(draw) 1 0.000 0.000 3.774 3.774 _default_app.py:57(run) 1 0.000 0.000 3.774 3.774 application.py:106(run) 1 0.000 0.000 3.774 3.774 _qt.py:212(_vispy_run) 1 0.489 0.489 3.774 3.774 {built-in method exec_} 16 0.000 0.000 3.423 0.214 mesh.py:268(draw) 16 0.001 0.000 2.703 0.169 mesh.py:178(_update_data) 16 1.673 0.105 2.658 0.166 meshdata.py:256(get_vertex_normals) `````` I'm not sure where we should make this faster, but it does solve part of the mystery regarding speed.
Member

### campagnola commented May 9, 2015

 Agreed--the only way I was able to get fast surface plots in pyqtgraph is by adding a flag that disabled normal recalculation and using a fragment shader that did not depend on normals. Ultimately we have a better option for vispy, though: we should be able to hold the z values in a texture, which would allow normals to be calculated in the vertex shader.

### SimonDanisch commented May 9, 2015

 we should be able to hold the z values in a texture, which would allow normals to be calculated in the vertex shader. I do that in GLVisualize.jl and I have a very smooth experience up to N=600. Normal calculation in the vertex shader must be very cheap, as turning it on and off wasn't making any noticeable difference for me. Background: I'm bench marking my stuff, mayavi and vispy at the moment, and vispy was so much behind, that I wanted to make sure that its not something I'm doing wrong ;)
Contributor

### rougier commented May 9, 2015

 Here is an example, must be pretty easy to adapt it to vispy: https://github.com/glumpy/glumpy/blob/master/examples/geometry-surface.py z values are held in a textures. The mesh is uploaded only once and can be of a different size than the texture array.
Member

### campagnola commented May 9, 2015

 You're not doing anything wrong. We still have a lot of optimization to do on the scenegraph.