当前位置: 首页 > 知识库问答 >
问题:

GTK3 GLArea与GLFW的Framebuffer问题(渲染到纹理):相同的OpenGL程序在GLFW中工作,但不在GTK3的GLArea中工作

鲁熙云
2023-03-14

关于我的项目:我在Linux上使用OpenGL3.2,我使用GTK3和GLArea小部件构建了一个基本的应用程序。该程序是用PyCharm IDE用Python编写的。项目解释器被设置为Python 3.8,我已经加载了以下包:Pillow 7.1.2、PyGObject 3.36.1、PyOpenGL 3.1.5、numpy 1.18、pyrr 0.10.3和glfw 1.11.2(见下图)

我有一个使用GLFW可以正确运行的程序,但使用gtk3的glarea不能正确运行。我试图使用自定义framebuffer对象呈现到纹理,基于GTK3的程序不能成功地呈现到自定义framebuffer。然而,基于GLFW的程序呈现得很好。在OpenGL代码中没有区别。我只是更改窗口代码。为了使用自定义framebuffers,GTK3是否需要启用一些东西?GTK3的文档(这里)只指出需要设置特殊标志来启用深度缓冲区和模具缓冲区(我已经启用了这两个),但与自定义纹理缓冲区没有任何关系。

任何和所有的见解都非常赞赏。

import sys
import gi, pyrr
import numpy

gi.require_version('Gtk', '3.0')
from pyrr import matrix44, Vector3
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram
from PIL import Image


class GLCanvas(Gtk.GLArea):
    def __init__(self):
        Gtk.GLArea.__init__(self)
        self.set_required_version(3, 2)             # Sets the version of OpenGL required by this OpenGL program
        self.connect("realize", self.on_initialize) # This signal is used to initialize the OpenGL state
        self.connect("render", self.on_render)      # This signal is emitted for each frame that is rendered
        self.add_tick_callback(self.tick)           # This is a frame time clock that is called each time a frame is rendered
        self.set_start_time = False                 # Boolean to track whether the clock has been initialized
        self.set_has_depth_buffer(True)
        self.set_has_stencil_buffer(True)

    def tick(self, widget, frame_clock):
        self.current_frame_time = frame_clock.get_frame_time()  # Gets the current timestamp in microseconds
        if self.set_start_time == False:                        # Initializes the timer at the start of the program
            self.starting_time = self.current_frame_time        # Stores the timestamp set when the program was initalized
            self.set_start_time = True                          # Prevents the initialization routine from running again in this instance
        self.application_clock = (self.current_frame_time - self.starting_time)/1000000    # Calculate the total number of seconds that the program has been running
        return True                                                     # Returns true to indicate that tick callback should contine to be called

    def on_initialize(self, gl_area):
        # Prints information about our OpenGL Context
        opengl_context = self.get_context()             # Retrieves the Gdk.GLContext used by gl_area
        opengl_context.make_current()                   # Makes the Gdk.GLContext current to the drawing surfaced used by Gtk.GLArea
        major, minor = opengl_context.get_version()     # Gets the version of OpenGL currently used by the opengl_context
        print("\033[93m OpenGL context created successfully.\n -- Using OpenGL Version \033[94m" + str(major) + "." + str(minor) + "\033[0m")

        # Checks to see if there were errors creating the context
        if gl_area.get_error() != None:
            print(gl_area.get_error())

        # Get information about current GTK GLArea canvas
        window = gl_area.get_allocation()

        w_width, w_height = window.width, window.height
        self.aspect_ratio = w_width / w_height

        self.cube_positions = [(1.0, 1.0, 0.0), (0.0, 0.0, 0.0), (2.0, 0.0, 0.0)]
        self.plane_position = matrix44.create_from_translation(Vector3([-3.0, 1.0, 0.0]))

        cube = [-0.5, -0.5, 0.5, 0.0, 0.0,
                0.5, -0.5, 0.5, 1.0, 0.0,
                0.5, 0.5, 0.5, 1.0, 1.0,
                -0.5, 0.5, 0.5, 0.0, 1.0,

                -0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, -0.5, -0.5, 1.0, 0.0,
                0.5, 0.5, -0.5, 1.0, 1.0,
                -0.5, 0.5, -0.5, 0.0, 1.0,

                0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, 0.5, -0.5, 1.0, 0.0,
                0.5, 0.5, 0.5, 1.0, 1.0,
                0.5, -0.5, 0.5, 0.0, 1.0,

                -0.5, 0.5, -0.5, 0.0, 0.0,
                -0.5, -0.5, -0.5, 1.0, 0.0,
                -0.5, -0.5, 0.5, 1.0, 1.0,
                -0.5, 0.5, 0.5, 0.0, 1.0,

                -0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, -0.5, -0.5, 1.0, 0.0,
                0.5, -0.5, 0.5, 1.0, 1.0,
                -0.5, -0.5, 0.5, 0.0, 1.0,

                0.5, 0.5, -0.5, 0.0, 0.0,
                -0.5, 0.5, -0.5, 1.0, 0.0,
                -0.5, 0.5, 0.5, 1.0, 1.0,
                0.5, 0.5, 0.5, 0.0, 1.0]

        cube = numpy.array(cube, dtype=numpy.float32)

        self.cube_indices = [0, 1, 2, 2, 3, 0,
                        4, 5, 6, 6, 7, 4,
                        8, 9, 10, 10, 11, 8,
                        12, 13, 14, 14, 15, 12,
                        16, 17, 18, 18, 19, 16,
                        20, 21, 22, 22, 23, 20]

        self.cube_indices = numpy.array(self.cube_indices, dtype=numpy.uint32)

        plane = [-0.5, -0.5, 0.0, 0.0, 0.0,
                 2.0, -0.5, 0.0, 1.0, 0.0,
                 2.0, 1.0, 0.0, 1.0, 1.0,
                 -0.5, 1.0, 0.0, 0.0, 1.0]

        plane = numpy.array(plane, dtype=numpy.float32)

        self.plane_indices = [0, 1, 2, 2, 3, 0]
        self.plane_indices = numpy.array(self.plane_indices, dtype=numpy.uint32)

        vertex_shader = """
        #version 330
        in layout(location = 0) vec3 position;
        in layout(location = 1) vec2 textCoords;
        uniform mat4 vp;
        uniform mat4 model;
        out vec2 outText;
        void main()
        {
            gl_Position =  vp * model * vec4(position, 1.0f);
            outText = textCoords;
        }
        """

        fragment_shader = """
        #version 330
        in vec2 outText;
        out vec4 outColor;
        uniform sampler2D renderedTexture;
        void main()
        {
            outColor = texture(renderedTexture, outText);
        }
        """

        shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
                                                  OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))

        # cube VAO
        self.cube_vao = glGenVertexArrays(1)
        glBindVertexArray(self.cube_vao)
        cube_VBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, cube_VBO)
        glBufferData(GL_ARRAY_BUFFER, cube.itemsize * len(cube), cube, GL_STATIC_DRAW)
        cube_EBO = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.cube_indices.itemsize * len(self.cube_indices), self.cube_indices, GL_STATIC_DRAW)
        # position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        # textures
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(12))
        glEnableVertexAttribArray(1)
        glBindVertexArray(0)

        # plane VAO
        self.plane_vao = glGenVertexArrays(1)
        glBindVertexArray(self.plane_vao)
        plane_VBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, plane_VBO)
        glBufferData(GL_ARRAY_BUFFER, plane.itemsize * len(plane), plane, GL_STATIC_DRAW)
        plane_EBO = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.plane_indices.itemsize * len(self.plane_indices), self.plane_indices,
                     GL_STATIC_DRAW)
        # position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        # textures
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(12))
        glEnableVertexAttribArray(1)
        glBindVertexArray(0)

        ###########################################################################################

        self.plane_texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.plane_texture)
        # texture wrapping params
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        # texture filtering params
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w_width, w_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
        glBindTexture(GL_TEXTURE_2D, 0)

        depth_buff = glGenRenderbuffers(1)
        glBindRenderbuffer(GL_RENDERBUFFER, depth_buff)
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w_width, w_height)

        self.FBO = glGenFramebuffers(1)
        glBindFramebuffer(GL_FRAMEBUFFER, self.FBO)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.plane_texture, 0)
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buff)
        glBindFramebuffer(GL_FRAMEBUFFER, 0)

        ###########################################################################################
        self.crate_texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.crate_texture)
        # Set the texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        # Set texture filtering parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        # load image
        image = Image.open("models/crate.jpg")
        img_data = numpy.array(list(image.getdata()), numpy.uint8)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
        glBindTexture(GL_TEXTURE_2D, 0)
        ###########################################################################################

        glEnable(GL_DEPTH_TEST)

        view = matrix44.create_from_translation(Vector3([0.0, 0.0, -5.0]))
        projection = matrix44.create_perspective_projection_matrix(45.0, self.aspect_ratio, 0.1, 100.0)

        vp = matrix44.multiply(view, projection)

        glUseProgram(shader)
        vp_loc = glGetUniformLocation(shader, "vp")
        self.model_loc = glGetUniformLocation(shader, "model")
        glUniformMatrix4fv(vp_loc, 1, GL_FALSE, vp)

        return True

    def on_render(self, gl_area, gl_context):

        glClearColor(0.2, 0.25, 0.27, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        rot_y = pyrr.Matrix44.from_y_rotation(self.application_clock * 2)

        # draw to the default frame buffer
        glBindVertexArray(self.cube_vao)
        glBindTexture(GL_TEXTURE_2D, self.crate_texture)
        for i in range(len(self.cube_positions)):
            model = matrix44.create_from_translation(self.cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(self.cube_indices), GL_UNSIGNED_INT, None)

        # draw to the custom frame buffer
        glBindFramebuffer(GL_FRAMEBUFFER, self.FBO)
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        for i in range(len(self.cube_positions)):
            model = matrix44.create_from_translation(self.cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(self.cube_indices), GL_UNSIGNED_INT, None)
        glBindVertexArray(0)
        glBindFramebuffer(GL_FRAMEBUFFER, 0)

        # draw the plane
        glBindVertexArray(self.plane_vao)
        glBindTexture(GL_TEXTURE_2D, self.plane_texture)
        glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, self.plane_position)
        glDrawElements(GL_TRIANGLES, len(self.plane_indices), GL_UNSIGNED_INT, None)
        glBindVertexArray(0)

        self.queue_draw()   # Schedules a redraw for Gtk.GLArea

class RootWindow(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_activate(self):
        window = Gtk.Window(application=self)
        window.set_title("Render To Texture")
        window.set_default_size(1280, 720)
        window.set_position(Gtk.WindowPosition.CENTER)
        window.add(GLCanvas())
        window.show_all()

win = RootWindow()
exit_status = win.run(sys.argv)
sys.exit(exit_status)
import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy
import pyrr
from pyrr import matrix44, Vector3
from PIL import Image


def window_resize(window, width, height):
    glViewport(0, 0, width, height)


cube_positions = [(1.0, 1.0, 0.0), (0.0, 0.0, 0.0), (2.0, 0.0, 0.0)]
plane_position = matrix44.create_from_translation(Vector3([-3.0, 1.0, 0.0]))


def main():
    if not glfw.init():
        return

    w_width, w_height = 1280, 720
    aspect_ratio = w_width / w_height

    window = glfw.create_window(w_width, w_height, "My OpenGL window", None, None)

    if not window:
        glfw.terminate()
        return

    glfw.make_context_current(window)
    glfw.set_window_size_callback(window, window_resize)

    cube = [-0.5, -0.5,  0.5, 0.0, 0.0,
             0.5, -0.5,  0.5, 1.0, 0.0,
             0.5,  0.5,  0.5, 1.0, 1.0,
            -0.5,  0.5,  0.5, 0.0, 1.0,

            -0.5, -0.5, -0.5, 0.0, 0.0,
             0.5, -0.5, -0.5, 1.0, 0.0,
             0.5,  0.5, -0.5, 1.0, 1.0,
            -0.5,  0.5, -0.5, 0.0, 1.0,

             0.5, -0.5, -0.5, 0.0, 0.0,
             0.5,  0.5, -0.5, 1.0, 0.0,
             0.5,  0.5,  0.5, 1.0, 1.0,
             0.5, -0.5,  0.5, 0.0, 1.0,

            -0.5,  0.5, -0.5, 0.0, 0.0,
            -0.5, -0.5, -0.5, 1.0, 0.0,
            -0.5, -0.5,  0.5, 1.0, 1.0,
            -0.5,  0.5,  0.5, 0.0, 1.0,

            -0.5, -0.5, -0.5, 0.0, 0.0,
             0.5, -0.5, -0.5, 1.0, 0.0,
             0.5, -0.5,  0.5, 1.0, 1.0,
            -0.5, -0.5,  0.5, 0.0, 1.0,

             0.5, 0.5, -0.5,  0.0, 0.0,
            -0.5, 0.5, -0.5,  1.0, 0.0,
            -0.5, 0.5,  0.5,  1.0, 1.0,
             0.5, 0.5,  0.5,  0.0, 1.0]

    cube = numpy.array(cube, dtype=numpy.float32)

    cube_indices = [ 0,  1,  2,  2,  3,  0,
                     4,  5,  6,  6,  7,  4,
                     8,  9, 10, 10, 11,  8,
                    12, 13, 14, 14, 15, 12,
                    16, 17, 18, 18, 19, 16,
                    20, 21, 22, 22, 23, 20]

    cube_indices = numpy.array(cube_indices, dtype=numpy.uint32)

    plane = [-0.5, -0.5, 0.0, 0.0, 0.0,
              2.0, -0.5, 0.0, 1.0, 0.0,
              2.0,  1.0, 0.0, 1.0, 1.0,
             -0.5,  1.0, 0.0, 0.0, 1.0]

    plane = numpy.array(plane, dtype=numpy.float32)

    plane_indices = [0, 1, 2, 2, 3, 0]
    plane_indices = numpy.array(plane_indices, dtype=numpy.uint32)

    vertex_shader = """
    #version 330
    in layout(location = 0) vec3 position;
    in layout(location = 1) vec2 textCoords;
    uniform mat4 vp;
    uniform mat4 model;
    out vec2 outText;
    void main()
    {
        gl_Position =  vp * model * vec4(position, 1.0f);
        outText = textCoords;
    }
    """

    fragment_shader = """
    #version 330
    in vec2 outText;
    out vec4 outColor;
    uniform sampler2D renderedTexture;
    void main()
    {
        outColor = texture(renderedTexture, outText);
    }
    """

    shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
                                              OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))

    # cube VAO
    cube_vao = glGenVertexArrays(1)
    glBindVertexArray(cube_vao)
    cube_VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, cube_VBO)
    glBufferData(GL_ARRAY_BUFFER, cube.itemsize * len(cube), cube, GL_STATIC_DRAW)
    cube_EBO = glGenBuffers(1)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_EBO)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, cube_indices.itemsize * len(cube_indices), cube_indices, GL_STATIC_DRAW)
    # position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    # textures
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(12))
    glEnableVertexAttribArray(1)
    glBindVertexArray(0)


    # plane VAO
    plane_vao = glGenVertexArrays(1)
    glBindVertexArray(plane_vao)
    plane_VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, plane_VBO)
    glBufferData(GL_ARRAY_BUFFER, plane.itemsize * len(plane), plane, GL_STATIC_DRAW)
    plane_EBO = glGenBuffers(1)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_EBO)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, plane_indices.itemsize * len(plane_indices), plane_indices, GL_STATIC_DRAW)
    # position
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(0))
    glEnableVertexAttribArray(0)
    # textures
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(12))
    glEnableVertexAttribArray(1)
    glBindVertexArray(0)

    ###########################################################################################

    plane_texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, plane_texture)
    # texture wrapping params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    # texture filtering params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w_width, w_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
    glBindTexture(GL_TEXTURE_2D, 0)

    depth_buff = glGenRenderbuffers(1)
    glBindRenderbuffer(GL_RENDERBUFFER, depth_buff)
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w_width, w_height)

    FBO = glGenFramebuffers(1)
    glBindFramebuffer(GL_FRAMEBUFFER, FBO)
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, plane_texture, 0)
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buff)
    glBindFramebuffer(GL_FRAMEBUFFER, 0)

    ###########################################################################################
    crate_texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, crate_texture)
    # Set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    # Set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    # load image
    image = Image.open("res/crate.jpg")
    img_data = numpy.array(list(image.getdata()), numpy.uint8)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
    glBindTexture(GL_TEXTURE_2D, 0)
    ###########################################################################################

    glEnable(GL_DEPTH_TEST)

    view = matrix44.create_from_translation(Vector3([0.0, 0.0, -5.0]))
    projection = matrix44.create_perspective_projection_matrix(45.0, aspect_ratio, 0.1, 100.0)

    vp = matrix44.multiply(view, projection)

    glUseProgram(shader)
    vp_loc = glGetUniformLocation(shader, "vp")
    model_loc = glGetUniformLocation(shader, "model")
    glUniformMatrix4fv(vp_loc, 1, GL_FALSE, vp)

    while not glfw.window_should_close(window):
        glfw.poll_events()

        glClearColor(0.2, 0.25, 0.27, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        rot_y = pyrr.Matrix44.from_y_rotation(glfw.get_time() * 2)

        # draw to the default frame buffer
        glBindVertexArray(cube_vao)
        glBindTexture(GL_TEXTURE_2D, crate_texture)
        for i in range(len(cube_positions)):
            model = matrix44.create_from_translation(cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(cube_indices), GL_UNSIGNED_INT, None)

        # draw to the custom frame buffer
        glBindFramebuffer(GL_FRAMEBUFFER, FBO)
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        for i in range(len(cube_positions)):
            model = matrix44.create_from_translation(cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(cube_indices), GL_UNSIGNED_INT, None)
        glBindVertexArray(0)
        glBindFramebuffer(GL_FRAMEBUFFER, 0)

        # draw the plane
        glBindVertexArray(plane_vao)
        glBindTexture(GL_TEXTURE_2D, plane_texture)
        glUniformMatrix4fv(model_loc, 1, GL_FALSE, plane_position)
        glDrawElements(GL_TRIANGLES, len(plane_indices), GL_UNSIGNED_INT, None)
        glBindVertexArray(0)

        glfw.swap_buffers(window)

    glfw.terminate()


if __name__ == "__main__":
    main()

共有1个答案

安奇
2023-03-14

事实证明,GLArea没有使用framebuffer0作为默认值。这里的问题是在使用glBindFramebuffer(GL_FRAMEBUFFER,0)的呈现循环结束时将framebuffer重置回0。相反,在呈现循环开始时使用default_ID=glGetIntegerv(GL_FRAMEBUFFER_BINDING)获取当前默认ID。在循环结束时,使用glBindFramebuffer(GL_FRAMEBUFFER,default_ID)重置为默认的framebuffer。

    import sys
import gi, pyrr
import numpy

gi.require_version('Gtk', '3.0')
from pyrr import matrix44, Vector3
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram
from PIL import Image


class GLCanvas(Gtk.GLArea):
    def __init__(self):
        Gtk.GLArea.__init__(self)
        self.set_required_version(3, 2)             # Sets the version of OpenGL required by this OpenGL program
        self.connect("realize", self.on_initialize) # This signal is used to initialize the OpenGL state
        self.connect("render", self.on_render)      # This signal is emitted for each frame that is rendered
        self.add_tick_callback(self.tick)           # This is a frame time clock that is called each time a frame is rendered
        self.set_start_time = False                 # Boolean to track whether the clock has been initialized
        self.set_has_depth_buffer(True)
        self.set_has_stencil_buffer(True)

    def tick(self, widget, frame_clock):
        self.current_frame_time = frame_clock.get_frame_time()  # Gets the current timestamp in microseconds
        if self.set_start_time == False:                        # Initializes the timer at the start of the program
            self.starting_time = self.current_frame_time        # Stores the timestamp set when the program was initalized
            self.set_start_time = True                          # Prevents the initialization routine from running again in this instance
        self.application_clock = (self.current_frame_time - self.starting_time)/1000000    # Calculate the total number of seconds that the program has been running
        return True                                                     # Returns true to indicate that tick callback should contine to be called

    def on_initialize(self, gl_area):
        # Prints information about our OpenGL Context
        opengl_context = self.get_context()             # Retrieves the Gdk.GLContext used by gl_area
        opengl_context.make_current()                   # Makes the Gdk.GLContext current to the drawing surfaced used by Gtk.GLArea
        major, minor = opengl_context.get_version()     # Gets the version of OpenGL currently used by the opengl_context
        # https://stackoverflow.com/questions/287871/how-to-print-colored-text-in-terminal-in-python
        print("\033[93m OpenGL context created successfully.\n -- Using OpenGL Version \033[94m" + str(major) + "." + str(minor) + "\033[0m")

        # Checks to see if there were errors creating the context
        if gl_area.get_error() != None:
            print(gl_area.get_error())

        # Get information about current GTK GLArea canvas
        window = gl_area.get_allocation()

        w_width, w_height = window.width, window.height
        self.aspect_ratio = w_width / w_height

        self.cube_positions = [(1.0, 1.0, 0.0), (0.0, 0.0, 0.0), (2.0, 0.0, 0.0)]
        self.plane_position = matrix44.create_from_translation(Vector3([-3.0, 1.0, 0.0]))

        cube = [-0.5, -0.5, 0.5, 0.0, 0.0,
                0.5, -0.5, 0.5, 1.0, 0.0,
                0.5, 0.5, 0.5, 1.0, 1.0,
                -0.5, 0.5, 0.5, 0.0, 1.0,

                -0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, -0.5, -0.5, 1.0, 0.0,
                0.5, 0.5, -0.5, 1.0, 1.0,
                -0.5, 0.5, -0.5, 0.0, 1.0,

                0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, 0.5, -0.5, 1.0, 0.0,
                0.5, 0.5, 0.5, 1.0, 1.0,
                0.5, -0.5, 0.5, 0.0, 1.0,

                -0.5, 0.5, -0.5, 0.0, 0.0,
                -0.5, -0.5, -0.5, 1.0, 0.0,
                -0.5, -0.5, 0.5, 1.0, 1.0,
                -0.5, 0.5, 0.5, 0.0, 1.0,

                -0.5, -0.5, -0.5, 0.0, 0.0,
                0.5, -0.5, -0.5, 1.0, 0.0,
                0.5, -0.5, 0.5, 1.0, 1.0,
                -0.5, -0.5, 0.5, 0.0, 1.0,

                0.5, 0.5, -0.5, 0.0, 0.0,
                -0.5, 0.5, -0.5, 1.0, 0.0,
                -0.5, 0.5, 0.5, 1.0, 1.0,
                0.5, 0.5, 0.5, 0.0, 1.0]

        cube = numpy.array(cube, dtype=numpy.float32)

        self.cube_indices = [0, 1, 2, 2, 3, 0,
                        4, 5, 6, 6, 7, 4,
                        8, 9, 10, 10, 11, 8,
                        12, 13, 14, 14, 15, 12,
                        16, 17, 18, 18, 19, 16,
                        20, 21, 22, 22, 23, 20]

        self.cube_indices = numpy.array(self.cube_indices, dtype=numpy.uint32)

        plane = [-0.5, -0.5, 0.0, 0.0, 0.0,
                 2.0, -0.5, 0.0, 1.0, 0.0,
                 2.0, 1.0, 0.0, 1.0, 1.0,
                 -0.5, 1.0, 0.0, 0.0, 1.0]

        plane = numpy.array(plane, dtype=numpy.float32)

        self.plane_indices = [0, 1, 2, 2, 3, 0]
        self.plane_indices = numpy.array(self.plane_indices, dtype=numpy.uint32)

        vertex_shader = """
        #version 330
        in vec3 position;
        in vec2 textCoords;
        uniform mat4 vp;
        uniform mat4 model;
        out vec2 outText;
        void main()
        {
            gl_Position =  vp * model * vec4(position, 1.0f);
            outText = textCoords;
        }
        """

        fragment_shader = """
        #version 330
        in vec2 outText;
        out vec4 outColor;
        uniform sampler2D renderedTexture;
        void main()
        {
            outColor = texture(renderedTexture, outText);
        }
        """

        shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
                                                  OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))

        # cube VAO
        self.cube_vao = glGenVertexArrays(1)
        glBindVertexArray(self.cube_vao)
        cube_VBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, cube_VBO)
        glBufferData(GL_ARRAY_BUFFER, cube.itemsize * len(cube), cube, GL_STATIC_DRAW)
        cube_EBO = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube_EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.cube_indices.itemsize * len(self.cube_indices), self.cube_indices, GL_STATIC_DRAW)
        # position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        # textures
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, cube.itemsize * 5, ctypes.c_void_p(12))
        glEnableVertexAttribArray(1)
        glBindVertexArray(0)

        # plane VAO
        self.plane_vao = glGenVertexArrays(1)
        glBindVertexArray(self.plane_vao)
        plane_VBO = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, plane_VBO)
        glBufferData(GL_ARRAY_BUFFER, plane.itemsize * len(plane), plane, GL_STATIC_DRAW)
        plane_EBO = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane_EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.plane_indices.itemsize * len(self.plane_indices), self.plane_indices,
                     GL_STATIC_DRAW)
        # position
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(0))
        glEnableVertexAttribArray(0)
        # textures
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, plane.itemsize * 5, ctypes.c_void_p(12))
        glEnableVertexAttribArray(1)
        glBindVertexArray(0)

        ###########################################################################################

        self.plane_texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.plane_texture)
        # texture wrapping params
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        # texture filtering params
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w_width, w_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
        glBindTexture(GL_TEXTURE_2D, 0)

        depth_buff = glGenRenderbuffers(1)
        glBindRenderbuffer(GL_RENDERBUFFER, depth_buff)
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w_width, w_height)

        self.FBO = glGenFramebuffers(1)
        glBindFramebuffer(GL_FRAMEBUFFER, self.FBO)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.plane_texture, 0)
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buff)
        glBindFramebuffer(GL_FRAMEBUFFER, 0)

        ###########################################################################################
        self.crate_texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.crate_texture)
        # Set the texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        # Set texture filtering parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        # load image
        image = Image.open("models/crate.jpg")
        img_data = numpy.array(list(image.getdata()), numpy.uint8)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
        glBindTexture(GL_TEXTURE_2D, 0)
        ###########################################################################################

        glEnable(GL_DEPTH_TEST)

        view = matrix44.create_from_translation(Vector3([0.0, 0.0, -5.0]))
        projection = matrix44.create_perspective_projection_matrix(45.0, self.aspect_ratio, 0.1, 100.0)

        vp = matrix44.multiply(view, projection)

        glUseProgram(shader)
        vp_loc = glGetUniformLocation(shader, "vp")
        self.model_loc = glGetUniformLocation(shader, "model")
        glUniformMatrix4fv(vp_loc, 1, GL_FALSE, vp)

        return True

    def on_render(self, gl_area, gl_context):
        default_ID = glGetIntegerv(GL_FRAMEBUFFER_BINDING)
        glClearColor(0.2, 0.25, 0.27, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        rot_y = pyrr.Matrix44.from_y_rotation(self.application_clock * 2)

        # draw to the default frame buffer
        glBindVertexArray(self.cube_vao)
        glBindTexture(GL_TEXTURE_2D, self.crate_texture)
        for i in range(len(self.cube_positions)):
            model = matrix44.create_from_translation(self.cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(self.cube_indices), GL_UNSIGNED_INT, None)

        # draw to the custom frame buffer
        glBindFramebuffer(GL_FRAMEBUFFER, self.FBO)
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        for i in range(len(self.cube_positions)):
            model = matrix44.create_from_translation(self.cube_positions[i])
            if i == 0:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, rot_y * model)
            elif i == 1:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)
            else:
                glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, model)

            glDrawElements(GL_TRIANGLES, len(self.cube_indices), GL_UNSIGNED_INT, None)

        glBindFramebuffer(GL_FRAMEBUFFER, default_ID)
        glBindVertexArray(0)

        # draw the plane
        glBindVertexArray(self.plane_vao)
        glBindTexture(GL_TEXTURE_2D, self.plane_texture)
        glUniformMatrix4fv(self.model_loc, 1, GL_FALSE, self.plane_position)
        glDrawElements(GL_TRIANGLES, len(self.plane_indices), GL_UNSIGNED_INT, None)
        glBindVertexArray(0)

        self.queue_draw()   # Schedules a redraw for Gtk.GLArea

class RootWindow(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_activate(self):
        window = Gtk.Window(application=self)
        window.set_title("Render To Texture")
        window.set_default_size(1280, 720)
        window.set_position(Gtk.WindowPosition.CENTER)
        window.add(GLCanvas())
        window.show_all()

win = RootWindow()
exit_status = win.run(sys.argv)
sys.exit(exit_status)
 类似资料:
  • 我正在对对象进行两次模糊处理。为了确保在中,整个场景都被我试图模糊的图像所覆盖。这是过程。 > < li >我设置了一个< code>FBO,其中包含我需要模糊的图像尺寸。 < li> 我正在使用以下函数设置< code >正交投影(称为< code >设置正交(FBO尺寸)): glViewport(0,0,w,h)glMatrixMode(GL _ PROJECTION)glload iden

  • 我使用OpenGL 3.2来渲染阴影贴图。为此,我构造了一个渲染深度纹理的帧缓冲区。 要将纹理附加到帧缓冲区,我使用: 这很有效。渲染灯光视图后,我的GLSL着色器可以对深度纹理进行采样,以解决灯光的可见性问题。 我现在试图解决的问题是有更多的阴影贴图,比如说50个。在我的主要渲染过程中,我不想从50个不同的纹理中采样。我可以使用图集,但我想知道:我可以将所有这些阴影贴图作为2D纹理数组的切片传递

  • 纹理根本不渲染,几何体都是黑色的。 截图:http://i.imgur.com/ypMdQY4.png 代码:http://pastebin.com/SvB8rxxt 我也会链接到我试图渲染的纹理和transformations.py模块,但是我没有被允许放置两个以上链接的声誉。谷歌搜索“现代opengl 02”会给你前者的教程,“转换py”会给你后者。 搜索“纹理材料开始”以查找纹理材料的设置位

  • 我对OpenGL、GLFW或GLEW没有太多的经验,所以我对这些库的故障排除能力微乎其微。我已经设法呈现了一个三角形([-1,-1,0],[1,-1,0],[0,1,0]),但是当使用顶点属性坐标和颜色属性作为立方体时,它似乎无法呈现。我的代码、着色器和矩阵运算可能有很多问题。我希望我对我所做的事情有更清楚的了解,这样我就可以对我的错误有更详细的描述。目前,上面的代码只呈现窗口。我最初遵循http

  • 我正在尝试使用OpenGL GLSL着色器渲染到纹理。首先,我尝试用白色填充30x30纹理的每个像素。我将顶点着色器索引从0传递到899,表示纹理的每个像素。对吗?顶点着色器: 片段着色器:

  • 我正在努力熟悉Java的LWJGL库,我一直在线学习一些教程,我似乎无法渲染模型。 我使用的是OpenGL 2.1(这似乎非常过时,但我不知道如何更新它,我知道它与你的硬件捆绑在一起,如果有人对我的规格感兴趣,我使用的是MacBook Pro 2017型号) 如果有人能看看我的代码,告诉我哪里做错了,我会非常感激!(现在呈现的只是一个红色窗口) 从我研究过的来源来看,这段代码应该会产生一个由两个三