如何在 python 中使用 OPenGL 制作移动矩形

How to make a moving rectangle using OPenGL in python

使用OpenGL绘制固定位置的矩形很容易。 但是问题是如何绘制一个移动的矩形。

每帧重绘场景。这意味着每帧都会清除视口,并且每帧都会绘制所有网格。在每一帧的不同位置绘制网格会产生运动的错觉。网格的位置由顶点着色器中的顶点变换定义。通常消息的位置取决于模型、视图和投影矩阵例如:

#version 460 core

layout (location = 0) in vec2 a_position;

layout (location = 0) uniform mat4 u_projection;
layout (location = 1) uniform mat4 u_model_view;

void main() 
{
    gl_Position = u_projection * u_model_view * vec4(a_position, 0.0, 1.0);
}

另见 LearnOpenGL - Transformations


最小 Python,(Py)OpenGL 示例:

from OpenGL.GLUT import *
from OpenGL.GL import *
import OpenGL.GL.shaders
import glm
import math

sh_vert = """
#version 460 core

layout (location = 0) in vec2 a_position;

layout (location = 0) uniform mat4 u_projection;
layout (location = 1) uniform mat4 u_model_view;

void main() 
{
    gl_Position = u_projection * u_model_view * vec4(a_position, 0.0, 1.0);
}
"""

sh_frag = """
#version 460 core

out vec4 frag_color;

void main()
{
    frag_color = vec4(1.0, 0.0, 0.0, 1.0);
}
"""

def display():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    
    projection = glm.ortho(-aspect, aspect, -1, 1, -1, 1)
    if aspect < 1:
        projection = glm.ortho(-1, 1, 1/-aspect, 1/aspect, -1, 1)

    elapsed_ms = glutGet(GLUT_ELAPSED_TIME)
    angle = elapsed_ms * math.pi * 2 / 5000.0
    model_view = glm.translate(glm.mat4(1), glm.vec3(math.cos(angle)*0.5, math.sin(angle)*0.5, 0))
    model_view = glm.scale(model_view, glm.vec3(0.2, 0.2, 1))
    glUniformMatrix4fv(0, 1, GL_FALSE, glm.value_ptr(projection))
    glUniformMatrix4fv(1, 1, GL_FALSE, glm.value_ptr(model_view))

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4)

    glutSwapBuffers()
    glutPostRedisplay()

aspect = 1
def reshape(width, height):
    global aspect
    glViewport(0, 0, width, height)
    aspect = width / height  

glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE)
glutSetOption(GLUT_MULTISAMPLE, 8)
glutInitWindowSize(640, 480)
glutCreateWindow(b"OpenGL Window")
glutDisplayFunc(display)
glutReshapeFunc(reshape)

attributes = (GLfloat * 8)(-1,-1, 1,-1, 1, 1, -1, 1) 

vao = glGenVertexArrays(1)
vbo = glGenBuffers(1)
glBindVertexArray(vao)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, attributes, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, False, 2*4, None)
glEnableVertexAttribArray(0)

program = OpenGL.GL.shaders.compileProgram(
    OpenGL.GL.shaders.compileShader(sh_vert, GL_VERTEX_SHADER),
    OpenGL.GL.shaders.compileShader(sh_frag, GL_FRAGMENT_SHADER)
)
glUseProgram(program)

glEnable(GL_DEPTH_TEST)
glClearColor(0.0, 0.0, 0.0, 0.0)
glutMainLoop()