Setting a custom uniform per mesh

In contrast to this question: http://hub.jmonkeyengine.org/groups/graphics/forum/topic/passing-a-custom-uniform-into-my-shader/

And this probably obsolete post: http://hub.jmonkeyengine.org/groups/effects/forum/topic/use-same-shader-with-different-parameters-uniform-on-several-meshes/ (can’t find this class anymore)



Suppose I have a lot of the same “chrismas ball” objects. How can I adjust the color per mesh, without creating 1000 material objects? Can I peek into the shader, just before I render my object? I was trying to set it via a control on controlRender(), but that didn’t work. Every object just gets one color.

If not, is there an alternative? (Assume the christmas balls are dynamic, so no mesh optimizing please)

Actually…there is no way to do this…afaik



@Momoko_Fan, what do you think? maybe we could add mesh dependent uniforms somehow?

Whats the problem with creating a 1000 material objects?

1 Like

It… doesn’t sound right in my context. I have this context: Create 1000 grass objects which all look the same. The only thing that differs is the wind vector, because I am creating animated grass. This means that I make a 1000 materials, which are actually all the same. So as far as I think about it, I don’t need so many materials.



Maybe I can do a proposal for the design to make the coupling between a Node and a Control a bit tighter:



A Node object should fire events, which the Control object can subscribe to. For example: OnPreRender, OnPostRender, OnCreation. We could use these events to change something for the object just before it gets drawn or just after it gets created (get the current material from the object).



Of course we can do everything in the OnCreation already in the SetSpatial(Spatial s) method, but pre-rendering sounds logical. For example: Our model looks different under water than above water. On the OnPreRender method, we can make our object a bit more blue-ish. And in the OnPostRender, we can reset the property back to what it was. This way, we don’t need to change the material (in context the material doesn’t change under water, but the light perception does).

the meta-problems are always more interesting to me…



Why is it that you are doing grass this way? Is it a requirement that they all have uniquely individual wind or are you just trying to make them look more random/varied? …because there are other ways to do that.



Even if they are required to have some kind of spatially calculated ‘wind’… sometimes a texture of some kind is better.



Note: I think performance-wise, there is no difference between one material and per-geometry uniform versus per-geometry materials. The same number of uniforms will get applied every frame… ie: all of them.

I am calculating semi-physics wind vectors per blade. Maybe I could use physics for it, but this is a school project and I need to implement most of it myselft. I could indeed fill a texture, but I will go for the 1000 materials approach probably and can always change my design to a texture. The trick is that I want to change my positions in the GPU and not by some CPU physics device.

Create an array of wind vectors, then upload it as a single uniform. Find the correct uniform index to fetch based on gl_VertexID divided by the number of vertices in a single grass object.

Even better is to use a 2D texture that gives the wind vector for a given XY location on the map, you’re still changing the positions on the GPU that way.

1 Like

Thanks for the workarounds, but I was just thinking about the concept of making the scenegraph a bit more dynamic this way. The 2D texture is an option I would go for indeed. But maybe I’ll create the 1000 materials, because this seems to be the medium between a mesh and the shader.