[SOLVED] Trouble with alpha channel and dynamic textures

chpod

15-07-2008 15:39:38

Hi all,

I sometimes have trouble with the alpha channel of my textures. But sometimes everything is ok... I tried to set up a minimalistic example.

I have one texture with alpha. It shows an orange mesh over a transparent background. Here is how it looks like with Photoshop:


I extended Demo._WX.py so that there is one big fish and a smaller one inside the big fish. I dynamically change the material of the big (outer) fish to see if the transparency is taken into account. The material is created is applied for every step of the wx.timeline.

Sometimes the result is ok, with correct transparency (0, 2, 3, 4, 5, 7, 9 and 11.png):


And sometimes the result is wrong (weird transparency): (1, 6, 8, 10 and 12.png):


I copied the texture file several time, so that I am sure that it is reladed every time.

Here is how I (dynamically) create the material:
mat = ogre.MaterialManager.getSingleton().create(matName,ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME)
mat.getTechnique(0).getPass(0).setSceneBlending(ogre.SBT_TRANSPARENT_ALPHA)
t = mat.getTechnique(0).getPass(0).createTextureUnitState(matFile)
print "Material created: ",matName

And the full source code Demo_WX_chpod.py:
import sys
sys.path.insert(0,'..')
import PythonOgreConfig
import traceback

if __name__=="__main__":
from OgreWindowWx import *
import wx.py as py #This modules gives access to the pyCrust interpreter widget

class DemoOgreWindow(OgreWindow):
"""This is a demo of how to subclass OgreWindow.
Many parts of the code are directely inspired from the beginner to
advance tutorials"""

fishIsSwiming=False #A variable to keep track whether the fish is swiming or not

def _PopulateScene(self):

"Creation of scene objects"
# create scene
sceneManager=self.sceneManager
sceneManager.AmbientLight = ogre.ColourValue(0.7, 0.7, 0.7 )
sceneManager.setSkyDome(True, 'Examples/CloudySky', 4.0, 8.0)

light = sceneManager.createLight('MainLight')
light.setPosition ( ogre.Vector3(20, 80, 130) )
self.sceneEntities.MainLight = light

# add some fog
sceneManager.setFog(ogre.FOG_EXP, ogre.ColourValue.White, 0.0002)

plane = ogre.Plane()
plane.normal = ogre.Vector3(0, 1, 0)
plane.d = 200
ogre.MeshManager.getSingleton().createPlane('FloorPlane', "General",plane, 200000.0, 200000.0,
20, 20, True, 1, 50.0, 50.0,ogre.Vector3(0, 0, 1),
ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY,
ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY,
True,True )

# create floor entity
entity = sceneManager.createEntity('floor', 'FloorPlane')
entity.setMaterialName('Examples/RustySteel')
sceneManager.getRootSceneNode().createChildSceneNode().attachObject(entity)
self.sceneEntities.floor = entity


# create fish entity
fishNode = sceneManager.getRootSceneNode().createChildSceneNode("fishNode")
entity = sceneManager.createEntity('Wanda', 'fish.mesh')
fishNode.attachObject(entity)
fishNode.setScale(10.0,10.0,10.0)


self.sceneEntities.fishNode = fishNode
self.sceneEntities.fish = entity
self.swimAnimationState = entity.getAnimationState('swim')
self.swimAnimationState.Enabled = True


# create second fish entity
fishNode2 = sceneManager.getRootSceneNode().createChildSceneNode("fishNode2")
entity2 = sceneManager.createEntity('Wanda2', 'fish.mesh')
fishNode2.attachObject(entity2)
fishNode2.setScale(15.0,15.0,15.0)

self.sceneEntities.fishNode2 = fishNode2
self.sceneEntities.fish2 = entity2


#create fish swiming path
fishAnimationNode = sceneManager.getRootSceneNode().createChildSceneNode("fishAnimationNode")
self.sceneEntities.fishAnimationNode = fishAnimationNode

animation = sceneManager.createAnimation('fishTrack', 10)
animation.interpolationMode = ogre.Animation.IM_SPLINE
animationTrack = animation.createNodeTrack(0, fishAnimationNode)
key = animationTrack.createNodeKeyFrame(0.0)
key = animationTrack.createNodeKeyFrame(1.0)
key.setTranslate (ogre.Vector3(80.0, 0.0, -40.0) )
key = animationTrack.createNodeKeyFrame(2.0)
key.setTranslate ( ogre.Vector3(120.0, 0.0, 0.0))
key = animationTrack.createNodeKeyFrame(3.0)
key.setTranslate(ogre.Vector3(80.0, 0.0, 80.0) )
key = animationTrack.createNodeKeyFrame(5.0)
key.setTranslate ( ogre.Vector3(-80.0, 0.0, -40.0) )
key = animationTrack.createNodeKeyFrame(6.0)
key.setTranslate ( ogre.Vector3(-120.0, 0.0, 0.0) )
key = animationTrack.createNodeKeyFrame(7.0)
key.setTranslate ( ogre.Vector3(-80.0, 0.0, 100.0))
key = animationTrack.createNodeKeyFrame(8.0)
key.setTranslate ( ogre.Vector3(30.0, 0.0, 90.0) )
key = animationTrack.createNodeKeyFrame(9.0)
key.setTranslate( ogre.Vector3(-20.0, 0.0, 40.0) )
key = animationTrack.createNodeKeyFrame(10.0)
key.setTranslate ( ogre.Vector3(0.0, 0.0, 0.0) )

self.fishAnimationState = sceneManager.createAnimationState('fishTrack')
self.fishAnimationState.Enabled = True

#create a duplicate fish swiming path for determining where the fish has to look to
self.sceneEntities.fishLookAtNode = fishLookAtNode = sceneManager.getRootSceneNode().createChildSceneNode("fishLookAtNode")
animation = sceneManager.createAnimation('fishLookAtTrack', 10)
animation.interpolationMode = ogre.Animation.IM_SPLINE
animationTrack = animation.createNodeTrack(0, fishLookAtNode)
key = animationTrack.createNodeKeyFrame(0.0)
key = animationTrack.createNodeKeyFrame(1.0)
key.Translate = ogre.Vector3(80.0, 0.0, -40.0)
key = animationTrack.createNodeKeyFrame(2.0)
key.Translate = ogre.Vector3(120.0, 0.0, 0.0)
key = animationTrack.createNodeKeyFrame(3.0)
key.Translate = ogre.Vector3(80.0, 0.0, 80.0)
key = animationTrack.createNodeKeyFrame(5.0)
key.Translate = ogre.Vector3(-80.0, 0.0, -40.0)
key = animationTrack.createNodeKeyFrame(6.0)
key.Translate = ogre.Vector3(-120.0, 0.0, 0.0)
key = animationTrack.createNodeKeyFrame(7.0)
key.Translate = ogre.Vector3(-80.0, 0.0, 100.0)
key = animationTrack.createNodeKeyFrame(8.0)
key.Translate = ogre.Vector3(30.0, 0.0, 90.0)
key = animationTrack.createNodeKeyFrame(9.0)
key.Translate = ogre.Vector3(-20.0, 0.0, 40.0)
key = animationTrack.createNodeKeyFrame(10.0)
key.Translate = ogre.Vector3(0.0, 0.0, 0.0)
self.fishLookAtAnimationState = sceneManager.createAnimationState('fishLookAtTrack')
self.fishLookAtAnimationState.Enabled = True
self.fishLookAtAnimationState.addTime(0.033) #Gives a 33ms headstart to the lookat node


def OnFrameStarted(self,event):
"In this example, we will make the fish swim along a path"
if self.fishIsSwiming :
#First : updates the position of the fish to the position of the moving node on the animation path
#The reason that we did not create an animationTrack for fishNode is that we are interested in
#keyframing only the node position, not the scale, orientation etc...
self.sceneEntities.fishNode.setPosition( self.sceneEntities.fishAnimationNode.Position )

#Then, takes care of the direction that the fish has to face to
directionToGo = self.sceneEntities.fishLookAtNode.Position - self.sceneEntities.fishAnimationNode.Position
src = self.sceneEntities.fishNode.Orientation * (-ogre.Vector3.UNIT_X) #the fish is originally
#facing the negative X direction


quat = src.getRotationTo(directionToGo) #Calculates the quaternion of the appropriate rotation
self.sceneEntities.fishNode.rotate(quat)#Rotates, the fish. Here, we know that no rotation of 180
#degrees will occur so we do not have to care about it



def ToggleSwimAnimation(self):
"Toggles on and off the animation"
self.fishIsSwiming = not self.fishIsSwiming

if self.fishIsSwiming : #Adds the animation states for use
self.animStates["fishAnimation"] = (self.fishAnimationState, 1.0)
self.animStates["fishLookAtAnimation"] = (self.fishLookAtAnimationState, 1.0)
self.animStates["swimAnimation"] = (self.swimAnimationState, 4)
else : #Removes animation states
self.animStates.pop("fishAnimation")
self.animStates.pop("fishLookAtAnimation")
self.animStates.pop("swimAnimation")

class DemoFrame(wx.Frame):
"""Creates a frame with an Ogre window and a pyCrust window
pyCrust is always nice to have around for study/debug purposes"""
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.pyCrust = wx.py.crust.Crust(self, -1)
self.ogreWin = DemoOgreWindow(self, -1)
self.swimButton = wx.Button(self, -1, "Start/Stop Swiming")
self.trackButton = wx.ToggleButton(self, -1, "Camera Auto Tracking")

self.slTimeline = wx.Slider(id=-1, maxValue=12,
minValue=0, name='slTimeline', parent=self,
pos=wx.Point(4, 4), size=wx.Size(320, 24), style=wx.SL_HORIZONTAL,
value=0)

self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_BUTTON, self.swimButtonCallback, self.swimButton)
self.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleAutoTracking, self.trackButton)

self.slTimeline.Bind(wx.EVT_SCROLL, self.OnSlTimelineScroll)

def __set_properties(self):
self.SetTitle("wxPyOgre Demo")
self.ogreWin.SetMinSize((640,480))
self.trackButton.SetValue(False)

def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.ogreWin, 2, wx.EXPAND, 0)
sizer_1.Add(self.swimButton,0, wx.ALIGN_CENTER, 0)
sizer_1.Add(self.trackButton,0, wx.ALIGN_CENTER, 0)
sizer_1.Add(self.slTimeline,0, wx.ALIGN_CENTER, 0)
sizer_1.Add(self.pyCrust, 1, wx.EXPAND, 0)
self.SetAutoLayout(True)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
sizer_1.SetSizeHints(self)
self.Layout()

def OnSlTimelineScroll(self, event):
print "Scroll: ",event.GetInt()
self.changeMaterial(event.GetInt())
event.Skip()

def changeMaterial(self, i):
matName = "MAT" + str(i)
print "Material id: ",i,"name:",matName

# check if material already exists
mat = ogre.MaterialManager.getSingleton().getByName(matName)
if (mat!=None):
print "Material already exists: ",mat.getName()
else:
# Create material
print "Creating material: ",matName
self.filepath = 'C:/PythonOgreRC2/demos/media/materials/textures/'
matFile = '' + str(i) + '.png'
#matFile = 'test.png'
import os.path
if (not os.path.exists(self.filepath+matFile)):
print "File does not exist: ",self.filepath+matFile
return(False)
try:
mat = ogre.MaterialManager.getSingleton().create(matName,ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME)
mat.getTechnique(0).getPass(0).setSceneBlending(ogre.SBT_TRANSPARENT_ALPHA)
t = mat.getTechnique(0).getPass(0).createTextureUnitState(matFile)
print "Material created: ",matName
except:
print "Trouble while creating material for ",matName
traceback.print_exc()

print "Materials created"


# Apply material to fish
self.ogreWin.sceneEntities.fish2.setMaterialName(matName)


def swimButtonCallback(self,event):
self.ogreWin.ToggleSwimAnimation()

def ToggleAutoTracking(self,event):
"Toggles on and off the automatic tracking of the fish by the camera"
self.ogreWin.sceneEntities.Camera.setAutoTracking(event.Checked(), self.ogreWin.sceneEntities.fishNode)



DemoApp = wx.PySimpleApp(0)
wx.InitAllImageHandlers() #you may or may not need this
MainFrame = DemoFrame(None, -1, "")

#put all the entities in self.ogreWin.sceneEntities in the local variables so that
#introspection with pyCrust is more user friendly
localVariableDic=locals()
localVariableDic.update(MainFrame.ogreWin.sceneEntities.__dict__)

DemoApp.SetTopWindow(MainFrame)
MainFrame.ogreWin.StartRendering()
MainFrame.Show()

DemoApp.MainLoop()


You can get the texture files here (the same file with different names):
http://chpod.free.fr/screenshots/20080715_texturefiles.zip
Copy files under demos\media\materials\textures

I have WinXP SP2, python-ogre RC2 and NVIDIA 6800 256MB.
I would appreciate any piece of advice!

Cheers
chpod

chpod

16-07-2008 15:46:48

Same behabiour with DirectX and openGL.

Could anyone reproduce this buggy situation?

dermont

16-07-2008 18:21:22

Try rendering your entity after the main render queue, e.g:

entity2.setRenderQueueGroup(ogre.RENDER_QUEUE_6)

http://www.ogre3d.org/docs/api/html/Ogr ... ource.html

chpod

16-07-2008 18:47:51

That does the trick!

And with 1) explanation, 2) working source code and 3) link to involved source file, all that in just three lines, i could not expect any better answer :D

Thx dermont!