pyopengl之cube

博客主要讲述几个坐标系变化矩阵的确定,未采用网上常见的现场矩阵库,而是用numpy自定义矩阵。还给出几种坐标体系的直观图示链接。此外,提到使用python库调用opengl接口时涉及数据类型转换,并给出示例。

 

    最 主要的是几个坐标系的变化矩阵的确定。网上很多资料的都是采用现场的矩阵库。此处使用numpy自定义矩阵。

    几种坐标体系的直观图示及功能如下图,转自:https://learnopengl.com/Getting-started/Coordinate-Systems

 

   此外使用python库,在调用opengl接口时,涉及到数据类型转换。例如

    float_size = sizeof(c_float)
    vertex_offset    = c_void_p(0 * float_size)  

   等 

# coding: utf-8
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import sys
from ctypes import sizeof, c_float, c_void_p, c_uint, string_at

from shader import *
import numpy, math

vertices=[
    -0.5, -0.5, -0.5,  0.0, 0.0,0.3,
     0.5, -0.5, -0.5,  1.0, 0.0,0.4,
     0.5,  0.5, -0.5,  1.0, 1.0,0.5,
     0.5,  0.5, -0.5,  1.0, 1.0,0.6,
    -0.5,  0.5, -0.5,  0.0, 1.0,0.7,
    -0.5, -0.5, -0.5,  0.0, 0.0,0.8,

    -0.5, -0.5,  0.5,  0.0, 0.0,0.2,
     0.5, -0.5,  0.5,  1.0, 0.0,0.4,
     0.5,  0.5,  0.5,  1.0, 1.0,0.3,
     0.5,  0.5,  0.5,  1.0, 1.0,0.6,
    -0.5,  0.5,  0.5,  0.0, 1.0,0.8,
    -0.5, -0.5,  0.5,  0.0, 0.0,1.0,

    -0.5,  0.5,  0.5,  1.0, 0.0,1.0,
    -0.5,  0.5, -0.5,  1.0, 1.0,0.3,
    -0.5, -0.5, -0.5,  0.0, 1.0,0.4,
    -0.5, -0.5, -0.5,  0.0, 1.0,0.7,
    -0.5, -0.5,  0.5,  0.0, 0.0,0.7,
    -0.5,  0.5,  0.5,  1.0, 0.0,0.7,

     0.5,  0.5,  0.5,  1.0, 0.0,0.8,
     0.5,  0.5, -0.5,  1.0, 1.0,0.8,
     0.5, -0.5, -0.5,  0.0, 1.0,0.8,
     0.5, -0.5, -0.5,  0.0, 1.0,0.8,
     0.5, -0.5,  0.5,  0.0, 0.0,0.8,
     0.5,  0.5,  0.5,  1.0, 0.0,0.8,

    -0.5, -0.5, -0.5,  0.0, 1.0,0.9,
     0.5, -0.5, -0.5,  1.0, 1.0,0.9,
     0.5, -0.5,  0.5,  1.0, 0.0,0.9,
     0.5, -0.5,  0.5,  1.0, 0.0,0.9,
    -0.5, -0.5,  0.5,  0.0, 0.0,0.9,
    -0.5, -0.5, -0.5,  0.0, 1.0,0.9,

    -0.5,  0.5, -0.5,  0.0, 1.0,0.5,
     0.5,  0.5, -0.5,  1.0, 1.0,0.5,
     0.5,  0.5,  0.5,  1.0, 0.0,0.5,
     0.5,  0.5,  0.5,  1.0, 0.0,0.5,
    -0.5,  0.5,  0.5,  0.0, 0.0,0.5,
    -0.5,  0.5, -0.5,  0.0, 1.0,0.5
]

screenWidth=512
screenHeight=512

cameraAngleX=218
cameraAngleY=10

zdistance=-0.2
mouseLeftDown=False
mouseRightDown=False
mouseX=0.0
mouseY=0.0

cameraDistance=1.7


def mydraw():

    # clear
    global cameraAngleX
    global cameraAngleY  
    global  zdistance
    #cameraAngleX=-55+cameraAngleX
    # zdistance=zdistance+0.1
    # if (zdistance>0.9):
        # zdistance=-0.9
    
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
    
    sinx=math.sin(math.radians(cameraAngleX))
    cosx=math.cos(math.radians(cameraAngleX))
    
    siny=math.sin(math.radians(cameraAngleY))
    cosy=math.cos(math.radians(cameraAngleY))
    #model 变换,将各个顶点分别以Y轴和X轴进行旋转。将顶点左边由物体自身的坐标体系转变为世界坐标体系
    modely = numpy.array([ cosy, 0.0, -siny,0.0, 
                           0,    1.0, 0.0,0.0, 
                           siny, 0, cosy, 0.0, 
                           0.0, 0.0, 0.0, 1.0], numpy.float32)
    modelx = numpy.array([ 1.0 ,0.0, -0.0,0.0,  
                          0.0,cosx, -sinx, 0,  
                          0.0, sinx, cosx, 0.0, 
                          0.0, 0.0, 0.0, 1.0], numpy.float32)
                                
    project=  numpy.array([ 1.0, 0.0,0.0, 0.0, 
                                0.0, 1, 0, 0.0, 
                                0.0, 0, -1/4, 0.0, 
                                0.0, 0.0, 0.0, 1.0], numpy.float32)
    #view 坐标转换,即物体离摄像机的远近。                            
    view=  numpy.array([ 1.0, 0.0,0.0, 0.0, 
                         0.0, 1, 0, 0.0, 
                         0.0, 0, 1, zdistance, 
                         0.0, 0.0, 0.0, 1.0], numpy.float32)
                                
    project=project.reshape(4,4)
    modelx=modelx.reshape(4,4)
    modely=modely.reshape(4,4)
    model=numpy.dot(modelx,modely)
    view=view.reshape(4,4)
       
    buffers = glGenBuffers(1)
    float_size = sizeof(c_float)
    vertex_offset    = c_void_p(0 * float_size)    
    glBindBuffer(GL_ARRAY_BUFFER, buffers)
    glBufferData(GL_ARRAY_BUFFER, 
            len(vertices)*4,  # byte size
            (ctypes.c_float*len(vertices))(*vertices), 
            GL_STATIC_DRAW)
    
    
    
    
    glVertexAttribPointer(0,3,GL_FLOAT, False, 6 * float_size, vertex_offset)
    glEnableVertexAttribArray(0) 
    
    color_offset    = c_void_p(3 * float_size) 
    glVertexAttribPointer(1,3,GL_FLOAT, False, 6 * float_size, color_offset)
    glEnableVertexAttribArray(1) 
    
    global shader
    if shader==None:
            shader=Shader()
            shader.initShader('''
   
    layout (location = 0) in vec3 aPos; 
    layout (location = 1) in vec3 acolor;
    out vec3 Color; 
    uniform  mat4 matrix; 
    uniform  mat4 view;
    uniform  mat4 project ;
    
    void main()
    {
        gl_Position = project*view*matrix*vec4(aPos.x, aPos.y, aPos.z, 1); 
        Color=acolor;
        
       
    }
            ''',
            '''
    out vec3 FragColor; 
    in vec3 Color;
    void main()
    {
        
        FragColor =Color; 
    }
            ''')

    
    shader.begin()
    mvp_matrix_loc = glGetUniformLocation(shader.program, 'matrix' )
    glUniformMatrix4fv(mvp_matrix_loc,1,GL_FALSE, model) 
    vp_matrix_loc = glGetUniformLocation(shader.program, 'view' )
    glUniformMatrix4fv(vp_matrix_loc,1,GL_FALSE, view)

    p_matrix_loc = glGetUniformLocation(shader.program, 'project' )
    glUniformMatrix4fv(p_matrix_loc,1,GL_FALSE, project)   
    
    
    glDrawArrays(GL_TRIANGLES, 0,36)
   
    shader.end()
    glDisableVertexAttribArray(0)
    glDisableVertexAttribArray(1)
    
   
    
def disp_func():    
    mydraw()    
    glutSwapBuffers()
    
def timerCB(millisec):

    glutTimerFunc(millisec, timerCB, millisec)
    glutPostRedisplay()
# 鼠标事件的响应处理。获取光标的位置信息,并更新到model 变化矩阵中,借此更新顶点的世界坐标  
def mouseCB( button,  state,  x,  y):
    global mouseX 
    global mouseY 
    mouseX = x
    mouseY = y
    global mouseLeftDown
    if(button == GLUT_LEFT_BUTTON):
    
        if(state == GLUT_DOWN):
        
            mouseLeftDown = True
            
        
        elif(state == GLUT_UP):
            mouseLeftDown = False
       

    elif(button == GLUT_RIGHT_BUTTON):
    
        if(state == GLUT_DOWN):
        
            mouseRightDown = True
        
        elif(state == GLUT_UP):
            mouseRightDown = False
    
    


def mouseMotionCB( x,  y):
    global cameraAngleX
    global cameraAngleY     
    global mouseLeftDown 
    
    global mouseX 
    global mouseY 
    
    if(mouseLeftDown):
    
        cameraAngleY += (x - mouseX)
        cameraAngleX += (y - mouseY)
        mouseX = x
        mouseY = y
        print(cameraAngleX)
    
    if(mouseRightDown):
    
        cameraDistance -= (y - mouseY) * 0.2
        mouseY = y
        
if __name__=="__main__":
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH| GLUT_STENCIL)
    glutInitWindowSize(screenWidth, screenHeight)
    glutCreateWindow(b"vbo")
    
    glutDisplayFunc(disp_func)
    glutTimerFunc(330, timerCB, 330)    
    glutMouseFunc(mouseCB) 
    glutMotionFunc(mouseMotionCB)
    
    glEnable(GL_DEPTH_TEST)
   
    
    glutMainLoop()

 

 

 

PyOpenGL 是 Python 中用于处理 OpenGL 图形渲染的库,而颜色分级(Color Grading)是图形和视频后期处理中常用的技术,旨在通过调整色彩曲线、色调映射等方式增强画面视觉效果。在 PyOpenGL 的上下文中实现颜色分级,通常涉及使用片段着色器(Fragment Shader)来处理图像的颜色映射。 颜色分级可以通过查找表(LUT, Look-Up Table)来实现,这种技术广泛应用于游戏和影视后期制作中。具体步骤如下: 1. **准备纹理图像**:将需要处理的图像加载为 OpenGL 纹理。 2. **创建 LUT 纹理**:设计一个 3D 或者 2D 的颜色查找表纹理,它包含了输入颜色与输出颜色之间的映射关系。 3. **编写 GLSL 着色器**:使用片段着色器读取原始纹理和 LUT 纹理,并根据当前像素的颜色值从 LUT 中获取新的颜色值[^1]。 4. **渲染到帧缓冲区**:将经过颜色分级处理后的图像渲染到屏幕或帧缓冲对象(FBO)中。 以下是一个简单的片段着色器代码示例,用于应用 LUT 进行颜色分级: ```glsl #version 330 core in vec2 TexCoords; out vec4 FragColor; uniform sampler2D screenTexture; uniform sampler3D lutTexture; // 假设使用的是 3D LUT void main() { vec3 originalColor = texture(screenTexture, TexCoords).rgb; // 应用 LUT 变换 vec3 gradedColor = texture(lutTexture, originalColor).rgb; FragColor = vec4(gradedColor, 1.0); } ``` 在 PyOpenGL 中实现上述功能时,需要完成以下几个关键步骤: - 初始化 OpenGL 上下文并设置必要的纹理参数。 - 加载纹理数据到 GPU,包括图像纹理和 LUT 纹理。 - 编译并链接着色器程序。 - 设置帧缓冲对象(如果需要离屏渲染)。 - 在主循环中进行渲染操作。 下面是一个简化的 Python 示例代码,展示如何初始化纹理和编译着色器: ```python from OpenGL.GL import * import pygame from pygame.locals import * def load_texture(image_path): 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) image = pygame.image.load(image_path) image_data = pygame.image.tostring(image, "RGB", True) width, height = image.get_size() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data) glBindTexture(GL_TEXTURE_2D, 0) return texture def compile_shader(shader_type, source): shader = glCreateShader(shader_type) glShaderSource(shader, source) glCompileShader(shader) return shader vertex_shader_source = """ #version 330 core layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoords; out vec2 TexCoords; void main() { TexCoords = aTexCoords; gl_Position = vec4(aPos, 1.0); } """ fragment_shader_source = """ #version 330 core in vec2 TexCoords; out vec4 FragColor; uniform sampler2D screenTexture; uniform sampler3D lutTexture; void main() { vec3 originalColor = texture(screenTexture, TexCoords).rgb; vec3 gradedColor = texture(lutTexture, originalColor).rgb; FragColor = vec4(gradedColor, 1.0); } """ def create_shader_program(): vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_source) fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_source) program = glCreateProgram() glAttachShader(program, vertex_shader) glAttachShader(program, fragment_shader) glLinkProgram(program) glDeleteShader(vertex_shader) glDeleteShader(fragment_shader) return program # 初始化 Pygame 和 OpenGL pygame.init() screen = pygame.display.set_mode((800, 600), DOUBLEBUF | OPENGL) glViewport(0, 0, 800, 600) # 加载纹理 texture = load_texture("path_to_your_image.jpg") shader_program = create_shader_program() # 启用着色器程序 glUseProgram(shader_program) # 设置顶点数据等... # 渲染循环 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) # 绑定纹理 glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, texture) glUniform1i(glGetUniformLocation(shader_program, "screenTexture"), 0) # 绑定 LUT 纹理... # 绘制四边形或其他几何体以显示纹理 pygame.display.flip() pygame.quit() ``` ### 注意事项: - **LUT 纹理**:为了简化示例,LUT 纹理的加载部分未完全展示。你需要加载一个预定义的 LUT 文件(如 `.cube` 格式),并将其转换为 OpenGL 支持的格式后上传到 GPU。 - **性能优化**:对于实时应用,确保纹理和着色器的设置尽可能高效,避免不必要的状态切换。 - **扩展性**:可以根据需求添加更多复杂的颜色调整逻辑,例如 gamma 校正、对比度调整等。 通过上述方法,可以在 PyOpenGL 中实现基本的颜色分级功能。进一步的优化和扩展可以根据具体应用场景进行调整。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

proware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值