{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%gui qt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Custom Visual for instanced rendering of a colored quad\n\n# this example is based on the tutorial: T01_basic_visual.py\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from vispy import app, gloo, visuals, scene, use\nimport numpy as np\n\n# full gl+ context is required for instanced rendering\nuse(gl='gl+')\n\n\nvertex_shader = \"\"\"\n// both these attributes will be defined on an instance basis (not per vertex)\nattribute vec2 shift;\nattribute vec4 color;\n\nvarying vec4 v_color;\nvoid main() {\n v_color = color;\n gl_Position = $transform(vec4($position + shift, 0, 1));\n}\n\"\"\"\n\nfragment_shader = \"\"\"\nvarying vec4 v_color;\n\nvoid main() {\n gl_FragColor = v_color;\n}\n\"\"\"\n\n\nclass InstancedRectVisual(visuals.Visual):\n def __init__(self, x, y, w, h):\n visuals.Visual.__init__(self, vertex_shader, fragment_shader)\n\n # vertices for two triangles forming a rectangle\n self.vbo = gloo.VertexBuffer(np.array([\n [x, y], [x+w, y], [x+w, y+h],\n [x, y], [x+w, y+h], [x, y+h]\n ], dtype=np.float32))\n\n self.shared_program.vert['position'] = self.vbo\n self._draw_mode = 'triangles'\n\n # create a vertex buffer with a divisor argument of 1. This means that the\n # attribute value is set to the next element of the array every 1 instance.\n # The length of the array multiplied by the divisor determines the number\n # of instances\n self.shifts = gloo.VertexBuffer(np.random.rand(100, 2).astype(np.float32) * 500, divisor=1)\n self.shared_program['shift'] = self.shifts\n\n # we can provide additional buffers with different divisors, as long as the\n # amount of instances (length * divisor) is the same. In this case, we will change\n # color every 5 instances\n self.color = gloo.VertexBuffer(np.random.rand(20, 4).astype(np.float32), divisor=5)\n self.shared_program['color'] = self.color\n\n def _prepare_transforms(self, view):\n view.view_program.vert['transform'] = view.get_transform()\n\n\n# create a visual node class to add it to the canvas\nInstancedRect = scene.visuals.create_visual_node(InstancedRectVisual)\n\ncanvas = scene.SceneCanvas(keys='interactive', show=True)\n\nrect = InstancedRect(0, 0, 20, 40, parent=canvas.scene)\n\nif __name__ == '__main__':\n import sys\n if sys.flags.interactive != 1:\n app.run()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.19" } }, "nbformat": 4, "nbformat_minor": 0 }