New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

surface slow and buggy #892

Open
SimonDanisch opened this Issue May 8, 2015 · 11 comments

Comments

Projects
None yet
5 participants
@SimonDanisch

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

This comment has been minimized.

Show comment
Hide comment
@SimonDanisch

SimonDanisch 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.

image

I'm not sure which version I'm running, but I installed it some days ago and I'm on windows 8.1.

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.

image

I'm not sure which version I'm running, but I installed it some days ago and I'm on windows 8.1.

@inclement

This comment has been minimized.

Show comment
Hide comment
@inclement

inclement May 8, 2015

Contributor

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.

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

This comment has been minimized.

Show comment
Hide comment
@SimonDanisch

SimonDanisch 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

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

This comment has been minimized.

Show comment
Hide comment
@SimonDanisch

SimonDanisch 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.

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.

@inclement

This comment has been minimized.

Show comment
Hide comment
@inclement

inclement May 8, 2015

Contributor

@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.

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.

@larsoner

This comment has been minimized.

Show comment
Hide comment
@larsoner

larsoner May 9, 2015

Member

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

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.

@campagnola

This comment has been minimized.

Show comment
Hide comment
@campagnola

campagnola May 9, 2015

Member

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.

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

This comment has been minimized.

Show comment
Hide comment
@SimonDanisch

SimonDanisch 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 ;)

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 ;)

@rougier

This comment has been minimized.

Show comment
Hide comment
@rougier

rougier May 9, 2015

Contributor

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.

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.

@campagnola

This comment has been minimized.

Show comment
Hide comment
@campagnola

campagnola May 9, 2015

Member

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

Member

campagnola commented May 9, 2015

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

@SimonDanisch

This comment has been minimized.

Show comment
Hide comment
@SimonDanisch

SimonDanisch May 9, 2015

That's good to know!
I appreciate your quick answers!

SimonDanisch commented May 9, 2015

That's good to know!
I appreciate your quick answers!

@larsoner larsoner added this to the version 0.5 milestone May 28, 2015

@larsoner larsoner modified the milestones: 0.6, 0.5 May 19, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment