基于Python的OpenGL 04 之变换
1. 概述
本文基于Python语言,描述OpenGL的变换
前置知识可参考:
笔者这里不过多描述每个名词、函数和细节,更详细的文档可以参考:
2. 导入GLM
平移、旋转、缩放等变换主要是使用变换矩阵来实现
OpenGL Mathematics(GLM)是一个基于GLSL的只有头文件的C++数学运算库
GLM的GitHub站点为:g-truc/glm: OpenGL Mathematics (GLM) (github.com)
PyGLM是GLM的Python绑定,其API基本一致
PyGLM的GitHub站点为:Zuzu-Typ/PyGLM: Fast OpenGL Mathematics (GLM) for Python (github.com)
PyGLM的PyPi地址为:PyGLM · PyPI
使用pip安装PyGLM:
pip install PyGLM
引入GLM:
import glm
3. 设置变换矩阵
设置一个平移、旋转、缩放的矩阵:
trans = glm.mat4(1.0) trans = glm.translate(trans, glm.vec3(0.5, -0.5, 0.0)*np.sin(glfw.get_time())) trans = glm.rotate(trans, glfw.get_time(), glm.vec3(0.0, 0.0, 1.0)) trans = glm.scale(trans, glm.vec3(1.0, 1.0, 0.0)*(np.sin(glfw.get_time())*0.5+0.5))
在顶点着色器中将变换矩阵与坐标结合:
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; uniform mat4 transform; void main() { gl_Position = transform * vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }
将变换矩阵输入到GPU:
glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgram, 'transform'), 1, GL_FALSE, glm.value_ptr(trans))
如果顺利的话,结果如下:
4. 完整代码
主要文件test.py
:
import glfw as glfw from OpenGL.GL import * import numpy as np from PIL.Image import open import glm as glm import shader as shader glfw.init() window = glfw.create_window(800, 600, "transformation", None, None) glfw.make_context_current(window) VAO = glGenVertexArrays(1) glBindVertexArray(VAO) vertices = np.array([ # ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 - 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, # 右上 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, # 右下 -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, # 左下 -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, # 左上 ]) VBO = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, VBO) glBufferData(GL_ARRAY_BUFFER, 8 * vertices.size, vertices, GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, int(8 * 8), None) glEnableVertexArrayAttrib(VAO, 0) glVertexAttribPointer(1, 3, GL_DOUBLE, GL_FALSE, int(8 * 8), ctypes.c_void_p(8 * 3)) glEnableVertexArrayAttrib(VAO, 1) glVertexAttribPointer(2, 2, GL_DOUBLE, GL_FALSE, int(8 * 8), ctypes.c_void_p(8 * 6)) glEnableVertexAttribArray(2) indices = np.array([ 0, 1, 3, # first triangle 1, 2, 3 # second triangle ]) EBO = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO) glBufferData(GL_ELEMENT_ARRAY_BUFFER, 8 * indices.size, indices, GL_STATIC_DRAW) image = open('./textures/container.jpg') texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) # 为当前绑定的纹理对象设置环绕、过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.size[0], image.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, image.tobytes()) glGenerateMipmap(GL_TEXTURE_2D) shader = shader.Shader("./glsl/test.vs.glsl", "./glsl/test.fs.glsl") while not glfw.window_should_close(window): glClearColor(0.2, 0.3, 0.3, 1.0) glClear(GL_COLOR_BUFFER_BIT) trans = glm.mat4(1.0) trans = glm.translate(trans, glm.vec3(0.5, -0.5, 0.0)*np.sin(glfw.get_time())) trans = glm.rotate(trans, glfw.get_time(), glm.vec3(0.0, 0.0, 1.0)) trans = glm.scale(trans, glm.vec3(1.0, 1.0, 0.0)*(np.sin(glfw.get_time())*0.5+0.5)) shader.use() glUniformMatrix4fv(glGetUniformLocation(shader.shaderProgram, 'transform'), 1, GL_FALSE, glm.value_ptr(trans)) glBindVertexArray(VAO) glActiveTexture(GL_TEXTURE0) # 在绑定纹理之前先激活纹理单元 glBindTexture(GL_TEXTURE_2D, texture) # glDrawArrays(GL_TRIANGLES, 0, 3) glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None) glfw.swap_buffers(window) glfw.poll_events() shader.delete()
顶点着色器test.vs.glsl
:
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; uniform mat4 transform; void main() { gl_Position = transform * vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }
片段着色器test.fs.glsl
:
#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D texture1; uniform sampler2D texture2; void main() { FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); }
5. 参考资料
[1]变换 - LearnOpenGL CN (learnopengl-cn.github.io)
[2]glm/manual.md at master · g-truc/glm (github.com)
[3]OpenGL学习笔记三——引入GLM库,实现transform_绿洲守望者的博客-CSDN博客_glm库
[4]OpenGL学习笔记(五)纹理 - 知乎 (zhihu.com)
[5]PyGLM · PyPI
[6]LearnOpenGL-Python/transformations.py at master · Zuzu-Typ/LearnOpenGL-Python (github.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律