Slide 1

Slide 1 text

Michael Fogleman 2014-10-23 michaelfogleman.com Modern OpenGL for Python pg

Slide 2

Slide 2 text

Introduction

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Links https://github.com/fogleman/pg http://pg.readthedocs.org/

Slide 8

Slide 8 text

Installation

Slide 9

Slide 9 text

git clone https://github.com/fogleman/pg.git cd pg python setup.py develop PyPI GitHub pip install pg GLFW brew tap homebrew/versions brew install glfw3

Slide 10

Slide 10 text

Windowing

Slide 11

Slide 11 text

import pg ! class Window(pg.Window): def setup(self): pass def teardown(self): pass def update(self, t, dt): pass def draw(self): pass ! if __name__ == '__main__': pg.run(Window)

Slide 12

Slide 12 text

Keyboard and Mouse

Slide 13

Slide 13 text

class Window(pg.Window): def on_size(self, width, height): pass def on_cursor_pos(self, x, y): pass def on_mouse_button(self, button, action, mods): pass def on_key(self, key, scancode, action, mods): pass def on_char(self, codepoint): pass

Slide 14

Slide 14 text

Shaders

Slide 15

Slide 15 text

program = pg.Program(vs_src, fs_src) context = pg.Context(program) context.matrix = matrix # uniform context.position = vb # attribute context.draw() # GL_TRIANGLES by default

Slide 16

Slide 16 text

Built-in Shaders

Slide 17

Slide 17 text

context = pg.Context(pg.DirectionalLightProgram()) context.light_direction = ... context.specular_multiplier = ...

Slide 18

Slide 18 text

class DirectionalLightProgram(BaseProgram): '''Renders the scene with a single, directional light source. Optionally, primitives can be textured or independently colored. ! :param matrix: the model-view-projection matrix, required :param model_matrix: the model matrix, required :param position: vertex buffer containing vertex positions, required :param normal: vertex buffer containing vertex normals, required :param uv: vertex buffer containing vertex texture coordinates, required if use_texture == True :param color: vertex buffer containing vertex colors, required if use_color == True :param sampler: texture to use, required if use_texture == True :param camera_position: the camera position in model space, required :param normal_matrix: the normal matrix, transposed inverse of model matrix, required :param light_direction: vector specifying light direction, default: (1, 1, 1) normalized :param object_color: color for all vertices if textures and color attributes are disabled, default: (0.4, 0.6, 0.8) :param ambient_color: ambient light color, default: (0.3, 0.3, 0.3) :param light_color: directional light color, default: (0.7, 0.7, 0.7) :param specular_power: controls exponent used in specular lighting, default: 32.0 :param specular_multiplier: controls intensity of specular lighting, default: 1.0 :param use_texture: controls whether a texture is to be used, default: False :param use_color: controls whether per-vertex colors are provided, default: False '''

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Vertex Buffers

Slide 21

Slide 21 text

vb = pg.VertexBuffer([(0, 0), (1, 0), (1, 1)]) context.position = vb ! ! sphere = pg.Sphere(...) vb = pg.VertexBuffer(sphere.positions) ! ! vb = pg.VertexBuffer(pg.interleave( sphere.positions, sphere.normals)) context.position, context.normal = vb.slices(3, 3)

Slide 22

Slide 22 text

Matrices

Slide 23

Slide 23 text

matrix = pg.Matrix() # identity matrix = matrix.rotate((0, 1, 0), pi) # y-axis, 180-degrees matrix = matrix.translate((1, 2, 3)) matrix = matrix.perspective(65, self.aspect, 1, 100) ! matrix * (1, 1, 1) matrix * mesh # transform all vertices ! context.matrix = matrix # glUniformMatrix4fv

Slide 24

Slide 24 text

Cameras

Slide 25

Slide 25 text

wasd = pg.WASD(self) # window_or_scene context.camera_position = wasd.position context.matrix = wasd.get_matrix() ! camera = pg.Camera() camera.look_at((1, 1, 1), (0, 0, 0)) context.camera_position = camera.position context.matrix = camera.get_matrix()

Slide 26

Slide 26 text

Textures

Slide 27

Slide 27 text

texture = pg.Texture(0, 'path/to/image.png') context.sampler = texture

Slide 28

Slide 28 text

Fonts

Slide 29

Slide 29 text

font = pg.Font(0, 'Arial.ttf', 12) font.render('Hello, world!', (x, y))

Slide 30

Slide 30 text

3D Geometric Primitives

Slide 31

Slide 31 text

sphere = pg.Sphere(3, 0.5, (0, 0, 0)) cube = pg.Cuboid(-1, 1, -1, 1, -1, 1) cylinder = pg.Cylinder((0, -1, 0), (0, 1, 0), 0.5, 18) cone = pg.Cylinder((0, -1, 0), (0, 1, 0), 0.5, 18) plane = pg.Plane((0, 0, 0), (0, 1, 0), 10) axes = pg.Axes(100) crosshairs = pg.Crosshairs()

Slide 32

Slide 32 text

3D Models

Slide 33

Slide 33 text

mesh = pg.OBJ('path/to/model.obj') mesh = pg.STL('path/to/model.stl') mesh.draw(context) mesh.bounding_box() # etc.

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Constructive Solid Geometry (CSG)

Slide 36

Slide 36 text

a = pg.Solid(sphere) b = pg.Solid(cylinder) c = a - b mesh = c.mesh() mesh.draw(context)

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Sprites

Slide 39

Slide 39 text

sheet = pg.SpriteSheet(0, 'path/to/folder') batch = pg.SpriteBatch(sheet) sprite = sheet.star(self.batch) sprite.position = (x, y) sprite.rotation = pi / 2 sprite.scale = 0.5 matrix = pg.Matrix().orthographic(0, w, 0, h, -1, 1) batch.draw(matrix)

Slide 40

Slide 40 text

Scenes

Slide 41

Slide 41 text

class Scene(pg.Scene): def setup(self): pass def teardown(self): pass def update(self, t, dt): pass def draw(self): pass ! window.set_scene(scene) window.push_scene(scene) window.pop_scene()

Slide 42

Slide 42 text

Threading

Slide 43

Slide 43 text

pg.async(func, *args, **kwargs) pg.call_after(func, *args, **kwargs) pg.Worker(...)

Slide 44

Slide 44 text

Questions? Live Coding Demo?