Important edit: I am using the PyOpenGL binding of OpenGL
I am trying not to use the glRotate
and glTranslate
functions, but I have not found any alternative to this two functions. This functions are deprecated. What can I use?
The modern way is to write a Shader program, to use Vertex Array Objects and to use Uniform variable(s) of type mat4
.
There is more code to write, in compare to the deprecated fixed function pipeline but the benefit is high flexibility and a far better performance, in compare to drawing by glBegin
/glEnd
sequences.
For the matrix calculations can be used the PyGLM library, which is the python version of the c++ OpenGL Mathematics (glm) library.
e.g. A scale, rotation matrix around the z-axis by an angle
and translation can set by:
model = glm.mat4(1)
model = glm.translate(model, glm.vec3(0.2, 0.2, 0))
model = glm.rotate(model, angle, glm.vec3(0, 0, 1))
model = glm.scale(model, glm.vec3(0.5, 0.5, 1))
In compare to the the Legacy OpenGL operation glRoatate
, the angle has to be set in radians.
Note, instead of using PyGLM it is also possible to use the popular NumPy library and numpy.matrix
, but PyGLM is closer to that what you know from Legacy OpenGL and the functions glScale
, glTranslate
and glRotate
.
Of course it would be possible to set the the 4x4 matrices with out any library and to implement the matrix operations by yourself, too.
See the small example program, which uses PyOpenGL and PyGLM (beside the modules math
and ctypes
):
import math
import ctypes
import glm
from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GL.shaders import *
class MyWindow:
__caption = 'OpenGL Window'
__vp_size = [800, 600]
__vp_valid = False
__glut_wnd = None
__glsl_vert = """
#version 450 core
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec4 a_col;
out vec4 v_color;
layout (location = 0) uniform mat4 u_proj;
layout (location = 1) uniform mat4 u_view;
layout (location = 2) uniform mat4 u_model;
void main()
{
v_color = a_col;
gl_Position = u_proj * u_view * u_model * vec4(a_pos.xyz, 1.0);
}
"""
__glsl_frag = """
#version 450 core
out vec4 frag_color;
in vec4 v_color;
void main()
{
frag_color = v_color;
}
"""
__program = None
__vao = None
__vbo = None
def __init__(self, w, h):
self.__vp_size = [w, h]
glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(self.__vp_size[0], self.__vp_size[1])
__glut_wnd = glutCreateWindow(self.__caption)
self.__program = compileProgram(
compileShader( self.__glsl_vert, GL_VERTEX_SHADER ),
compileShader( self.__glsl_frag, GL_FRAGMENT_SHADER ),
)
attribures = [
# x y z R G B A
-0.866, -0.5, 0, 1, 0, 0, 1,
0.866, -0.5, 0, 1, 1, 0, 1,
0, 1.0, 0, 0, 0, 1, 1
]
vertex_attributes = (GLfloat * len(attribures))(*attribures)
itemsize = ctypes.sizeof(ctypes.c_float)
self.__vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.__vbo)
glBufferData(GL_ARRAY_BUFFER, vertex_attributes, GL_STATIC_DRAW)
self.__vao = glGenVertexArrays(1)
glBindVertexArray(self.__vao)
glVertexAttribPointer(0, 3, GL_FLOAT, False, 7*itemsize, None)
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 4, GL_FLOAT, False, 7*itemsize, ctypes.c_void_p(3*itemsize))
glEnableVertexAttribArray(1)
glUseProgram(self.__program)
glutReshapeFunc(self.__reshape)
glutDisplayFunc(self.__mainloop)
def run(self):
self.__starttime = 0
self.__starttime = self.elapsed_ms()
glutMainLoop()
def elapsed_ms(self):
return glutGet(GLUT_ELAPSED_TIME) - self.__starttime
def __reshape(self, w, h):
self.__vp_valid = False
def __mainloop(self):
if not self.__vp_valid:
self.__vp_size = [glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)]
self.__vp_valid = True
glViewport(0, 0, self.__vp_size[0], self.__vp_size[1])
proj = glm.mat4(1)
view = glm.mat4(1)
model = glm.mat4(1)
aspect = self.__vp_size[0]/self.__vp_size[1]
aspect_x = aspect if self.__vp_size[0] > self.__vp_size[1] else 1.0
aspect_y = 1/aspect if self.__vp_size[0] < self.__vp_size[1] else 1.0
proj = glm.ortho(-aspect_x, aspect_x, -aspect_y, aspect_y, -1.0, 1.0)
angle = self.elapsed_ms() * math.pi * 2 / 3000.0
model = glm.translate(model, glm.vec3(0.2, 0.2, 0))
model = glm.rotate(model, angle, glm.vec3(0, 0, 1))
model = glm.scale(model, glm.vec3(0.5, 0.5, 1))
glUniformMatrix4fv(0, 1, GL_FALSE, glm.value_ptr(proj) )
glUniformMatrix4fv(1, 1, GL_FALSE, glm.value_ptr(view) )
glUniformMatrix4fv(2, 1, GL_FALSE, glm.value_ptr(model) )
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawArrays(GL_TRIANGLES, 0, 3)
glutSwapBuffers()
glutPostRedisplay()
window = MyWindow(800, 600)
window.run()