What Might Clear a Colour-Scale...?

So, this is an odd bug in my game that’s been troubling me, to the point of frustration.

I have an object in a scene that has a colour-scale applied. (Via a call to “setColorScale” in code.) I’ve confirmed that the colour-scale is being applied. (Including via a call to “getColorScale”.)

However, by the time that I get to see the object in-game, the colour-scale appears to have been reset: there is no visible colour-scaling effect, test-code in the relevant shader indicates a (non-alpha) colour-scale of 1, 1, 1, and a call to “getColorScale” on the object returns (1, 1, 1, 1).

The thing is… I’m not managing to find a place in my code in which the colour-scale is clearly being changed after the initial (correct) application.

So I’d like to ask: What might change an applied colour-scale? Be it a method that I might have forgotten or overlooked, or an engine feature, or… whatever!

Just… something that I might search for in order to locate the offending party in this. :/

(I’ve already looked for calls to “setColorScale”, and to “clearAttrib”, I believe. Although it’s possible that I’ve missed or overlooked a usage somewhere.)

(I have tried creating a small test-program, but colour-scaling appears to work as expected there. I daresay that it’s something, somewhere in my main project–I just don’t know what or where, or what to search for.)

I think that the principle of hierarchical inheritance works in your case, if you have applied this method to the parent node somewhere. You may be using someone’s code that changes the attributes of the parent node via setColorScale or setAttrib, for example render.

The thing is, I’ve tried walking up the parentage of the object and printing out each node’s colour-scale, and all are just (1, 1, 1, 1).

Further, note that the value that I’m getting from “getColourScale” for the object in question is itself (1, 1, 1, 1)–despite being set otherwise, and a call to “getColourScale” reflecting that it’s set otherwise, earlier in the code.

[edit]
That is, my situation looks something like this:

Early on in the code…

myObj.setColorScale(a, b, c, 1)
print (myObj.getColorScale()) # Prints: a, b, c, 1

Later in the code…

print (myObj.getColorScale()) # Prints: 1, 1, 1, 1

[/edit]

So it really seems like something is clearing/resetting the colour-scale on the object itself… :/

I meant this situation.

from direct.showbase.ShowBase import ShowBase

from panda3d.core import ColorScaleAttrib, NodePath

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        test = NodePath("test")
        test.reparent_to(render)
        test.set_color_scale((0.5, 1, 1, 1))

        render.set_color_scale((2, 1, 1, 1))

        color_attr = test.get_net_state().get_attrib(ColorScaleAttrib.get_class_type())
        
        print(test.get_color_scale())
        print(color_attr.get_scale())

app = MyApp()
app.run()

LVecBase4f(0.5, 1, 1, 1)
LVecBase4f(1, 1, 1, 1)

interesting, to keep in mind,
get_color_scale returns the local state of the NodePath,
ColorScaleAttrib is combined down through the scene graph by compose_impl:

new_scale(ta->_scale[0] * _scale[0],
          ta->_scale[1] * _scale[1],
          ta->_scale[2] * _scale[2],
          ta->_scale[3] * _scale[3]);

(0.5, 1, 1, 1) * (2, 1, 1, 1) = (1, 1, 1, 1)

1 Like

I’m aware.

But note that when I read the colour-scale above, I’m just using “getColorScale”, not “getNetState”. As such, I should be getting only the colour-scale as applied to that node. And that output is returning (1, 1, 1, 1).

i.e. Something like this:

from direct.showbase.ShowBase import ShowBase

from panda3d.core import PandaNode, NodePath, ColorScaleAttrib

from panda3d import __version__ as pandaVersion
print (pandaVersion)

import sys
print (sys.version)


class Game(ShowBase):
	def __init__(self):
		ShowBase.__init__(self)
		
		mew = NodePath(PandaNode("mew"))
		mew.setColorScale(2, 1, 1, 1)
		
		meow = mew.attachNewNode(PandaNode("meow"))
		meow.setColorScale(0.5, 1, 1, 1)
		
		# Prints as you describe: (1, 1, 1, 1)
		print (meow.getNetState().getAttrib(ColorScaleAttrib.getClassType()).getScale())
		
		# Prints as I describe: (0.5, 1, 1, 1)
		print (meow.getColorScale())

app = Game()
app.run()

Except that where in the above the second print-statement outputs (0.5, 1, 1, 1) (as expected), in my own program I’m seeing (1, 1, 1, 1) (which is unexpected).

That is, “getColorScale” reports the colour-scale applied directly to that node, not the overall colour-scale affecting that node due to its own colour-scale and whatever colour-scales are applied above it in the scene-graph.

As you correctly noted, it works differently in your program, but the key aspect here is your code. Because you’re a stickler for tricks and manipulations with the Panda3D API. I think that you are doing strange tricks in the code somewhere, which causes this problem, everything can be broken.

from direct.showbase.ShowBase import ShowBase

from panda3d.core import PandaNode, NodePath, ColorScaleAttrib, RenderState

from panda3d import __version__ as pandaVersion
print (pandaVersion)

import sys
print (sys.version)


class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        mew = NodePath(PandaNode("mew"))
        mew.setColorScale(2, 1, 1, 1)
        mew.setState(RenderState.make_empty())

        meow = mew.attachNewNode(PandaNode("meow"))
        meow.setColorScale(0.5, 1, 1, 1)
        
        # Prints as you describe: (0.5, 1, 1, 1)
        print (meow.getNetState().getAttrib(ColorScaleAttrib.getClassType()).getScale())
        
        # Prints as I describe: (0.5, 1, 1, 1)
        print (meow.getColorScale())

app = Game()
app.run()

I use tricks when I see reason to do so–I don’t do it just because. :stuck_out_tongue:

But indeed, it’s possible that there’s something that I’m doing somewhere that’s changing state unexpectedly…

And, while I don’t remember using “RenderState.makeEmpty()”, that is something to check for, so thank you for raising it!

Well, exactly.

That’s why I’m asking for things that I might be doing that could have this effect: because I have a large program doing lots of things, and I’ve checked for the obvious method-calls. As such, I’m looking for less-obvious method-calls, ones that I might not have thought to search for…

(Like your suggestion of “RenderState.makeEmpty()”, above.)

(I must also–likely tomorrow–try stepping through a particular portion of my code that has occurred to me to examine, watching for changes in the colour-scale of the object in question. Perhaps that’ll point me in the right direction…)

In addition to this, also note that applying intervals actually changes this node parameter.

That’s fair–although in this particular project, I don’t think that I’m using Intervals anywhere.

(That other thread was for another project–one that uses Intervals and the like extensively–as I recall.)

[edit]
And I’ve found it!

It turns out that the culprit in this case was…

The “flattenLight” method!

Now just to figure out whether that flatten is important, and if so, whether there’s a good way to work around it without having to enact major changes to a section of code that’s otherwise very stable!..

[edit 2]
I think that, rather than mess with a long-standing and stable part of my code, I’m going to mark the relevant node as a “model-node”. That should prevent the flattening from affecting it, I believe…

1 Like

flattenLight will probably move the color scale to the Geom state. It’ll still be there, but not on the node.

Hmm, interesting. Does it make any changes in doing so?

In particular, I was using colour-scales greater than 1 (in my actual use-case, taking a grey object and making it lighter and bluer). Could the code that moves the colour-scale perhaps be clamping the values in each channel to the range [0, 1]?