X-mirror rendering

you want myriads of peoples running around in your growd… thats not a big deal anymore :slight_smile: just use the “framerate related object multi split render buffering method # dirk hochegger 2009”

:slight_smile:

here in this piece of code is this method running, i modified therefor the motion trail tutorial…

#Author: Josh Yelon
#modifeid : dirk hochegger
# This is a tutorial to show one of the simplest applications
# of copy-to-texture: motion trails.
#

import direct.directbase.DirectStart
from pandac.PandaModules import GraphicsOutput
from pandac.PandaModules import Filename,Texture
from pandac.PandaModules import CardMaker,Vec4
from pandac.PandaModules import NodePath,TextNode
from pandac.PandaModules import AmbientLight,DirectionalLight
from direct.showbase.DirectObject import DirectObject
from direct.gui.OnscreenText import OnscreenText
from direct.task.Task import Task
from direct.actor.Actor import Actor
from random import uniform
import sys,os

base.disableMouse()
camera.setPos(0, -26, 4)
base.setBackgroundColor(0,0,0)

MYDIR=os.path.abspath(sys.path[0])
MYDIR=Filename.fromOsSpecific(MYDIR).getFullpath()

font = loader.loadFont("cmss12")
def addInstructions(pos, msg):
    return OnscreenText(text=msg, font=font,
     	                style=1, fg=(1,1,1,1), pos=(-1.3, pos),
                        align=TextNode.ALeft, scale = .05)
 
character = {}
x = -2
c = 0
for i in range (1):  
    x += 1 
    c += .1
    character[i]=Actor()
    character[i].loadModel('models/dancer')
    character[i].reparentTo(render)
    character[i].loadAnims({'win':'models/dancer'})
    character[i].loop('win')
    character[i].setScale(.2,.2,.2)
    character[i].setPos(x,0,0)
    

class MotionTrails(DirectObject):
    def __init__(self):
        taskMgr.remove('igLoop')
        # create a texture into which we can copy the main window.

        self.tex = Texture()
        self.tex.setMinfilter(Texture.FTLinear)
        base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture)
        
        # Create another 2D camera. Tell it to render before the main camera.

        self.backcam = base.makeCamera2d(base.win, sort=-10)
        self.background = NodePath("background")
        self.backcam.reparentTo(self.background)
        self.background.setDepthTest(0)
        self.background.setDepthWrite(0)
        self.backcam.node().getDisplayRegion(0).setClearDepthActive(0)

        # Obtain two texture cards. One renders before the dragon, the other after.
        self.bcard = base.win.getTextureCard()
        self.bcard.reparentTo(self.background)
        self.bcard.setTransparency(1)
        self.fcard = base.win.getTextureCard()
        self.fcard.reparentTo(render2d)
        self.fcard.setTransparency(1)

        # Initialize one of the nice effects.
        self.chooseEffectPaintBrush()
        
        # Add the task that initiates the screenshots.
        taskMgr.add(self.takeSnapShot, "takeSnapShot")

        # Create some black squares on top of which we will
        # place the instructions.
        blackmaker = CardMaker("blackmaker")
        blackmaker.setColor(0,0,0,1)
        blackmaker.setFrame(-1.00, -0.50, 0.65, 1.00)
        instcard = NodePath(blackmaker.generate())
        instcard.reparentTo(render2d)
        blackmaker.setFrame(-0.5, 0.5, -1.00, -0.85)
        titlecard = NodePath(blackmaker.generate())
        titlecard.reparentTo(render2d)

        # Panda does its best to hide the differences between DirectX and
        # OpenGL.  But there are a few differences that it cannot hide.
        # One such difference is that when OpenGL copies from a
        # visible window to a texture, it gets it right-side-up.  When
        # DirectX does it, it gets it upside-down.  There is nothing panda
        # can do to compensate except to expose a flag and let the 
        # application programmer deal with it.  You should only do this
        # in the rare event that you're copying from a visible window
        # to a texture.

        if (base.win.getGsg().getCopyTextureInverted()):
            print "Copy texture is inverted."
            self.bcard.setScale(1,1,-1)
            self.fcard.setScale(1,1,-1)

        # Put up the instructions
        title = OnscreenText(text="Panda3D: Tutorial - Motion Trails",
                             style=1, fg=(1,1,1,1), font = font,
                             pos=(0,-0.95), scale = .07)
        
        instr0 = addInstructions(0.95, "Press ESC to exit")
        instr1 = addInstructions(0.90, "Press 1: Ghost effect")
        instr2 = addInstructions(0.85, "Press 2: PaintBrush effect")
        instr3 = addInstructions(0.80, "Press 3: Double Vision effect")
        instr4 = addInstructions(0.75, "Press 4: Wings of Blue effect")
        instr5 = addInstructions(0.70, "Press 5: Whirlpool effect")
        instr5 = addInstructions(-.80, "50 instances used multisplitrenderbuffering")
        
        # enable the key events
        self.accept("escape", sys.exit, [0])
        self.accept("1", self.chooseEffectGhost)
        self.accept("2", self.chooseEffectPaintBrush)
        self.accept("3", self.chooseEffectDoubleVision)
        self.accept("4", self.chooseEffectWingsOfBlue)
        self.accept("5", self.chooseEffectWhirlpool)
        
    def takeSnapShot(self, task):
        #################################################
        #framerate related object multi split buffering # 
        #############dirk hochegger 2009#################
        ####################TEST#########################
        #################################################
        y = 0
        x = -5
        for xx in range(len(character)):
            for i in range(50):
                
                character[xx].setPos(x,0,y)
                
                x+=1
                
                if (x >= 5):
                    x=-5
                    y+=1
                base.graphicsEngine.renderFrame()
                base.win.triggerCopy()
        #######################
        #######################
        if (task.time > self.nextclick):
            self.nextclick += 1.0 / self.clickrate
            if (self.nextclick < task.time):
                self.nextclick = task.time
            base.win.triggerCopy()
           
        return Task.cont

    def chooseEffectGhost(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.hide()
        self.fcard.show()
        self.fcard.setColor(1.0,1.0,1.0,0.99)
        self.fcard.setScale(1.00)
        self.fcard.setPos(0,0,0)
        self.fcard.setR(0)
        self.clickrate = 30
        self.nextclick = 0
        
    def chooseEffectPaintBrush(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.fcard.hide()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(1.0)
        self.bcard.setPos(0,0,0)
        self.bcard.setR(0)
        self.clickrate = 10
        self.nextclick = 0

    def chooseEffectDoubleVision(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(1.0)
        self.bcard.setPos(-0.05,0,0)
        self.bcard.setR(0)
        self.fcard.show()
        self.fcard.setColor(1,1,1,0.60)
        self.fcard.setScale(1.0)
        self.fcard.setPos(0.05,0,0)
        self.fcard.setR(0)
        self.clickrate = 10000
        self.nextclick = 0

    def chooseEffectWingsOfBlue(self):
        base.setBackgroundColor(0,0,0,1)
        self.fcard.hide()
        self.bcard.show()
        self.bcard.setColor(1.0,0.90,1.0,254.0/255.0)
        self.bcard.setScale(1.1,0,0.95)
        self.bcard.setPos(0,0,0.05)
        self.bcard.setR(0)
        self.clickrate = 30
        self.nextclick = 0

    def chooseEffectWhirlpool(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.fcard.hide()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(0.999)
        self.bcard.setPos(0,0,0)
        self.bcard.setR(1)
        self.clickrate = 10000
        self.nextclick = 0

        
t=MotionTrails()



    
# character.hprInterval(15, Point3(360, 0,0)).loop()

#put some lighting on the model
dlight = DirectionalLight('dlight')
alight = AmbientLight('alight')
dlnp = render.attachNewNode(dlight.upcastToPandaNode()) 
alnp = render.attachNewNode(alight.upcastToPandaNode())
dlight.setColor(Vec4(1.0, 0.9, 0.8, 1))
alight.setColor(Vec4(0.2, 0.3, 0.4, 1))
dlnp.setHpr(0, -60, 0) 
render.setLight(dlnp)
render.setLight(alnp)

run()





so i played a again a bit around on it…
now im moving the objects independently on a regular track.

#Author: Josh Yelon
#modifeid : dirk hochegger
# This is a tutorial to show one of the simplest applications
# of copy-to-texture: motion trails.
#

import direct.directbase.DirectStart
from pandac.PandaModules import GraphicsOutput
from pandac.PandaModules import Filename,Texture
from pandac.PandaModules import CardMaker,Vec4
from pandac.PandaModules import NodePath,TextNode
from pandac.PandaModules import AmbientLight,DirectionalLight
from direct.showbase.DirectObject import DirectObject
from direct.gui.OnscreenText import OnscreenText
from direct.task.Task import Task
from direct.actor.Actor import Actor
from random import uniform
import sys,os,random,math

base.disableMouse()
camera.setPos(0, -26, 4)
base.setBackgroundColor(0,0,0)

MYDIR=os.path.abspath(sys.path[0])
MYDIR=Filename.fromOsSpecific(MYDIR).getFullpath()

font = loader.loadFont("cmss12")
def addInstructions(pos, msg):
    return OnscreenText(text=msg, font=font,
     	                style=1, fg=(1,1,1,1), pos=(-1.3, pos),
                        align=TextNode.ALeft, scale = .05)
 
character = {}
x = -2
c = 0
for i in range (1):  
    x += 1 
    c += .1
    character[i]=Actor()
    character[i].loadModel('models/dancer')
    character[i].reparentTo(render)
    character[i].loadAnims({'win':'models/dancer'})
    character[i].loop('win')
    character[i].setScale(.2,.2,.2)
    character[i].setPos(x,0,0)
    

class MotionTrails(DirectObject):
    def __init__(self):
        taskMgr.remove('igLoop')
        # create a texture into which we can copy the main window.

        self.tex = Texture()
        self.tex.setMinfilter(Texture.FTLinear)
        base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture)
        
        # Create another 2D camera. Tell it to render before the main camera.

        self.backcam = base.makeCamera2d(base.win, sort=-10)
        self.background = NodePath("background")
        self.backcam.reparentTo(self.background)
        self.background.setDepthTest(0)
        self.background.setDepthWrite(0)
        self.backcam.node().getDisplayRegion(0).setClearDepthActive(0)

        # Obtain two texture cards. One renders before the dragon, the other after.
        self.bcard = base.win.getTextureCard()
        self.bcard.reparentTo(self.background)
        self.bcard.setTransparency(1)
        self.fcard = base.win.getTextureCard()
        self.fcard.reparentTo(render2d)
        self.fcard.setTransparency(1)

        # Initialize one of the nice effects.
        self.chooseEffectPaintBrush()
        
        # Add the task that initiates the screenshots.
        taskMgr.add(self.takeSnapShot, "takeSnapShot")

        # Create some black squares on top of which we will
        # place the instructions.
        blackmaker = CardMaker("blackmaker")
        blackmaker.setColor(0,0,0,1)
        blackmaker.setFrame(-1.00, -0.50, 0.65, 1.00)
        instcard = NodePath(blackmaker.generate())
        instcard.reparentTo(render2d)
        blackmaker.setFrame(-0.5, 0.5, -1.00, -0.85)
        titlecard = NodePath(blackmaker.generate())
        titlecard.reparentTo(render2d)

        # Panda does its best to hide the differences between DirectX and
        # OpenGL.  But there are a few differences that it cannot hide.
        # One such difference is that when OpenGL copies from a
        # visible window to a texture, it gets it right-side-up.  When
        # DirectX does it, it gets it upside-down.  There is nothing panda
        # can do to compensate except to expose a flag and let the 
        # application programmer deal with it.  You should only do this
        # in the rare event that you're copying from a visible window
        # to a texture.

        if (base.win.getGsg().getCopyTextureInverted()):
            print "Copy texture is inverted."
            self.bcard.setScale(1,1,-1)
            self.fcard.setScale(1,1,-1)

        # Put up the instructions
        title = OnscreenText(text="Panda3D: Tutorial - Motion Trails",
                             style=1, fg=(1,1,1,1), font = font,
                             pos=(0,-0.95), scale = .07)
        
        instr0 = addInstructions(0.95, "Press ESC to exit")
        instr1 = addInstructions(0.90, "Press 1: Ghost effect")
        instr2 = addInstructions(0.85, "Press 2: PaintBrush effect")
        instr3 = addInstructions(0.80, "Press 3: Double Vision effect")
        instr4 = addInstructions(0.75, "Press 4: Wings of Blue effect")
        instr5 = addInstructions(0.70, "Press 5: Whirlpool effect")
        instr5 = addInstructions(-.80, "50 instances used multisplitrenderbuffering")
        
        # enable the key events
        self.accept("escape", sys.exit, [0])
        self.accept("1", self.chooseEffectGhost)
        self.accept("2", self.chooseEffectPaintBrush)
        self.accept("3", self.chooseEffectDoubleVision)
        self.accept("4", self.chooseEffectWingsOfBlue)
        self.accept("5", self.chooseEffectWhirlpool)
        
    def takeSnapShot(self, task):
        #################################################
        #framerate related object multi split buffering # 
        #############dirk hochegger 2009#################
        ####################TEST#########################
        #################################################
        time = task.time
        y = 0
        x = -5
        r = 0
        c= .2
        values = [0,.01,2,0,.03,1.5]
        colors = [(1,0,0,1),(0,1,0,1),(0,0,1,1),(.5,.5,0,1),(0,.5,.5,1)]
        pos = [(math.sin(time),0,math.cos(time)),(1+math.sin(math.sin(time)*10),0,math.cos(time)),(-1,0,0),(.5,0,.5),(-.2,0,.8)]
        for xx in range(len(character)):
            for i in range(5):
                getVALUE = values[x]
                getCOLOR = colors[x]
                getPOS = pos[x]
                character[xx].setPos(getPOS)
             #   character[xx].setH(r)
             #   character[xx].setScale(c,c,c)
                character[xx].setPlayRate(getVALUE, 'win')
                character[xx].setColor(getCOLOR)
                print getVALUE
                c += .1
                x+=1
                r += 10
                if (x >= 5):
                    x=-5
                    y+=1
                    r = 0
                base.graphicsEngine.renderFrame()
                base.win.triggerCopy()
        ###############################################
        ###############################################
        if (task.time > self.nextclick):
            self.nextclick += 1.0 / self.clickrate
            if (self.nextclick < task.time):
                self.nextclick = task.time
            base.win.triggerCopy()
           
        return Task.cont

    def chooseEffectGhost(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.hide()
        self.fcard.show()
        self.fcard.setColor(1.0,1.0,1.0,0.99)
        self.fcard.setScale(1.00)
        self.fcard.setPos(0,0,0)
        self.fcard.setR(0)
        self.clickrate = 30
        self.nextclick = 0
        
    def chooseEffectPaintBrush(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.fcard.hide()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(1.0)
        self.bcard.setPos(0,0,0)
        self.bcard.setR(0)
        self.clickrate = 10
        self.nextclick = 0

    def chooseEffectDoubleVision(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(1.0)
        self.bcard.setPos(-0.05,0,0)
        self.bcard.setR(0)
        self.fcard.show()
        self.fcard.setColor(1,1,1,0.60)
        self.fcard.setScale(1.0)
        self.fcard.setPos(0.05,0,0)
        self.fcard.setR(0)
        self.clickrate = 10000
        self.nextclick = 0

    def chooseEffectWingsOfBlue(self):
        base.setBackgroundColor(0,0,0,1)
        self.fcard.hide()
        self.bcard.show()
        self.bcard.setColor(1.0,0.90,1.0,254.0/255.0)
        self.bcard.setScale(1.1,0,0.95)
        self.bcard.setPos(0,0,0.05)
        self.bcard.setR(0)
        self.clickrate = 30
        self.nextclick = 0

    def chooseEffectWhirlpool(self):
        base.setBackgroundColor(0,0,0,1)
        self.bcard.show()
        self.fcard.hide()
        self.bcard.setColor(1,1,1,1)
        self.bcard.setScale(0.999)
        self.bcard.setPos(0,0,0)
        self.bcard.setR(1)
        self.clickrate = 10000
        self.nextclick = 0

        
t=MotionTrails()



    
# character.hprInterval(15, Point3(360, 0,0)).loop()

#put some lighting on the model
dlight = DirectionalLight('dlight')
alight = AmbientLight('alight')
dlnp = render.attachNewNode(dlight.upcastToPandaNode()) 
alnp = render.attachNewNode(alight.upcastToPandaNode())
dlight.setColor(Vec4(1.0, 0.9, 0.8, 1))
alight.setColor(Vec4(0.2, 0.3, 0.4, 1))
dlnp.setHpr(0, -60, 0) 
render.setLight(dlnp)
render.setLight(alnp)

run()

Is that how it’s supposed to look?

thx pretty cool, thx for posting this.

whats your macintosh doing while u running the normal motiontrail demo?
run the demo without a transparency background or u need to clear the card after some render steps.

when i find time again for playing around on my method…

it should only symbolize u, that u can create a different way to reach instances just by using pageflipping, which arnt changing your main framerate.

it start to feel perfect for my particular effects .
actually i did a new test, now i tried how easy it is to touch the instances with mouse… as next i will bring some self collisions in. this thing is going to boost my effects hopefully.

at the moment im using for performance boosts at my particle effects:
rastering, time delays and this method…

im running out of ideas, where to win any better performance anymore.

'''
Created on 16.07.2009

@author: dirk
'''
import direct.directbase.DirectStart
from pandac.PandaModules import GraphicsOutput
from pandac.PandaModules import Filename,Texture
from pandac.PandaModules import CardMaker,Vec4,Vec3
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import MouseWatcher
from direct.task.Task import Task
import math

taskMgr.remove('igLoop')

base.disableMouse()
camera.setPos(0, -26, 4)
base.setBackgroundColor(0,0,0)
instances = 100 
count = 1 #count of roots in the scene, in this case i created only one object
character = {}
for i in range (count):  
    character[i] = loader.loadModel('models/planeZ.egg')
    character[i].reparentTo(render2d)
    character[i].setScale(.05,.05,.05)
    
class msrb(DirectObject):
    '''
    classdocs
    '''
    def __init__(self):
        '''
        Constructor
        '''
        self.tex = Texture()
        base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture)

        self.card = base.win.getTextureCard()
        self.card.reparentTo(render2d)
        self.card.setTransparency(1)
        
        taskMgr.add(self.buffering, "bufferingTASK")
        
    def buffering(self, task):
        
        time = task.time
        
        mpos=base.mouseWatcherNode.getMouse()
        y = -.5
        x = -.5
        c = 0
        colors = [(1,0,0,1),(0,1,0,1),(0,0,1,1)]
        pos = {}   
           
        for xx in range(len(character)):
            for i in range(instances):
                getCOLOR = colors[c]
                character[xx].setPos(x,0,y)
                
                pos[i] = character[xx].getPos()
                c+=1
                if (c >=3):
                    c=0
                x+=.1
                if (x > .4):
                    x=-.5
                    y+=.1
                mouseVEC = Vec3(mpos.getX(),0,mpos.getY())
                distance = mouseVEC - character[xx].getPos()
                dis = distance.length()
                if (dis < .2):
                    character[xx].setPos(character[xx].getX()+math.sin(time)/10,0,character[xx].getZ()+math.cos(time)/10)
                    print dis
                else:
                    character[xx].setColor(getCOLOR)
                base.graphicsEngine.renderFrame()
                base.win.triggerCopy()
        return Task.cont
    

m=msrb()
run()

planeZ.egg

<CoordinateSystem> { Y-Up }

<Comment> {
  "maya2egg2008 planeZ.mb planeZ.egg"
}
<Texture> initialShadingGroup {
  "../textures/cityBLOOM.png"
  <Scalar> wrapu { repeat }
  <Scalar> wrapv { repeat }
  <Scalar> minfilter { linear_mipmap_linear }
  <Scalar> magfilter { linear }
}
<Group> groundPlane_transform {
}
<Group> pPlane1 {
  <VertexPool> pPlaneShape1.verts {
    <Vertex> 0 {
      -0.5 -0.5 -3.33067e-016
      <UV> { 0 0 }
      <Normal> { 0 0 1 }
      <RGBA> { 1 1 1 1 }
    }
    <Vertex> 1 {
      0.5 -0.5 -3.33067e-016
      <UV> { 1 0 }
      <Normal> { 0 0 1 }
      <RGBA> { 1 1 1 1 }
    }
    <Vertex> 2 {
      0.5 0.5 3.33067e-016
      <UV> { 1 1 }
      <Normal> { 0 0 1 }
      <RGBA> { 1 1 1 1 }
    }
    <Vertex> 3 {
      -0.5 0.5 3.33067e-016
      <UV> { 0 1 }
      <Normal> { 0 0 1 }
      <RGBA> { 1 1 1 1 }
    }
  }
  <Polygon> {
    <Normal> { 0 0 1 }
    <TRef> { initialShadingGroup }
    <VertexRef> { 0 1 2 3 <Ref> { pPlaneShape1.verts } }
  }
}