在PyOpenGL中更改相机位置

hmmo2u0o  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(224)

我已经用PyOpenGL画了一个立方体,但是需要改变相机的位置,从不同的Angular 看它(例如,把相机移到(1,2,3),然后看原点)。这是我画立方体的代码(用三角形)。当我运行它的时候,我得到了一个正方形(我假设这只是我的立方体从正面看)。

from OpenGL import GL as gl
import glfw
import ctypes
import sys
import glm

# for capture screen shots

def dump_framebuffer_to_ppm(ppm_name, fb_width, fb_height):
    pixelChannel = 3
    pixels = gl.glReadPixels(0, 0, fb_width, fb_height, gl.GL_RGB, gl.GL_UNSIGNED_BYTE)
    fout = open(ppm_name, "w")
    fout.write('P3\n{} {}\n255\n'.format(int(fb_width), int(fb_height)))
    for i in range(0, fb_height):
        for j in range(0, fb_width):
            cur = pixelChannel * ((fb_height - i - 1) * fb_width + j)
            fout.write('{} {} {} '.format(int(pixels[cur]), int(pixels[cur+1]), int(pixels[cur+2])))
        fout.write('\n')
    fout.flush()
    fout.close()

screen_width, screen_height = 512, 512
ss_id = 0 # screenshot id

# create window

if not glfw.init():
    sys.exit(1)
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.window_hint(glfw.RESIZABLE, glfw.FALSE)
title = 'Assignment0'
window = glfw.create_window(screen_width, screen_height, title, None, None)
if not window:
    print('GLFW Window Failed')
    sys.exit(2)
glfw.make_context_current(window)
gl.glClearColor(0.3, 0.4, 0.5, 0)

# create triangle vertex arrays and buffers

vertex_array_id = gl.glGenVertexArrays(1)
gl.glBindVertexArray(vertex_array_id)

vertex_data = [-0.5,-0.5,-0.5,
    -0.5,-0.5, 0.5,
    -0.5, 0.5, 0.5,
    0.5, 0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5,-0.5,
    0.5,-0.5, 0.5,
    -0.5,-0.5,-0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5,-0.5,
    0.5,-0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5, 0.5,
    -0.5, 0.5,-0.5,
    0.5,-0.5, 0.5,
    -0.5,-0.5, 0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5, 0.5,
    -0.5,-0.5, 0.5,
    0.5,-0.5, 0.5,
    0.5, 0.5, 0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5,-0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5, 0.5,
    0.5,-0.5, 0.5,
    0.5, 0.5, 0.5,
    0.5,0.5,-0.5,
    -0.5, 0.5,-0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5,-0.5,
    -0.5, 0.5, 0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5, 0.5,
    0.5,-0.5, 0.5] # top mid

attr_id = 0
vertex_buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertex_buffer)
array_type = (gl.GLfloat * len(vertex_data))
sizeof_float = ctypes.sizeof(ctypes.c_float)
gl.glBufferData(gl.GL_ARRAY_BUFFER,
                len(vertex_data) * sizeof_float,
                array_type(*vertex_data),
                gl.GL_STATIC_DRAW)
gl.glVertexAttribPointer(
    attr_id,  # attribute 0.
    3,  # components per vertex attribute
    gl.GL_FLOAT,  # type
    False,  # to be normalized?
    0,  # stride
    None  # array buffer offset
)
gl.glEnableVertexAttribArray(attr_id)

color_data = [
    0.583,  0.771,  0.014,
    0.609,  0.115,  0.436,
    0.327,  0.483,  0.844,
    0.822,  0.569,  0.201,
    0.435,  0.602,  0.223,
    0.310,  0.747,  0.185,
    0.597,  0.770,  0.761,
    0.559,  0.436,  0.730,
    0.359,  0.583,  0.152,
    0.483,  0.596,  0.789,
    0.559,  0.861,  0.639,
    0.195,  0.548,  0.859,
    0.014,  0.184,  0.576,
    0.771,  0.328,  0.970,
    0.406,  0.615,  0.116,
    0.676,  0.977,  0.133,
    0.971,  0.572,  0.833,
    0.140,  0.616,  0.489,
    0.997,  0.513,  0.064,
    0.945,  0.719,  0.592,
    0.543,  0.021,  0.978,
    0.279,  0.317,  0.505,
    0.167,  0.620,  0.077,
    0.347,  0.857,  0.137,
    0.055,  0.953,  0.042,
    0.714,  0.505,  0.345,
    0.783,  0.290,  0.734,
    0.722,  0.645,  0.174,
    0.302,  0.455,  0.848,
    0.225,  0.587,  0.040,
    0.517,  0.713,  0.338,
    0.053,  0.959,  0.120,
    0.393,  0.621,  0.362,
    0.673,  0.211,  0.457,
    0.820,  0.883,  0.371,
    0.982,  0.099,  0.879]

attr_id = 1
color_buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, color_buffer)
array_type = (gl.GLfloat * len(color_data))
sizeof_float = ctypes.sizeof(ctypes.c_float)
gl.glBufferData(gl.GL_ARRAY_BUFFER,
                len(color_data) * sizeof_float,
                array_type(*color_data),
                gl.GL_STATIC_DRAW)
gl.glVertexAttribPointer(
    attr_id,  # attribute 0.
    3,  # components per vertex attribute
    gl.GL_FLOAT,  # type
    False,  # to be normalized?
    0,  # stride
    None  # array buffer offset
)
gl.glEnableVertexAttribArray(attr_id)

shaders = { #ADDED LINE 166 (ACOLOR)
    gl.GL_VERTEX_SHADER: '''\
    #version 330 core
    layout(location = 0) in vec3 aPos;
    layout(location = 1) in vec3 aColor;
    out vec3 fragmentColor;
    void main() {
        gl_Position = vec4(aPos, 1);
        fragmentColor = aColor;
    }
''',
    gl.GL_FRAGMENT_SHADER: '''\
    #version 330 core
    in vec3 fragmentColor;
    out vec3 color;
    void main() {
      color = fragmentColor;
    }
'''}

# color = vec3(0.9,0.8,0.7);

program_id = gl.glCreateProgram()
shader_ids = []
for shader_type, shader_src in shaders.items():
    shader_id = gl.glCreateShader(shader_type)
    gl.glShaderSource(shader_id, shader_src)
    gl.glCompileShader(shader_id)
    # check if compilation was successful
    result = gl.glGetShaderiv(shader_id, gl.GL_COMPILE_STATUS)
    nlog = gl.glGetShaderiv(shader_id, gl.GL_INFO_LOG_LENGTH)
    if nlog:
        logmsg = gl.glGetShaderInfoLog(shader_id)
        print("Shader Error", logmsg)
        sys.exit(1)
    gl.glAttachShader(program_id, shader_id)
    shader_ids.append(shader_id)

gl.glLinkProgram(program_id)
result = gl.glGetProgramiv(program_id, gl.GL_LINK_STATUS)
nlog = gl.glGetProgramiv(program_id, gl.GL_INFO_LOG_LENGTH)
if nlog:
    logmsg = gl.glGetProgramInfoLog(program_id)
    print("Link Error", logmsg)
    sys.exit(1)
gl.glUseProgram(program_id)

while (
    glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and
    not glfw.window_should_close(window)
):

    #press key p will capture screen shot
    if glfw.get_key(window, glfw.KEY_P) == glfw.PRESS:
        print ("Capture Window ", ss_id)
        buffer_width, buffer_height = glfw.get_framebuffer_size(window)
        ppm_name = "Assignment0-ss" + str(ss_id) + ".ppm"
        dump_framebuffer_to_ppm(ppm_name, buffer_width, buffer_height)
        ss_id += 1

    #draw triangle
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 12*3)
    glfw.swap_buffers(window)
    glfw.poll_events()

# release resource

for shader_id in shader_ids:
    gl.glDetachShader(program_id, shader_id)
    gl.glDeleteShader(shader_id)
gl.glUseProgram(0)
gl.glDeleteProgram(program_id)

几乎所有我找到/得到的资源都是用c++编写的,我不知道如何在python中语法上做到这一点。
也就是说

glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);

GLuint MatrixID = glGetUniformLocation(programID, "MVP");

gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

等等。

raogr8fs

raogr8fs1#

将Uniform变量添加到viewprojection矩阵的着色器程序中,并使用矩阵变换顶点位置(请注意,矩阵乘法不是commutative,乘法的顺序很重要):


# version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;

out vec3 fragmentColor;

uniform mat4 projection;
uniform mat4 view;

void main() {
    gl_Position = projection * view * vec4(aPos, 1);
    fragmentColor = aColor;
}

在程序链接后获取Unforms的位置:

gl.glLinkProgram(program_id)

# [...]

projection_loc = gl.glGetUniformLocation(program_id, 'projection')
view_loc = gl.glGetUniformLocation(program_id, 'view')

定义透视投影和查看场景,并在安装glUseProgram程序后设置Uniform变量:

gl.glUseProgram(program_id)

projection_matrix = glm.perspective(glm.radians(90), 1, 0.1, 10)
gl.glUniformMatrix4fv(projection_loc, 1, False, glm.value_ptr(projection_matrix))

view_matrix = glm.lookAt(glm.vec3(1, -2, 0), glm.vec3(0, 0, 0), glm.vec3(0, 0, 1))
gl.glUniformMatrix4fv(view_loc, 1, False, glm.value_ptr(view_matrix))

请不要忘记启用Depth Test

gl.glEnable(gl.GL_DEPTH_TEST)

完整代码

from OpenGL import GL as gl
import glfw
import ctypes
import sys
import glm

# for capture screen shots

def dump_framebuffer_to_ppm(ppm_name, fb_width, fb_height):
    pixelChannel = 3
    pixels = gl.glReadPixels(0, 0, fb_width, fb_height, gl.GL_RGB, gl.GL_UNSIGNED_BYTE)
    fout = open(ppm_name, "w")
    fout.write('P3\n{} {}\n255\n'.format(int(fb_width), int(fb_height)))
    for i in range(0, fb_height):
        for j in range(0, fb_width):
            cur = pixelChannel * ((fb_height - i - 1) * fb_width + j)
            fout.write('{} {} {} '.format(int(pixels[cur]), int(pixels[cur+1]), int(pixels[cur+2])))
        fout.write('\n')
    fout.flush()
    fout.close()

screen_width, screen_height = 512, 512
ss_id = 0 # screenshot id

# create window

if not glfw.init():
    sys.exit(1)
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.window_hint(glfw.RESIZABLE, glfw.FALSE)
title = 'Assignment0'
window = glfw.create_window(screen_width, screen_height, title, None, None)
if not window:
    print('GLFW Window Failed')
    sys.exit(2)
glfw.make_context_current(window)
gl.glClearColor(0.3, 0.4, 0.5, 0)

# create triangle vertex arrays and buffers

vertex_array_id = gl.glGenVertexArrays(1)
gl.glBindVertexArray(vertex_array_id)

vertex_data = [-0.5,-0.5,-0.5,
    -0.5,-0.5, 0.5,
    -0.5, 0.5, 0.5,
    0.5, 0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5,-0.5,
    0.5,-0.5, 0.5,
    -0.5,-0.5,-0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5,-0.5,
    0.5,-0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5, 0.5,
    -0.5, 0.5,-0.5,
    0.5,-0.5, 0.5,
    -0.5,-0.5, 0.5,
    -0.5,-0.5,-0.5,
    -0.5, 0.5, 0.5,
    -0.5,-0.5, 0.5,
    0.5,-0.5, 0.5,
    0.5, 0.5, 0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5,-0.5,
    0.5,-0.5,-0.5,
    0.5, 0.5, 0.5,
    0.5,-0.5, 0.5,
    0.5, 0.5, 0.5,
    0.5,0.5,-0.5,
    -0.5, 0.5,-0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5,-0.5,
    -0.5, 0.5, 0.5,
    0.5, 0.5, 0.5,
    -0.5, 0.5, 0.5,
    0.5,-0.5, 0.5] # top mid

attr_id = 0
vertex_buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vertex_buffer)
array_type = (gl.GLfloat * len(vertex_data))
sizeof_float = ctypes.sizeof(ctypes.c_float)
gl.glBufferData(gl.GL_ARRAY_BUFFER,
                len(vertex_data) * sizeof_float,
                array_type(*vertex_data),
                gl.GL_STATIC_DRAW)
gl.glVertexAttribPointer(
    attr_id,  # attribute 0.
    3,  # components per vertex attribute
    gl.GL_FLOAT,  # type
    False,  # to be normalized?
    0,  # stride
    None  # array buffer offset
)
gl.glEnableVertexAttribArray(attr_id)

color_data = [
    0.583,  0.771,  0.014,
    0.609,  0.115,  0.436,
    0.327,  0.483,  0.844,
    0.822,  0.569,  0.201,
    0.435,  0.602,  0.223,
    0.310,  0.747,  0.185,
    0.597,  0.770,  0.761,
    0.559,  0.436,  0.730,
    0.359,  0.583,  0.152,
    0.483,  0.596,  0.789,
    0.559,  0.861,  0.639,
    0.195,  0.548,  0.859,
    0.014,  0.184,  0.576,
    0.771,  0.328,  0.970,
    0.406,  0.615,  0.116,
    0.676,  0.977,  0.133,
    0.971,  0.572,  0.833,
    0.140,  0.616,  0.489,
    0.997,  0.513,  0.064,
    0.945,  0.719,  0.592,
    0.543,  0.021,  0.978,
    0.279,  0.317,  0.505,
    0.167,  0.620,  0.077,
    0.347,  0.857,  0.137,
    0.055,  0.953,  0.042,
    0.714,  0.505,  0.345,
    0.783,  0.290,  0.734,
    0.722,  0.645,  0.174,
    0.302,  0.455,  0.848,
    0.225,  0.587,  0.040,
    0.517,  0.713,  0.338,
    0.053,  0.959,  0.120,
    0.393,  0.621,  0.362,
    0.673,  0.211,  0.457,
    0.820,  0.883,  0.371,
    0.982,  0.099,  0.879]

attr_id = 1
color_buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, color_buffer)
array_type = (gl.GLfloat * len(color_data))
sizeof_float = ctypes.sizeof(ctypes.c_float)
gl.glBufferData(gl.GL_ARRAY_BUFFER,
                len(color_data) * sizeof_float,
                array_type(*color_data),
                gl.GL_STATIC_DRAW)
gl.glVertexAttribPointer(
    attr_id,  # attribute 0.
    3,  # components per vertex attribute
    gl.GL_FLOAT,  # type
    False,  # to be normalized?
    0,  # stride
    None  # array buffer offset
)
gl.glEnableVertexAttribArray(attr_id)

shaders = { #ADDED LINE 166 (ACOLOR)
    gl.GL_VERTEX_SHADER: '''\
    #version 330 core
    layout(location = 0) in vec3 aPos;
    layout(location = 1) in vec3 aColor;
    out vec3 fragmentColor;
    uniform mat4 projection;
    uniform mat4 view;
    void main() {
        gl_Position = projection * view * vec4(aPos, 1);
        fragmentColor = aColor;
    }
''',
    gl.GL_FRAGMENT_SHADER: '''\
    #version 330 core
    in vec3 fragmentColor;
    out vec3 color;
    void main() {
      color = fragmentColor;
    }
'''}

# color = vec3(0.9,0.8,0.7);

program_id = gl.glCreateProgram()
shader_ids = []
for shader_type, shader_src in shaders.items():
    shader_id = gl.glCreateShader(shader_type)
    gl.glShaderSource(shader_id, shader_src)
    gl.glCompileShader(shader_id)
    # check if compilation was successful
    result = gl.glGetShaderiv(shader_id, gl.GL_COMPILE_STATUS)
    nlog = gl.glGetShaderiv(shader_id, gl.GL_INFO_LOG_LENGTH)
    if nlog:
        logmsg = gl.glGetShaderInfoLog(shader_id)
        print("Shader Error", logmsg)
        sys.exit(1)
    gl.glAttachShader(program_id, shader_id)
    shader_ids.append(shader_id)

gl.glLinkProgram(program_id)
result = gl.glGetProgramiv(program_id, gl.GL_LINK_STATUS)
nlog = gl.glGetProgramiv(program_id, gl.GL_INFO_LOG_LENGTH)
if nlog:
    logmsg = gl.glGetProgramInfoLog(program_id)
    print("Link Error", logmsg)
    sys.exit(1)

projection_loc = gl.glGetUniformLocation(program_id, 'projection')
view_loc = gl.glGetUniformLocation(program_id, 'view')

gl.glUseProgram(program_id)

projection_matrix = glm.perspective(glm.radians(90), 1, 0.1, 10)
gl.glUniformMatrix4fv(projection_loc, 1, False, glm.value_ptr(projection_matrix))

view_matrix = glm.lookAt(glm.vec3(1, -2, 0), glm.vec3(0, 0, 0), glm.vec3(0, 0, 1))
gl.glUniformMatrix4fv(view_loc, 1, False, glm.value_ptr(view_matrix))

gl.glEnable(gl.GL_DEPTH_TEST)

while (
    glfw.get_key(window, glfw.KEY_ESCAPE) != glfw.PRESS and
    not glfw.window_should_close(window)
):

    #press key p will capture screen shot
    if glfw.get_key(window, glfw.KEY_P) == glfw.PRESS:
        print ("Capture Window ", ss_id)
        buffer_width, buffer_height = glfw.get_framebuffer_size(window)
        ppm_name = "Assignment0-ss" + str(ss_id) + ".ppm"
        dump_framebuffer_to_ppm(ppm_name, buffer_width, buffer_height)
        ss_id += 1

    #draw triangle
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 12*3)
    glfw.swap_buffers(window)
    glfw.poll_events()

# release resource

for shader_id in shader_ids:
    gl.glDetachShader(program_id, shader_id)
    gl.glDeleteShader(shader_id)
gl.glUseProgram(0)
gl.glDeleteProgram(program_id)

相关问题