[SOLVED] set transparency of a texture

I can set the transparency of the model and I can set the transparency of a texture in the image file, but thats not what I want to do. I need a model with 2 textures slowly replacing each other (hiding one and showing the other) with a lerp interval.
So how to set the transparency of the actual textures?

Am I correct to assume you prefer to do so without writing a shader?

What if yes? Do you know of a solution? Or do you have a shader for this?

Just create an instance of the model and fade it.

s=loader.loadModel('smiley')
s.reparentTo(render)
s.setY(5)
s.posInterval(5,Point3(-1,0,0)).start()

f=loader.loadTexture('maps/frowney.rgb')
s2=s.instanceUnderNode(s.getParent(),'')
s2.setTexture(f,1)
s2.setDepthOffset(1)
s2.setTransparency(1)

Sequence(
  s2.colorScaleInterval(3,Vec4(1),Vec4(1,1,1,0)),
  Func(s.setTexture,f,1),
  Func(s2.removeNode)
).start()

A shader solution would look something like this (untested):

//Cg

void vshader(
  in float4 vtx_color: COLOR,
  out float4 l_color0 : COLOR0,
  in float4 vtx_position : POSITION,
  out float4 l_position : POSITION,
  in float2 vtx_texcoord0 : TEXCOORD0,
  out float2 l_texcoord0 : TEXCOORD0,
  in uniform float4x4 mat_modelproj)
{
  l_color0 = vtx_color;
  l_position = mul(mat_modelproj, vtx_position);
  l_texcoord0 = vtx_texcoord0;
}

void fshader(
  in float4 l_color0 : COLOR0,
  in float2 l_texcoord0: TEXCOORD0,
  in uniform sampler2D tex_0: TEXUNIT0,
  in uniform sampler2D tex_1: TEXUNIT1,
  in uniform float4 k_fade,
  out float4 o_color : COLOR)
{
  first_color = tex2D(tex_0, l_texcoord0) * (float4(1.0, 1.0, 1.0, 1.0) - k_fade)
  second_color = tex2D(tex_1, l_texcoord0) * k_fade;
  o_color = (first_color + second_color) * l_color0;
}

Then you just need to use setShaderInput to control the fade parameter in a task or equivalent method.

@ynjh_jo: isn’t instanceTo and the like for Actors?
I actually need to fade in and out 4 textures of a skydome, is loading 4 copies of the same model the only way of doing it?

@teedee: thanks

No, it works for any node.
It’s the simplest one I could think of, without involving multitexture and shader, so that should work on any card.

If it’s only for sky, which is rendered before everything else, you could replace setDepthOffset() with seDepthTest(0), in case the driver fails to apply the offset. Just need to ensure that the instance is drawn right after the first model.

panda3d.org/blog/?p=44
Maybe I’m missing something.

That’s hardware instancing. You don’t need it for your case, since there are only 2 copies of sky model (during the transition), which isn’t built of so many vertices, is it ?
Or did you make it highpoly ?

But the quote isn’t.
I’m just saying, I could just use copyTo() because instanceTo() or instanceUnderNode() (Behaves like instance_to(), but implicitly creates a new node to instance the geometry under)

Oh, that’s because I want any operation on the original model also done to the copy too, eg. transform. I used posInterval there. If you use copyTo, the copy won’t be affected by the interval, because the copy is a competely independent node, not an instance.

Finally some free time.
Ok, but I actaully have the 3 models of the sky together in 1 file.
Here is the egg file and source:
mediafire.com/?goznkmjmmjd
the fading is weird: the model flashes in an instance.

Not sure what happens, but I have a simple solution.
In the interval, limit the alpha below 1.0, 0.98 is good.

Maybe it’s the render order, the transparent one rendered last, but when it’s opaque, it’s rendered first.

Interesting.

In my case I got s and its instance s2. I apply a looping Sequence to s, and s2 turns around with it, as expected.
Problem is the instance(s) dont get removed when s is removed. All s’s are stored in a list and then deleted if necessary. When I add s2 explicitely to my list that stores the s’s to delete them, the loop does not apply anymore to the s2’s. Which means that the s’s spin and the s2’s stay behind. Which is weird, just because a node is appended to a list, it shouldnt lose attributes or transformations or whatever is lost here.

code please…

This was just a lazy experiment after I saw your code.
The desired effect is for organic, alien entities to have a dark base texture, where the brighter, contrasting elements fade in and out.
Since I also want to apply the same effect to spaceships and not just non-moving space stations, I would prefer a two layer texture solution, where the above layer is fading in and out.

for some loop:
	spob = loader.loadModel("../mcstructures/"
	+StobList[self.StobIdentifier][4+i*13]+"/"
	+StobList[self.StobIdentifier][4+i*13])
	spob.reparentTo(render)
#	spob.setShaderOff()
	spob.setPos(StobList[self.StobIdentifier][5+i*13])
	spob.setScale(StobList[self.StobIdentifier][6+i*13])
	spob.setHpr(-140,0,0)
				
if some condition:
	glowtex = loader.loadTexture("../mcstructures/"
	+StobList[self.StobIdentifier][4+i*13]+"/"
	+StobList[self.StobIdentifier][4+i*13]+"_glow.png")
		
#	tex = loader.loadTexture("../mcstructures/"
#	+StobList[self.StobIdentifier][4+i*13]+"/"
#	+StobList[self.StobIdentifier][4+i*13]+".png")
#	spob.setTexture(tex)
	# the above is the standard texture, already coming from the egg file
	spobinstance = spob.instanceUnderNode(spob.getParent(),'')
	spobinstance.setTexture(glowtex,1)
	spobinstance.setDepthOffset(1)
	spobinstance.setTransparency(1)
	spobinstance.setShaderOff()
					
	spob_glow_sequence = Sequence(
	spobinstance.colorScaleInterval(0.75,Vec4(1,1,1,0.25),Vec4(1,1,1,1),blendType="easeIn"),
#	Wait(0.5),
	spobinstance.colorScaleInterval(2.0,Vec4(1,1,1,1),Vec4(1,1,1,0.25),blendType="easeOut"),
	Wait(3.0))
	spob_glow_sequence.loop()
	self.EnvIntervals.append(spob_glow_sequence)					
#	self.SpobObjects.append(spobinstance)
				
self.SpobObjects.append(spob)
		
for SpobObject in self.SpobObjects:
	spob_rotation_interval = SpobObject.hprInterval(240,Vec3(220,0,0))
	spob_rotation_interval.loop()
	self.EnvIntervals.append(spob_rotation_interval)

To remove things I only do:

for interval in self.EnvIntervals:
	interval.finish()
for SpobObject in self.SpobObjects:
	SpobObject.removeNode()

where spobinstance was added to SpobObject before.

Removing the instances by adding them to the list is the only way. It shouldn’t break any instance behaviour.

So you append them before the hprInterval for loop. That means the instances are affected by the interval twice. You should append them after the for loop.

Well, I don’t think I understand all of that, but I guess you pointed me in the right direction, so thanks. This one works:

for i in range(StobList[self.StobIdentifier][2]):
	spob = loader.loadModel("../mcstructures/"
	+StobList[self.StobIdentifier][4+i*13]+"/"
	+StobList[self.StobIdentifier][4+i*13])
	spob.reparentTo(render)
	spob.setPos(StobList[self.StobIdentifier][5+i*13])
	spob.setScale(StobList[self.StobIdentifier][6+i*13])
	spob.setHpr(-140,0,0)
				
	if StarmapData[self.StobIdentifier][6] == 7 and i in (0,1):
		glowtex = loader.loadTexture("../mcstructures/"
		+StobList[self.StobIdentifier][4+i*13]+"/"
		+StobList[self.StobIdentifier][4+i*13]+"_glow.png")
					
		spobinstance = spob.instanceUnderNode(spob.getParent(),'')
		spobinstance.setTexture(glowtex,1)
		spobinstance.setDepthOffset(1)
		spobinstance.setTransparency(1)
		spobinstance.setShaderOff()
					
		spob_glow_sequence = Sequence(
		spobinstance.colorScaleInterval(0.75,Vec4(1,1,1,0.25),Vec4(1,1,1,1),blendType="easeIn"),
	#	Wait(0.5),
		spobinstance.colorScaleInterval(2.0,Vec4(1,1,1,1),Vec4(1,1,1,0.25),blendType="easeOut"),
		Wait(3.0))
		spob_glow_sequence.loop()
		self.EnvIntervals.append(spob_glow_sequence)
					
		self.SpobObjects.append(spobinstance)
				
	spob_rotation_interval = spob.hprInterval(240,Vec3(220,0,0))
	spob_rotation_interval.loop()
	self.EnvIntervals.append(spob_rotation_interval)
				
	self.SpobObjects.append(spob)

The loop that applied the rotation to all objects in self.SpobObjects is gone.
I thought that instances dont receive the transformations of their parent node, but it seems they do.

Still I hoped you could give me a more general solution with texture stages where the top layer texture is fading in and out.

Notice that the current solution produces some interesting bugs … This is how the space station normally looks like:

To select a space object for landing, I hit L and a selection frame is parented to the space object (here: a space station).

This is how it is supposed to look like (and does on all objects without the instance technique):

In case of objects using the instance technique, the texture of the space object is applied to the selection frame parented to the parent of the instance:

That texture also fades in and out:

Also note that like with all transparent objects the FPS drop to near zero if you apply the shader generator to the node (here: the instance). That means that the parent node has the shader, the transparent glow textured instance has not. In my situation that is healthy actually since it increases the effect.

I don’t think it’s possible. You can’t fade texture stages.

The selection frame is parented to the station, so it’s also instanced. To avoid that, don’t instance the whole station (the ModelRoot), but its children only. That way, to destroy the station, you only need to remove the ModelRoot altogether. If it has more than 1 children, you could insert an intervening node below ModelRoot and steal ModelRoot’s children.

Well, the effect I want is in some egg files I use via modulate_glow. Isn’t there a way like

model.getGlow()

?

Uh I don’t think I got all that … But all this was a quick experiment anyway. I will come back to this later. Guess I need somebody to write a shader for me.