def build_buffer(): buffer = gl.GLuint(0) gl.glGenFramebuffers(1, ctypes.byref(buffer)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, buffer) texture = gl.GLuint(0) gl.glGenTextures(1, ctypes.byref(texture)) gl.glEnable(gl.GL_TEXTURE_2D) gl.glBindTexture(gl.GL_TEXTURE_2D, texture) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, BUF_WIDTH, BUF_HEIGHT, 0, gl.GL_RGBA, gl.GL_FLOAT, None) 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.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, texture, 0) if (gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE): raise RuntimeError('Framebuffer incomplete !') gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) gl.glBindTexture(gl.GL_TEXTURE_2D, 0) gl.glDisable(gl.GL_TEXTURE_2D) return buffer, texture
def setupFBOandTextures(self): self.framebufferA0 = (gl.GLuint * args["resolution"])() self.A0_tex = gl.GLuint(0) self.draw_buffersA0 = (gl.GLenum * args["resolution"])( gl.GL_COLOR_ATTACHMENT0) gl.glGenFramebuffers(args["resolution"], self.framebufferA0) gl.glGenTextures(1, ctypes.byref(self.A0_tex)) #create textures #A gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_3D, self.A0_tex) gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, args["resolution"], args["resolution"], args["resolution"], 0, gl.GL_RED, gl.GL_FLOAT, 0) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) #A for i in range(args["resolution"]): gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferA0[i]) gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, self.A0_tex, 0, i) assert (gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE)
def __init__(self, width, height, wwidth, wheight): self.width = width self.height = height self.windowwidth = wwidth self.windowheight = wheight self.framebuffer = gl.GLuint(0) self.rendered_texture = Texture() gl.glGenFramebuffers(1, ctypes.byref(self.framebuffer)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebuffer) # Set up the texture as the target for color output with self.rendered_texture: gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, self.width, self.height, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, 0) 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.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.rendered_texture.name, 0) if gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE: raise ValueError('Framebuffer not set up completely') gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
def setup_framebuffer(): gl.glGenFramebuffers(1, ctypes.byref(framebuffer)) gl.glGenTextures(1, ctypes.byref(input_texture)) gl.glGenTextures(1, ctypes.byref(rendered_texture)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, framebuffer) # Set up the input texture gl.glBindTexture(gl.GL_TEXTURE_3D, input_texture) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_WRAP_R, gl.GL_CLAMP_TO_EDGE) # Set up the render target texture gl.glBindTexture(gl.GL_TEXTURE_3D, rendered_texture) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
def __init__(self): self.fbo = gl.GLuint(0) self.rendered_texture = gl.GLuint(0) self.depthrenderbuffer = gl.GLuint(0) self.pickingbuffer = gl.GLuint(0) self.vertex_buffer = gl.GLuint(0) self.program = GlProgram(shaders.vertex_copy, shaders.fragment_copy) gl.glGenBuffers(1, pointer(self.vertex_buffer)) data = (gl.GLfloat * 16)(-1, -1, 0, 0, - 1, 1, 0, 1, 1, 1, 1, 1, 1, -1, 1, 0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, sizeof(data), data, gl.GL_STATIC_DRAW) gl.glGenFramebuffers(1, pointer(self.fbo)) if not self.fbo: logging.error('failed fbo') gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) gl.glGenTextures(1, pointer(self.rendered_texture)) if not self.rendered_texture: logging.error('failed rendered_texture') gl.glGenRenderbuffers(1, pointer(self.depthrenderbuffer)) gl.glGenRenderbuffers(1, pointer(self.pickingbuffer)) self.resize(1, 1)
def __init__(self, width, height, window, num_color_attachments=1, mapping_mode=None, provide_depth=False, provide_stencil=False): """"Create an arbitrary layer framebuffer, I'll add stencil and depthbuffers if I ever package this for resuse, in pyweek, those args are pretty much placeholders""" if mapping_mode is None: mapping_mode = gl.GL_NEAREST assert not provide_stencil, 'stencil buffer not implemented' assert not provide_depth, 'depth buffer not implemented' self.window = window self.width = width self.height = height self.bufferId = gl.GLuint(0) self.textureIds = [] self.buffer_args = [] #create the vram objects? gl.glGenFramebuffers(1, rf(self.bufferId)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.bufferId) for bufferIndex in range(num_color_attachments): newTex = gl.GLuint(0) gl.glGenTextures(1, rf(newTex)) self.textureIds.append(newTex) gl.glBindTexture(gl.GL_TEXTURE_2D, newTex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, width, height, 0, gl.GL_RGB, gl.GL_UNSIGNED_INT, 0) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, mapping_mode) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, mapping_mode) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0 + bufferIndex, gl.GL_TEXTURE_2D, newTex, 0) self.buffer_args.append(gl.GL_COLOR_ATTACHMENT0 + bufferIndex) #assign one of the vram objects to the framebuffer cache? if provide_depth: self.buffer_args.append(gl.GL_DEPTH_ATTACHMENT) if provide_stencil: self.buffer_args.append(gl.GL_STENCIL_ATTACHMENT) self.buffers_provided = (gl.GLenum * len(self.buffer_args))(*self.buffer_args) gl.glDrawBuffers(len(self.buffer_args), self.buffers_provided) self.textures = [ Texture(self.width, self.height, gl.GL_TEXTURE_2D, texId.value) for texId in self.textureIds ] assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER ) == gl.GL_FRAMEBUFFER_COMPLETE, "I don't know why this happened, but at least I can find out"
def createFramebuffer(width, height): """Function for setting up additional buffer""" # create a new framebuffer fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) # create a texture to render to, required for warping texId = GL.GLuint() GL.glGenTextures(1, ctypes.byref(texId)) GL.glBindTexture(GL.GL_TEXTURE_2D, texId) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA32F_ARB, int(width), int(height), 0, GL.GL_RGBA, GL.GL_FLOAT, None) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, texId, 0) # create a render buffer rbId = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(rbId)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, rbId) GL.glRenderbufferStorage( GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, int(width), int(height)) GL.glFramebufferRenderbuffer( GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, rbId) GL.glFramebufferRenderbuffer( GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, rbId) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) # clear the buffer GL.glClear(GL.GL_COLOR_BUFFER_BIT) GL.glClear(GL.GL_STENCIL_BUFFER_BIT) GL.glClear(GL.GL_DEPTH_BUFFER_BIT) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) return fboId, texId, rbId
def __init__(self, target=gl.GL_FRAMEBUFFER): """Create an OpenGL Framebuffer object. :rtype: :py:class:`~pyglet.image.Framebuffer` .. versionadded:: 2.0 """ self._id = gl.GLuint() gl.glGenFramebuffers(1, self._id) self._attachment_types = 0 self._width = 0 self._height = 0
def __init__(self, width, height): self.fbo = gl.GLuint(0) gl.glGenFramebuffers(1, ctypes.byref(self.fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) self.texture = pyglet.image.Texture.create(width, height) gl.glBindTexture(self.texture.target, 0) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.texture.id, 0) draw_buffers = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glDrawBuffers(1, draw_buffers) assert gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
def setup_framebuffer(): gl.glGenFramebuffers(1, ctypes.byref(framebuffer)) gl.glGenTextures(1, ctypes.byref(rendered_texture)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, framebuffer) # Set up the texture as the target for color output gl.glBindTexture(gl.GL_TEXTURE_2D, rendered_texture) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, FB_WIDTH, FB_HEIGHT, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, 0) 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.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, rendered_texture, 0) draw_buffers = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glDrawBuffers(1, draw_buffers) assert gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE
def __init__(self, width, height): self.fbo = gl.GLuint(0) gl.glGenFramebuffers(1, ctypes.byref(self.fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) self.texture = pyglet.image.Texture.create(width, height) gl.glBindTexture(self.texture.target, 0) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.texture.id, 0) draw_buffers = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glDrawBuffers(1, draw_buffers) assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
def __init__(self): self.id = gl.GLuint(0) gl.glGenFramebuffers(1, ctypes.byref(self.id))
def create_frame_buffers(width, height, num_samples): """Create the frame buffer objects""" from pyglet import gl # Create a frame buffer (rendering target) multi_fbo = gl.GLuint(0) gl.glGenFramebuffers(1, byref(multi_fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, multi_fbo) # The try block here is because some OpenGL drivers # (Intel GPU drivers on macbooks in particular) do not # support multisampling on frame buffer objects try: if not gl.gl_info.have_version(major=3, minor=2): raise Exception('OpenGL version 3.2+ required for \ GL_TEXTURE_2D_MULTISAMPLE') # Create a multisampled texture to render into fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, fbTex) gl.glTexImage2DMultisample(gl.GL_TEXTURE_2D_MULTISAMPLE, num_samples, gl.GL_RGBA32F, width, height, True) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D_MULTISAMPLE, fbTex, 0) # Attach a multisampled depth buffer to the FBO depth_rb = gl.GLuint(0) gl.glGenRenderbuffers(1, byref(depth_rb)) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depth_rb) gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, num_samples, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depth_rb) except: logger.debug('Falling back to non-multisampled frame buffer') # Create a plain texture texture to render into fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D, fbTex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_FLOAT, None) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, fbTex, 0) # Attach depth buffer to FBO depth_rb = gl.GLuint(0) gl.glGenRenderbuffers(1, byref(depth_rb)) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depth_rb) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depth_rb) # Sanity check import pyglet if pyglet.options['debug_gl']: res = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert res == gl.GL_FRAMEBUFFER_COMPLETE # Create the frame buffer used to resolve the final render final_fbo = gl.GLuint(0) gl.glGenFramebuffers(1, byref(final_fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, final_fbo) # Create the texture used to resolve the final render fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D, fbTex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_FLOAT, None) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, fbTex, 0) import pyglet if pyglet.options['debug_gl']: res = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert res == gl.GL_FRAMEBUFFER_COMPLETE # Enable depth testing gl.glEnable(gl.GL_DEPTH_TEST) # Unbind the frame buffer gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) return multi_fbo, final_fbo
def createFBO(attachments=()): """Create a Framebuffer Object. Parameters ---------- attachments : :obj:`list` or :obj:`tuple` of :obj:`tuple` Optional attachments to initialize the Framebuffer with. Attachments are specified as a list of tuples. Each tuple must contain an attachment point (e.g. GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, etc.) and a buffer descriptor type (Renderbuffer or TexImage2D). If using a combined depth/stencil format such as GL_DEPTH24_STENCIL8, GL_DEPTH_ATTACHMENT and GL_STENCIL_ATTACHMENT must be passed the same buffer. Alternatively, one can use GL_DEPTH_STENCIL_ATTACHMENT instead. If using multisample buffers, all attachment images must use the same number of samples!. As an example, one may specify attachments as 'attachments=(( GL.GL_COLOR_ATTACHMENT0, frameTexture), (GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRenderBuffer))'. Returns ------- :obj:`Framebuffer` Framebuffer descriptor. Notes ----- - All buffers must have the same number of samples. - The 'userData' field of the returned descriptor is a dictionary that can be used to store arbitrary data associated with the FBO. - Framebuffers need a single attachment to be complete. Examples -------- # empty framebuffer with no attachments fbo = createFBO() # invalid until attachments are added # create a render target with multiple color texture attachments colorTex = createTexImage2D(1024,1024) # empty texture depthRb = createRenderbuffer(800,600,internalFormat=GL.GL_DEPTH24_STENCIL8) # attach images GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo.id) attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_ATTACHMENT, depthRb) attach(GL.GL_STENCIL_ATTACHMENT, depthRb) # or attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # above is the same as with useFBO(fbo): attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_ATTACHMENT, depthRb) attach(GL.GL_STENCIL_ATTACHMENT, depthRb) # examples of userData some custom function might access fbo.userData['flags'] = ['left_eye', 'clear_before_use'] GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb.id) # bind for drawing # depth only texture (for shadow mapping?) depthTex = createTexImage2D(800, 600, internalFormat=GL.GL_DEPTH_COMPONENT24, pixelFormat=GL.GL_DEPTH_COMPONENT) fbo = createFBO([(GL.GL_DEPTH_ATTACHMENT, depthTex)]) # is valid # discard FBO descriptor, just give me the ID frameBuffer = createFBO().id """ fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) # create a framebuffer descriptor fboDesc = Framebuffer(fboId, GL.GL_FRAMEBUFFER, dict()) # initial attachments for this framebuffer if attachments: with useFBO(fboDesc): for attachPoint, imageBuffer in attachments: attach(attachPoint, imageBuffer) return fboDesc
def createMultisampleFBO(width, height, samples, colorFormat=GL.GL_RGBA8): """Create a multisample framebuffer for rendering. Objects drawn to the framebuffer will be anti-aliased if 'GL_MULTISAMPLE' is active. A combined depth and stencil buffer is created with 'GL_DEPTH24_STENCIL8' format. Multisampling is computationally intensive for your graphics hardware and consumes substantial amounts of VRAM. Furthermore, samples must be 'resolved' prior to display by copying (using blitFramebuffer, see Examples) to a non-multisample buffer. Parameters ---------- width : :obj:`int` Buffer width in pixels. height : :obj:`int` Buffer height in pixels. samples : :obj:`int` Number of samples for multi-sampling, should be >1 and power-of-two. Work with one sample, but will raise a warning. colorFormat : :obj:`int` Format for color renderbuffer data (e.g. GL_RGBA8). Returns ------- :obj:`list` of :obj:`int` List of OpenGL ids (FBO, Color RB, Depth/Stencil RB). Examples -------- # create a multisample FBO with 8 samples msaaFbo, colorRb, depthRb = createMultisampleFBO(800, 600, 8) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, msaaFbo) # bind it # resolve samples into another framebuffer texture GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, msaaFbo) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, fbo) gltools.blitFramebuffer((0, 0, 800, 600)) """ # determine if the 'samples' value is valid max_samples = getIntegerv(GL.GL_MAX_SAMPLES) if isinstance(samples, int): if (samples & (samples - 1)) != 0: raise ValueError( 'Invalid number of samples, must be power-of-two.') elif samples < 0 or samples > max_samples: raise ValueError( 'Invalid number of samples, must be <{}.'.format(max_samples)) elif samples == 1: # warn that you are creating a single sample texture, use a regular # FBO instead. logging.warning('Creating a multisample FBO with one sample!') elif isinstance(samples, str): if samples == 'max': samples = max_samples # create the FBO, bind it for attachments fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) # Color render buffer only instead of a texture. I can't think of a use case # to pass around a multisampled texture (yet). colorRbId = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(colorRbId)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, colorRbId) GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, colorFormat, int(width), int(height)) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_RENDERBUFFER, colorRbId) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) # setup the render buffer for depth and stencil depthRbId = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(depthRbId)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRbId) GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, GL.GL_DEPTH24_STENCIL8, int(width), int(height)) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRbId) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, depthRbId) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) # clear VRAM garbage GL.glClear(GL.GL_STENCIL_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # check completeness if not checkFramebufferComplete(fboId): # delete the framebuffer and all the resources associated with it GL.glDeleteRenderbuffers(1, colorRbId) GL.glDeleteRenderbuffers(1, depthRbId) GL.glDeleteFramebuffers(1, fboId) raise RuntimeError( 'Failed to create a multisample framebuffer. Exiting.') return fboId, colorRbId, depthRbId
def createFBO(width, height, colorFormat=GL.GL_RGBA8): """Generate a new Framebuffer object (FBO) for use as a render target. Parameters ---------- width : :obj:`int` Buffer width in pixels. height : :obj:`int` Buffer height in pixels. colorFormat : :obj:`int` Format for color renderbuffer data (e.g. GL_RGBA8). Returns ------- :obj:`list` of :obj:`int` List of OpenGL ids (FBO, Color Texture, Depth/Stencil RB). Examples -------- # create a FBO frameBuffer, frameTexture, stencilTexture = createFBO( 800, 600, GL.GL_RGBA32F_ARB) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, frameBuffer) # bind it """ # Create a texture render target for color data, same _setupFramebuffer() # # We should avoid creating a texture here in the future since we might want # to bind an existing texture from elsewhere and reuse the same FBO. # colorTextureId = GL.GLuint() GL.glGenTextures(1, ctypes.byref(colorTextureId)) GL.glBindTexture(GL.GL_TEXTURE_2D, colorTextureId) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, colorFormat, int(width), int(height), 0, GL.GL_RGBA, GL.GL_FLOAT, None) GL.glBindTexture(GL.GL_TEXTURE_2D, 0) fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) # attach texture to the frame buffer GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, colorTextureId, 0) # create depth and stencil render buffers depthRbId = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(depthRbId)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRbId) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, int(width), int(height)) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRbId) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, depthRbId) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) # clear VRAM garbage GL.glClear(GL.GL_STENCIL_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # check completeness if not checkFramebufferComplete(fboId): # delete the framebuffer and all the resources associated with it GL.glDeleteTextures(1, colorTextureId) GL.glDeleteRenderbuffers(1, depthRbId) GL.glDeleteFramebuffers(1, fboId) raise RuntimeError('Failed to create a framebuffer. Exiting.') return fboId, colorTextureId, depthRbId
def setupFBOandTextures(self): self.framebufferA0 = (gl.GLuint * self.dimz)() self.framebufferA1 = (gl.GLuint * self.dimz)() self.framebufferB0 = (gl.GLuint * self.dimz)() self.framebufferB1 = (gl.GLuint * self.dimz)() self.A0_tex = gl.GLuint(0) self.A1_tex = gl.GLuint(0) self.B0_tex = gl.GLuint(0) self.B1_tex = gl.GLuint(0) self.draw_buffersA0 = (gl.GLenum * self.dimz)( gl.GL_COLOR_ATTACHMENT0) self.draw_buffersA1 = (gl.GLenum * self.dimz)( gl.GL_COLOR_ATTACHMENT0) self.draw_buffersB0 = (gl.GLenum * self.dimz)( gl.GL_COLOR_ATTACHMENT0) self.draw_buffersB1 = (gl.GLenum * self.dimz)( gl.GL_COLOR_ATTACHMENT0) #gl.glGenFramebuffers(self.dimz, ctypes.byref(self.framebufferA0)) #gl.glGenFramebuffers(self.dimz, ctypes.byref(self.framebufferA1)) #gl.glGenFramebuffers(self.dimz, ctypes.byref(self.framebufferB0)) #gl.glGenFramebuffers(self.dimz, ctypes.byref(self.framebufferB1)) gl.glGenFramebuffers(self.dimz, self.framebufferA0) gl.glGenFramebuffers(self.dimz, self.framebufferA1) gl.glGenFramebuffers(self.dimz, self.framebufferB0) gl.glGenFramebuffers(self.dimz, self.framebufferB1) gl.glGenTextures(1, ctypes.byref(self.A0_tex)) gl.glGenTextures(1, ctypes.byref(self.A1_tex)) gl.glGenTextures(1, ctypes.byref(self.B0_tex)) gl.glGenTextures(1, ctypes.byref(self.B1_tex)) #create textures #A gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_3D, self.A0_tex) gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, self.dimx, self.dimy, self.dimz, 0, gl.GL_RED, gl.GL_FLOAT, self.Ap) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glActiveTexture(gl.GL_TEXTURE1) gl.glBindTexture(gl.GL_TEXTURE_3D, self.A1_tex) gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, self.dimx, self.dimy, self.dimz, 0, gl.GL_RED, gl.GL_FLOAT, self.Ap) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) #B gl.glActiveTexture(gl.GL_TEXTURE2) gl.glBindTexture(gl.GL_TEXTURE_3D, self.B0_tex) gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, self.dimx, self.dimy, self.dimz, 0, gl.GL_RED, gl.GL_FLOAT, self.Bp) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glActiveTexture(gl.GL_TEXTURE3) gl.glBindTexture(gl.GL_TEXTURE_3D, self.B1_tex) gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, self.dimx, self.dimy, self.dimz, 0, gl.GL_RED, gl.GL_FLOAT, self.Bp) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_3D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) #A for i in range(self.dimz): gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferA0[i]) gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, self.A0_tex, 0, i) assert (gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferA1[i]) gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, self.A1_tex, 0, i) assert (gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferB0[i]) gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, self.B0_tex, 0, i) assert (gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferB1[i]) gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, self.B1_tex, 0, i) assert (gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE)
def setupFBOandTextures(self): self.framebufferA0 = gl.GLuint(0) self.framebufferA1 = gl.GLuint(0) self.framebufferB0 = gl.GLuint(0) self.framebufferB1 = gl.GLuint(0) self.A0_tex = gl.GLuint(0) self.A1_tex = gl.GLuint(0) self.B0_tex = gl.GLuint(0) self.B1_tex = gl.GLuint(0) self.draw_buffersA0 = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) self.draw_buffersA1 = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) self.draw_buffersB0 = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) self.draw_buffersB1 = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glGenFramebuffers(1, ctypes.byref(self.framebufferA0)) gl.glGenFramebuffers(1, ctypes.byref(self.framebufferA1)) gl.glGenFramebuffers(1, ctypes.byref(self.framebufferB0)) gl.glGenFramebuffers(1, ctypes.byref(self.framebufferB1)) gl.glGenTextures(1, ctypes.byref(self.A0_tex)) gl.glGenTextures(1, ctypes.byref(self.A1_tex)) gl.glGenTextures(1, ctypes.byref(self.B0_tex)) gl.glGenTextures(1, ctypes.byref(self.B1_tex)) #A gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferA0) gl.glBindTexture(gl.GL_TEXTURE_2D, self.A0_tex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, self.dimx, self.dimy, 0, gl.GL_RGBA, gl.GL_FLOAT, self.Ap) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.A0_tex, 0) gl.glDrawBuffers(1, self.draw_buffersA0) assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE gl.glActiveTexture(gl.GL_TEXTURE1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferA1) # Set up the texture as the target for color output gl.glBindTexture(gl.GL_TEXTURE_2D, self.A1_tex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, self.dimx, self.dimy, 0, gl.GL_RGBA, gl.GL_FLOAT, self.Ap) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.A1_tex, 0) gl.glDrawBuffers(1, self.draw_buffersA1) assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE #B gl.glActiveTexture(gl.GL_TEXTURE2) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferB0) gl.glBindTexture(gl.GL_TEXTURE_2D, self.B0_tex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, self.dimx, self.dimy, 0, gl.GL_RGBA, gl.GL_FLOAT, self.Bp) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.B0_tex, 0) gl.glDrawBuffers(1, self.draw_buffersB0) assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE gl.glActiveTexture(gl.GL_TEXTURE3) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.framebufferB1) # Set up the texture as the target for color output gl.glBindTexture(gl.GL_TEXTURE_2D, self.B1_tex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, self.dimx, self.dimy, 0, gl.GL_RGBA, gl.GL_FLOAT, self.Bp) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.B1_tex, 0) gl.glDrawBuffers(1, self.draw_buffersB1) assert gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE
def __init__(self, ctx: "Context", *, color_attachments=None, depth_attachment=None): """ :param Context ctx: The context this framebuffer belongs to :param List[arcade.gl.Texture] color_attachments: List of color attachments. :param arcade.gl.Texture depth_attachment: A depth attachment (optional) """ if not color_attachments: raise ValueError( "Framebuffer must at least have one color attachment") self._ctx = ctx self._color_attachments = (color_attachments if isinstance( color_attachments, list) else [color_attachments]) self._depth_attachment = depth_attachment self._glo = fbo_id = gl.GLuint() # The OpenGL alias/name self._samples = 0 # Leaving this at 0 for future sample support self._depth_mask = True # Determines if the depth buffer should be affected self._prev_fbo = None # Create the framebuffer object gl.glGenFramebuffers(1, self._glo) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self._glo) # Ensure all attachments have the same size. # OpenGL do actually support different sizes, # but let's keep this simple with high compatibility. expected_size = (self._color_attachments[0] if self._color_attachments else self._depth_attachment).size for layer in [*self._color_attachments, self._depth_attachment]: if layer and layer.size != expected_size: raise ValueError( "All framebuffer attachments should have the same size") self._width, self._height = expected_size self._viewport = 0, 0, self._width, self._height # Attach textures to it for i, tex in enumerate(self._color_attachments): # TODO: Possibly support attaching a specific mipmap level # but we can read from specific mip levels from shaders. gl.glFramebufferTexture2D( gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0 + i, gl.GL_TEXTURE_2D, tex.glo, 0, # Level 0 ) if self.depth_attachment: gl.glFramebufferTexture2D( gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, self.depth_attachment._target, self.depth_attachment.glo, 0, ) # Ensure the framebuffer is sane! self._check_completeness() # Set up draw buffers. This is simply a prepared list of attachments enums # we use in the use() method to activate the different color attachment layers layers = [ gl.GL_COLOR_ATTACHMENT0 + i for i, _ in enumerate(self._color_attachments) ] # pyglet wants this as a ctypes thingy, so let's prepare it self._draw_buffers = (gl.GLuint * len(layers))(*layers) # Restore the original bound framebuffer to avoid confusion self.ctx.active_framebuffer.use(force=True) self.ctx.stats.incr("framebuffer") weakref.finalize(self, Framebuffer.release, ctx, fbo_id)
def create_frame_buffers(width: int, height: int, num_samples: int) -> Tuple[int, int]: """Create the frame buffer objects""" # Create a frame buffer (rendering target) multi_fbo = gl.GLuint(0) gl.glGenFramebuffers(1, byref(multi_fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, multi_fbo) # The try block here is because some OpenGL drivers # (Intel GPU drivers on macbooks in particular) do not # support multisampling on frame buffer objects # noinspection PyBroadException try: # Create a multisampled texture to render into fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, fbTex) gl.glTexImage2DMultisample(gl.GL_TEXTURE_2D_MULTISAMPLE, num_samples, gl.GL_RGBA32F, width, height, True) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D_MULTISAMPLE, fbTex, 0) # Attach a multisampled depth buffer to the FBO depth_rb = gl.GLuint(0) gl.glGenRenderbuffers(1, byref(depth_rb)) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depth_rb) gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, num_samples, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depth_rb) except BaseException as e: # logger.warning(e=traceback.format_exc()) logger.debug("Falling back to non-multisampled frame buffer") # Create a plain texture texture to render into fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D, fbTex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_FLOAT, None) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, fbTex, 0) # Attach depth buffer to FBO depth_rb = gl.GLuint(0) gl.glGenRenderbuffers(1, byref(depth_rb)) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depth_rb) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depth_rb) # Sanity check if pyglet.options["debug_gl"]: res = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert res == gl.GL_FRAMEBUFFER_COMPLETE # Create the frame buffer used to resolve the final render final_fbo = gl.GLuint(0) gl.glGenFramebuffers(1, byref(final_fbo)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, final_fbo) # Create the texture used to resolve the final render fbTex = gl.GLuint(0) gl.glGenTextures(1, byref(fbTex)) gl.glBindTexture(gl.GL_TEXTURE_2D, fbTex) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_FLOAT, None) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, fbTex, 0) if pyglet.options["debug_gl"]: res = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert res == gl.GL_FRAMEBUFFER_COMPLETE # Enable depth testing gl.glEnable(gl.GL_DEPTH_TEST) # Unbind the frame buffer gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) return multi_fbo, final_fbo