def __init__(self, width, height, drawFunc): tex = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, tex) GL.glTexParameter(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST) GL.glTexParameter(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) self.enabled = False self._texID = tex if bool(FBO.glGenFramebuffers) and "Intel" not in GL.glGetString(GL.GL_VENDOR): buf = FBO.glGenFramebuffers(1) depthbuffer = FBO.glGenRenderbuffers(1) FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, buf) FBO.glBindRenderbuffer(FBO.GL_RENDERBUFFER, depthbuffer) FBO.glRenderbufferStorage(FBO.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT, width, height) FBO.glFramebufferRenderbuffer(FBO.GL_FRAMEBUFFER, FBO.GL_DEPTH_ATTACHMENT, FBO.GL_RENDERBUFFER, depthbuffer) FBO.glFramebufferTexture2D(FBO.GL_FRAMEBUFFER, FBO.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tex, 0) status = FBO.glCheckFramebufferStatus(FBO.GL_FRAMEBUFFER) if status != FBO.GL_FRAMEBUFFER_COMPLETE: print "glCheckFramebufferStatus", status self.enabled = False return FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, buf) with gl.glPushAttrib(GL.GL_VIEWPORT_BIT): GL.glViewport(0, 0, width, height) drawFunc() FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, 0) FBO.glDeleteFramebuffers(1, [buf]) FBO.glDeleteRenderbuffers(1, [depthbuffer]) self.enabled = True else: GL.glReadBuffer(GL.GL_BACK) if bool(window_pos.glWindowPos2dARB): pixels = GL.glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE) GL.glPushAttrib(GL.GL_VIEWPORT_BIT | GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_TEST | GL.GL_STENCIL_BUFFER_BIT) GL.glDisable(GL.GL_STENCIL_TEST) GL.glViewport(0, 0, width, height) GL.glScissor(0, 0, width, height) with gl.glEnable(GL.GL_SCISSOR_TEST): drawFunc() GL.glBindTexture(GL.GL_TEXTURE_2D, tex) GL.glReadBuffer(GL.GL_BACK) GL.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height) if bool(window_pos.glWindowPos2dARB): window_pos.glWindowPos2dARB(0,0) GL.glDrawPixels(width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixels) GL.glPopAttrib()
def renderToArray(self, size, format=GL_BGRA, type=GL_UNSIGNED_BYTE, textureSize=1024, padding=256): w,h = map(int, size) self.makeCurrent() tex = None fb = None try: output = np.empty((w, h, 4), dtype=np.ubyte) fb = glfbo.glGenFramebuffers(1) glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, fb ) glEnable(GL_TEXTURE_2D) tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) texwidth = textureSize data = np.zeros((texwidth,texwidth,4), dtype=np.ubyte) ## Test texture dimensions first glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, texwidth, texwidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) if glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) == 0: raise Exception("OpenGL failed to create 2D texture (%dx%d); too large for this hardware." % shape[:2]) ## create teture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texwidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.transpose((1,0,2))) self.opts['viewport'] = (0, 0, w, h) # viewport is the complete image; this ensures that paintGL(region=...) # is interpreted correctly. p2 = 2 * padding for x in range(-padding, w-padding, texwidth-p2): for y in range(-padding, h-padding, texwidth-p2): x2 = min(x+texwidth, w+padding) y2 = min(y+texwidth, h+padding) w2 = x2-x h2 = y2-y ## render to texture glfbo.glFramebufferTexture2D(glfbo.GL_FRAMEBUFFER, glfbo.GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0) self.paintGL(region=(x, h-y-h2, w2, h2), viewport=(0, 0, w2, h2)) # only render sub-region glBindTexture(GL_TEXTURE_2D, tex) # fixes issue #366 ## read texture back to array data = glGetTexImage(GL_TEXTURE_2D, 0, format, type) data = np.fromstring(data, dtype=np.ubyte).reshape(texwidth,texwidth,4).transpose(1,0,2)[:, ::-1] output[x+padding:x2-padding, y+padding:y2-padding] = data[padding:w2-padding, -(h2-padding):-padding] finally: self.opts['viewport'] = None glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, 0) glBindTexture(GL_TEXTURE_2D, 0) if tex is not None: glDeleteTextures([tex]) if fb is not None: glfbo.glDeleteFramebuffers([fb]) return output
def initializeGL(self): super(AbstractCam, self).initializeGL() print '[cam] initializeGL(): hello' self.mode_polygon = GL_FILL self.tex = glGenTextures(1) print '[cam] self.tex: %s' % self.tex # ref: songho/fboDepth/main.cpp glBindTexture(GL_TEXTURE_2D, self.tex) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) #glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) #glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE) # use None for 0 in PyOpenGL !! # glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, # self.viewport_width, self.viewport_height, # 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, # self.viewport_width, self.viewport_height, # broken image 640, 640, # fixme: how to get correct 640x480 depth texture? 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) #glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, self.viewport_width, self.viewport_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, None) glBindTexture(GL_TEXTURE_2D, 0) # unbind self.fbo = glfbo.glGenFramebuffers(1) print '[cam] self.fbo: %s' % self.fbo glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, self.fbo) # the last arg is mipmap level. http://pyopengl.sourceforge.net/documentation/manual-3.0/glFramebufferTexture.html glfbo.glFramebufferTexture2D(glfbo.GL_FRAMEBUFFER, glfbo.GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, self.tex, 0) glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) glfbo.glBindFramebuffer(glfbo.GL_FRAMEBUFFER, 0) # unbind if 1: AbstractCam.set_mat_proj_xtion() else: glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(90.0, 1.0, 1.0, 100.0)
def __init__(self, width, height, drawFunc): tex = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, tex) GL.glTexParameter(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST) GL.glTexParameter(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) self.enabled = False self._texID = tex if bool(FBO.glGenFramebuffers) and "Intel" not in GL.glGetString(GL.GL_VENDOR): buf = FBO.glGenFramebuffers(1) depthbuffer = FBO.glGenRenderbuffers(1) FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, buf) FBO.glBindRenderbuffer(FBO.GL_RENDERBUFFER, depthbuffer) FBO.glRenderbufferStorage(FBO.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT, width, height) FBO.glFramebufferRenderbuffer(FBO.GL_FRAMEBUFFER, FBO.GL_DEPTH_ATTACHMENT, FBO.GL_RENDERBUFFER, depthbuffer) FBO.glFramebufferTexture2D(FBO.GL_FRAMEBUFFER, FBO.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tex, 0) status = FBO.glCheckFramebufferStatus(FBO.GL_FRAMEBUFFER) if status != FBO.GL_FRAMEBUFFER_COMPLETE: print ("glCheckFramebufferStatus: " + str(status)) self.enabled = False return FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, buf) with gl.glPushAttrib(GL.GL_VIEWPORT_BIT): GL.glViewport(0, 0, width, height) drawFunc() FBO.glBindFramebuffer(FBO.GL_FRAMEBUFFER, 0) FBO.glDeleteFramebuffers(1, [buf]) FBO.glDeleteRenderbuffers(1, [depthbuffer]) self.enabled = True else: GL.glReadBuffer(GL.GL_BACK) GL.glPushAttrib(GL.GL_VIEWPORT_BIT | GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_TEST | GL.GL_STENCIL_BUFFER_BIT) GL.glDisable(GL.GL_STENCIL_TEST) GL.glViewport(0, 0, width, height) GL.glScissor(0, 0, width, height) with gl.glEnable(GL.GL_SCISSOR_TEST): drawFunc() GL.glBindTexture(GL.GL_TEXTURE_2D, tex) GL.glReadBuffer(GL.GL_BACK) GL.glCopyTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height) GL.glPopAttrib()
def create(self): """ creates the fbo, call only once after configuration done. you have to add textures before. """ self.hasColor = self.colorTextures != [] self.hasDepth = self.depthTexture != None self.hasStencil = self.stencilTexture != None self.hasDepthStencil = self.depthStencilTexture != None self.depthOnly = self.hasDepth and not self.hasColor # create and bind fbo self.glFBO = glFBO.glGenFramebuffers(1) glFBO.glBindFramebuffer(glFBO.GL_FRAMEBUFFER, self.glFBO) if self.depthOnly: # only draw depth gl.glDrawBuffer(gl.GL_NONE) gl.glReadBuffer(gl.GL_NONE) # add textures for i in range(len(self.colorTextures)): tex = self.colorTextures[i] glFBO.glFramebufferTexture2D(glFBO.GL_FRAMEBUFFER, glFBO.GL_COLOR_ATTACHMENT0+i, tex.targetType, tex.glID, 0) if self.hasDepth: glFBO.glFramebufferTexture2D(glFBO.GL_FRAMEBUFFER, glFBO.GL_DEPTH_ATTACHMENT, self.depthTexture.targetType, self.depthTexture.glID, 0) if self.hasStencil: glFBO.glFramebufferTexture2D(glFBO.GL_FRAMEBUFFER, glFBO.GL_STENCIL_ATTACHMENT, self.stencilTexture.targetType, self.stencilTexture.glID, 0) if self.hasDepthStencil: glFBO.glFramebufferTexture2D(glFBO.GL_FRAMEBUFFER, glFBO.GL_DEPTH_STENCIL_ATTACHMENT, self.depthStencilTexture.targetType, self.depthStencilTexture.glID, 0) # check if everything is ok with the fbo self.checkError() # release fbo glFBO.glBindFramebuffer(glFBO.GL_FRAMEBUFFER, 0) # remember color buffers if self.colorTextures != []: self.numBuffers = len(self.colorTextures) data = map(lambda x: glFBO.GL_COLOR_ATTACHMENT0+x, range(self.numBuffers)) self.colorBuffers = NumpyArray(data, "I")