def attach_texture(self, target, attachment, texture): """Attach a Texture to the Framebuffer :Parameters: `target` : int Specifies the framebuffer target. target must be gl.GL_DRAW_FRAMEBUFFER, gl.GL_READ_FRAMEBUFFER, or gl.GL_FRAMEBUFFER. gl.GL_FRAMEBUFFER is equivalent to gl.GL_DRAW_FRAMEBUFFER. `attachment` : int Specifies the attachment point of the framebuffer. attachment must be gl.GL_COLOR_ATTACHMENTi, gl.GL_DEPTH_ATTACHMENT, gl.GL_STENCIL_ATTACHMENT or gl.GL_DEPTH_STENCIL_ATTACHMENT. `texture` : pyglet.image.Texture Specifies the texture object to attach to the framebuffer attachment point named by attachment. """ self.bind() gl.glFramebufferTexture2D(target, attachment, texture.target, texture.id, texture.level) # gl.glFramebufferTexture2D(target, attachment, texture.target, # texture.id, texture.level) self._attachment_types |= attachment self._width = max(texture.width, self._width) self._height = max(texture.height, self._height) self.unbind()
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 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 _link(self): for attachment, tex in zip(COLOR_ATTACHMENTS, self.textures): gl.glBindTexture(gl.GL_TEXTURE_2D, tex) 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) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, self.width, self.height, 0, gl.GL_RGBA, gl.GL_FLOAT, None) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, attachment, gl.GL_TEXTURE_2D, tex, 0) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.depthbuf) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT16, self.width, self.height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, self.depthbuf) assert gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE, \ "Framebuffer is not complete!"
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 bind_texture(self, texture): with texture: gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, texture.id, 0) if (gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE): raise RuntimeError('Framebuffer incomplete !')
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, 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 _setup(self): self.name = gl.GLuint() gl.glCreateFramebuffers(1, byref(self.name)) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.name) self.cubemap_texture = gl.GLuint() gl.glGenTextures(gl.GL_TEXTURE_CUBE_MAP, byref(self.name)) gl.glBindTexture(gl.GL_TEXTURE_CUBE_MAP, self.cubemap_texture) w, h = self.size # initialize the texture (IMPORTANT!!!) for i in range(6): gl.glTexImage2D(gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.GL_DEPTH_COMPONENT, w, h, 0, gl.GL_DEPTH_COMPONENT, gl.GL_FLOAT, 0) gl.glFramebufferTexture2D(gl.GL_DRAW_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_TEXTURE_CUBE_MAP_POSITIVE_X, self.cubemap_texture, 0) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_BASE_LEVEL, 0) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MAX_LEVEL, 0) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_TEXTURE_WRAP_R, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_CUBE_MAP, gl.GL_DEPTH_TEXTURE_MODE, gl.GL_LUMINANCE) gl.glBindTexture(gl.GL_TEXTURE_CUBE_MAP, 0) status = gl.glCheckFramebufferStatus(gl.GL_DRAW_FRAMEBUFFER) assert status == gl.GL_FRAMEBUFFER_COMPLETE, f"Could not setup framebuffer! {status}"
def attach(attachPoint, imageBuffer): """Attach an image to a specified attachment point on the presently bound FBO. Parameters ---------- attachPoint :obj:`int` Attachment point for 'imageBuffer' (e.g. GL.GL_COLOR_ATTACHMENT0). imageBuffer : :obj:`TexImage2D` or :obj:`Renderbuffer` Framebuffer-attachable buffer descriptor. Returns ------- None Examples -------- # with descriptors colorTex and depthRb GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo) attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, lastBoundFbo) # same as above, but using a context manager with useFBO(fbo): attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb) """ # We should also support binding GL names specified as integers. Right now # you need as descriptor which contains the target and name for the buffer. # if isinstance(imageBuffer, (TexImage2D, TexImage2DMultisample)): GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, attachPoint, imageBuffer.target, imageBuffer.id, 0) elif isinstance(imageBuffer, Renderbuffer): GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, attachPoint, imageBuffer.target, imageBuffer.id)
def resize(self, width, height): ''' resizes the framebuffer to the given dimensions ''' gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) gl.glBindTexture(gl.GL_TEXTURE_2D, self.rendered_texture) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, width, 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, 0) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.depthrenderbuffer) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, self.depthrenderbuffer) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.pickingbuffer) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_R16UI, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT1, gl.GL_RENDERBUFFER, self.pickingbuffer) draw_buffers = (gl.GLenum * 2)(gl.GL_COLOR_ATTACHMENT0, gl.GL_COLOR_ATTACHMENT1) gl.glDrawBuffers(2, draw_buffers) if gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE: logging.error('setting up fbo failed') gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
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 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 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