内容包括:可编程管线、着色器、纹理。
用pip下载pyopengl,没去官网。OpenGL的初始化函数自然无法被调用,所以就用pygame来显示。
这是我最终的效果。注意改一下图片的路径,图片放在与本代码一起的文件夹内
import pygame from pygame.locals import * from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * from PIL.Image import open # 初始化pygame pygame.init() # 设置窗口尺寸 WINDOW_WIDTH, WINDOW_HEIGHT = 800, 600 # 创建窗口 display = (WINDOW_WIDTH, WINDOW_HEIGHT) pygame.display.set_mode(display, DOUBLEBUF | OPENGL) # 初始化OpenGL gluPerspective(45, (WINDOW_WIDTH / float(WINDOW_HEIGHT)), 0.1, 50.0) glTranslatef(0.0, 0.0, -5) # 准备顶点位置和颜色数据 position_data = [ -1.0, -1.0, 0.0, # 左下 1.0, -1.0, 0.0, # 右下 -1.0, 1.0, 0.0, # 左上 1.0, 1.0, 0.0 # 右上 ] # position_data = [ # 0.0, 0.0, 0.0, # 左下 # 1.0, 0.0, 0.0, # 右下 # 0.0, 1.0, 0.0, # 左上 # 1.0, 1.0, 0.0 # 右上 # ] color_data = [ 1.0, 0.0, 0.0, 1.0, # 红色 0.0, 1.0, 0.0, 1.0, # 绿色 0.0, 0.0, 1.0, 1.0, # 蓝色 1.0, 1.0, 0.0, 1.0 # 黄色 ] # 设置纹理坐标 aTexCoord = [ 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 ] # 图片数据 image = open('./myphoto.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) # 设置纹理坐标 # 转移至准备数据的位置 # 指定纹理坐标属性 # 转移至VAO的位置 # 创建VBO posVbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, posVbo) glBufferData(GL_ARRAY_BUFFER, len(position_data) * 4, (ctypes.c_float * len(position_data))(*position_data), GL_STATIC_DRAW) colorVbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, colorVbo) glBufferData(GL_ARRAY_BUFFER, len(color_data) * 4, (ctypes.c_float * len(color_data))(*color_data), GL_STATIC_DRAW) aTexCoordVbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, aTexCoordVbo) glBufferData(GL_ARRAY_BUFFER, len(aTexCoord) * 4, (ctypes.c_float * len(aTexCoord))(*aTexCoord), GL_STATIC_DRAW) # 创建VAO vao = glGenVertexArrays(1) glBindVertexArray(vao) # 绑定VBO到VAO,并设置顶点属性 glEnableVertexAttribArray(0) # 位置属性位置 glBindBuffer(GL_ARRAY_BUFFER, posVbo) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(1) # 颜色属性位置 glBindBuffer(GL_ARRAY_BUFFER, colorVbo) glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, None) # 指定纹理坐标属性 glEnableVertexAttribArray(2) glBindBuffer(GL_ARRAY_BUFFER, aTexCoordVbo) glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, None) glBindVertexArray(0) # 解绑VAO # shader部分 #顶点着色器部分 a = """ #version 330 layout (location = 0) in vec3 Position; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; void main() { gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0); ourColor = aColor; TexCoord = aTexCoord; } """ # gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0); # gl_Position = vec4(Position.x, Position.y, Position.z, 1.0); # 片段着色器部分,字符串类型 b = """ #version 330 in vec3 ourColor; in vec2 TexCoord; out vec4 FragColor; uniform sampler2D texture1; void main() { FragColor = texture(texture1, TexCoord); } """ # FragColor = vec4(0.0, 1.0, 0.0, 1.0); # FragColor = texture(texture1, TexCoord); # FragColor = vec4(ourColor, 1.0); # 创建Shader程序 my_vertex = glCreateShader(GL_VERTEX_SHADER) my_fragment = glCreateShader(GL_FRAGMENT_SHADER) # 为程序输入代码 glShaderSource(my_vertex, a, None) glShaderSource(my_fragment, b, None) # 代码编译 glCompileShader(my_vertex) glCompileShader(my_fragment) # 创建program空壳子 program = glCreateProgram() # 将编译好的结果放入program空壳子中 glAttachShader(program, my_vertex) glAttachShader(program, my_fragment) # 执行program的链接操作,形成最终可执行的shader程序 glLinkProgram(program) # 清理 glDeleteShader(my_vertex) glDeleteShader(my_fragment) # 绘制循环 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 清除屏幕和深度缓冲区 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 这个地方也可以绘制,不太好,要升级 # glRotatef(1, 3, 1, 1) # 绘制 glUseProgram(program) glBindVertexArray(vao) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) # 刷新显示 pygame.display.flip() pygame.time.wait(10) # 退出pygame和OpenGL,并删除不需要用的、GUI内的、上文中被申请的存储空间 glDeleteVertexArrays(1, [vao]) glDeleteBuffers(1, [posVbo]) glDeleteBuffers(1, [colorVbo]) pygame.quit()