def swapBuffers(self): # first call the swap on the QGLWidget start = long(now()*1000) self.glw.swapBuffers() #self.glw.makeCurrent() # The following is taken from the PsychToolbox # Draw a single pixel in left-top area of back-buffer. # This will wait/stall the rendering pipeline # until the buffer flip has happened, aka immediately after the VBL has started. # We need the pixel as "synchronization token", so the following glFinish() really # waits for VBL instead of just "falling through" due to the asynchronous nature of # OpenGL: glDrawBuffer(GL_BACK) # We draw our single pixel with an alpha-value of zero - so effectively it doesn't # change the color buffer - just the z-buffer if z-writes are enabled... glColor4f(0.0,0.0,0.0,0.0) glBegin(GL_POINTS) glVertex2i(10,10) glEnd() # This glFinish() will wait until point drawing is finished, ergo backbuffer was ready # for drawing, ergo buffer swap in sync with start of VBL has happened. glFinish() finish = long(now()*1000) fdiff = finish - self.last_finish self.last_finish = finish return (start,finish-start,fdiff)
def bind_depth_texture(self, size): """Create depth texture for shadow map.""" width, height = size texture_type = GL_TEXTURE_2D self.__depth_map_fbo = glGenFramebuffers(1) depth_map = self.__textures_ids[len(self.__textures)] glBindTexture(texture_type, depth_map) self.__textures.append(2) glTexImage2D(texture_type, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS) glBindFramebuffer(GL_FRAMEBUFFER, self.__depth_map_fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0) glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) glBindFramebuffer(GL_FRAMEBUFFER, 0)
def swapBuffers(self): # first call the swap on the QGLWidget start = long(now() * 1000) self.glw.swapBuffers() #self.glw.makeCurrent() # The following is taken from the PsychToolbox # Draw a single pixel in left-top area of back-buffer. # This will wait/stall the rendering pipeline # until the buffer flip has happened, aka immediately after the VBL has started. # We need the pixel as "synchronization token", so the following glFinish() really # waits for VBL instead of just "falling through" due to the asynchronous nature of # OpenGL: glDrawBuffer(GL_BACK) # We draw our single pixel with an alpha-value of zero - so effectively it doesn't # change the color buffer - just the z-buffer if z-writes are enabled... glColor4f(0.0, 0.0, 0.0, 0.0) glBegin(GL_POINTS) glVertex2i(10, 10) glEnd() # This glFinish() will wait until point drawing is finished, ergo backbuffer was ready # for drawing, ergo buffer swap in sync with start of VBL has happened. glFinish() finish = long(now() * 1000) fdiff = finish - self.last_finish self.last_finish = finish return (start, finish - start, fdiff)
def create(self, app): """ creates resources. """ self.app = app shadowMaps = self.shadowMaps # reserve a texture unit for shadow texture self.textureUnit = app.reserveTextureUnit() # create a 3D texture using GL_TEXTURE_2D_ARRAY self.texture = DepthTexture3D(self.sizeI, self.sizeI) self.texture.targetType = GL_TEXTURE_2D_ARRAY self.texture.internalFormat = GL_DEPTH_COMPONENT24 self.texture.numTextures = self.numShadowMaps self.texture.pixelType = GL_FLOAT self.texture.minFilterMode = GL_LINEAR self.texture.magFilterMode = GL_LINEAR self.texture.wrapMode = GL_CLAMP_TO_EDGE self.texture.compareFunc = GL_LEQUAL if self.textureType=="sampler2DArrayShadow": self.texture.compareMode = GL_COMPARE_R_TO_TEXTURE else: self.texture.compareMode = GL_NONE self.texture.create() # create a depth only fbo for the 3D texture self.fbo = glGenFramebuffers(1) glBindFramebuffer(GL_FRAMEBUFFER, self.fbo) glDrawBuffer(GL_NONE) glBindFramebuffer(GL_FRAMEBUFFER, 0) # the frustum slice far value must be accessable in the shader. # uniforms does not support array, so we split # the frustum slices in vec4 instances.... numVecs = self.numShadowMaps/4; mod = self.numShadowMaps%4 self.farVecs = [4]*numVecs if mod != 0: self.farVecs.append( mod ) numVecs += 1 # create shadow maps for i in range(self.numShadowMaps): shadowMap = shadowMaps[i] shadowMap.textureMatrixUnit = app.reserveTextureMatrixUnit() shadowMap.textureLayer = i shadowMap.create(app)
def __init__(self, w, h, color_texture, depth_texture): self._gl_id = glGenFramebuffers(1); self._ct = color_texture self._dt = depth_texture with self: glDrawBuffer(GL_COLOR_ATTACHMENT0) glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gl_id(color_texture), 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, gl_id(depth_texture), 0); rid = glGenRenderbuffers(1) glBindRenderbuffer(GL_RENDERBUFFER, rid) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rid) glBindRenderbuffer(GL_RENDERBUFFER, 0) e = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if e != GL_FRAMEBUFFER_COMPLETE: raise Exception('GOT PROBLEMS {}'.format(e))
def do_scroll_paints(self, scrolls, flush=0, callbacks=[]): log("do_scroll_paints%s", (scrolls, flush)) context = self.gl_context() if not context: log.warn("Warning: cannot paint scroll, no OpenGL context!") return def fail(msg): log.error("Error: %s", msg) fire_paint_callbacks(callbacks, False, msg) with context: bw, bh = self.size self.set_rgb_paint_state() #paste from offscreen to tmp with delta offset: glBindFramebuffer(GL_READ_FRAMEBUFFER, self.offscreen_fbo) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glReadBuffer(GL_COLOR_ATTACHMENT0) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.tmp_fbo) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_TMP_FBO]) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_TMP_FBO], 0) glDrawBuffer(GL_COLOR_ATTACHMENT1) #copy current fbo: glBlitFramebuffer(0, 0, bw, bh, 0, 0, bw, bh, GL_COLOR_BUFFER_BIT, GL_NEAREST) for x,y,w,h,xdelta,ydelta in scrolls: if abs(xdelta)>=bw: fail("invalid xdelta value: %i" % xdelta) continue if abs(ydelta)>=bh: fail("invalid ydelta value: %i" % ydelta) continue if ydelta==0 and xdelta==0: fail("scroll has no delta!") continue if w<=0 or h<=0: fail("invalid scroll area size: %ix%i" % (w, h)) continue #these should be errors, #but desktop-scaling can cause a mismatch between the backing size #and the real window size server-side.. so we clamp the dimensions instead if x+w>bw: w = bw-x if y+h>bh: h = bh-y if x+w+xdelta>bw: w = bw-x-xdelta if w<=0: continue #nothing left! if y+h+ydelta>bh: h = bh-y-ydelta if h<=0: continue #nothing left! if x+xdelta<0: fail("horizontal scroll by %i: rectangle %s overflows the backing buffer size %s" % (xdelta, (x, y, w, h), self.size)) continue if y+ydelta<0: fail("vertical scroll by %i: rectangle %s overflows the backing buffer size %s" % (ydelta, (x, y, w, h), self.size)) continue #opengl buffer is upside down, so we must invert Y coordinates: bh-(..) glBlitFramebuffer(x, bh-y, x+w, bh-(y+h), x+xdelta, bh-(y+ydelta), x+w+xdelta, bh-(y+h+ydelta), GL_COLOR_BUFFER_BIT, GL_NEAREST) glFlush() #now swap references to tmp and offscreen so tmp becomes the new offscreen: tmp = self.offscreen_fbo self.offscreen_fbo = self.tmp_fbo self.tmp_fbo = tmp tmp = self.textures[TEX_FBO] self.textures[TEX_FBO] = self.textures[TEX_TMP_FBO] self.textures[TEX_TMP_FBO] = tmp #restore normal paint state: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glBindFramebuffer(GL_READ_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) self.unset_rgb_paint_state() self.paint_box("scroll", True, x+xdelta, y+ydelta, x+w+xdelta, y+h+ydelta) self.present_fbo(0, 0, bw, bh, flush) fire_paint_callbacks(callbacks, True)
def attach(self): glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, self.texture, 0) glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE)
def OnPaint(self, event): # startTime = time.time() if not self.init: self.context = GLContext(self) self.SetCurrent(self.context) glEnable(GL_DEPTH_TEST); self.init = True if self._refreshAll: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # prepareTime = time.time() - startTime if self.dataNum == 0: self.SwapBuffers() return eyePos = self.eyeDistance ex = 0.0 ey = 0.0 ez = 0.0 dx = 0.0 dy = 0.0 dz = 0.0 ux = 0.0 uy = 0.0 uz = 0.0 xLen = max(abs(self.xMax), abs(self.xMin)) * 2 yLen = max(abs(self.yMax), abs(self.yMin)) * 2 zLen = max(abs(self.zMax), abs(self.zMin)) * 2 # print 'transX, transY:', self.transX, self.transY if self.is3D: r2s = max(xLen, yLen, zLen) / self.size.width tX = self.transX * r2s tY = self.transY * r2s if not zLen == 0: z = zLen / 2 if yLen / zLen > self.size.width / self.size.height: z = yLen * self.size.height / self.size.width / 2 z *= 1.5 usedAngle = pi / 2 - viewPosAngle cfovy1 = (eyePos - z * cos(usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(usedAngle)) cfovy2 = (eyePos - z * cos(pi - usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(pi - usedAngle)) fovy1 = degrees(acos(cfovy1)) fovy2 = degrees(acos(cfovy2)) self.fovy = 3 * max(fovy1, fovy2) angleX = viewPosAngle + radians(self.angleHorizontal) angleZ = viewPosAngle + radians(self.angleVertical) ex = eyePos * cos(angleZ) * cos(angleX) ey = eyePos * cos(angleZ) * sin(angleX) ez = eyePos * sin(angleZ) ux = 0.0 uy = cos(pi / 2 - radians(self.angleFlat)) uz = sin(pi / 2 - radians(self.angleFlat)) flatAngle = radians(self.angleFlat) dx = -tX * cos(flatAngle) * sin(angleX) - tX * sin(flatAngle) * sin(angleZ) * sin(angleX) dx += tY * sin(flatAngle) * sin(angleX) - tY * cos(flatAngle) * sin(angleZ) * cos(angleX) dy = tX * cos(flatAngle) * cos(angleX) - tX * sin(flatAngle) * sin(angleZ) * cos(angleX) dy += -tY * sin(flatAngle) * cos(angleX) - tY * cos(flatAngle) * sin(angleZ) * sin(angleX) dz = tX * sin(flatAngle) * cos(angleZ) dz += tY * cos(flatAngle) * cos(angleZ) else: r2s = xLen / self.size.width dx = self.transX * r2s dy = self.transY * r2s dz = 0.0 y = yLen / 2 if xLen / yLen > self.size.width / self.size.height: y = xLen * self.size.height / self.size.width / 2 y += yLen / 10 self.fovy = 2 * degrees(atan(y / eyePos)) ez = eyePos ux = sin(radians(self.angleFlat)) uy = cos(radians(self.angleFlat)) uz = 0.0 scale = 1 if self.size != None: scale = float(self.size.width) / self.size.height # userCalculationTime = time.time() - startTime - prepareTime glMatrixMode(GL_PROJECTION) glLoadIdentity() if self.is3D: gluPerspective(self.fovy * self.scaleFactor, scale, 0.1, self.eyeDistance * 2) else: gluPerspective(self.fovy * self.scaleFactor, scale, self.eyeDistance - self.zMax - 10, self.eyeDistance - self.zMin + 10) glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(ex, ey, ez, -dx, -dy, -dz, ux, uy, uz) self._startPointIdx = 0 if self.isDragging: # draw the frame instead of all data glLineWidth(1.0) glColor3f(0.0, 0.5, 0.0) glBegin(GL_LINES) glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glEnd() glFlush() self.SwapBuffers() return glEnableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glEnableClientState(GL_COLOR_ARRAY) glDrawBuffer(GL_FRONT_AND_BACK) if self._startPointIdx + self._drawnPointsNum >= self.dataNum: glDrawArrays(GL_POINTS, self._startPointIdx, self.dataNum - self._startPointIdx) if self.displaySelected: selNum = len(self.displayedSelPoints) if selNum >= 2: glLineWidth(2.0) glColor3f(0.0, 1.0, 0.0) glBegin(GL_LINES) for i in xrange(1, selNum): glVertex3f(self.displayedSelPoints[i - 1][0], self.displayedSelPoints[i - 1][1], self.displayedSelPoints[i - 1][2]) glVertex3f(self.displayedSelPoints[i][0], self.displayedSelPoints[i][1], self.displayedSelPoints[i][2]) glVertex3f(self.displayedSelPoints[selNum - 1][0], self.displayedSelPoints[selNum - 1][1], self.displayedSelPoints[selNum - 1][2]) glVertex3f(self.displayedSelPoints[0][0], self.displayedSelPoints[0][1], self.displayedSelPoints[0][2]) glEnd() self._refreshAll = True else: glDrawArrays(GL_POINTS, self._startPointIdx, self._drawnPointsNum) self._refreshAll = False self._isFront = not self._isFront self._startPointIdx += self._drawnPointsNum if self._isFront else 0 glDisableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glDisableClientState(GL_COLOR_ARRAY) glFlush() self.SwapBuffers() # drawingTime = time.time() - startTime - prepareTime - userCalculationTime # print "preparation time:", str(prepareTime), "user calculation time:",\ # str(userCalculationTime), "drawing time:", str(drawingTime) if not self._refreshAll: PostEvent(self, PaintEvent()) event.Skip()