一、环境准备
1、适用系统:Windows,MacOS,Linux
2、适用Python版本:Python3
3、前提条件:Python环境
二、安装步骤
1、安装命令
pip install PyOpenGL -i https://pypi.tuna.tsinghua.edu.cn/simple
三、使用与测试
1、使用测试环境Python版本:Python3.9
2、测试代码
代码1:
from OpenGL.GL import *
from OpenGL.GLUT import *
def draw():
glClear(GL_COLOR_BUFFER_BIT)
glBegin(GL_TRIANGLES)
glColor3f(1,0,0); glVertex2f(-0.6,-0.6)
glColor3f(0,1,0); glVertex2f(0.6,-0.6)
glColor3f(0,0,1); glVertex2f(0,0.6)
glEnd()
glutSwapBuffers()
glutInit()
glutCreateWindow(b"OpenGL Test") # 字节串标题
glutDisplayFunc(draw)
glutMainLoop()
运行结果:

代码2:
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import math
import time
import sys
import numpy as np
# 全局变量
window_width = 800
window_height = 600
rotation_x = 0.0
rotation_y = 0.0
zoom_level = -8.0
mouse_dragging = False
prev_mouse_x = 0
prev_mouse_y = 0
animation_enabled = True
current_time = 0.0
render_mode = 0 # 0:填充, 1:线框, 2:点
light_enabled = True
texture_enabled = False
current_shape = 0 # 0:立方体, 1:球体, 2:茶壶
texture_id = None
current_mouse_button = None # 跟踪当前按下的鼠标按钮
# 纹理数据(简单的棋盘格纹理)
def create_checker_texture():
texture_data = []
for i in range(64):
for j in range(64):
c = 255 if ((i & 8) ^ (j & 8)) else 127
texture_data.extend([c, c, c, 255]) # RGBA
return (GLubyte * len(texture_data))(*texture_data)
# 初始化函数
def init():
global texture_id
print("=== OpenGL复杂测试环境信息 ===")
print(f"OpenGL版本: {glGetString(GL_VERSION).decode('utf-8')}")
print(f"显卡供应商: {glGetString(GL_VENDOR).decode('utf-8')}")
print(f"渲染器: {glGetString(GL_RENDERER).decode('utf-8')}")
print(f"GLSL版本: {glGetString(GL_SHADING_LANGUAGE_VERSION).decode('utf-8')}")
# 设置基本OpenGL状态
glEnable(GL_DEPTH_TEST)
glClearColor(0.1, 0.1, 0.2, 1.0) # 深蓝色背景
# 设置光照
setup_lighting()
# 设置材质
setup_material()
# 创建纹理
setup_texture()
print("\n=== 控制说明 ===")
print("鼠标左键拖拽: 旋转场景")
print("鼠标右键拖拽: 缩放场景")
print("空格键: 切换动画")
print("R键: 重置视角")
print("L键: 切换光照")
print("T键: 切换纹理")
print("M键: 切换渲染模式")
print("S键: 切换形状")
print("ESC键: 退出程序")
# 设置光照
def setup_lighting():
# 环境光
ambient_light = [0.2, 0.2, 0.2, 1.0]
# 漫反射光
diffuse_light = [0.8, 0.8, 0.8, 1.0]
# 光源位置
light_position = [2.0, 2.0, 2.0, 1.0]
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light)
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light)
glLightfv(GL_LIGHT0, GL_POSITION, light_position)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHTING)
# 设置材质
def setup_material():
# 材质环境光反射
mat_ambient = [0.7, 0.7, 0.7, 1.0]
# 材质漫反射
mat_diffuse = [0.8, 0.8, 0.8, 1.0]
# 材质镜面反射
mat_specular = [1.0, 1.0, 1.0, 1.0]
# 镜面反射指数
mat_shininess = [100.0]
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient)
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse)
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular)
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess)
# 设置纹理
def setup_texture():
global texture_id
# 生成纹理ID
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)
# 设置纹理参数
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)
# 创建并上传纹理数据
texture_data = create_checker_texture()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0,
GL_RGBA, GL_UNSIGNED_BYTE, texture_data)
# 绘制彩色立方体
def draw_color_cube():
vertices = [
# 前面 (红色)
[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1],
# 后面 (绿色)
[-1, -1, -1], [-1, 1, -1], [1, 1, -1], [1, -1, -1],
# 上面 (蓝色)
[-1, 1, -1], [-1, 1, 1], [1, 1, 1], [1, 1, -1],
# 下面 (黄色)
[-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1],
# 右面 (洋红色)
[1, -1, -1], [1, 1, -1], [1, 1, 1], [1, -1, 1],
# 左面 (青色)
[-1, -1, -1], [-1, -1, 1], [-1, 1, 1], [-1, 1, -1]
]
colors = [
[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], # 红
[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], # 绿
[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], # 蓝
[1, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0], # 黄
[1, 0, 1], [1, 0, 1], [1, 0, 1], [1, 0, 1], # 洋红
[0, 1, 1], [0, 1, 1], [0, 1, 1], [0, 1, 1] # 青
]
indices = [
[0, 1, 2, 3], # 前面
[4, 5, 6, 7], # 后面
[8, 9, 10, 11], # 上面
[12, 13, 14, 15], # 下面
[16, 17, 18, 19], # 右面
[20, 21, 22, 23] # 左面
]
glBegin(GL_QUADS)
for i, face in enumerate(indices):
for vertex_idx in face:
if not light_enabled:
glColor3fv(colors[vertex_idx])
glVertex3fv(vertices[vertex_idx])
glEnd()
# 绘制纹理立方体
def draw_textured_cube():
vertices = [
[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1], # 前面
[-1, -1, -1], [-1, 1, -1], [1, 1, -1], [1, -1, -1], # 后面
[-1, 1, -1], [-1, 1, 1], [1, 1, 1], [1, 1, -1], # 上面
[-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1], # 下面
[1, -1, -1], [1, 1, -1], [1, 1, 1], [1, -1, 1], # 右面
[-1, -1, -1], [-1, -1, 1], [-1, 1, 1], [-1, 1, -1] # 左面
]
tex_coords = [
[0, 0], [1, 0], [1, 1], [0, 1],
[0, 0], [0, 1], [1, 1], [1, 0],
[0, 1], [0, 0], [1, 0], [1, 1],
[0, 1], [1, 1], [1, 0], [0, 0],
[0, 0], [0, 1], [1, 1], [1, 0],
[1, 0], [0, 0], [0, 1], [1, 1]
]
indices = [
[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11],
[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]
]
glBegin(GL_QUADS)
for face in indices:
for i, vertex_idx in enumerate(face):
glTexCoord2fv(tex_coords[vertex_idx])
glVertex3fv(vertices[vertex_idx])
glEnd()
# 绘制球体
def draw_sphere():
slices = 20
stacks = 20
radius = 1.0
for i in range(stacks):
lat0 = math.pi * (-0.5 + float(i) / stacks)
z0 = math.sin(lat0)
zr0 = math.cos(lat0)
lat1 = math.pi * (-0.5 + float(i + 1) / stacks)
z1 = math.sin(lat1)
zr1 = math.cos(lat1)
glBegin(GL_QUAD_STRIP)
for j in range(slices + 1):
lng = 2 * math.pi * float(j) / slices
x = math.cos(lng)
y = math.sin(lng)
glNormal3f(x * zr0, y * zr0, z0)
glVertex3f(x * zr0 * radius, y * zr0 * radius, z0 * radius)
glNormal3f(x * zr1, y * zr1, z1)
glVertex3f(x * zr1 * radius, y * zr1 * radius, z1 * radius)
glEnd()
# 绘制场景
def draw_scene():
global current_time
# 清空缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# 设置模型视图矩阵
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# 设置相机位置
gluLookAt(0, 0, zoom_level, # 相机位置
0, 0, 0, # 观察点
0, 1, 0) # 上方向
# 应用旋转
glRotatef(rotation_x, 1, 0, 0)
glRotatef(rotation_y, 0, 1, 0)
# 动画旋转
if animation_enabled:
current_time = time.time()
glRotatef(current_time * 30, 0, 1, 0) # Y轴旋转
glRotatef(current_time * 20, 1, 0, 0) # X轴旋转
# 设置渲染模式
if render_mode == 1:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
elif render_mode == 2:
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)
else:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
# 启用/禁用光照
if light_enabled:
glEnable(GL_LIGHTING)
else:
glDisable(GL_LIGHTING)
# 启用/禁用纹理
if texture_enabled and texture_id:
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture_id)
else:
glDisable(GL_TEXTURE_2D)
if not light_enabled:
glColor3f(0.8, 0.8, 0.8) # 默认颜色
# 绘制选定的形状
if current_shape == 0:
if texture_enabled:
draw_textured_cube()
else:
draw_color_cube()
elif current_shape == 1:
draw_sphere()
elif current_shape == 2:
glutSolidTeapot(1.0)
# 重置多边形模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
# 交换缓冲区
glutSwapBuffers()
# 窗口调整大小回调
def reshape(width, height):
global window_width, window_height
window_width = width
window_height = height
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, width / height, 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
# 空闲回调(用于动画)
def idle():
glutPostRedisplay()
# 鼠标点击回调
def mouse(button, state, x, y):
global mouse_dragging, prev_mouse_x, prev_mouse_y, current_mouse_button
if state == GLUT_DOWN:
mouse_dragging = True
prev_mouse_x = x
prev_mouse_y = y
current_mouse_button = button
else:
mouse_dragging = False
current_mouse_button = None
# 鼠标移动回调 - 修正版
def motion(x, y):
global rotation_x, rotation_y, zoom_level, prev_mouse_x, prev_mouse_y
if mouse_dragging:
dx = x - prev_mouse_x
dy = y - prev_mouse_y
# 根据鼠标按钮决定行为
if current_mouse_button == GLUT_RIGHT_BUTTON:
# 右键拖拽缩放
zoom_level += dy * 0.1
else:
# 左键拖拽旋转
rotation_x += dy * 0.5
rotation_y += dx * 0.5
prev_mouse_x = x
prev_mouse_y = y
glutPostRedisplay()
# 键盘回调
def keyboard(key, x, y):
global animation_enabled, rotation_x, rotation_y, zoom_level
global render_mode, light_enabled, texture_enabled, current_shape
key = key.decode('utf-8').lower()
if key == ' ':
# 空格键切换动画
animation_enabled = not animation_enabled
print(f"动画: {'启用' if animation_enabled else '禁用'}")
elif key == 'r':
# R键重置视角
rotation_x = 0.0
rotation_y = 0.0
zoom_level = -8.0
print("视角已重置")
elif key == 'l':
# L键切换光照
light_enabled = not light_enabled
print(f"光照: {'启用' if light_enabled else '禁用'}")
elif key == 't':
# T键切换纹理
texture_enabled = not texture_enabled
print(f"纹理: {'启用' if texture_enabled else '禁用'}")
elif key == 'm':
# M键切换渲染模式
render_mode = (render_mode + 1) % 3
modes = ["填充", "线框", "点"]
print(f"渲染模式: {modes[render_mode]}")
elif key == 's':
# S键切换形状
current_shape = (current_shape + 1) % 3
shapes = ["立方体", "球体", "茶壶"]
print(f"当前形状: {shapes[current_shape]}")
elif key == '\x1b': # ESC键
print("程序退出")
sys.exit(0)
glutPostRedisplay()
# 特殊键回调(方向键等)
def special_keys(key, x, y):
global rotation_x, rotation_y
if key == GLUT_KEY_UP:
rotation_x -= 5
elif key == GLUT_KEY_DOWN:
rotation_x += 5
elif key == GLUT_KEY_LEFT:
rotation_y -= 5
elif key == GLUT_KEY_RIGHT:
rotation_y += 5
glutPostRedisplay()
# 主函数
def main():
# 初始化GLUT
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(window_width, window_height)
glutInitWindowPosition(100, 100)
glutCreateWindow(b"OpenGL Complex Test - 3D Graphics Demo")
# 初始化OpenGL
init()
# 注册回调函数
glutDisplayFunc(draw_scene)
glutReshapeFunc(reshape)
glutIdleFunc(idle)
glutMouseFunc(mouse)
glutMotionFunc(motion)
glutKeyboardFunc(keyboard)
glutSpecialFunc(special_keys)
print("\n=== 测试开始 ===")
print("使用控制说明中的按键进行交互")
# 进入主循环
glutMainLoop()
if __name__ == "__main__":
main()
运行结果:

茶壶:

球体:

2469

被折叠的 条评论
为什么被折叠?



