基于Python的OpenGL 01 之Hello Triangle
1. 引言
本文基于Python语言,描述OpenGL的绘制流程,这里描述的是OpenGL的核心模式(Core-profile)
本文基于GLFW与PyOpenGL库进行开发,Python语言下的OpenGL环境搭建可参考:
笔者这里不过多描述每个名词、函数和细节,更详细的文档可以参考:
2. 流程综述
OpenGL的绘制流程(图形渲染管线,Graphics Pipeline)如下:
- 顶点着色(vertex shader)阶段将CPU传入的数据进行一定的变换处理
- 图元装配(shape assembly)阶段的就是上阶段的顶点数据处理成图元(如,三角形)
- 几何着色(geometry shader)阶段是根据一定规则将输入的图元变更或输出更多的图元(可选)
- 光栅化(rasterization)阶段的是将上阶段的图元进行计算得到图元占据的屏幕像素列表
- 片元着色(fragment)阶段是将上阶段生成的片元进行着色处理后
- 测试与混合阶段计算片元的深度、颜色等从而进行舍弃或保留
绘制流程繁琐,然而,我们能配置的只有三个蓝色的着色器部分。几何着色器可选,一般配置顶点着色器和片段着色器即可,即,以下步骤就是配置顶点着色器和片段着色器
3. 生成顶点数据
生成顶点缓冲对象(Vertex Buffer Objects, VBO)并加载数据:
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)
4. 链接属性数据
顶点数组对象(Vertex Array Object, VAO)与VBO绑定,用于保存属性数据(先绑定VAO,再创建VBO就会绑定到VAO上):
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)
5. 创建顶点着色器
创建顶点着色器(Vertex Shader)并编译:
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)
6. 创建片段着色器
创建片段着色器(Fragment Shader)并编译:
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)
7. 链接着色器
着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本:
shaderProgram = glCreateProgram()
glAttachShader(shaderProgram, vertexShader)
glAttachShader(shaderProgram, fragmentShader)
glLinkProgram(shaderProgram)
8. 绘制
开始(循环)绘制:
glClearColor(0.2, 0.3, 0.3, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
9. 完整代码
基于GLFW、PyOpenGL和Numpy创建OpenGL开发环境,完整代码如下:
import glfw
from OpenGL.GL import *
import numpy as np
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_LINE_STRIP, 0, 3)
glfw.swap_buffers(window)
glfw.poll_events()
运行结果如下:
10. 参考资料
[1]你好,三角形 - LearnOpenGL CN (learnopengl-cn.github.io)
[2]【Learn OpenGL笔记】三角形(Triangle) - 知乎 (zhihu.com)
[3]基于GLFW的PyOpenGL的使用 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
[4](Python OpenGL)【3】着色器 PyOpenGL - WSX_1994 - 博客园 (cnblogs.com)
最新文章
- 在Linux终端命令行下播放音乐的命令(Ubuntu)
- Backbone Collection——数据模型集合
- 在JS中设置Select和radio选中
- c 整数的逆序输出 输入3,2就算 2+22+222的结果
- display:inline-block的运用
- react-router 学习笔记
- hdu1198 Farm Irrigation 并查集
- alpha-咸鱼冲刺day6
- continue #结束本次循环,继续下一次代码
- SpringCloud启动类指定扫描包路径
- springcloud的finchley.RC2的bug
- C#Windows Service服务程序的安装/卸载、启动/停止 桌面客户端管理程序设计
- WebLogic 中的基本概念【转】
- HDU 6061 RXD and functions(NTT)
- ofstream和ifstream
- 【WPF/C#】图层筛选/拾取——Color Picker
- mp4v2 基本知识
- linux yum 安装wget、gcc、ifconfig、vim、setup
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure 分治暴力
- django-上下文渲染器,将后端内容提供给模板使用,自定义渲染器
热门文章
- 【Hadoop面试】基础概念、HDFS、MapReduce、Yarn、实战
- android nativate 动态注册 静态注册
- JDBC的一些基础认识,写的不是特别完善,希望大家看的时候别太介意嘿嘿嘿
- [OpenCV实战]17 基于卷积神经网络的OpenCV图像着色
- 2_cookie、session、token、sign
- python进阶之路3之数据类型
- Java基础篇——集合框架
- 《Effective C++》继承与面向对象设计
- Ubuntu 22.04 安装 utools 时的疑难杂症
- 异步async await 相关知识点总结以及代码练习