python - pyOpenGL纹理不渲染

标签 python python-3.x opengl pyopengl

所以我一直在绞尽脑汁地不断尝试和犯错。我觉得我总是带着关于同一件事的问题回来,这令人沮丧。

我正在按照教程查看 C++ 代码,并按照 Python 尝试复制结果。我注意到通过反复试验存在细微的差异,并且我在互联网上进行了多次搜索,看看其他人是否遇到了我的问题。 9/10 次是因为纹理没有绑定(bind),但是,我的情况是这样。 https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/4.1.textures/textures.cpp

所以我想知道我做错了什么......有什么帮助吗?

import os       # For mac... I am using a mac
import glfw     # We're using this instead of GLUT as we have more flexibility
import numpy as np    # We will use numpy for our arrays
# Using the API wrapper instead of something mugh higher. Keep in mind that the API is a state machine
from OpenGL.GL import *
from OpenGL.arrays import *
from ctypes import c_void_p
from PIL import Image

class HelloWindow():

    width = 800
    height = 640
    title = 'Hello Window'
    window = None
    shader_program = None
    vao = None
    vbo = None
    texture = None

    vertex_gsl = """
        #version 410 core
        layout (location = 0) in vec3 aPos;
        layout (location = 1) in vec3 aColor;
        layout (location = 3) in vec2 aTexCoord;

        out vec3 ourColor;
        out vec2 TexCoord;

        void main() {
            gl_Position = vec4(aPos, 1.0);
            ourColor = aColor;
            TexCoord = vec2(aTexCoord);
        }
    """

    fragment_gsl = """
        #version 410 core
        out vec4 FragColor;

        in vec3 ourColor;
        in vec2 TexCoord;

        uniform sampler2D texture1;

        void main() {
            FragColor = texture(texture1, TexCoord);
        }
    """

    def __init__(self):
        if not glfw.init():
            raise TypeError('Unable to initalize glfw')
        self.main()

    def main(self):
        # Set window hints
        self.set_window_hints()
        # Create the window
        self.create_window()

        max_vertex_attributes = glGetIntegerv(GL_MAX_VERTEX_ATTRIBS)
        print('Maximum number of vertex attributes in a vertex shader is: ' + str(max_vertex_attributes))

        # Keep the window open in a loop
        self.loop()

    def set_window_hints(self):
        glfw.window_hint(glfw.SAMPLES, 4)
        # Using the core version in Mac OS but can be set to something else
        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)

    def create_window(self):
        self.window = glfw.create_window(self.width, self.height, self.title, None, None)

        if not self.window:
            raise TypeError('Unable to create the window')
            glfw.terminate()

        glfw.make_context_current(self.window)
        glfw.set_framebuffer_size_callback(self.window, self.frame_buffer_size)


        ### Let's setup our data
        verts = np.array([
            # positions         # colors        # texture coords
            [-0.5, 0.5, 0.0,    1.0, 0.0, 0.0,  0.0, 1.0],
            [-0.5, -0.5, 0.0,   0.0, 1.0, 0.0,  0.0, 0.0],
            [0.5, -0.5, 0.0,    0.0, 0.0, 1.0,  1.0, 0.0],
            [0.5, 0.5, 0.0,     1.0, 1.0, 0.0,  1.0, 1.0]
        ], dtype=np.float32) # OpenGL expects 32 bit data. Not 64 bit if you're on a 64 bit machine

        indicies = np.array([
            [0, 1, 3],
            [1, 2, 3]
        ], dtype=np.uint32)

        self.vao = glGenVertexArrays(1)
        self.vbo = glGenBuffers(1)
        self.ebo = glGenBuffers(1)

        glBindVertexArray(self.vao)

        glBindBuffer(GL_ARRAY_BUFFER, self.vbo) # Bind the buffer as an array buffer and not an element buffer
        glBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ebo)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies, GL_STATIC_DRAW)

        glVertexAttribPointer(0, 3, GL_FLOAT, False, 8 * verts.itemsize, None)
        glEnableVertexAttribArray(0)

        glVertexAttribPointer(1, 3, GL_FLOAT, False, 8 * verts.itemsize, c_void_p(3 * verts.itemsize))
        glEnableVertexAttribArray(1)

        glVertexAttribPointer(2, 2, GL_FLOAT, False, 8 * verts.itemsize, c_void_p(6 * verts.itemsize))
        glEnableVertexAttribArray(2)

        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.setup_shader()

        self.texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.texture)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)

        # Set the wrapping texture parameters for x,y equivalents
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)

        # Set the texture filtering parameters from min to max
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        # Load our image
        img = Image.open('../res/container.jpg')
        img.transpose(Image.FLIP_TOP_BOTTOM)
        img.convert('RGB')
        data = np.array(list(img.getdata()), np.uint8)

        # Set the texture data
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width, img.height, 0, GL_RGB, GL_UNSIGNED_BYTE, data)
        glGenerateMipmap(GL_TEXTURE_2D)

        #img.close()

    def loop(self):
        while not glfw.window_should_close(self.window):
            glClearColor(0.2, 0.3, 0.3, 1.0)
            glClear(GL_COLOR_BUFFER_BIT)    # We always use this after we clear the color

            # Maintain aspect ratio (optional)
            glfw.set_window_aspect_ratio(self.window, self.width, self.height)

            # Handle input
            self.capture_input()

            # Bind the texture
            glBindTexture(GL_TEXTURE_2D, self.texture)

            # Do some rendering
            glUseProgram(self.shader_program)
            glBindVertexArray(self.vao)
            #glEnableVertexAttribArray(0)
            #glDrawArrays(GL_TRIANGLES, 0, 3)
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)

            glfw.swap_interval(1)
            glfw.swap_buffers(self.window)
            glfw.poll_events()

        glfw.destroy_window(self.window)

        # Add the vao and vbo to an array so they're deleted. We can use this when creating several vaos and vbos
        vao_list = np.array([self.vao], dtype=np.uint32)
        vbo_list = np.array([self.vbo], dtype=np.uint32)

        glDeleteVertexArrays(1, vao_list)
        glDeleteBuffers(1, vbo_list)
        glfw.terminate()

    def capture_input(self):
        if glfw.get_key(self.window, glfw.KEY_ESCAPE) == glfw.PRESS: # Get the key pressed and check if it is escape key
            glfw.set_window_should_close(self.window, True)

    def frame_buffer_size(self, window, width, height):
        glViewport(0, 0, width, height)

    def setup_shader(self):
        vertex_shader = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vertex_shader, self.vertex_gsl)
        glCompileShader(vertex_shader)

        if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS):
            glGetShaderInfoLog(vertex_shader, 512, None)
            raise TypeError('vertex_shader did not compile correctly. Check the GSL')

        fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
        glShaderSource(fragment_shader, self.fragment_gsl)
        glCompileShader(fragment_shader)

        if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS):
            glGetShaderInfoLog(fragment_shader, 512, None)
            raise TypeError('fragment_shader did not compile correctly. Check the GSL')

        self.shader_program = glCreateProgram()
        glAttachShader(self.shader_program, vertex_shader)
        glAttachShader(self.shader_program, fragment_shader)
        glLinkProgram(self.shader_program)

        if not glGetProgramiv(self.shader_program, GL_LINK_STATUS):
            glGetProgramInfoLog(self.shader_program, 512, None)

        glDeleteShader(vertex_shader)
        glDeleteShader(fragment_shader)


if __name__ == '__main__':
    hello_window = HelloWindow()

最佳答案

程序中为纹理坐标数组指定的属性索引为2:

glVertexAttribPointer(2, 2, GL_FLOAT, False, 8 * verts.itemsize, c_void_p(6 * verts.itemsize))
glEnableVertexAttribArray(2)

但是在顶点着色器中为纹理坐标指定的属性索引是3,由Layout Qualifier :

layout (location = 3) in vec2 aTexCoord;

在这两种情况下使用相同的属性索引,您的纹理就会显示出来。

关于python - pyOpenGL纹理不渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49699388/

相关文章:

python - qtablewidget 的 pyqt 自定义项目委托(delegate)

Python输出从方法返回的MySQL数据

python - 在 C++ 应用程序中嵌入 python 环境

旋转前后的 OpenGL 平移

opengl - 在 OpenGL 中使用不同的缓冲区绘制多个对象

python - 新手 Python 关于参数为 : "%%s"? 的字符串的问题

python - Pytest 和 Python 3

python-3.x - Flask-Pandas 创建下载文件

python - 在使用 Glade 创建的 Python GTK3 程序中导入 CSS 文件

C++:使用带尖括号的#include <>放置文件的位置