Vertex colours over 1?

Is there something in the engine that clamps vertex-colour values to lie between 0 and 1?

I’m storing some data in my vertex-colours, and it would be handy to be able to store values greater than 1 in a given channel. I’ve modified YABEE to export such values, and they’re reflected in my test egg-file–but by the time that they reach my shaders, they seem to have been clamped to 1.

I can seem to store values greater than 1 in colour-scales, which is why I’m surprised to be having trouble with vertex-colours…

Are you using this to store custom vertex columns? Is there a particular reason you are not using the Aux fields rather than the RGBA fields in the egg file?

If I understand you correctly, then no. I’m using this to store information used by the shader to alter the colouring of a given vertex, in particular saturation and lightness.

Hmm… I think that I wrote the basis of these shaders before I was aware of the “aux” fields–and to be honest, before your post above, I don’t think that I was aware that they were significantly different to the RGBA vertex-colour fields. And by now my shaders are expecting things to be in vertex-colours, and I have a fair few models already storing this data there, I believe…

As a result, changing things now would be a significant task, and one rather prone to mistakes, I fear. :/

In addition, it (admittedly only slightly) complicates vertex-painting in Blender to have to skip over the first set of vertex-colours in order to store data.

That said, there’s already some of that in my current implementation: Blender doesn’t allow the painting of alpha-values in vertex-colours, so I’ve modified YABEE to output the red-channel of the second vertex-colour layer (if present) as alpha.

(And since Blender doesn’t allow painting of values over 1, I’m using the green and blue channels of the second vertex-colour layer to modify the same channels in my vertex-colours in order to achieve the desired values greater than 1.)

It’s a bit of a mess, but rather that than go back and try to re-engineer the various shaders and fix the data in the various models. :/

An aux column is almost the same as a color column, and accessed in almost the same way, you just have to change the name of the variable in the shader.

The problem is that the EggLoader understands the color column to contain colors, and therefore encodes them as four 8-bit (0-255) integers in the GeomVertexFormat. Not just because some fixed-function hardware requires this, but also because it makes colors take up only a quarter of the space compared to full floating-point numbers. Auxiliary columns, on the other hand, it adds as full floating-point numbers. Outside aux columns, I do not think that there is an easy way to get around this without making changes to the Panda source.

Indeed, I do have aux-data being used in a few places.

However, it wouldn’t be a matter of changing just the variable names: I’d have to change the data in all of the relevant models (and I have quite a few models). Further, I’d presumably want to modify YABEE further to export the first two vertex-colour layers to aux-data instead of vertex-colour, so that it still exports extant items as the shaders expect…

Ah, I see. I was afraid that it was something like that. :/ Indeed, I came recently upon mention of something else doing similarly–I think that it was Blender itself, in fact.

Ah well. That’s a pain, but it’s fair enough, and understandable.

I’ll likely give further thought to how I approach this when I’m (hopefully) less tired than I am today…

Well, thank you for the answers! :slight_smile:

Depending on the range of values you need, would it be possible to have the 0-1 value represent a percentage of some maximum value? Then you can just multiply it in the shader to get the desired value. Precision might become a problem if the maximum value is too high. (For example if you just need integers, I think you’d be able to go as high as 1000, given that Blender rounds colours to 3 decimal places* - or maybe 3/4000 if you did use all 3/4 channels and add them together.)

Either way, for fixing your existing models you could perhaps write a script to run within Blender - so in theory you’d only need to open a file, run the script, save and repeat. Or perhaps in general you might benefit from writing a Blender addon to help in your fight against Blender’s limitations (I do this often).

If you’re willing and able to describe exactly what you’re trying to achieve, perhaps we can get more creative with some solutions.

* It occurs to me now that this may only be a superficial limitation within the UI; Blender may in fact retain your original value in the background - in which case you could have a greater range of values. I’ve never tested it myself.

I don’t think that that would work in this case, I’m afraid. To explain:

I’m using my vertex-colours to control various things, in some cases differing from shader to shader. However, one simple example in one of the most frequently-used shaders is lightening a surface.

If I recall correctly, as it stands one of my main shaders takes the green channel of a given vertex-colour, and uses it to lighten the model’s surface–not in the sense of light falling on it, but of altering the surface’s colour without having to make a new texture.

However, it would be nice to be able to use the same channel for darkening the surface–after all, the maths is pretty much the same.

Now, a simple approach to this might be to treat the vertex-colour value similarly to normal-map colours: a value of 0 would darken the model, a value of 0.5 would have no effect, and a value of 1 would lighten it.

However, I want models without vertex-colours to be unaffected by such alterations. And since the default vertex-colour when none are applied is white–i.e. a value of 1 in all channels–I in fact want the “no effect value” to be 1; a “no effect value” of 0.5 would result in most objects having the colour altered.

Now, I suppose that I could use some trick by which a value of 1 has no effect, values between 1 and 0.5 lighten, and values between 0.5 and 0 darken. However, as values are interpolated (and I want that to be the case), that would result in a darkened area shading to a “no effect” area developing a rim of lightening as it shades through the 1 to 0.5 values.

So, what the shader actually does is subtracts the channel colour from one, and uses that new value to lighten the surface. Thus a value of 1 produces no change, a value of 0 lightens, and the effect shades in intensity between vertex colours.

And, theoretically speaking, the above approach would easily produce darkening if given a vertex-colour value greater than 1. The above subtraction performed with the vertex-colour would produce a negative value, shading up to 0 as the vertex-colour shades to 1. In the fragment calculations, this negative value should cause the lightening code to darken the surface instead of lightening it.

Hence my desire for values greater than 1!

Note that, aside from the green channel mentioned above, I’m already using the red, blue, and alpha channels for other things in this shader. Red produces a different sort of darkening, roughly speaking; blue desaturates; and alpha saturates. If I had a fifth channel, I could do for lightening what I did for saturation, and combine two channels!

Hmm… I suppose that I could do something like that, maybe, providing an additional channel via an aux input? If a shader requires a vector aux input, but one isn’t provided, what happens? Do you get a default value, and if so, what value is that, and does it vary in any way (i.e. across graphics cards, etc.)?

Indeed, I was just thinking about something like that. (Albeit that I was thinking of a script–likely Python, I imagine–running over my egg-files. I really, really don’t want to re-export all of the fairly-many models that I already have…)

However, the point about different shaders doing different things prompted me to realise that it might be called for that such a script account for that, checking for tags that indicate shaders to be loaded, and skipping such files…

Not in this case, I think: I’ve checked a test egg-file, and I do see values greater than 1 there, I believe.

RE the interpolation issue: Would this not only be the case for the fragment shader? Could you not change the values in the vertex shader so that they’ll be interpolated in the way you desire?

For the record, if other options are difficult for you, I’d be open to receiving a patch that adds an egg-float-color-array (or something of the sort) config variable that changes the column type that the .egg loader uses for color representations.

This value is guaranteed to be (0, 0, 0, 1). For p3d_Color, we exceptionally default it to whatever color was specified via nodePath.setColor().

Hmm… Maybe; you might be right, yes.

Still, doing so now would require changing quite a few models–possibly some each of Blender and extant egg-files–I think (and which seems likely to be prone to mistakes), as well as altering at the least my main shader to match.

(In short, this isn’t being done in a new project; it’s a project that I’ve been working on for quite some time, and which this has quite a few assets and a fair few shaders already made.)

I appreciate that, thank you. :slight_smile:

That said, while I’ve somewhat painted myself into a corner here, I’m not sure that it would be wise for me to give up the advantages that you cited for the default behaviour for the purpose of those occasions on which it would be handy to have full-float vertex-colours.

Ah, thank you.

I do somewhat rely on the fact that vertex colours default to white! Having a reliable default value is very useful indeed, I think.

As noted, I’m used to the vertex-colours defaulting to white–but I should be able to work with a default of black in the case of the aux-colours, I think.

So, I may well do that, then: store the data that would have been stored in values greater than one instead in an aux-channel.

Just to check: is there any way to alter this default value? While I can work with it being black, it would be convenient for it to be white. (As it means that I don’t have to remember to make this one specific set of vertex colours different to the others, and that objects using such colours aren’t blacked out by default when rendered with their vertex-colours.)

There is no way to alter this in Panda at present. (It’s not obvious to me where such a value would be specified, either, but suggestions welcome.)

Fair enough–it seemed worth asking!

As to where it might be specified, I suppose that it could just be a config variable. “default-aux-color (1, 1, 1, 1)”, or something like that.

However, having aux-values default to black is only a minor inconvenience, so I don’t intend to ask for new functionality to be added against it!