I’m a bit confused on how to read a buffer’s content to a PNMImage. The contents of my pnmimage seem to be the main window’s content instead of my buffer. The test code and related files can be downloaded from here
from direct.showbase.DirectObject import *
from pandac.PandaModules import Texture, PNMImage, GraphicsOutput, NodePath, Filename, TextureStage, Vec3, PandaNode, Point3
from direct.interval.IntervalGlobal import *
import sys
class ShaderPaintTest(DirectObject):
def __init__(self):
self.makeBuffer()
base.disableMouse()
self.smiley = loader.loadModel('models/smiley')
self.smiley.reparentTo(render)
self.smiley.setPos(-3, 0, 10)
self.frown = loader.loadModel('models/frowney')
self.frown.reparentTo(render)
self.frown.setPos(3, 0, 10)
base.camera.setPos(0, -40, 15)
base.camera.lookAt(0,0,5)
frownTurn = LerpHprInterval(self.frown, 5, Vec3(360,0,0))
smileTurn = LerpHprInterval(self.smiley, 5, Vec3(360,0,0))
frownTurn.loop()
smileTurn.loop()
camPan = LerpPosInterval(base.camera, 10, Point3(0, -40, 10))
camPan.loop()
self.makeStages()
taskMgr.add(self.paintTask, "Paint Task")
self.isPainting = False
self.accept('mouse1', setattr, [self, 'isPainting', True])
self.accept('mouse1-up', setattr, [self, 'isPainting', False])
self.accept('[', self.writeImg)
self.pickLayer = PNMImage()
self.windowX = base.win.getXSize()
self.windowY = base.win.getYSize()
self.accept('v', base.bufferViewer.toggleEnable)
self.accept('V',base.bufferViewer.toggleEnable)
def makeStages(self):
self.paintTexture = loader.loadTexture('index-512-256.png')
self.painterStage = TextureStage('Painter')
self.painterStage.setMode(TextureStage.MReplace)
self.painterStage.setSort(1)
render.setTexture(self.painterStage, self.paintTexture)
self.frownStage = TextureStage('Frown')
self.frownStage.setMode(TextureStage.MReplace)
self.frownStage.setSort(2)
self.frown.setTexture(self.frownStage, self.frown.findTexture("**"))
self.smileyStage = TextureStage('Smiley')
self.smileyStage.setMode(TextureStage.MReplace)
self.smileyStage.setSort(3)
self.smiley.setTexture(self.smileyStage, self.smiley.findTexture("**"))
def makeBuffer(self):
self.pickTex = Texture()
self.pickLayer = PNMImage()
self.buffer = base.win.makeTextureBuffer("pickBuffer", base.win.getXSize(), base.win.getYSize())
#self.buffer.addRenderTexture(self.pickTex, GraphicsOutput.RTMCopyRam)
self.buffCam = base.makeCamera(self.buffer, lens=base.cam.node().getLens())
self.shader = loader.loadShader('painter.sha')
tempnode = NodePath(PandaNode("temp node"))
tempnode.setShader(self.shader)
self.buffCam.node().setInitialState(tempnode.getState())
def paintTask(self, task):
if not base.mouseWatcherNode.hasMouse():
return task.cont
if self.isPainting is False:
return task.cont
if self.buffer.getScreenshot(self.pickLayer) is False:
return task.cont
print "PNIMage size", self.pickLayer.getXSize(),self.pickLayer.getYSize()
mpos = base.mouseWatcherNode.getMouse()
mx = int(((mpos.getX()+1)/2)*self.windowX)
my = self.windowY - int(((mpos.getY()+1)/2)*self.windowY)
# get the color below the mousepick from the rendered frame
r = self.pickLayer.getRedVal(mx,my)
g = self.pickLayer.getGreenVal(mx,my)
b = self.pickLayer.getBlueVal(mx,my)
# calculate uv-texture position from the color
x = r + ((b%16)*256)
y = g + ((b//16)*256)
print "UV Coordinates:", x, y
return task.cont
def writeImg(self):
self.pickLayer.write(Filename('test.png'))
if __name__ == "__main__":
import direct.directbase.DirectStart
s = ShaderPaintTest()
run()
sys.exit()
painter.sha
//Cg
void vshader(
uniform float4x4 mat_modelproj,
in float4 vtx_position : POSITION,
in float2 vtx_texcoord0 : TEXCOORD0,
out float2 l_my : TEXCOORD0,
out float4 l_position : POSITION)
{
l_position = mul(mat_modelproj, vtx_position);
l_my = vtx_texcoord0;
}
void fshader(
uniform sampler2D tex_0 : TEXUNIT0,
uniform sampler2D tex_1 : TEXUNIT1,
in float2 l_my : TEXCOORD0,
out float4 o_color : COLOR)
{
o_color = tex2D(tex_1, l_my);
}