Search code examples
openglvispy

Is possible to draw more than one object in vispy gloo?


I have been trying to render two objects at the same time, but I don't find the right way.

The way I'm proceeding is by creating two different position vector matrix "V1" and "V2" for being able to move them independently inside the timer callback.

Is that possible?, I have tried it in many ways but none of them worked...

#!/usr/bin/env python

import numpy as np
from os import path as op


from vispy import gloo, app, scene
from vispy.gloo import Program, VertexBuffer, IndexBuffer
from vispy.util.transforms import perspective, translate, rotate


vertex = """
uniform mat4 model1;
uniform mat4 model2;
uniform mat4 view;
uniform mat4 projection;
uniform sampler2D texture;

attribute vec3 position1;
attribute vec3 position2;
attribute vec2 texcoord;

varying vec2 v_texcoord;
void main()
{
    vec4 mp1 = model1 * vec4(position1,1.0);
    vec4 mp2 = model2 * vec4(position2,1.0);
    vec4 mp = mp1+mp2;
    gl_Position = projection * view * mp;
    v_texcoord = texcoord;
}
"""

fragment = """
void main()
{

}
"""

class Canvas(app.Canvas):
    def __init__(self):
        app.Canvas.__init__(self, keys='interactive')

        V = np.zeros(4, [("position1", np.float32, 3),
                 ("texcoord",   np.float32, 2)])
        V2 = np.zeros(4, [("position2", np.float32, 3),
                 ("texcoord",   np.float32, 2)])

        V["position1"] = [[ 1, 1, 0], [-1, 1, 0], [-1,-1, 0], [ 1,-1, 0]]
        V2["position2"] = [[ 1, 1, 1], [-1, 1, 1], [-1,-1, 1], [ 1,-1, 1]]
        V["texcoord"] = [[0,0], [0,1], [1,1], [1,0]]
        V2["texcoord"] = [[0,0], [0,1], [1,1], [1,0]]
        I = [0, 1, 2, 0, 2, 3]

        vertices = VertexBuffer(V)
        self.indices = IndexBuffer(I)

        vertices2 = VertexBuffer(V2)
        self.indices2 = IndexBuffer(I)

        # Build program1
        self.program1 = Program(vertex, fragment)
        self.program1.bind(vertices)
        self.program1.bind(vertices2)
        # Build program1

        # Build view, model, projection & normal
        #view = np.eye(4, dtype=np.float32)
        view = translate((0, 0, -5)).dot(rotate(-45, (1, 0, 0)))
        model2 = np.eye(4, dtype=np.float32)
        self.x,self.y, self.z = 0,5,0
        model1 = translate((self.x, self.y, self.z))

        self.program1['model1'] = model1
        self.program1['view'] = view

        gloo.set_viewport(0, 0, self.physical_size[0], self.physical_size[1])
        self.projection = perspective(45.0, self.physical_size[0] /
                                            float(self.physical_size[1]), 2.0, 30.0)

        self.program1['projection'] = self.projection

        # OpenGL initalization
        gloo.set_state(clear_color=(1, 1, 1, 1.), depth_test=True)

        self.show()

    def on_draw(self, event):
        gloo.clear(color=True, depth=True)
        self.program1.draw('triangles', self.indices)
        #self.program2.draw('triangles', self.indices2)


if __name__ == '__main__':

    canvas = Canvas()
    app.run()

Solution

  • I got it, anyway I don't know if it is the best way. Here is the code if it helps anyone:

    #!/usr/bin/env python
    
    import numpy as np
    
    from vispy import gloo, app, scene
    from vispy.gloo import Program, VertexBuffer, IndexBuffer
    from vispy.util.transforms import perspective, translate, rotate
    
    
    vertex = """
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    attribute vec3 position;
    void main()
    {
        gl_Position = projection * view * model * vec4(position,1.0);
    }
    """
    
    fragment = """
    void main()
    {
        //gl_FragColor = vec4 (0.0, 0.5, 0.0, 0.1);
    }
    """
    
    class Canvas(app.Canvas):
        def __init__(self):
            app.Canvas.__init__(self, keys='interactive')
    
            V = np.zeros(4, [("position", np.float32, 3)])
    
            V["position"] = [[ 1, 1, 0], [-1, 1, 0], [-1,-1, 0], [ 1,-1, 0]]
            I = [0, 1, 2, 0, 2, 3]
    
            vertices = VertexBuffer(V)
            self.indices = IndexBuffer(I)
    
            # Build program1
            self.program1 = Program(vertex, fragment)
            self.program2 = Program(vertex, fragment)
            self.program1.bind(vertices)
            self.program2.bind(vertices)
    
            # Build view, model, projection & normal
            view = translate((0, 0, -5)).dot(rotate(-45, (1, 0, 0)))
            self.model1 = translate((0, 5, 0))
            self.model2 = self.model1.dot(translate((0, 0, 1)))
    
            self.program1['model'] = self.model1
            self.program2['model'] = self.model2
            self.program1['view'] = view
            self.program2['view'] = view
    
            gloo.set_viewport(0, 0, self.physical_size[0], self.physical_size[1])
            self.projection = perspective(45.0, self.physical_size[0] /
                                                float(self.physical_size[1]), 2.0, 30.0)
    
            self.program1['projection'] = self.projection
            self.program2['projection'] = self.projection
    
            # OpenGL initalization
            gloo.set_state(clear_color=(1, 1, 1, 1.), depth_test=True)
    
            self._timer = app.Timer('auto', connect=self.on_timer, start=True)
            self.show()
    
        def on_draw(self, event):
            gloo.clear(color=True, depth=True)
            self.program1.draw('triangles', self.indices)
            self.program2.draw('triangles', self.indices)
    
        def on_timer(self, event):
            self.model1 = self.model1.dot(rotate(1, (0, 1, 0)))
            self.model2 = self.model2.dot(rotate(-1, (0, 1, 0)))
    
            self.program1['model'] = self.model1
            self.program2['model'] = self.model2
    
            self.update()
    
    if __name__ == '__main__':
    
        canvas = Canvas()
        app.run()