9 - OpenGL
9 - OpenGL
OpenGL
3D Programming with PyOpenGL
OpenGL
1
12/14/22
OpenGL
+ The general way to use OpenGL is to draw everything you need to draw,
then show this image with a platform-dependent buffer swapping
command.
+ If you need to update the image, you draw everything again, even if you
only need to update part of the image. If you want to animate objects
moving on the screen, you need a loop that constantly clears and redraws
the screen.
+ There are techniques for only updating a portion of the screen. And you
can use OpenGL with these techniques. But OpenGL itself doesn't do it
internally; you must remember where you drew everything.
OpenGL
2
12/14/22
Important Titles
PyOpenGL
3
12/14/22
Start coding
+ import pygame as pg
+ from pygame.locals import *
4
12/14/22
Initialization:
+ pg.init()
+ display = (1920,1080) #Full HD
+ # OpenGL with double buffering
+ pg.display.set_mode(display, DOUBLEBUF|OPENGL)
Double buffering
10
5
12/14/22
Camera
11
Frustum
12
6
12/14/22
13
Code
+ Documentation:
+ void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
14
7
12/14/22
Planes
15
16
8
12/14/22
Drawing Objects
17
Important concepts:
18
9
12/14/22
Drawing in OpenGL
19
20
10
12/14/22
Vertices
Edges
Quads
21
Intuitive
22
11
12/14/22
+ def wireCube():
+ glBegin(GL_LINES)
+ for cubeEdge in cubeEdges:
+ for cubeVertex in cubeEdge:
+ glVertex3fv(cubeVertices[cubeVertex])
+ glEnd()
23
wireCube()
24
12
12/14/22
glVertex3fv()
25
Other functions
26
13
12/14/22
+ def solidCube():
+ glBegin(GL_QUADS)
+ for cubeQuad in cubeQuads:
+ for cubeVertex in cubeQuad:
+ glVertex3fv(cubeVertices[cubeVertex])
+ glEnd()
27
Event
28
14
12/14/22
Behaviour
+ handleEvents()
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
+ doTransformationsAndDrawing()
+ pg.display.flip()
+ pg.time.wait(1)
29
Some notes:
30
15
12/14/22
31
Loop
32
16
12/14/22
Code
+ while True:
+ handleEvents()
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
+ doTransformationsAndDrawing()
+ pg.display.flip()
+ pg.time.wait(1)
33
Utilizing
Transformation
Matrices
+ glTranslatef(1,1,1)
+ glRotatef(30,0,0,1)
+ glTranslatef(-1,-1,-1)
34
17
12/14/22
35
36
18
12/14/22
Code
37
Result
38
19
12/14/22
39
Updated solidCube():
+ def solidCube():
+ glBegin(GL_QUADS)
+ for cubeQuad in cubeQuads:
+ for cubeVertex in cubeQuad:
+ glColor3fv(colors[cubeVertex])
+ glVertex3fv(cubeVertices[cubeVertex])
+ glEnd()
40
20
12/14/22
Result
41
Code
42
21
12/14/22
43
Keyboard events
+ if event.type == pg.KEYDOWN:
+ if event.key == pg.K_LEFT:
+ glTranslatef(-0.5,0,0)
+ if event.key == pg.K_RIGHT:
+ glTranslatef(0.5,0,0)
+ if event.key == pg.K_UP:
+ glTranslatef(0,1,0)
+ if event.key == pg.K_DOWN:
+ glTranslatef(0,-1,0)
44
22
12/14/22
Mouse events
+ if event.type == pg.MOUSEBUTTONDOWN:
+ if event.button == 4:
+ glTranslatef(0,0,1.0)
+ if event.button == 5:
+ glTranslatef(0,0,-1.0)
45
Result
46
23
12/14/22
47
Camera
+ camera_x = x[3][0]
+ camera_y = x[3][1]
+ camera_z = x[3][2]
48
24
12/14/22
Automatic movement
49
Exercise
50
25
12/14/22
Textures
51
Important
52
26
12/14/22
Texture
53
Texture Wrapping
54
27
12/14/22
Texture Wrapping
55
Texture Filtering
56
28
12/14/22
Texture Filtering
57
OpenGL Textures
58
29
12/14/22
+ def loadTexture(filename):
+ textureSurface = pg.image.load(filename)
+ textureData = pg.image.tostring(textureSurface, "RGBA", 1)
+ width = textureSurface.get_width()
+ height = textureSurface.get_height()
+ glEnable(GL_TEXTURE_2D)
+ texid = glGenTextures(1)
+ glBindTexture(GL_TEXTURE_2D, texid)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)
59
OpenGL Textures
60
30
12/14/22
OpenGL Textures
+ uv = ((1, 1), (1, 0), (0, 0), (0, 1))
+ def solidCube():
+ glColor3f(1, 1, 1)
+ glBegin(GL_QUADS)
+ for cubeQuad in cubeQuads:
+ for i, cubeVertex in enumerate(cubeQuad):
+ #glColor3fv(colors[cubeVertex])
+ glTexCoord2fv(uv[i])
+ glVertex3fv(cubeVertices[cubeVertex])
+ glEnd()
61
Depth Test
If you want that the sides of the cube, which are near to the
camera, cover the sides which are behind them, then
you've to enable the Depth
Test by glEnable(GL_DEPTH_TEST).
62
31
12/14/22
Game loop
+ def main():
+ …
+ loadTexture("wood.jpeg")
+ glEnable(GL_DEPTH_TEST)
+ while True:
+ solidCube()
+ pg.display.flip()
+ pg.time.wait(10)
63
Result
64
32
12/14/22
Tinkercad
+ Tinkercad is an online
collection of software
tools from Autodesk
that enable complete
beginners to
create 3D models.
65
66
33
12/14/22
Player 3D
model
+ We will create a 3D
model and export it in
“.obj” file.
+ Then, we can import
the model for our
OpenGL app.
+ The file can be
accessed through
InforEstudante.
67
pywavefront
68
34
12/14/22
69
70
35
12/14/22
Player
+ Each scene consists of meshes (scene.mesh_list) and
each mesh has triangle faces (mesh.faces).
+ Each face is an array of 3 indies which refer to the array
of vertices [scene.vertices].
+ Therefore, we can crate a function which sets the scale
and translation and draw the model in nested loops.
71
Player
+ def Player():
+ glPushMatrix()
+ glScalef(*scene_scale)
+ glTranslatef(*scene_trans)
+ for mesh in scene.mesh_list:
+ glBegin(GL_TRIANGLES)
+ for face in mesh.faces:
+ for vertex_i in face:
+ glColor3fv((1,0,0))
+ glVertex3f(*scene.vertices[vertex_i])
+ glEnd()
+ glPopMatrix()
72
36
12/14/22
glPolygonMode
73
Result
74
37
12/14/22
+ https://www.khronos.org/opengl/wiki/Getting_Started#U
sing_OpenGL
75
38