Fade from one camera to another

Hey guys,

saw this post: [url]fade from one camera to another?]

And it gave me a good idea on how to fade from one camera perspective to another, and so I wrote a small script (mostly a function) that will do this for you, it’s pretty simply and has a really pleasing effect.

EDIT (script updated): Fixed the clear color of the buffer so that the previous scene never shows through

Here it is (No models / textures required for it):

#- Start panda
import direct.directbase.DirectStart

#- Basic imports needed for this function
from direct.interval.IntervalGlobal import *
from panda3d.core import Point3, Vec3, CardMaker

#- Display a model, load your scene, idk
panda = loader.loadModel('environment')

#- Disable mouse driven camera, so that calls to camera.setPos, etc work

#- Our fadeCamera function, this fades the currently viewed scene to a new camera perspective
#- over a period of (fadeInDuration) seconds
def fadeCamera(pos, rot, fadeInDuration = 1.0):
	#- Create a new live texture buffer that will render the new camera perspective each frame
	#- while we are fading the new camera perspective into full view
	buffer2 = base.win.makeTextureBuffer('mybuffer', base.win.getXSize(), base.win.getYSize())
	buffer2.setClearColorActive(True) #- Enable the clear color, so that the background color is shown
	col = base.getBackgroundColor() #- Get the current background color
	col[3] = 1 #- Make 100% sure that the background color is solid (otherwise the previos scene will show through)
	buffer2.setClearColor(col) #- Set the clear color to it now
	#- Create a new camera, for the buffer, and position/rotate it to the new perspective
	cam2 = base.makeCamera(buffer2)

	#- Create a fullscreen card for displaying the live scene (from the new camera perspective)
	cm = CardMaker('displayCard')
	cm.setFrame(-1, 1, -1, 1)
	cm.setUvRange(buffer2.getTexture()) #- Make sure we set the UV range properly!
	card = render2d.attachNewNode(cm.generate())

	#- Here is where the magic happens
	#- First fade the card with the live scene texture in
	#- Then move the actual camera
	#- Then cleanup the temporary camera, the card for displaying the live scene, and the buffer
	#- Perform all of these in order, using a Sequence
	fadeCardIn = card.colorScaleInterval(fadeInDuration, 1, 0)
	moveActualCamera = Func(camera.setPosHpr, render, cam2.getPos(), cam2.getHpr())
	cleanupCamera = Func(cam2.remove)
	cleanupCard = Func(card.remove)
	cleanupBuffer = Func(base.graphicsEngine.removeWindow, buffer2)
	Sequence(fadeCardIn, moveActualCamera, cleanupCard, cleanupCamera, cleanupBuffer).start()

#- Place the camera at one perspective
camera.setPosHpr(Point3(6.3, -45.9, 7.8), Vec3(0, 0, 0))
print 'Performing initial fade!'
fadeCamera(Point3(99, -851, 150), Vec3(7, -10, 0)) #- Do our initial fade

def doRandomFade():
	#- Just get a random position / rotation for the new camera perspective
	#- This part is really un-important
	import random
	p = Point3(random.randrange(-900, 900), random.randrange(-900, 900), random.randrange(90, 190))
	tmp = render.attachNewNode('tmp')
	tmp.lookAt(0, 0, 0)
	r = tmp.getHpr()
	#- Actuall fade to the new position and rotation for the camera perspective
	fadeCamera(p, r)
	print 'Performing random fade!'

#- Set it such that when the user presses space it goes to the new perspective
base.accept('space', doRandomFade)


Hope this helps,

Nice. However, there seems to be some problem alpha textures during fading.

Right, they appear to somewhat “pop” out which I find odd (to be honest) I see no reason why they should be doing that, considering it’s a fully solid image coming into view, perhaps someone more experienced with the lower levels of panda’s rendering system could shed some light on this?

Other than that (rather minor IMO) issue, I think it works OK.


Yeah, there’s trickery related to depth sorting involved with transparency. Read the manual page on “Transparency and Blending” for more information.

I’m still a bit new to DXS, but aren’t these already in the API? Because if it isn’t then I 100% believe that it should be.