Reputation: 25
I'm trying to render a texture in OpenGL. However, the texture is completely black.
The texture is rendered on a screen-sized quad made of 2 triangles. The triangles are rendered with the triangle fan mode.
It would be really helpful if someone could point out the problem in my code.
Creating the texture:
texture = gl.glGenTextures(1)
gl.glActiveTexture(gl.GL_TEXTURE0)
gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT);
viewport = gl.glGetIntegerv(gl.GL_VIEWPORT)
width = viewport[2]
height = viewport[3]
print(width, height)
image = Image.open("./madeline.jpg").convert('RGB')
data = np.array(image).flatten()
#gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, width, height, 0, gl.GL_RGB, gl.GL_FLOAT, None)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, 1920, 1080, 0, gl.GL_RGB, gl.GL_UNSIGNED_INT, data)
gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
vertex data:
# vertex -> x, y, z, u, v
vertices = [
-1, 1, 0, 0, 1, # top-left
1, 1, 0, 1, 1, # top-right
1, -1, 0, 1, 0, # bottom-right
-1, -1, 0, 0, 0 # bottom-left
]
Setting up buffer:
# setup buffers
vao = gl.glGenVertexArrays(1)
vbo = gl.glGenBuffers(1)
gl.glBindVertexArray(vao)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo)
gl.glBufferData(gl.GL_ARRAY_BUFFER, len(vertices) * floatSize, np.array(vertices, dtype="float32"), gl.GL_STATIC_DRAW)
gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 5 * floatSize, None)
gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, 5 * floatSize, 3 * floatSize)
gl.glEnableVertexAttribArray(0)
gl.glEnableVertexAttribArray(1)
gl.glBindVertexArray(vao)
vertex shader:
#version 430 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 texCoord;
out vec2 tex;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
tex = texCoord;
}
fragment shader:
#version 430 core
out vec4 fragColour;
in vec2 tex;
uniform sampler2D ourTex;
void main(){
fragColour = texture(ourTex, tex);
}
main loop:
while not glfwWindowShouldClose(window):
gl.glClearColor(0.2, 0.3, 0.3, 1.0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
#gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_INT, 0)
gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4)
glfwSwapBuffers(window)
glfwPollEvents()
code: https://github.com/RandomPigYT/raytracer
Upvotes: 1
Views: 70
Reputation: 210909
You cannot load the image object directly into a NumPy array. You must retrieve the contents of the image with Image.getdata
. The type of the image data is GL_UNSIGNED_BYTE
and I suggest using the size
attribute of the Image
object.
image = Image.open("./madeline.jpg").convert('RGBA')
data = np.array(list(image.getdata()), np.uint8)
width, height = image.size
gl.glTexImage2D(
gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0,
gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, data)
You can also use Image.tobytes
to return the image as a bytes object.
image = Image.open("./madeline.jpg").convert('RGBA')
data = image.tobytes()
width, height = image.size
gl.glTexImage2D(
gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0,
gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, data)
The last argument of glVertexAttribPointer
is a pointer not an integer:
gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, 5 * floatSize, 3 * floatSize)
gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, gl.GL_FALSE, 5 * floatSize,
ctypes.c_void_p(3 * floatSize))
Upvotes: 0