def _init_framebuffer_object(self): """ returns a Framebuffer Object to support offscreen rendering. http://learnopengl.com/#!Advanced-OpenGL/Framebuffers """ fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) rbo = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, rbo) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_RGBA, self.init_width, self.init_height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rbo) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) fbo_status = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) if fbo_status != gl.GL_FRAMEBUFFER_COMPLETE: gl.glDeleteFramebuffers([fbo]) glfw.terminate() raise Exception('Framebuffer failed status check: %s' % fbo_status) self._fbo = fbo self._rbo = rbo
def create_render_FBO(self): #create a color buffer self.TARGET = [GL.glGenTextures(1) for i in range(6)] for d in range(6): GL.glBindTexture(GL.GL_TEXTURE_2D, self.TARGET[d]) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB32F, self.res, self.res, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 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.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE) report_GL_error() #create a render buffer self.DEPTH = [GL.glGenRenderbuffers(1) for i in range(6)] for d in range(6): GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.DEPTH[d]) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32, self.res, self.res) report_GL_error() #create a frame buffer self.FBORENDER = GL.glGenFramebuffers(1) report_GL_error()
def __init__(self, width, height): self.render_framebuffer_id = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.render_framebuffer_id) # self.depth_buffer_id = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.depth_buffer_id) GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, 4, GL.GL_DEPTH_COMPONENT, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, self.depth_buffer_id) # self.render_texture_id = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D_MULTISAMPLE, self.render_texture_id) GL.glTexImage2DMultisample(GL.GL_TEXTURE_2D_MULTISAMPLE, 4, GL.GL_RGBA8, width, height, True) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D_MULTISAMPLE, self.render_texture_id, 0) # self.resolve_framebuffer_id = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.resolve_framebuffer_id) # self.resolve_texture_id = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, self.resolve_texture_id) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_LEVEL, 0) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.resolve_texture_id, 0) status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) assert status == GL.GL_FRAMEBUFFER_COMPLETE
def renderGL(w, h, func, data): # TODO store original GL context and restore it afterwards? startGL() fbid = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbid) dbid = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, dbid) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT, w, h) tid = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, tid) 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_RGB, w, h, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, None) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tid, 0) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, dbid) assert GL.glCheckFramebufferStatus( GL.GL_FRAMEBUFFER) == GL.GL_FRAMEBUFFER_COMPLETE, 'GL error' GL.glViewport(0, 0, w, h) if isinstance(data, tuple): func(*data) else: func(data) data = GL.glReadPixels(0, 0, w, h, GL.GL_RGB, GL.GL_UNSIGNED_BYTE) GL.glBindTexture(GL.GL_TEXTURE_2D, 0) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glDeleteTextures([tid]) GL.glDeleteFramebuffers(1, [fbid]) GL.glDeleteRenderbuffers(1, [dbid]) return np.fromstring(data, dtype=np.uint8).reshape(h, w, 3)
def _init_framebuffer_object(self): """ returns a Framebuffer Object to support offscreen rendering. http://learnopengl.com/#!Advanced-OpenGL/Framebuffers """ fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) rbo = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, rbo) gl.glRenderbufferStorage( gl.GL_RENDERBUFFER, gl.GL_RGBA, self.init_width, self.init_height ) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rbo) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) fbo_status = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) if fbo_status != gl.GL_FRAMEBUFFER_COMPLETE: gl.glDeleteFramebuffers([fbo]) glfw.terminate() raise Exception('Framebuffer failed status check: %s' % fbo_status) self._fbo = fbo self._rbo = rbo
def setup_fbo(self): self.ctx.makeCurrent(self.offscreen_surface) self.tex = GL.glGenTextures(1) self.fbo = GL.glGenFramebuffers(1) self.rbuf = GL.glGenRenderbuffers(1) GL.glBindTexture(GL.GL_TEXTURE_2D, self.tex) 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.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, OffscreenModelRendererThread.TEX_SIZE, OffscreenModelRendererThread.TEX_SIZE, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.rbuf) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, OffscreenModelRendererThread.TEX_SIZE, OffscreenModelRendererThread.TEX_SIZE) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fbo) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, self.rbuf) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.tex, 0) if GL.glCheckFramebufferStatus( GL.GL_FRAMEBUFFER) != GL.GL_FRAMEBUFFER_COMPLETE: raise RuntimeError("Framebuffer is not complete!") GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0)
def bind_frame_buffer(self, width, height): frame_buffer_name = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, frame_buffer_name) fbo_texture = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, fbo_texture) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, width, height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, 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.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE) depth_render_buffer = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depth_render_buffer) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT, width, height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depth_render_buffer) gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, fbo_texture, 0) drawbuffers = [gl.GL_COLOR_ATTACHMENT0] gl.glDrawBuffers(1, drawbuffers) if gl.glCheckFramebufferStatus( gl.GL_FRAMEBUFFER) != gl.GL_FRAMEBUFFER_COMPLETE: return False return True
def createDepthBuffer(self, width, height): textureId = (gl.GLuint * 1)() gl.glGenRenderbuffers(1, textureId) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, textureId[0]) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT, width, height) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) return textureId[0]
def __init__(self, bufferFormats, width, height): if len(bufferFormats) > 6: raise RuntimeError("Number of attachement to buffer too high: " + str(len(bufferFormats))) # Create the frame buffer. self.textures_ = [] self.fbo_ = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fbo_) self.colorAttList_ = [ GL.GL_COLOR_ATTACHMENT0, GL.GL_COLOR_ATTACHMENT1, GL.GL_COLOR_ATTACHMENT2, GL.GL_COLOR_ATTACHMENT3, GL.GL_COLOR_ATTACHMENT4, GL.GL_COLOR_ATTACHMENT5, GL.GL_COLOR_ATTACHMENT6 ] self.formatDict_ = { GL.GL_RGBA32F: (GL.GL_RGBA, GL.GL_FLOAT), GL.GL_RGBA: (GL.GL_RGBA, GL.GL_UNSIGNED_BYTE), GL.GL_R32I: (GL.GL_RED_INTEGER, GL.GL_INT), GL.GL_RGBA32I: (GL.GL_RGBA_INTEGER, GL.GL_INT) } # Create the textures of the frame buffer. for it, currFormat in enumerate(bufferFormats): if not (currFormat in self.formatDict_): raise RuntimeError( "The texture format is not in the dictionary: " + str(currFormat)) myFormat = self.formatDict_[currFormat] texture = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, texture) 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, currFormat, width, height, 0, myFormat[0], myFormat[1], None) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, self.colorAttList_[it], GL.GL_TEXTURE_2D, texture, 0) self.textures_.append(texture) # Creaet the render buffer. self.rbo_ = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.rbo_) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, self.rbo_) # Check if the frame buffer was created properly. if not GL.glCheckFramebufferStatus( GL.GL_FRAMEBUFFER) == GL.GL_FRAMEBUFFER_COMPLETE: raise RuntimeError("Bind frame buffer failed") GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glBindTexture(GL.GL_TEXTURE_2D, 0) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0)
def setup_fb(self, width, height): '''Sets up FrameBuffer that will be used as container for 1 pass of rendering''' # Clean up old FB and Texture if self.fb_texture is not None and \ GL.glIsTexture(self.fb_texture): GL.glDeleteTextures([self.fb_texture]) if self.fbo is not None and GL.glIsFramebuffer(self.fbo): GL.glDeleteFramebuffers(1, [self.fbo]) # initialize FrameBuffer self.fbo = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fbo) depthbuffer = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthbuffer) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32F, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthbuffer) # end of FrameBuffer initialization # generate the texture we render to, and set parameters self.fb_texture = GL.glGenTextures(1) # create target texture # bind to new texture, all future texture functions will modify this # particular one GL.glBindTexture(GL.GL_TEXTURE_2D, self.fb_texture) # set how our texture behaves on x,y boundaries GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT) # set how our texture is filtered 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) # occupy width x height texture memory, (None at the end == empty # image) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA32F, width, height, 0, GL.GL_RGBA, GL.GL_FLOAT, None) # --- end texture init # Set "fb_texture" as our colour attachement #0 GL.glFramebufferTexture2D( GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.fb_texture, 0 # mipmap level, normally 0 ) # verify that everything went well status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) assert status == GL.GL_FRAMEBUFFER_COMPLETE, status
def __init__(self, width: int, height: int, renderbuffer_format=gl.GL_RGBA): self._format = renderbuffer_format self._width = width self._height = height self._id = gl.glGenRenderbuffers(1) # allocate storage. gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self._id) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, self._format, self._width, self._height) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0)
def resize(self, width, height): '''Resize to new width and height. For safety, this actually destroys and recreates the framebuffer and all attachments. ''' #Check to make sure we actually changed something. if self.width == width and self.height == height: return # print(width, height) self.delete() self.width = width self.height = height self.id = GL.glGenFramebuffers(1) self.bind() self.texture = Texture((self.width, self.height), **self.textureKwargs) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, self.texture.target, self.texture.id, 0) if self.depth: if self._depthTexture: self.depthTexture = Texture((self.width, self.height), **self.depthTextureKwargs) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, self.depthTexture.target, self.depthTexture.id, 0) else: self.depthId = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.depthId) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, self.depthType, self.width, self.height) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, self.depthId) status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) if status != GL.GL_FRAMEBUFFER_COMPLETE: errs = dict((int(globals()[item]), item) for item in globals() if 'GL_FRAMEBUFFER_' in item) raise RuntimeError("Framebuffer status: %s" % errs.get(status, status)) self.aspect = self.width / self.height
def bind(self, clear=True): self.viewport = tuple(GL.glGetIntegerv(GL.GL_VIEWPORT)) if not self.initialized: GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fb_id) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.rb_id) GL.glRenderbufferStorage( GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32F, self.viewport[2], self.viewport[3], ) GL.glFramebufferRenderbuffer( GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, self.rb_id, ) GL.glFramebufferTexture2D( GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.fb_tex.texture_name, 0, # mipmap level, normally 0 ) GL.glFramebufferTexture2D( GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_TEXTURE_2D, self.db_tex.texture_name, 0, # mipmap level, normally 0 ) status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) if status != GL.GL_FRAMEBUFFER_COMPLETE: raise RuntimeError self.initialized = True GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fb_id) if clear: GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) yield GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
def setup_texture_and_buffers(self): GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE) GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, self.width, self.height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.depth_buffer) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT16, self.width, self.height) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.framebuffer) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.texture, 0) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, self.depth_buffer) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
def _init_render(self): """ Initialize framebuffers to render offscreen, i.e. without displaying a window """ # Framebuffer self.fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) # Color renderbuffer self.rbo_color = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.rbo_color) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_RGBA8, self.width, self.height) gl.glFramebufferRenderbuffer(gl.GL_DRAW_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, self.rbo_color) # Depth and stencil renderbuffer. self.rbo_depth_stencil = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.rbo_depth_stencil) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH24_STENCIL8, self.width, self.height) gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_STENCIL_ATTACHMENT, gl.GL_RENDERBUFFER, self.rbo_depth_stencil) gl.glDrawBuffer(gl.GL_COLOR_ATTACHMENT0) gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) # Sanity check assert fbos.glCheckFramebufferStatusEXT(gl.GL_FRAMEBUFFER) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
def _initFBO(self): self.fboWidth = self.width self.fboHeight = self.height # Create three Render buffers. One for color one for XYZW one for depth_component self.renderBuffers = GL.glGenRenderbuffers(3) # initialize storage for the render buffers for i in range(2): GL.glBindRenderbuffer(GL.GL_RENDERBUFFER,self.renderBuffers[i]) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER,GL.GL_RGBA32F,self.fboWidth,self.fboHeight) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER,0) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER,self.renderBuffers[2]) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER,GL.GL_DEPTH_COMPONENT,self.fboWidth,self.fboHeight) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER,0) self.fbo = GL.glGenFramebuffers(1) # bind buffer and populate with RenderBuffers GL.glBindFramebuffer(GL.GL_FRAMEBUFFER,self.fbo) self.renderBufferAt = [GL.GL_COLOR_ATTACHMENT0,GL.GL_COLOR_ATTACHMENT1] GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,self.renderBufferAt[0],GL.GL_RENDERBUFFER,self.renderBuffers[0]) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,self.renderBufferAt[1],GL.GL_RENDERBUFFER,self.renderBuffers[1]) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,GL.GL_DEPTH_ATTACHMENT,GL.GL_RENDERBUFFER,self.renderBuffers[2]) # make sure that the new FBO is complete status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) if status != GL.GL_FRAMEBUFFER_COMPLETE: raise StandardError("Failed to properly setup FBO. OpenGL returned FBO status: ",status) #unbind FBO GL.glBindFramebuffer(GL.GL_FRAMEBUFFER,0) print "FBO initialized correctly."
def bind(self): gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.id)
def initializeGL(self): GL.glClearColor(0.50, 0.50, 0.50, 1.0) self.mode = 2 self.xN = 200 self.yN = 200 self.yawN = 0 self.pathX = np.linspace(450, 550, 100) self.pathNode = 0 self.renderMode = 0 self.heightMap = HeightMap('textures/atacama_height2.png') self.projection = QMatrix4x4() self.projection.perspective(self.fov, self.width / self.height, 0.01, 10000) self.cameraPos = QVector3D(0.0, 1.0, 1.0) self.terrainPos = QVector3D(0.0, 0.0, 0.0) self.roverPos = QVector3D(0.0, 0.0, 0.0) print(GL.glGetString(GL.GL_VERSION)) self.camera = Camera(self.cameraPos, self.heightMap) self.camera.setProjection(self.fov, self.width, self.height, 0.01, 1000) self.roverCamera = Camera(self.cameraPos, self.heightMap) self.roverCamera.setProjection(self.fov, self.width, self.height, 0.01, 1000) self.terrain = Terrain(self.terrainPos, self.heightMap) self.mask = np.zeros([1001, 1001]) self.terrain.updateRewards(self.mask) # set up frame buffer self.fbo = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fbo) # Attachments for frame buffer : Texture self.Frametexture = GL.glGenTextures(1) GL.glBindTexture(GL.GL_TEXTURE_2D, self.Frametexture) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, 640, 480, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, None) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.Frametexture, 0) self.rbo = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.rbo) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, 640, 480) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, self.rbo) if (GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) != GL.GL_FRAMEBUFFER_COMPLETE): print("Framebuffer not complete") GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
def init_gl(self): # Set up framebuffer and render textures self.fb = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.fb) self.depth_buffer = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self.depth_buffer) if self.multisample > 0: GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, self.multisample, GL.GL_DEPTH24_STENCIL8, self.width, self.height) else: GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, self.width, self.height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, self.depth_buffer) self.texture_id = int(GL.glGenTextures(1)) if self.multisample > 0: GL.glBindTexture(GL.GL_TEXTURE_2D_MULTISAMPLE, self.texture_id) GL.glTexImage2DMultisample(GL.GL_TEXTURE_2D_MULTISAMPLE, self.multisample, GL.GL_RGBA8, self.width, self.height, True) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D_MULTISAMPLE, self.texture_id, 0) else: GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture_id) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, self.width, self.height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) 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.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_LEVEL, 0) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.texture_id, 0) status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) if status != GL.GL_FRAMEBUFFER_COMPLETE: GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) raise Exception("Incomplete framebuffer") # Resolver framebuffer in case of multisample antialiasing if self.multisample > 0: self.resolve_fb = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.resolve_fb) self.resolve_texture_id = int(GL.glGenTextures(1)) GL.glBindTexture(GL.GL_TEXTURE_2D, self.resolve_texture_id) 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.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAX_LEVEL, 0) GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA8, self.width, self.height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, None) GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, self.resolve_texture_id, 0) status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER) if status != GL.GL_FRAMEBUFFER_COMPLETE: GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) raise Exception("Incomplete framebuffer") GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # OpenVR texture data self.texture = openvr.Texture_t() if self.multisample > 0: self.texture.handle = self.resolve_texture_id else: self.texture.handle = self.texture_id self.texture.eType = openvr.TextureType_OpenGL self.texture.eColorSpace = openvr.ColorSpace_Gamma
def renderToImage(self, width, height, filename=None, num_samples=16): """Render the current active GLWindow into a file""" import copy import OpenGL.GL as GL from qtpy import QtOpenGL viewport = GL.glGetIntegerv( GL.GL_VIEWPORT ) GL.glViewport(0, 0, width, height) GL.glEnable(GL.GL_MULTISAMPLE) # ======================================= # create framebuffer without multisampling simple_fb = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, simple_fb) # create renderbuffer for image without multisampling simple_rb = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, simple_rb) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_RGBA8, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_RENDERBUFFER, simple_rb) # ======================================= # create framebuffer with multisampling fb = GL.glGenFramebuffers(1) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb) # create renderbuffer for image rb = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, rb) GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, num_samples, GL.GL_RGBA8, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_RENDERBUFFER, rb) # renderbuffer for depth depth_rb = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb) GL.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, num_samples, GL.GL_DEPTH_COMPONENT32, width, height) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth_rb) # render image self.window_tabber.activeGLWindow.glWidget.paintGL() GL.glFinish() # blit image from multisampled framebuffer to simple frambuffer GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, fb) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, simple_fb) GL.glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, simple_fb) data = GL.glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, outputType=None) import PIL.Image as im image = im.frombytes('RGBA', (width,height), data).transpose(im.FLIP_TOP_BOTTOM) if filename!=None: image.save(filename) # cleanup GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glDeleteFramebuffers(2, [fb, simple_fb]) GL.glDeleteRenderbuffers(2, [rb, simple_rb]) GL.glDeleteRenderbuffers(1, [depth_rb]) GL.glViewport(*viewport) return image
def unbind(self): gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0)
def get_frame_image(app, art, frame, allow_crt=True, scale=1, bg_color=(0, 0, 0, 0)): "returns a PIL image of given frame of given art, None on failure" post_fb_class = ExportFramebuffer if allow_crt else ExportFramebufferNoCRT # determine art's native size in pixels w = art.charset.char_width * art.width h = art.charset.char_height * art.height w, h = int(w * scale), int(h * scale) # error out if over max texture size if w > app.max_texture_size or h > app.max_texture_size: app.log( "ERROR: Image output size (%s x %s) exceeds your hardware's max supported texture size (%s x %s)!" % (w, h, app.max_texture_size, app.max_texture_size), error=True) app.log( ' Please export at a smaller scale or chop up your artwork :[', error=True) return None # create CRT framebuffer post_fb = post_fb_class(app, w, h) # create render target and target framebuffer that will become image export_fb = GL.glGenFramebuffers(1) render_buffer = GL.glGenRenderbuffers(1) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, render_buffer) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_RGBA8, w, h) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, export_fb) GL.glFramebufferRenderbuffer(GL.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_RENDERBUFFER, render_buffer) GL.glViewport(0, 0, w, h) # do render GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, post_fb.framebuffer) # bg_color might be None GL.glClearColor(*bg_color or (0, 0, 0, 0)) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # render to it art.renderables[0].render_frame_for_export(frame) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, export_fb) post_fb.render() GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0) # read pixels from it pixels = GL.glReadPixels(0, 0, w, h, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, outputType=None) # cleanup / deinit of GL stuff GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) GL.glViewport(0, 0, app.window_width, app.window_height) GL.glDeleteFramebuffers(1, [export_fb]) GL.glDeleteRenderbuffers(1, [render_buffer]) post_fb.destroy() # GL pixel data as numpy array -> bytes for PIL image export pixel_bytes = pixels.flatten().tobytes() src_img = Image.frombytes(mode='RGBA', size=(w, h), data=pixel_bytes) src_img = src_img.transpose(Image.FLIP_TOP_BOTTOM) return src_img
def gl_init_routine(): global program global fbo global rb global pb global image # Compile and link shaders vert_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER) frag_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER) with open('surface_vert.glsl') as f: vert_shader_text = f.read() with open('surface_frag.glsl') as f: frag_shader_text = f.read() gl.glShaderSource(vert_shader, vert_shader_text) gl.glShaderSource(frag_shader, frag_shader_text) gl.glCompileShader(vert_shader) gl.glCompileShader(frag_shader) if not gl.glGetShaderiv(vert_shader, gl.GL_COMPILE_STATUS): print("Vertex shader did not compile") return False if not gl.glGetShaderiv(frag_shader, gl.GL_COMPILE_STATUS): print("Fragment shader did not compile") return False program = gl.glCreateProgram() gl.glAttachShader(program, vert_shader) gl.glAttachShader(program, frag_shader) gl.glLinkProgram(program) gl.glDetachShader(program, vert_shader) gl.glDetachShader(program, frag_shader) gl.glUseProgram(program) if not gl.glGetProgramiv(program, gl.GL_LINK_STATUS): print("Shader not linked") return False # Create and bind buffers # Vertex data buffer vert_dtype = np.dtype([('position', np.float32, 2)]) data = np.zeros(4, dtype=vert_dtype) data['position'] = [(-1, -1), (-1, 1), (1, -1), (1, 1)] stride = data.strides[0] # vb is the vertex buffer vb, pb = gl.glGenBuffers(2) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vb) gl.glBufferData(gl.GL_ARRAY_BUFFER, data.nbytes, data, gl.GL_DYNAMIC_DRAW) offset = ctypes.c_void_p(0) loc = gl.glGetAttribLocation(program, 'position') gl.glEnableVertexAttribArray(loc) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vb) gl.glVertexAttribPointer(loc, 2, gl.GL_FLOAT, False, stride, offset) # Offscreen framebuffer for OpenCV fbo = gl.glGenFramebuffers(1) rb = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, rb) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_RGBA8, WINDOW_WIDTH, WINDOW_HEIGHT) gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, fbo) gl.glFramebufferRenderbuffer(gl.GL_DRAW_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rb) return True
def main(): # start GLFW if not glfw.init(): return -1 # setup GLFW window options glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 2) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) # open the window window = glfw.create_window(800, 600, "Oculus Test", None, None) if not window: glfw.terminate() # always call this before setting up render layers glfw.make_context_current(window) # disable v-sync, we are syncing to the v-trace of head-set, leaving this on # will cause the HMD to lock to the frequency/phase of the display. glfw.swap_interval(0) # -------------------------------------------------------------------------- # Configure Rendering # initialize the runtime if failure(initialize()): _, msg = getLastErrorInfo() raise RuntimeError(msg) # create a new session if failure(create()): _, msg = getLastErrorInfo() raise RuntimeError(msg) # get general information about the HMD hmdInfo = getHmdInfo() # specify the eye render FOV for each render layer for eye, fov in enumerate(hmdInfo.defaultEyeFov): setEyeRenderFov(eye, fov) # get the optimal buffer dimensions for each eye texSizeLeft = calcEyeBufferSize(LIBOVR_EYE_LEFT) texSizeRight = calcEyeBufferSize(LIBOVR_EYE_RIGHT) # We are using a shared texture, so we need to combine dimensions. bufferW = texSizeLeft[0] + texSizeRight[0] bufferH = max(texSizeLeft[1], texSizeRight[1]) # initialize texture swap chain createTextureSwapChainGL(LIBOVR_TEXTURE_SWAP_CHAIN0, bufferW, bufferH) # set the same swap chain for both eyes since we are using a shared buffer for eye in range(LIBOVR_EYE_COUNT): setEyeColorTextureSwapChain(eye, LIBOVR_TEXTURE_SWAP_CHAIN0) # determine the viewports for each eye's image on the buffer eye_w = int(bufferW / 2) eye_h = bufferH # set the viewports viewports = ((0, 0, eye_w, eye_h), (eye_w, 0, eye_w, eye_h)) for eye, vp in enumerate(viewports): setEyeRenderViewport(eye, vp) # enable high quality mode setHighQuality(True) # create a frame buffer object as a render target for the HMD textures fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) depthRb_id = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(depthRb_id)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRb_id) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, int(bufferW), int(bufferH)) # buffer size used here! GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # mirror texture FBO mirrorFbo = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(mirrorFbo)) # setup a mirror texture, same size as the window createMirrorTexture(800, 600) # frame index, increment this every frame frame_index = 0 # begin application loop while not glfw.window_should_close(window): # wait for the buffer to be freed by the compositor, this is like # waiting for v-sync. waitToBeginFrame(frame_index) # predicted mid-frame time abs_time = getPredictedDisplayTime(frame_index) # get the current tracking state tracking_state, calibrated_origin = getTrackingState(abs_time, True) # calculate eye poses, this needs to be called every frame headPose, state = tracking_state[LIBOVR_TRACKED_DEVICE_TYPE_HMD] calcEyePoses(headPose.pose) # start frame rendering beginFrame(frame_index) # bind the render FBO GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) # get the current texture handle for this eye view, these are queued # in the swap chain and released when free. Making draw calls to # any other texture in the swap chain not returned here will report # and error. _, swapIdx = getTextureSwapChainCurrentIndex( LIBOVR_TEXTURE_SWAP_CHAIN0) _, tex_id = getTextureSwapChainBufferGL(LIBOVR_TEXTURE_SWAP_CHAIN0, swapIdx) # bind the returned texture ID to the frame buffer's texture slot GL.glFramebufferTexture2D(GL.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tex_id, 0) # for each eye, do some rendering for eye in range(LIBOVR_EYE_COUNT): # Set the viewport as what was configured for the render layer. We # also need to enable scissor testings with the same rect as the # viewport. This constrains rendering operations to one partition of # of the buffer since we are using a 'packed' layout. vp = getEyeRenderViewport(eye) GL.glViewport(*vp) GL.glScissor(*vp) # Get view and projection matrices, must be flattened assuming # column-major ('F') order into a 1x16 vector. P = np.ctypeslib.as_ctypes( getEyeProjectionMatrix(eye).flatten('F')) MV = np.ctypeslib.as_ctypes(getEyeViewMatrix(eye).flatten('F')) # Note - you don't need to get eye projection matrices each frame, # they are computed only when the eye FOVs are updated. You can # compute the eye projection matrices once before entering your # render loop if you don't plan on changing them during a session. # # However, the view matrices should be computed every frame! GL.glEnable(GL.GL_SCISSOR_TEST) # enable scissor test GL.glEnable(GL.GL_DEPTH_TEST) # Set the projection matrix. GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMultMatrixf(P) # Set the view matrix. This contains the translation for the head in # the virtual space computed by the API. GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glMultMatrixf(MV) # Note - We are not using shaders here to keep things simple. # However, you can pass computed transforms to a shader program # if you like. # Okay, let's begin drawing stuff. Clear the background first. GL.glClearColor(0.5, 0.5, 0.5, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # Draw a white 2x2 meter square positioned 5 meters in front of the # virtual space's origin. GL.glColor3f(1.0, 1.0, 1.0) GL.glPushMatrix() GL.glBegin(GL.GL_QUADS) GL.glVertex3f(-1.0, -1.0, -5.0) GL.glVertex3f(-1.0, 1.0, -5.0) GL.glVertex3f(1.0, 1.0, -5.0) GL.glVertex3f(1.0, -1.0, -5.0) GL.glEnd() GL.glPopMatrix() GL.glDisable(GL.GL_DEPTH_TEST) # commit the texture when were done drawing to it commitTextureSwapChain(LIBOVR_TEXTURE_SWAP_CHAIN0) # unbind the frame buffer, we're done with it GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) # end frame rendering, submitting the eye layer to the compositor endFrame(frame_index) # increment frame index frame_index += 1 # blit mirror texture GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, mirrorFbo) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) _, mirrorId = getMirrorTexture() # bind the rift's mirror texture to the framebuffer GL.glFramebufferTexture2D(GL.GL_READ_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, mirrorId, 0) # render the mirror texture to the on-screen window's back buffer GL.glViewport(0, 0, 800, 600) GL.glScissor(0, 0, 800, 600) GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) GL.glBlitFramebuffer( 0, 0, 800, 600, 0, 600, 800, 0, # this flips the texture GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # if button 'A' is released on the touch controller, recenter the # viewer in the scene. If 'B' was pressed, exit the loop. updateInputState(LIBOVR_CONTROLLER_TYPE_TOUCH) A = getButton(LIBOVR_CONTROLLER_TYPE_TOUCH, LIBOVR_BUTTON_A, 'falling') B = getButton(LIBOVR_CONTROLLER_TYPE_TOUCH, LIBOVR_BUTTON_B, 'falling') if A[0]: # first value is the state, second is the polling time recenterTrackingOrigin() elif B[0]: # exit if button 'B' is pressed break # flip the GLFW window and poll events glfw.swap_buffers(window) glfw.poll_events() # free resources destroyMirrorTexture() destroyTextureSwapChain(LIBOVR_TEXTURE_SWAP_CHAIN0) destroy() # end the rift session cleanly shutdown() # close the GLFW application glfw.terminate() return 0
def __enter__(self): self.nests += 1 if self.nests > 1: return self ovr.initialize() ovr.create() # get response devices controllers_ok = False while not controllers_ok: controllers = ovr.getConnectedControllerTypes() if len(controllers) == 0: if self._require_controller: try_again = easygui.ccbox(msg="Pair a touch device", choices=["Try again", "Cancel"]) if not try_again: raise ValueError("User cancelled") else: self._controller = None controllers_ok = True elif len(controllers) == 1: (self._controller, ) = controllers controllers_ok = True else: use_left_controller = easygui.boolbox( msg="Which controller?", choices=["Left", "Right"]) if use_left_controller: controller_id = ovr.CONTROLLER_TYPE_LTOUCH else: controller_id = ovr.CONTROLLER_TYPE_RTOUCH self._controller = controllers[controllers.index( controller_id)] controllers_ok = True self._last_thumb = 0.0 self.hmd_info = ovr.getHmdInfo() i_left = ovr.EYE_LEFT i_right = ovr.EYE_RIGHT i_eyes = (i_left, i_right) symm = self.hmd_info.symmetricEyeFov # symmetric for monoscopic for (i_eye, eye_fov) in zip(i_eyes, symm): ovr.setEyeRenderFov(eye=i_eye, fov=eye_fov) tex_sizes = [ovr.calcEyeBufferSize(i_eye) for i_eye in i_eyes] assert tex_sizes[0] == tex_sizes[1] (self.tex_size, _) = tex_sizes (self.tex_width, self.tex_height) = self.tex_size self.viewport = [0, 0, self.tex_size[0], self.tex_size[1]] for i_eye in i_eyes: ovr.setEyeRenderViewport(eye=i_eye, values=self.viewport) self.proj_mat = ovr.getEyeProjectionMatrix(0) assert np.all(self.proj_mat == ovr.getEyeProjectionMatrix(1)) ovr.createTextureSwapChainGL( ovr.TEXTURE_SWAP_CHAIN0, width=self.tex_width, height=self.tex_height, textureFormat=ovr.FORMAT_R8G8B8A8_UNORM_SRGB, ) for i_eye in i_eyes: ovr.setEyeColorTextureSwapChain(eye=i_eye, swapChain=ovr.TEXTURE_SWAP_CHAIN0) ovr.setHighQuality(True) gl.glViewport(*self.viewport) # generate the MSAA buffer if self._msaa > 1: self.i_msaa_fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.i_msaa_fbo) self.i_msaa_rbo = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.i_msaa_rbo) gl.glRenderbufferStorageMultisample( gl.GL_RENDERBUFFER, self._msaa, gl.GL_SRGB8_ALPHA8, self.tex_width, self.tex_height, ) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, self.i_msaa_rbo, ) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) self.i_msaa_depth_rbo = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.i_msaa_depth_rbo) gl.glRenderbufferStorageMultisample( gl.GL_RENDERBUFFER, self._msaa, gl.GL_DEPTH24_STENCIL8, self.tex_width, self.tex_height, ) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, self.i_msaa_depth_rbo, ) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_STENCIL_ATTACHMENT, gl.GL_RENDERBUFFER, self.i_msaa_depth_rbo, ) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) gl.glClear(gl.GL_STENCIL_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) self.i_fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.i_fbo) self.i_rbo = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.i_rbo) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH24_STENCIL8, self.tex_width, self.tex_height) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_DEPTH_STENCIL_ATTACHMENT, gl.GL_RENDERBUFFER, self.i_rbo, ) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) if self.mirror: ovr.createMirrorTexture( width=self.tex_width, height=self.tex_height, mirrorOptions=ovr.MIRROR_OPTION_RIGHT_EYE_ONLY, ) self.i_mirror_fbo = gl.glGenFramebuffers(1) return self
def release(self): gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0)
def paintGL(self): """Paint the scene.""" # clear the color and depth buffer gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # initialize FrameBuffer fbo = gl.glGenFramebuffers(1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) depthbuffer = gl.glGenRenderbuffers(1) gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, depthbuffer) gl.glRenderbufferStorage(gl.GL_RENDERBUFFER, gl.GL_DEPTH_COMPONENT24, self.width, self.height) gl.glFramebufferRenderbuffer( gl.GL_FRAMEBUFFER, gl.GL_DEPTH_ATTACHMENT, gl.GL_RENDERBUFFER, depthbuffer ) # --- end FB init # generate the texture we render to, and set parameters renderedTexture = gl.glGenTextures(1) # create target texture # bind to new texture, all future texture functions will modify this # particular one gl.glBindTexture(gl.GL_TEXTURE_2D, renderedTexture) # set how our texture behaves on x,y boundaries gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) # set how our texture is filtered 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) # occupy width x height texture memory, (None at the end == empty # image) gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, self.width, self.height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_INT, None) # --- end texture init # Set "renderedTexture" as our colour attachement #0 gl.glFramebufferTexture2D( gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, renderedTexture, 0 # mipmap level, normally 0 ) status = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert status == gl.GL_FRAMEBUFFER_COMPLETE, status # bind to fb gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbo) # viewport is shared with the main context gl.glViewport(0, 0, self.width, self.height) # Clear the screen gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # --- at this point everything should be set, draw away # THIS IS DRAWING PART # bind the VBO self.vbo.bind() # tell OpenGL that the VBO contains an array of vertices # prepare the shader gl.glEnableVertexAttribArray(0) # these vertices contain 2 single precision coordinates gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None) gl.glUseProgram(self.shaders_program) # draw "count" points from the VBO gl.glDrawArrays(gl.GL_LINE_STRIP, 0, len(self.data)) # END OF DRAWING PART debug_buffer = gl.glReadPixels(0, 0, self.width, self.height, gl.GL_RGB, gl.GL_UNSIGNED_BYTE) image = Image.frombytes(mode="RGB", size=(self.width, self.height), data=debug_buffer) image = image.transpose(Image.FLIP_TOP_BOTTOM) image.save("/tmp/foo.jpg") gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) # unbind FB gl.glBindTexture(gl.GL_TEXTURE_2D, renderedTexture) # bind to result ?? # THIS IS DRAWING PART II # vertex arrays must be enabled using glEnableClientState gl.glEnable(gl.GL_TEXTURE_2D) # ??? texId = gl.glGetUniformLocation(self.my_shaders_program, "renderedTexture") gl.glUseProgram(self.my_shaders_program) # HOW TO DRAW TEXTURE gl.glActiveTexture(gl.GL_TEXTURE0); gl.glBindTexture(gl.GL_TEXTURE_2D, renderedTexture) # bind to result ?? # Set our "renderedTexture" sampler to user Texture Unit 0 gl.glUniform1i(texId, 0); gl.glBegin(gl.GL_QUADS) gl.glVertex3f(-1.0,-1.0, 0.0) gl.glVertex3f( 1.0,-1.0, 0.0) gl.glVertex3f( 1.0, 1.0, 0.0) gl.glVertex3f(-1.0, 1.0, 0.0) gl.glEnd()
def main(): # start GLFW if not glfw.init(): return -1 # setup GLFW window options glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 2) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) # open the window window = glfw.create_window(800, 600, "Oculus Test", None, None) if not window: glfw.terminate() # always call this before setting up render layers glfw.make_context_current(window) # disable v-sync, we are syncing to the v-trace of head-set, leaving this on # will cause the HMD to lock to the frequency/phase of the display. glfw.swap_interval(0) # start an Oculus session capi.startSession() # get general information about the HMD hmd_desc = capi.getHmdDesc() # set the perf hud on capi.perfHudMode("PerfSummary") # configure the internal render descriptors for each eye for eye in range(capi.ovrEye_Count): capi.configEyeRenderDesc(eye, hmd_desc.DefaultEyeFov[eye]) # Get the buffer dimensions specified by the Rift SDK, we need them to # setup OpenGL frame buffers. tex_size_left = capi.getFovTextureSize( capi.ovrEye_Left, hmd_desc.DefaultEyeFov[0]) tex_size_right = capi.getFovTextureSize( capi.ovrEye_Right, hmd_desc.DefaultEyeFov[1]) # We are using a shared texture, so we need to combine dimensions. buffer_w = tex_size_left.w + tex_size_right.w buffer_h = max(tex_size_left.h, tex_size_right.h) # Allocate a swap chain for render buffer textures, the handle used is an # integer. You can allocated up to 32 swap chains, however you will likely # run out of video memory by then. # configure the swap chain swap_config = capi.ovrTextureSwapChainDesc() swap_config.Format = capi.OVR_FORMAT_R8G8B8A8_UNORM_SRGB swap_config.Type = capi.ovrTexture_2D swap_config.Width = buffer_w swap_config.Height = buffer_h # Initialize texture swap chain swap_chain = capi.createTextureSwapChainGL(swap_config) # Since we are using a shared texture, each eye's viewport is half the width # of the allocated buffer texture. eye_w = int(buffer_w / 2) eye_h = buffer_h # setup the render layer viewports = (vrmath.ovrRecti(0, 0, eye_w, eye_h), vrmath.ovrRecti(eye_w, 0, eye_w, eye_h)) for eye in range(capi.ovrEye_Count): capi.setRenderViewport(eye, viewports[eye]) capi.setRenderSwapChain(0, swap_chain) # set the swap chain #rift.setRenderSwapChain(1, None) # create a frame buffer object as a render target for the HMD textures fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) depthRb_id = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(depthRb_id)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRb_id) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, int(buffer_w), int(buffer_h)) # buffer size used here! GL.glFramebufferRenderbuffer( GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glFramebufferRenderbuffer( GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) # mirror texture FBO mirrorFbo = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(mirrorFbo)) # setup a mirror texture mirror_config = capi.ovrMirrorTextureDesc() mirror_config.Width = 800 mirror_config.Height = 600 capi.setupMirrorTexture(mirror_config) # same size as window # frame index, increment this every frame frame_index = 0 # compute projection matrices proj_left = capi.getEyeProjectionMatrix(capi.ovrEye_Left) proj_right = capi.getEyeProjectionMatrix(capi.ovrEye_Right) # get the player height print(capi.getPlayerHeight()) # begin application loop while not glfw.window_should_close(window): # wait for the buffer to be freed by the compositor, this is like # waiting for v-sync. capi.waitToBeginFrame(frame_index) #print(proj_left.M) # get current display time + predicted mid-frame time abs_time = capi.getDisplayTime(frame_index) # get the current tracking state tracking_state = capi.getTrackingState(abs_time) # Calculate eye poses, this needs to be called every frame, do this # after calling 'wait_to_begin_frame' to minimize the motion-to-photon # latency. left_eye_pose, right_eye_pose = capi.calcEyePoses( tracking_state) # get the view matrix from the HMD after calculating the pose view_left = capi.getEyeViewMatrix(left_eye_pose) view_right = capi.getEyeViewMatrix(right_eye_pose) # start frame rendering capi.beginFrame(frame_index) # bind the render FBO GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) # get the current texture handle for this eye view, these are queued # in the swap chain and released when free. Making draw calls to # any other texture in the swap chain not returned here will report # and error. tex_id = capi.getTextureSwapChainBufferGL(swap_chain) # bind the returned texture ID to the frame buffer's texture slot GL.glFramebufferTexture2D( GL.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tex_id, 0) # for each eye, do some rendering for eye in range(capi.ovrEye_Count): # Set the viewport as what was configured for the render layer. We # also need to enable scissor testings with the same rect as the # viewport. This constrains rendering operations to one partition of # of the buffer since we are using a 'packed' layout. vp = capi.getRenderViewport(eye) GL.glViewport(*vp.asTuple()) GL.glScissor(*vp.asTuple()) GL.glEnable(GL.GL_SCISSOR_TEST) # enable scissor test GL.glEnable(GL.GL_DEPTH_TEST) # Here we can make whatever OpenGL we wish to draw our image. As an # example, I'm going to clear the eye buffer texture all some color, # with the colour determined by the active eye buffer. if eye == capi.ovrEye_Left: GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMultMatrixf(proj_left.ctypes) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() if HEAD_TRACKING: GL.glMultMatrixf(view_left.ctypes) GL.glClearColor(0.5, 0.5, 0.5, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glColor3f(1.0, 1.0, 1.0) GL.glPushMatrix() GL.glBegin(GL.GL_QUADS) GL.glVertex3f(-1.0, -1.0, -5.0) GL.glVertex3f(-1.0, 1.0, -5.0) GL.glVertex3f(1.0, 1.0, -5.0) GL.glVertex3f(1.0, -1.0, -5.0) GL.glEnd() GL.glPopMatrix() elif eye == capi.ovrEye_Right: GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMultMatrixf(proj_right.ctypes) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() if HEAD_TRACKING: GL.glMultMatrixf(view_right.ctypes) GL.glClearColor(0.5, 0.5, 0.5, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glColor3f(1.0, 1.0, 1.0) GL.glPushMatrix() GL.glBegin(GL.GL_QUADS) GL.glVertex3f(-1.0, -1.0, -5.0) GL.glVertex3f(-1.0, 1.0, -5.0) GL.glVertex3f(1.0, 1.0, -5.0) GL.glVertex3f(1.0, -1.0, -5.0) GL.glEnd() GL.glPopMatrix() GL.glDisable(GL.GL_DEPTH_TEST) # commit the texture when were done drawing to it capi.commitSwapChain(swap_chain) # unbind the frame buffer, we're done with it GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) # end frame rendering, submitting the eye layer to the compositor capi.endFrame(frame_index) # increment frame index frame_index += 1 # update session status session_status = capi.getSessionStatus() # blit mirror texture GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, mirrorFbo) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) # bind the rift's texture to the framebuffer GL.glFramebufferTexture2D( GL.GL_READ_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, capi.getMirrorTexture(), 0) GL.glViewport(0, 0, 800, 600) GL.glScissor(0, 0, 800, 600) GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) GL.glBlitFramebuffer(0, 0, 800, 600, 0, 600, 800, 0, # this flips the texture GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) capi.pollController('touch') # update touch controller state # if button 'A' is released on the touch controller, recenter the # viewer in the scene. if capi.getButtons('touch', 'A', 'falling'): capi.recenterTrackingOrigin() elif capi.getButtons('touch', 'B', 'falling'): # exit if button 'B' is pressed break # flip the GLFW window and poll events glfw.swap_buffers(window) glfw.poll_events() # switch off the performance summary capi.perfHudMode("Off") # end the rift session cleanly, all swap chains are destroyed here capi.endSession() # close the GLFW application glfw.terminate() return 0
def main(): if not glfw.init(): return -1 if not glfw.init(): return -1 glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 2) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) window = glfw.create_window(800, 600, "Oculus Test", None, None) if not window: glfw.terminate() glfw.make_context_current(window) glfw.swap_interval(0) if failure(initialize()): return -1 if failure(create()): shutdown() return -1 hmdInfo = getHmdInfo() for eye, fov in enumerate(hmdInfo.defaultEyeFov): setEyeRenderFov(eye, fov) texSizeLeft = calcEyeBufferSize(EYE_LEFT) texSizeRight = calcEyeBufferSize(EYE_RIGHT) bufferW = texSizeLeft[0] + texSizeRight[0] bufferH = max(texSizeLeft[1], texSizeRight[1]) createTextureSwapChainGL(TEXTURE_SWAP_CHAIN0, bufferW, bufferH) for eye in range(EYE_COUNT): setEyeColorTextureSwapChain(eye, TEXTURE_SWAP_CHAIN0) eye_w = int(bufferW / 2) eye_h = bufferH viewports = ((0, 0, eye_w, eye_h), (eye_w, 0, eye_w, eye_h)) for eye, vp in enumerate(viewports): setEyeRenderViewport(eye, vp) setHighQuality(True) fboId = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(fboId)) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) depthRb_id = GL.GLuint() GL.glGenRenderbuffers(1, ctypes.byref(depthRb_id)) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, depthRb_id) GL.glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, int(bufferW), int(bufferH)) # buffer size used here! GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, depthRb_id) GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) mirrorFbo = GL.GLuint() GL.glGenFramebuffers(1, ctypes.byref(mirrorFbo)) createMirrorTexture(800, 600, mirrorOptions=MIRROR_OPTION_DEFAULT) frame_index = 0 projectionMatrix = [] for eye in range(EYE_COUNT): projectionMatrix.append(getEyeProjectionMatrix(eye)) planePose = LibOVRPose((0., 0., -2.)) # begin application loop while not glfw.window_should_close(window): waitToBeginFrame(frame_index) abs_time = getPredictedDisplayTime(frame_index) tracking_state = getTrackingState(abs_time, True) calcEyePoses(tracking_state.headPose.thePose) beginFrame(frame_index) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fboId) _, swapIdx = getTextureSwapChainCurrentIndex(TEXTURE_SWAP_CHAIN0) _, tex_id = getTextureSwapChainBufferGL(TEXTURE_SWAP_CHAIN0, swapIdx) GL.glFramebufferTexture2D(GL.GL_DRAW_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, tex_id, 0) for eye in range(EYE_COUNT): vp = getEyeRenderViewport(eye) GL.glViewport(*vp) GL.glScissor(*vp) P = projectionMatrix[eye] MV = getEyeViewMatrix(eye) GL.glEnable(GL.GL_SCISSOR_TEST) GL.glEnable(GL.GL_DEPTH_TEST) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadTransposeMatrixf(P) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadTransposeMatrixf(MV) GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glPushMatrix() GL.glMultTransposeMatrixf(planePose.modelMatrix) GL.glBegin(GL.GL_QUADS) GL.glColor3f(1.0, 0.0, 0.0) GL.glVertex3f(-1.0, -1.0, 0.0) GL.glColor3f(0.0, 1.0, 0.0) GL.glVertex3f(-1.0, 1.0, 0.0) GL.glColor3f(0.0, 0.0, 1.0) GL.glVertex3f(1.0, 1.0, 0.0) GL.glColor3f(1.0, 1.0, 1.0) GL.glVertex3f(1.0, -1.0, 0.0) GL.glEnd() GL.glPopMatrix() GL.glDisable(GL.GL_DEPTH_TEST) commitTextureSwapChain(TEXTURE_SWAP_CHAIN0) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) endFrame(frame_index) frame_index += 1 GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, mirrorFbo) GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, 0) _, mirrorId = getMirrorTexture() GL.glFramebufferTexture2D(GL.GL_READ_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, mirrorId, 0) GL.glViewport(0, 0, 800, 600) GL.glScissor(0, 0, 800, 600) GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) GL.glBlitFramebuffer(0, 0, 800, 600, 0, 600, 800, 0, GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0) glfw.swap_buffers(window) updateInputState(CONTROLLER_TYPE_TOUCH) A = getButton(CONTROLLER_TYPE_TOUCH, BUTTON_A, 'falling') B = getButton(CONTROLLER_TYPE_TOUCH, BUTTON_B, 'falling') if A[0]: recenterTrackingOrigin() elif B[0]: break glfw.poll_events() _, sessionStatus = getSessionStatus() if sessionStatus.shouldQuit: break destroyMirrorTexture() destroyTextureSwapChain(TEXTURE_SWAP_CHAIN0) destroy() # shutdown() causes access violation on exit return 0