问题遇到的现象和发生背景
你好,我需要OpenGL实现框选的动画,就是鼠标按下移动时会跟随鼠标生成矩形,松开时矩形消失
遇到的现象和发生背景,请写出第一个错误信息
顶点应该是正确的,但窗口上没有图像
用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
import numpy as np
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GL import shaders
class RectPainter():
def __init__(self):
"""准备模型数据"""
vshader_src = """
#version 420 core
layout (location = 0) in vec3 aPos;
void main(){
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); // gl_Position是内置变量
}
"""
fshader_src = """
#version 420 core
out vec4 frag_color;
void main(){
frag_color = vec4(1.0f, 0.5f, 0.2f, 1.0f);// gl_FragColor是内置变量
}
"""
vshader = shaders.compileShader(vshader_src, GL_VERTEX_SHADER)
fshader = shaders.compileShader(fshader_src, GL_FRAGMENT_SHADER)
self.PROGRAM = shaders.compileProgram(vshader, fshader)
self.start_x = 0
self.start_y = 0
self.end_x = 0
self.end_y = 0
self.clear_flag = False
self.vao = glGenVertexArrays(1)
self.vertices_buffer = glGenBuffers(1)
def draw(self):
"""绘制模型"""
glClearColor(178 / 255, 195 / 255, 234 / 255, 0.5)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 清除缓冲区
glUseProgram(self.PROGRAM)
glBindVertexArray(self.vao)
if self.clear_flag is True:
self.start_x = 0
self.start_y = 0
self.end_x = 0
self.end_y = 0
# 顶点数据
vertices = [[self.start_x, self.start_y, 0.0], [self.end_x, self.start_y, 0.0], [self.end_x, self.end_y, 0.0], [self.start_x, self.end_y, 0.0]]
vertices = np.array(vertices, dtype=np.float32)
glBindBuffer(GL_ARRAY_BUFFER, self.vertices_buffer)
glBufferData(GL_ARRAY_BUFFER, vertices, GL_DYNAMIC_DRAW) # 动态绘制
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(0)
# 绘制
print("四点数据:", vertices)
glDrawArrays(GL_LINE_LOOP, 0, 4)
# 结束
glBindVertexArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glUseProgram(0)
glFlush() # 执行缓冲区指令
def mymouse(button, state, x, y):
if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN:
painter.start_x, painter.start_y = x, y
painter.end_x, painter.end_y = x, y
painter.clear_flag = False
elif button == GLUT_LEFT_BUTTON and state == GLUT_UP:
painter.end_x, painter.end_y = x, y
painter.clear_flag = True
glutPostRedisplay()#update
'''
glutPostRedisplay()是一个OpenGL函数,用于重绘当前窗口。
它通知OpenGL重新渲染整个窗口,以便更新视图。
这通常用于动画等场景,在窗口大小、位置或其他视图参数发生变化时也会调用。
'''
def mymotion(x, y):
painter.end_x, painter.end_y = x, y
glutPostRedisplay()#update
if __name__ == "__main__":
glutInit() # 1. 初始化glut库
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE) # 2. 设置显示模式
glutInitWindowSize(600, 400) # 3. 设置窗口大小
glutCreateWindow('OpenGL Demo') # 2. 创建glut窗口
painter = RectPainter() # 3. 生成着色器程序、顶点数据集、颜色数据集
glutDisplayFunc(painter.draw) # 4. 绑定模型绘制函数
glutMouseFunc(mymouse) # 5. 绑定鼠标事件
glutMotionFunc(mymotion)
glutMainLoop() # 6. 进入glut主循环
我的解答思路和尝试过的方法
定义一个类RectPainter,包含了初始化,绘图方法,重写鼠标点击,释放事件,在点击释放时记录坐标,释放时clear_flag为True,这样绘制时顶点坐标重置为0(不绘制)同时更新画面,重写鼠标移动事件,鼠标移动时记录坐标并更新画面