{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%gui qt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Show a rotating cube with lighting\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n\nfrom vispy import gloo, app\nfrom vispy.gloo import Program, VertexBuffer, IndexBuffer\nfrom vispy.util.transforms import perspective, translate, rotate\nfrom vispy.geometry import create_cube\n\n\nvertex = \"\"\"\nuniform mat4 u_model;\nuniform mat4 u_view;\nuniform mat4 u_projection;\nuniform vec4 u_color;\n\nattribute vec3 position;\nattribute vec2 texcoord;\nattribute vec3 normal;\nattribute vec4 color;\n\nvarying vec3 v_position;\nvarying vec3 v_normal;\nvarying vec4 v_color;\n\nvoid main()\n{\n v_normal = normal;\n v_position = position;\n v_color = color * u_color;\n gl_Position = u_projection * u_view * u_model * vec4(position,1.0);\n}\n\"\"\"\n\nfragment = \"\"\"\nuniform mat4 u_model;\nuniform mat4 u_view;\nuniform mat4 u_normal;\n\nuniform vec3 u_light_intensity;\nuniform vec3 u_light_position;\n\nvarying vec3 v_position;\nvarying vec3 v_normal;\nvarying vec4 v_color;\n\nvoid main()\n{\n // Calculate normal in world coordinates\n vec3 normal = normalize(u_normal * vec4(v_normal,1.0)).xyz;\n\n // Calculate the location of this fragment (pixel) in world coordinates\n vec3 position = vec3(u_view*u_model * vec4(v_position, 1));\n\n // Calculate the vector from this pixels surface to the light source\n vec3 surfaceToLight = u_light_position - position;\n\n // Calculate the cosine of the angle of incidence (brightness)\n float brightness = dot(normal, surfaceToLight) /\n (length(surfaceToLight) * length(normal));\n brightness = max(min(brightness,1.0),0.0);\n\n // Calculate final color of the pixel, based on:\n // 1. The angle of incidence: brightness\n // 2. The color/intensities of the light: light.intensities\n // 3. The texture and texture coord: texture(tex, fragTexCoord)\n\n gl_FragColor = v_color * brightness * vec4(u_light_intensity, 1);\n}\n\"\"\"\n\n\nclass Canvas(app.Canvas):\n def __init__(self):\n app.Canvas.__init__(self, size=(512, 512), title='Lighted cube',\n keys='interactive')\n self.timer = app.Timer('auto', self.on_timer)\n\n # Build cube data\n V, F, outline = create_cube()\n vertices = VertexBuffer(V)\n self.faces = IndexBuffer(F)\n self.outline = IndexBuffer(outline)\n\n # Build view, model, projection & normal\n # --------------------------------------\n self.view = translate((0, 0, -5))\n model = np.eye(4, dtype=np.float32)\n normal = np.array(np.matrix(np.dot(self.view, model)).I.T)\n\n # Build program\n # --------------------------------------\n self.program = Program(vertex, fragment)\n self.program.bind(vertices)\n self.program[\"u_light_position\"] = 2, 2, 2\n self.program[\"u_light_intensity\"] = 1, 1, 1\n self.program[\"u_model\"] = model\n self.program[\"u_view\"] = self.view\n self.program[\"u_normal\"] = normal\n self.phi, self.theta = 0, 0\n\n self.activate_zoom()\n\n # OpenGL initialization\n # --------------------------------------\n gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00), depth_test=True,\n polygon_offset=(1, 1),\n blend_func=('src_alpha', 'one_minus_src_alpha'),\n line_width=0.75)\n self.timer.start()\n\n self.show()\n\n def on_draw(self, event):\n gloo.clear(color=True, depth=True)\n # program.draw(gl.GL_TRIANGLES, indices)\n\n # Filled cube\n gloo.set_state(blend=False, depth_test=True, polygon_offset_fill=True)\n self.program['u_color'] = 1, 1, 1, 1\n self.program.draw('triangles', self.faces)\n\n # Outlined cube\n gloo.set_state(polygon_offset_fill=False, blend=True, depth_mask=False)\n self.program['u_color'] = 0, 0, 0, 1\n self.program.draw('lines', self.outline)\n gloo.set_state(depth_mask=True)\n\n def on_resize(self, event):\n self.activate_zoom()\n\n def activate_zoom(self):\n gloo.set_viewport(0, 0, *self.physical_size)\n projection = perspective(45.0, self.size[0] / float(self.size[1]),\n 2.0, 10.0)\n self.program['u_projection'] = projection\n\n def on_timer(self, event):\n self.theta += .5\n self.phi += .5\n model = np.dot(rotate(self.theta, (0, 0, 1)),\n rotate(self.phi, (0, 1, 0)))\n normal = np.linalg.inv(np.dot(self.view, model)).T\n self.program['u_model'] = model\n self.program['u_normal'] = normal\n self.update()\n\nif __name__ == '__main__':\n c = Canvas()\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 }