在 PyOpenGL 中使用 VAO 获取黑屏
Getting black screen using VAO in PyOpenGL
我正在使用 python 和 OpenGL 渲染一些 3d 图形。
虽然使用更简单的方法(没有 VAO 和复杂属性指针)成功呈现,如所述here(仅使用两次调用来绑定我的 VBO:glEnableClientState(GL_VERTEX_ARRAY); glVertexPointerf( vbo )
)
当尝试组合简单的 VBO(仅包含顶点位置数据)和 VAO 时,我总是出现黑屏。为了实现当前的代码版本,我发现这个 SO answer 详细描述了应该如何完成。但是我自己写这个除了黑屏什么都没有。
简化代码:
import OpenGL
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import shaders
from OpenGL.arrays import vbo
import numpy as np
glutInit()
glutInitContextVersion(3, 3)
glutInitContextProfile(GLUT_CORE_PROFILE)
### Init Widow
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
glutInitWindowPosition(0, 0)
wind = glutCreateWindow("OpenGL Window")
###
### Load shaders from files and compile into program
with open("vert.glsl", "r") as f:
vert_text = f.read()
with open("frag.glsl", "r") as f:
frag_text = f.read()
vert_shader = shaders.compileShader(vert_text, GL_VERTEX_SHADER)
frag_shader = shaders.compileShader(frag_text, GL_FRAGMENT_SHADER)
main_shader = shaders.compileProgram(vert_shader, frag_shader)
###
### Create Vertex Buffer Object
data_arr = np.array(
[[-1, -1, 0], [0, 1, 0], [1, -1, 0]], dtype=np.float32
) # define vertices
vvbo = glGenBuffers(1) # generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vvbo) # bind buffer
glBufferData(
GL_ARRAY_BUFFER, data_arr.nbytes, data_arr, GL_DYNAMIC_DRAW
) # setud data for buffer
###
### Setup VAO
mvao = glGenVertexArrays(1) # Create Vertex Array Object
glBindVertexArray(mvao) # Bind VAO
glEnableVertexAttribArray(0) # Enable attribute: 0
glBindBuffer(GL_ARRAY_BUFFER, vvbo) # bind vertice's buffer
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0
) # setup attribute layout
###
glBindVertexArray(0) # unbind vao
glDisableVertexAttribArray(0) # desibale attribute
glBindBuffer(GL_ARRAY_BUFFER, 0) # unbind data buffer
def showScreen():
global main_shader, mvao
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear screen
glUseProgram(main_shader) # enable main shader
glBindVertexArray(mvao) # bind VAO
glDrawArrays(GL_TRIANGLES, 0, 3) # draw
glBindVertexArray(0) # unbind VAO
glUseProgram(0) # unbind shader
glutSwapBuffers() # update screen
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMainLoop()
frag.glsl:
#version 330 core
out vec4 _fragColor;
void main()
{
_fragColor = vec4(0.5);
}
vert.glsl:
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
那么我到底做错了什么?
Python 版本 -> 3.8
如果绑定了命名缓冲区对象,则 glVertexAttribPointer
的第 6 个参数被视为缓冲区对象数据存储中的字节偏移量。但是参数的类型无论如何都是指针(c_void_p
).
所以如果偏移量为0,那么第6个参数可以是None
或者c_void_p(0)
:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0)
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, None
)
我正在使用 python 和 OpenGL 渲染一些 3d 图形。
虽然使用更简单的方法(没有 VAO 和复杂属性指针)成功呈现,如所述here(仅使用两次调用来绑定我的 VBO:glEnableClientState(GL_VERTEX_ARRAY); glVertexPointerf( vbo )
)
当尝试组合简单的 VBO(仅包含顶点位置数据)和 VAO 时,我总是出现黑屏。为了实现当前的代码版本,我发现这个 SO answer 详细描述了应该如何完成。但是我自己写这个除了黑屏什么都没有。
简化代码:
import OpenGL
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import shaders
from OpenGL.arrays import vbo
import numpy as np
glutInit()
glutInitContextVersion(3, 3)
glutInitContextProfile(GLUT_CORE_PROFILE)
### Init Widow
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
glutInitWindowPosition(0, 0)
wind = glutCreateWindow("OpenGL Window")
###
### Load shaders from files and compile into program
with open("vert.glsl", "r") as f:
vert_text = f.read()
with open("frag.glsl", "r") as f:
frag_text = f.read()
vert_shader = shaders.compileShader(vert_text, GL_VERTEX_SHADER)
frag_shader = shaders.compileShader(frag_text, GL_FRAGMENT_SHADER)
main_shader = shaders.compileProgram(vert_shader, frag_shader)
###
### Create Vertex Buffer Object
data_arr = np.array(
[[-1, -1, 0], [0, 1, 0], [1, -1, 0]], dtype=np.float32
) # define vertices
vvbo = glGenBuffers(1) # generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vvbo) # bind buffer
glBufferData(
GL_ARRAY_BUFFER, data_arr.nbytes, data_arr, GL_DYNAMIC_DRAW
) # setud data for buffer
###
### Setup VAO
mvao = glGenVertexArrays(1) # Create Vertex Array Object
glBindVertexArray(mvao) # Bind VAO
glEnableVertexAttribArray(0) # Enable attribute: 0
glBindBuffer(GL_ARRAY_BUFFER, vvbo) # bind vertice's buffer
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0
) # setup attribute layout
###
glBindVertexArray(0) # unbind vao
glDisableVertexAttribArray(0) # desibale attribute
glBindBuffer(GL_ARRAY_BUFFER, 0) # unbind data buffer
def showScreen():
global main_shader, mvao
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear screen
glUseProgram(main_shader) # enable main shader
glBindVertexArray(mvao) # bind VAO
glDrawArrays(GL_TRIANGLES, 0, 3) # draw
glBindVertexArray(0) # unbind VAO
glUseProgram(0) # unbind shader
glutSwapBuffers() # update screen
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMainLoop()
frag.glsl:
#version 330 core
out vec4 _fragColor;
void main()
{
_fragColor = vec4(0.5);
}
vert.glsl:
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
那么我到底做错了什么?
Python 版本 -> 3.8
如果绑定了命名缓冲区对象,则 glVertexAttribPointer
的第 6 个参数被视为缓冲区对象数据存储中的字节偏移量。但是参数的类型无论如何都是指针(c_void_p
).
所以如果偏移量为0,那么第6个参数可以是None
或者c_void_p(0)
:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, 0)
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, 3 * data_arr.dtype.itemsize, None
)