问题描述
我正在尝试将木质纹理添加到三角形中。代码仅适用于三角形。但是在尝试添加纹理时会引发错误。我认为问题出在GLSL或创建EBO / VBO(不确定)中。整个屏幕保持黑色。
from OpenGL.GL import *
from OpenGL.glu import *
from OpenGL.GL import shaders
import glfw
import numpy as np
from PIL import Image
VERTEX_SHADER = """
#version 330
layout (location = 0) in vec4 position;
in vec2 InTexCoords;
out vec2 OutTexCoords;
void main(){
gl_Position = position;
OutTexCoords = InTexCoords;
}
"""
FRAGMENT_SHADER = """
#version 330
out vec4 FragColor;
uniform vec4 triangleColor;
in vec2 OutTexCoords;
uniform sampler2D sampleTex;
void main() {
FragColor = texture(sampleTex,OutTexCoords);
}
"""
shaderProgram = None
def initialize():
global VERTEXT_SHADER
global FRAGMENT_SHADER
global shaderProgram
#compiling shaders
vertexshader = shaders.compileShader(VERTEX_SHADER,GL_VERTEX_SHADER)
fragmentshader = shaders.compileShader(FRAGMENT_SHADER,GL_FRAGMENT_SHADER)
#creating shaderProgram
shaderProgram = shaders.compileProgram(vertexshader,fragmentshader)
#vertex and indices data
#triangle #texture
vertices = [-0.5,-0.5,0.0,0.5,1.0,1.0]
indices = [0,1,2]
vertices = np.array(vertices,dtype=np.float32)
indices = np.array(vertices,dtype=np.float32)
#add vertices to buffer
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,VBO)
glBufferData(GL_ARRAY_BUFFER,vertices.nbytes,vertices,GL_STATIC_DRAW)
#add indices to buffer
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices,GL_STATIC_DRAW)
position = 0
glVertexAttribPointer(position,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(0))
glEnabLevertexAttribArray(position)
texCoords = 1
glBindAttribLocation( shaderProgram,texCoords,'InTexCoords')
glVertexAttribPointer(texCoords,2,ctypes.c_void_p(12))
glEnabLevertexAttribArray(texCoords)
#creating texture
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_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
image = Image.open("wood.jpg")
img_data = np.array(list(image.getdata()),np.uint8)
glTexImage2D(GL_TEXTURE_2D,GL_RGB,512,GL_UNSIGNED_BYTE,img_data)
def render(window):
global shaderProgram
glClearColor(0,1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
gluseProgram(shaderProgram)
glDrawElements(GL_TRIANGLES,GL_UNSIGNED_INT,None)
gluseProgram(0)
glfw.swap_buffers(window)
def main():
glfw.init()
window = glfw.create_window(640,640,"EXAMPLE PROGRAM",None,None)
glfw.make_context_current(window)
initialize()
while not glfw.window_should_close(window):
glfw.poll_events()
render(window)
glfw.terminate()
if __name__ == '__main__':
main()
我试图遵循本教程learnopengl。但是本教程使用C ++。此外,我的方法略有不同。我不在顶点添加颜色代码。但我认为这不是添加纹理的问题。
解决方法
glVertexAttribPointer
的跨度参数指定连续的通用顶点属性之间的字节偏移。您的属性由具有3个分量的顶点坐标和具有2个分量的纹理坐标组成。因此,您的跨步参数必须为20(5 * 4个字节),而不是24:
glVertexAttribPointer(position,3,GL_FLOAT,GL_FALSE,24,ctypes.c_void_p(0))
glVertexAttribPointer(position,20,ctypes.c_void_p(0))
glVertexAttribPointer(texCoords,2,ctypes.c_void_p(12))
glVertexAttribPointer(texCoords,ctypes.c_void_p(12))
索引的数据类型必须是整数。绘图调用(glDrawElements(...,...,GL_UNSIGNED_INT,...)
)中的类型必须与此类型匹配。使用uint32
而不是float
(和vertices
-> indices
):
indices = np.array(vertices,dtype=np.float32)
indices = np.array(indices,dtype=np.uint32)
必须在链接程序之前(在glBindAttribLocation
之前)将通用顶点属性索引与命名属性变量(glLinkProgram
)关联。
我建议通过Layout Qualifier设置属性索引:
layout (location = 0) in vec4 position;
layout (location = 1) in vec2 InTexCoords;