基于Python的OpenGL 03 之纹理
1. 概述
本文基于Python语言,描述OpenGL的着色器
前置知识可参考:
笔者这里不过多描述每个名词、函数和细节,更详细的文档可以参考:
2. 纹理使用流程
参考:纹理 - LearnOpenGL CN (learnopengl-cn.github.io)
OpenGL中纹理使用流程大致如下:
- 加载图片数据
- 创建纹理对象
- 绑定纹理对象
- 使用图片数据生成纹理
- 设置纹理坐标
- 在顶点着色器中传递纹理
- 在片段着色器中采用纹理
- (绘制时)激活纹理并绑定纹理
3. 具体流程
3.1 加载图片数据
使用PIL(Pillow )实现图片数据的读取
参考官方说明:Image Module - Pillow (PIL Fork) 9.2.0 documentation
使用以下方式导入:
from PIL.Image import open
加载图片数据:
image = open('./textures/container.jpg')
3.2 创建纹理对象
纹理对象也是使用ID进行引用:
texture = glGenTextures(1)
3.3 绑定纹理对象
绑定纹理对象,进行之后的纹理配置:
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);
3.4 使用图片数据生成纹理
通过glTexImage2D()生成纹理:
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)
3.5 设置纹理坐标
纹理坐标:
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 # 左上
])
现在内存中的坐标格式:

指定纹理坐标属性:
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, int(8 * 8), ctypes.c_void_p(8 * 6));
glEnableVertexAttribArray(2);
3.6 在顶点着色器中传递纹理坐标
在顶点着色器中编写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;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
3.7 在片段着色器中采用纹理
在片段着色器中接收纹理坐标与纹理:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
}
使用GLSL内置的texture函数来采样纹理的颜色
3.8 激活纹理并绑定纹理(绘制时)
激活纹理单元并绑定纹理数据:
glActiveTexture(GL_TEXTURE0) # 在绑定纹理之前先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture);
4. 代码总结
一个简单的纹理绘制流程完整代码如下:
import glfw as glfw
from OpenGL.GL import *
import numpy as np
from PIL.Image import open
import shader as shader
glfw.init()
window = glfw.create_window(800, 600, "texture", 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')
# print(image.tobytes())
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)
shaderProgram = 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)
shaderProgram.use()
glBindVertexArray(VAO)
glActiveTexture(GL_TEXTURE0) # 在绑定纹理之前先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
glfw.swap_buffers(window)
glfw.poll_events()
shaderProgram.delete()
shader.py见 基于Python的OpenGL 02 之着色器 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
图片
container下载自:https://learnopengl-cn.github.io/img/01/06/container.jpg
顶点着色器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;
void main()
{
gl_Position = 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;
void main()
{
FragColor = texture(texture1, TexCoord);
}
编译代码并运行:

5. 参考资料
[1]纹理 - LearnOpenGL CN (learnopengl-cn.github.io)
[2]nothings/stb: stb single-file public domain libraries for C/C++ (github.com)
[3]OpenGL学习笔记(五)纹理 - 知乎 (zhihu.com)
[4]PyOpenGL 3.1.0 Function Reference (sourceforge.net)
[5]~mcfletch/openglcontext/trunk : contents of tests/dek_texturesurf.py at revision 699 (launchpad.net)
[6]Image Module - Pillow (PIL Fork) 9.2.0 documentation
基于Python的OpenGL 03 之纹理的更多相关文章
- 基于Cocos2d-x学习OpenGL ES 2.0之多纹理
没想到原文出了那么多错别字,实在对不起观众了.介绍opengl es 2.0的不多.相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧.~~ 子龙山人出了一个系列: ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)
在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-P ...
- Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信
Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...
- 基于python的opcode优化和模块按需加载机制研究(学习与个人思路)(原创)
基于python的opcode优化和模块按需加载机制研究(学习与思考) 姓名:XXX 学校信息:XXX 主用编程语言:python3.5 个人技术博客:http://www.cnblogs.com/M ...
- 基于Python的机器学习实战:KNN
1.KNN原理: 存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应 ...
- 基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0
基于python+Testlink+Jenkins实现的接口自动化测试框架V3.0 目录 1. 开发环境2. 主要功能逻辑介绍3. 框架功能简介 4. 数据库的创建 5. 框架模块详细介绍6. Tes ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)
在上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了.在这篇文章中,我们不再画三角形了,改为画四边形.下篇教程,我们就可以画立方体了, ...
- 基于Python操作redis介绍
(注:本文部分内容摘自互联网,由于作者水平有限,不足之处,还望留言指正.) 毕业前的最后一个学期(2016.03),龙哥结婚了.可是总有些人喜欢嘲笑别人,调侃我.当时我就理直气壮的告诉他们,等龙哥孩子 ...
- 看我如何基于Python&Facepp打造智能监控系统
由于种种原因,最近想亲自做一个基于python&facepp打造的智能监控系统. 0×00:萌芽 1:暑假在家很无聊 想出去玩,找不到人.玩个lol(已卸载),老是坑人.实在是无聊至极,不过, ...
- 从零学习基于Python的RobotFramework自动化
从零学习基于Python的RobotFramework自动化 一. Python基础 1) 版本差异 版本 编码 语法 其他 2.X ASCII try: raise Type ...
随机推荐
- 论文翻译:2022_DNS_1th:Multi-scale temporal frequency convolutional network with axial attention for speech enhancement
论文地址:带轴向注意的多尺度时域频率卷积网络语音增强 论文代码:https://github.com/echocatzh/MTFAA-Net 引用:Zhang G, Yu L, Wang C, et ...
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(36)-掌握Fiddler中Fiddler Script用法,你会有多牛逼-上篇
1.简介 Fiddler是一款强大的HTTP抓包工具,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说,都有 ...
- Vuex极速入门
01.什么是Vuex? 1.1.为什么需要状态管理? 在复杂的系统中,我们会把系统按照业务逻辑拆分为多个层次.多个模块,采用组件式的开发方式.而此时不同模块.父子模块之间的通信就成了一个问题. 为了解 ...
- vue3项目,记录我是如何用1h实现产品预估1天工作量的界面需求
最近在编写前端界面,硬是一人一周时间加班加点写完了一个项目的前端界面(一级菜单有12个页面+一个控制台大屏,二三级界面有N个),之前预估前端界面的编写需要一个月,我是自己把自己卷死了(没有办法,项目经 ...
- ARL灯塔系统搭建
前言 ARL(Asset Reconnaissance Lighthouse)资产侦查灯塔,是一个良好的资产收集系统,旨在为渗透测试人员以及安全团队基于企业的网络安全能快速查找到指定企业资产中的脆弱点 ...
- Java开发学习(五十)----MyBatisPlus快速开发之代码生成器解析
1.代码生成器原理分析 造句: 我们可以往空白内容进行填词造句,比如: 在比如: 观察我们之前写的代码,会发现其中也会有很多重复内容,比如: 那我们就想,如果我想做一个Book模块的开发,是不是只需要 ...
- 用了这么久 IDEA,你竟然不知道 Live Templates ?
大家好,我是风筝,公众号「古时的风筝」,专注于 Java技术 及周边生态. 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. Live Templa ...
- 问一个 Windows 窗口的 Capture 问题
好久没写了,上来先问一个问题...羞射... 有 A.B 两个窗口,A 是 B 的 Owner,B 不激活不抢焦点.在 B 的 WM_LBUTTONDOWN 的时候,设置 A 窗口为 Capture: ...
- 《Effective C++》模版与泛型编程
Item41:了解隐式接口和编译期多态. 纵使你从未使用过templates,应该不陌生"运行期多态"和"编译期多态"之间的差异.因为它类似于"哪一个 ...
- 【公式详解】【优秀论文解读】EDPLVO: Efficient Direct Point-Line Visual Odometry
前言 多的不说哈 2022最佳优秀论文 来自美团无人机团队 作者提出了一种使用点和线的高效的直接视觉里程计(visual odometry,VO)算法-- EDPLVO .他们证明了,2D 线上的 3 ...