gpt4 book ai didi

python - PyOpenGL 透视投影

转载 作者:行者123 更新时间:2023-12-01 02:42:41 28 4
gpt4 key购买 nike

我对 PyOpenGL 比较陌生,并开始学习转换以及模型、 View 和投影矩阵。一切都很好,直到我编译并运行我的代码,发现我的对象突然消失了,说实话,我不知道 OpenGL 是否正在裁剪我的对象,或者只是因为某些相机错误而没有显示它,但我相信它有一些东西与我的代码中实现的投影矩阵有关,因为当我从代码中删除投影矩阵并运行我的程序时,一切都突然再次工作,除了我不会实现透视投影这一事实。无论如何,任何人都会非常感激:D

这是我的 PyOpenGL 代码。

import OpenGL, PIL, pygame, numpy, pyrr, math, sys, os

from OpenGL.GL import *
from PIL import Image
from pyrr import Matrix44, Vector4, Vector3, Quaternion

VERT_DATA = numpy.array([0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0,
-0.5, 0.5, 0.0],
dtype="float32")

COLOR_DATA = numpy.array([1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 1.0, 1.0],
dtype="float32")

TEXTURE_COORD_DATA = numpy.array([0.5, 0.5,
0.5, -0.5,
-0.5, -0.5,
-0.5, 0.5],
dtype="float32")

INDICES = numpy.array([0, 1, 3,
1, 2, 3],
dtype="int32")

class GLProgram:
def __init__(self):
self.gl_program = glCreateProgram()
self.mvp_matrix = self.projection()
self.shaders()
self.gl_buffers()

def gl_texture(self, texture_path):
image = Image.open(texture_path).transpose(Image.FLIP_TOP_BOTTOM)
image_data = numpy.fromstring(image.tobytes(), numpy.uint8)
width, height = image.size

texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data)
glGenerateMipmap(GL_TEXTURE_2D)

return texture

def gl_buffers(self):
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)

self.pos_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.pos_vbo)
glBufferData(GL_ARRAY_BUFFER, VERT_DATA, GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(0)

self.text_coord_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.text_coord_vbo)
glBufferData(GL_ARRAY_BUFFER, TEXTURE_COORD_DATA, GL_STATIC_DRAW)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(1)

self.pos_ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.pos_ebo)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.pos_ebo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES, GL_STATIC_DRAW)

self.brick_texture = self.gl_texture("check.jpg")

def shaders(self):
vertex_shader = glCreateShader(GL_VERTEX_SHADER)
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)

with open("VertexShader.vert", "r") as vert_file:
vert_source = vert_file.read()
with open("FragmentShader.frag", "r") as frag_file:
frag_source = frag_file.read()

glShaderSource(vertex_shader, vert_source)
glShaderSource(fragment_shader, frag_source)

glCompileShader(vertex_shader)
if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS):
info_log = glGetShaderInfoLog(vertex_shader)
print ("Compilation Failure for " + vertex_shader + " shader:\n" + info_log)

glCompileShader(fragment_shader)
if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS):
info_log = glGetShaderInfoLog(fragment_shader)
print ("Compilation Failure for " + fragment_shader + " shader:\n" + info_log)

glAttachShader(self.gl_program, vertex_shader)
glAttachShader(self.gl_program, fragment_shader)

glLinkProgram(self.gl_program)

glDeleteShader(vertex_shader)
glDeleteShader(fragment_shader)

def projection(self):
scale_matrix = pyrr.matrix44.create_from_scale(Vector3([1, 1, 1]))
rot_matrix = Matrix44.identity()
trans_matrix = pyrr.matrix44.create_from_translation(Vector3([1, 1, 0]))

model_matrix = scale_matrix * rot_matrix * trans_matrix
view_matrix = pyrr.matrix44.create_look_at(numpy.array([4, 3, 3]), numpy.array([1, 1, 0]), numpy.array([0, 1, 0]))
proj_matrix = pyrr.matrix44.create_perspective_projection_matrix(45.0, 1280/720, 0.1, 1000.0)
mvp_matrix = proj_matrix * view_matrix * model_matrix

return mvp_matrix

def display(self):
glEnable(GL_DEPTH_TEST)

glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

glUseProgram(self.gl_program)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.brick_texture)
texture_uniform = glGetUniformLocation(self.gl_program, "the_texture")
glUniform1i(texture_uniform, 0)

trans_uniform = glGetUniformLocation(self.gl_program, "mvp")
glUniformMatrix4fv(trans_uniform, 1, GL_FALSE, self.mvp_matrix)

glBindVertexArray(self.vao)

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
glUseProgram(0)

def main():
pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.set_caption("3D Graphics")
pygame.display.set_mode((1280, 720), pygame.DOUBLEBUF | pygame.OPENGL)
clock = pygame.time.Clock()
gl = GLProgram()

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

clock.tick(60)
gl.display()
pygame.display.flip()

if __name__ == "__main__":
main()

顶点着色器:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 text_coord;

out vec2 final_text_coord;

uniform mat4 mvp;

void main() {
gl_Position = mvp * vec4(position, 1.0);
final_text_coord = text_coord;
}

片段着色器:

#version 330 core

in vec2 final_text_coord;

out vec4 frag_color;

uniform sampler2D the_texture;

void main() {
frag_color = texture(the_texture, final_text_coord);
}

最佳答案

您的代码存在一些问题:

  1. 矩阵乘法。将两个二维 numpy 数组相乘会产生按分量乘积,而不是矩阵乘法。使用 numpy.matmul 可以解决这个问题。

  2. 矩阵约定不明确。

    正如pyrr 的文档所述,矩阵在内存中按行优先排列,这与 GL 的默认约定相反。此外,pyrr 创建转置为标准 GL 约定的矩阵。人们可能会认为这两件事都会自行抵消,这只是在一定程度上是正确的。每当您实际对这些矩阵执行其他操作(例如乘法)时,它就会中断,然后使用 native 约定,然后把事情搞砸。

我确实修改了你的代码,提供了两种不同的解决方案。由于您在问题和答案之间稍微更改了代码,因此我最终得到了两个版本的疯狂组合。我还禁用了纹理功能,因为我缺少一些库(和图像文件)。我相应地修改了片段着色器,但这并不重要。

import OpenGL, PIL, pygame, numpy, pyrr, math, sys, os

from OpenGL.GL import *
from PIL import Image
from pyrr import Matrix44, Vector4, Vector3, Quaternion

VERT_DATA = numpy.array([0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0,
-0.5, 0.5, 0.0],
dtype="float32")

COLOR_DATA = numpy.array([1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 1.0, 1.0],
dtype="float32")

TEXTURE_COORD_DATA = numpy.array([0.5, 0.5,
0.5, -0.5,
-0.5, -0.5,
-0.5, 0.5],
dtype="float32")

INDICES = numpy.array([0, 1, 3,
1, 2, 3],
dtype="int32")

WINDOW_WIDTH=1280
WINDOW_HEIGHT=720

class GLProgram:
def __init__(self):
self.gl_program = glCreateProgram()
self.mvp_matrix = self.projection()
self.shaders()
self.gl_buffers()
self.cube_model_matrix, self.cube_view_matrix, self.cube_proj_matrix = self.gl_translate(Vector3([1.0, 1.0, 1.0]), 45.0, Vector3([0.5, 0.5, 0.5]))
self.cube_mvp = self.gl_translate3(Vector3([1.0, 1.0, 1.0]), -45.0, Vector3([0.5, 0.5, 0.5]))

def gl_texture(self, texture_path):
return 0

def gl_buffers(self):
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)

self.pos_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.pos_vbo)
glBufferData(GL_ARRAY_BUFFER, VERT_DATA, GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(0)

self.text_coord_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.text_coord_vbo)
glBufferData(GL_ARRAY_BUFFER, TEXTURE_COORD_DATA, GL_STATIC_DRAW)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, None)
glEnableVertexAttribArray(1)

self.pos_ebo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.pos_ebo)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.pos_ebo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDICES, GL_STATIC_DRAW)

self.brick_texture = self.gl_texture("check.jpg")

def shaders(self):
vertex_shader = glCreateShader(GL_VERTEX_SHADER)
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)

with open("VertexShader.vert", "r") as vert_file:
vert_source = vert_file.read()
with open("FragmentShader.frag", "r") as frag_file:
frag_source = frag_file.read()

glShaderSource(vertex_shader, vert_source)
glShaderSource(fragment_shader, frag_source)

glCompileShader(vertex_shader)
if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS):
info_log = glGetShaderInfoLog(vertex_shader)
print ("Compilation Failure for " + vertex_shader + " shader:\n" + info_log)

glCompileShader(fragment_shader)
if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS):
info_log = glGetShaderInfoLog(fragment_shader)
print ("Compilation Failure for " + fragment_shader + " shader:\n" + info_log)

glAttachShader(self.gl_program, vertex_shader)
glAttachShader(self.gl_program, fragment_shader)

glLinkProgram(self.gl_program)

glDeleteShader(vertex_shader)
glDeleteShader(fragment_shader)

def projection(self):
scale_matrix = pyrr.matrix44.create_from_scale(Vector3([1, 1, 1]))
rot_matrix = Matrix44.identity()
trans_matrix = pyrr.matrix44.create_from_translation(Vector3([1, 1, 0]))

model_matrix = scale_matrix * rot_matrix * trans_matrix
view_matrix = pyrr.matrix44.create_look_at(numpy.array([4, 3, 3]), numpy.array([1, 1, 0]), numpy.array([0, 1, 0]))
proj_matrix = pyrr.matrix44.create_perspective_projection_matrix(45.0, 1280/720, 0.1, 1000.0)
mvp_matrix = proj_matrix * view_matrix * model_matrix

return mvp_matrix
def gl_translate(self, translation, rotation, scale):
trans_matrix = pyrr.matrix44.create_from_translation(translation)
rot_matrix = numpy.transpose(pyrr.matrix44.create_from_y_rotation(rotation))
scale_matrix = numpy.transpose(pyrr.matrix44.create_from_scale(scale))

model_matrix = scale_matrix * rot_matrix * trans_matrix
view_matrix = pyrr.matrix44.create_look_at(numpy.array([2.0, 2.0, 3.0], dtype="float32"),
numpy.array([0.0, 0.0, 0.0], dtype="float32"),
numpy.array([0.0, 1.0, 0.0], dtype="float32"))
proj_matrix = pyrr.matrix44.create_perspective_projection(45.0, WINDOW_WIDTH/WINDOW_HEIGHT, 0.1, 200.0)

return model_matrix, view_matrix, proj_matrix

def gl_translate2(self, translation, rotation, scale):
trans_matrix = pyrr.matrix44.create_from_translation(translation)
rot_matrix = pyrr.matrix44.create_from_y_rotation(rotation)
scale_matrix = pyrr.matrix44.create_from_scale(scale)

model_matrix = numpy.matmul(numpy.matmul(scale_matrix,rot_matrix),trans_matrix)
view_matrix = pyrr.matrix44.create_look_at(numpy.array([2.0, 2.0, 3.0], dtype="float32"),
numpy.array([0.0, 0.0, 0.0], dtype="float32"),
numpy.array([0.0, 1.0, 0.0], dtype="float32"))
proj_matrix = pyrr.matrix44.create_perspective_projection(45.0, WINDOW_WIDTH/WINDOW_HEIGHT, 0.1, 200.0)
m = numpy.matmul(numpy.matmul(model_matrix,view_matrix),proj_matrix)

return m
def gl_translate3(self, translation, rotation, scale):
trans_matrix = numpy.transpose(pyrr.matrix44.create_from_translation(translation))
rot_matrix = numpy.transpose(pyrr.matrix44.create_from_y_rotation(rotation))
scale_matrix = numpy.transpose(pyrr.matrix44.create_from_scale(scale))

model_matrix = numpy.matmul(numpy.matmul(trans_matrix,rot_matrix),scale_matrix)
view_matrix = numpy.transpose(pyrr.matrix44.create_look_at(numpy.array([2.0, 2.0, 3.0], dtype="float32"),
numpy.array([0.0, 0.0, 0.0], dtype="float32"),
numpy.array([0.0, 1.0, 0.0], dtype="float32")))
proj_matrix = numpy.transpose(pyrr.matrix44.create_perspective_projection(45.0, WINDOW_WIDTH/WINDOW_HEIGHT, 0.1, 200.0))
m = numpy.matmul(numpy.matmul(proj_matrix,view_matrix),model_matrix)

return numpy.transpose(m)

def display(self):
glEnable(GL_DEPTH_TEST)

glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

glUseProgram(self.gl_program)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.brick_texture)
texture_uniform = glGetUniformLocation(self.gl_program, "the_texture")
glUniform1i(texture_uniform, 0)

trans_uniform = glGetUniformLocation(self.gl_program, "mvp")
glUniformMatrix4fv(trans_uniform, 1, GL_FALSE, self.cube_mvp)
#model_location = glGetUniformLocation(self.gl_program, "model")
#glUniformMatrix4fv(model_location, 1, GL_FALSE, self.cube_model_matrix)
#view_location = glGetUniformLocation(self.gl_program, "view")
#glUniformMatrix4fv(view_location, 1, GL_FALSE, self.cube_view_matrix)
#proj_location = glGetUniformLocation(self.gl_program, "proj")
#glUniformMatrix4fv(proj_location, 1, GL_FALSE, self.cube_proj_matrix)
glBindVertexArray(self.vao)

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)
glUseProgram(0)

def main():
pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.set_caption("3D Graphics")
pygame.display.set_mode((1280, 720), pygame.DOUBLEBUF | pygame.OPENGL)
clock = pygame.time.Clock()
gl = GLProgram()

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

clock.tick(60)
gl.display()
pygame.display.flip()

if __name__ == "__main__":
main()

使用此顶点着色器:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 text_coord;

out vec2 final_text_coord;

uniform mat4 mvp;

void main() {
gl_Position = mvp * vec4(position, 1.0);
final_text_coord = text_coord;
}

还有这个片段着色器:

#version 330 core

in vec2 final_text_coord;

out vec4 frag_color;

uniform sampler2D the_texture;

void main() {
frag_color = vec4(1,0,0,1);
}

我专门添加了方法gl_translate2gl_translate3。两者都会产生相同的矩阵,2 变体仅使用 pyrr 库的 native 乘法顺序约定,而 gl_translate3 使用 GL 约定.

我还创建了具有不同参数的矩阵

self.cube_mvp = self.gl_translate3(Vector3([1.0, 1.0, 1.0]), -45.0, Vector3([0.5, 0.5, 0.5]))

其不同之处在于旋转的负号(并补偿您在 gl_transaltion 中执行的额外转置)。

结果与您在发布的答案中得到的结果不同,但这是由于您的模型矩阵在该答案中被破坏,这是由于错误的乘法函数(特别是删除了平移部分并将旋转扭曲为一些剪切操作)。

我使用 gl_translate2gl_translate3 得到的结果是: screenshot showing a perspectively distorted square 对于指定的参数来说,这看起来非常合理。

关于python - PyOpenGL 透视投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45514353/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com