python之OpenGL应用(二)Hello Triangle

上一篇文章介绍了使用glfw和pyopengl库的简单流程并给出了绘制三角形的入门代码,从本篇开始,将结合三角形的绘制过程来介绍OpenGL绘制图形的基本原理。

1 绘制流程

OpenGL的图形绘制遵循下图所示的图形渲染管线:

图1 OpenGL图形渲染管线

  • **顶点着色(vertex shader)阶段:**将CPU传入的数据进行一定的变换处理
  • **几何着色(geometry shader)阶段:**根据一定规则将输入的图元变更或输出更多的图元(可选)
  • 图元装配(shape assembly)阶段:将上阶段的顶点数据处理成图元(如,三角形)
  • 光栅化(rasterization)阶段:将上阶段的图元进行计算得到图元占据的屏幕像素列表
  • **片段着色(fragment)阶段:**将上阶段生成的片元进行着色处理后
  • 测试与混合(test and blending)阶段:计算片元的深度、颜色等从而进行舍弃或保留

绘制流程比较繁琐,然而,我们能配置的只有三个蓝色的着色器部分,即:顶点着色器、 几何着色器(可选)和片段着色器,一般只需配置顶点着色器和片段着色器即可。

2 生成顶点数据

生成顶点缓冲对象(Vertex Buffer Objects, VBO)并加载数据,代码如下:

python 复制代码
#生成顶点数据
vertices = np.array([[-0.5, -0.5, 0.0],
                     [0.5, -0.5, 0.0],
                     [0.0, 0.5, 0.0]])
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, 8*vertices.size, vertices, GL_STATIC_DRAW)

3 链接属性数据

顶点数组对象(Vertex Array Object, VAO)与VBO绑定,用于保存属性数据(先绑定VAO,再创建VBO就会绑定到VAO上),代码如下:

python 复制代码
#链接属性数据
glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, int(8*3), None)
glEnableVertexArrayAttrib(VAO, 0)

4 创建顶点着色器

创建顶点着色器(Vertex Shader)并编译,代码如下:

python 复制代码
#创建顶点着色器
vertexShaderSource = """
    #version 330 core
    layout (location = 0) in vec3 aPos;
    
    void main()
    {
        gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    }
"""
vertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertexShader, vertexShaderSource)
glCompileShader(vertexShader)

5 创建片段着色器

创建片段着色器(Fragment Shader)并编译:

python 复制代码
#创建片段着色器
fragmentShaderSource = """
    #version 330 core
    out vec4 FragColor;
    
    void main()
    {
        FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    } 
"""
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragmentShader, fragmentShaderSource)
glCompileShader(fragmentShader)

6 链接着色器

着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本:

python 复制代码
#链接着色器
shaderProgram = glCreateProgram()
glAttachShader(shaderProgram, vertexShader)
glAttachShader(shaderProgram, fragmentShader)
glLinkProgram(shaderProgram)

7 绘制

python 复制代码
#绘制
glClearColor(0.2, 0.3, 0.3, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
 
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

8 完整代码

python 复制代码
# 导入相关库
import glfw
from OpenGL.GL import *
import numpy as np

#初始化glfw环境
glfw.init()
#创建窗口
window = glfw.create_window(800, 600, "hello triangle", None, None)
glfw.make_context_current(window)
#生成顶点数据并链接属性
VAO = glGenVertexArrays(1)
glBindVertexArray(VAO) 
vertices = np.array([[-0.5, -0.5, 0.0],
                     [0.5, -0.5, 0.0],
                     [0.0, 0.5, 0.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*3), None)
glEnableVertexArrayAttrib(VAO, 0)
#创建顶点着色器
vertexShaderSource = """
    #version 330 core
    layout (location = 0) in vec3 aPos;
    
    void main()
    {
        gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    }
"""
vertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertexShader, vertexShaderSource)
glCompileShader(vertexShader)
#创建片段着色器
fragmentShaderSource = """
    #version 330 core
    out vec4 FragColor;
    
    void main()
    {
        FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    } 
"""
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragmentShader, fragmentShaderSource)
glCompileShader(fragmentShader)
# 链接着色器
shaderProgram = glCreateProgram()
glAttachShader(shaderProgram, vertexShader)
glAttachShader(shaderProgram, fragmentShader)
glLinkProgram(shaderProgram)
# 删除着色器
glDeleteShader(vertexShader)
glDeleteShader(fragmentShader)
# 循环绘制
while not glfw.window_should_close(window):
    #绘制
    glClearColor(0.2, 0.3, 0.3, 1.0)
    glClear(GL_COLOR_BUFFER_BIT)
 
    glUseProgram(shaderProgram)
    glBindVertexArray(VAO)
    glDrawArrays(GL_TRIANGLES, 0, 3)
        
    glfw.swap_buffers(window)
    glfw.poll_events()
# 结束glfw环境
glfw.terminate()

参考资料:

(5 封私信 / 14 条消息) 【Learn OpenGL笔记】三角形(Triangle) - 知乎

基于Python的OpenGL 01 之Hello Triangle - 当时明月在曾照彩云归 - 博客园

相关推荐
wangchunyu1149 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
2501_9445215910 小时前
Immer 跨端三方库仓颉适配全流程
python·eclipse·django
信誓旦旦的程序猿10 小时前
【Python量化实战宝典 #26】止损与回撤控制手册:移动止损、最大回撤(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
2501_9445215910 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
Patrick在香港11 小时前
同一行 strftime,两台机器跑出两种日期
python·datetime·时区·locale·日期处理
2601_9679873711 小时前
用Python+OpenCV+YOLO写个游戏脚本:从自动瞄准到自动采集的保姆级教程
python·opencv·yolo·目标检测·游戏自动化
meiying883811 小时前
快递单号批量查询Python脚本:从手动到自动化的完整实现
开发语言·python·自动化
人工智能导论实践课11 小时前
【GUI桌面开发3】PyCharm配置外部工具
ide·python·pycharm
一千柯橘11 小时前
LangChain 的实时输出处理: stream_events 和 Streaming
python·langchain·agent
贾公子11 小时前
图片 AIGC 检测接入实战——URL 与 Base64 的取舍、体积校验与「你送过去的可能不是那张图」
python·aigc