RigidBodyCombiner and setShaderInput

I have a case where there are many of the same model.
The only thing that is different (besides transform) is a setShaderInput with a Mat4 to supply lighting information. I identified this as the point of failure for RigidBodyCombiner to actually combine the geoms.
Is there any way I can keep my shader input and still have the geoms combine? Perhaps with some code changes in the RigidBodyCombiner?

No, changing the shader input will always require a different Geom, because that’s part of the render state. A Geom can only be sent as a single render state.

If you need to send different data to different objects within a single Geom, that data has to be encoded in the vertices somehow. This is possible, theoretically (this is how people handle joint animation within the GPU, for instance), but it is well beyond the scope of the RigidBodyCombiner.

Short answer: to use the RigidBodyCombiner successfully, you must find a way to design your shader not to require a different Mat4 for each object (other than transform).


I took a look at the RigidBodyCombiner code, it appears to be creating a new GeomVertexFormat based on the old one and adding a transform column to it. Could I potentially add my own column(s) and have them read their values from somewhere, the same way the transform column gets its values?

That’s the hard way. If you’re going to do all that, abandon the RigidBodyCombiner and set up your own vertex structure completely, and add whatever columns you need, and then write a shader to understand those columns.

In fact, if you’re writing your own shader, you might as well take advantage of GPU instancing as described in rdb’s blog post last year. Then you don’t even need to muck around with the CPU instancing that the RigidBodyCombiner gives you.


I had considered the hardware instancing, though I had a few concerns with it.

The main concern was I couldn’t find any information on what ATI cards supported the shader profile needed for instancing. On the NVIDIA side it looked like 8000-series or better which while I was hoping to target 7000-series would probably be OK.

The other hurdle was a lack of example code. The best one I found was the Panda SE demo with 1000 Ralphs, but the shader included is hard-coded for 1000 instances and there is no example how to do an on-the-fly instance count.

Specific example from the Panda SE demo:
in ralphDemo.py:

self.ralph.setShaderInput("Ly", input)

“input” is a PTAVecBase4 with length 1000.
in shader.c:

uniform float4 Ly[1000],

Is that a limitation in the shader language, Panda’s implementation of instancing, or the example?

Looking a bit deeper, I see CG does allow “unsized” arrays in a shader, but a size still needs to be set in code somewhere using:

cgSetArraySize(CGparameter param, int size);

I don’t find any instance of this function in the source code.
Even still, from what I read in the NVIDIA “GPU Gems” it sounded like you need to set this before compiling the shader, so you would use it at runtime but not during runtime. I could be quite wrong about this though.
I guess that wouldn’t be so bad, I could keep an array of shaders initialized with different lengths. Certainly much better than having tons of the same shader with different hard-coded values.