[2.1] Associate renderable with different shader in runtime Topic is solved

Problems building or running the engine, queries about how to use features etc.
Post Reply
gabbsson
Halfling
Posts: 59
Joined: Wed Aug 08, 2018 9:03 am
x 9

[2.1] Associate renderable with different shader in runtime

Post by gabbsson » Thu Oct 18, 2018 9:45 am

Ogre Version: 2.1
Operating System: Linux
Render System: GL3Plus

Hello again! I have run into some more problems (still regarding clipping, but in a different way).
My goal is to have clipping done per pass, using a HlmsListener, but to let individual Renderables to switch clipping on and off.

In my previous post I was told it is better to have two different shaders, one that has clipping code and one that does not to promote portability. While portability is not my greatest concern I wanted to give it a try to "do it right".

I figured I should be able to do so without changing too much, and decided I wanted to add clipping as a property in the shader.
I managed to add the code in the shader using the preprocessor and it works fine (I'm leaving out the glsl code to save some space).

Here is what I did to set the property from C++ (as seen in multiple other posts):

Code: Select all

void OgreHlmsClipUnlit::calculateHashForPreCreate(Renderable* renderable, PiecesMap* inOutPieces)
{
    Ogre::HlmsUnlit::calculateHashForPreCreate(renderable, inOutPieces);
    
    if (renderable.hasCustomParameter(0))	// <- Always fails for some reason, despite setting it upon creation. Worked in fillBuffersFor.
    	setProperty( HlmsBaseProp::PsoClipDistances, 8 );
}
As my comment says the customParameter part fails everytime for some reason.
Just to be able to move on I instead count the calls to the function and I set the property for the first renderable, just to see that it does in fact create two shaders. So this will work fine once I figure out the problem with customParameter.

So what I have working is an inherited Hlms implementation that has two different shaders, where uniforms are set using an inherited HlmsListener.

As far as I can tell calculateHashForPreCreate is done once for each renderable (basically an initialization).
When the function is called the renderable gets "associated" with that specific shader (by hash I presume?). If I want to stop using clipping on a specific renderable I'm not sure how to tell the Hlms that the object should now be associated with the "other" shader.

So my question is:
How do I re-associate a renderable with a different shader during runtime?

Ps.

I haven't found any posts that do this exactly, many are "near" but I haven't been able to figure out how to translate it to my case.
While this post is very similar I don't really need to send per renderable data to the shader. I just want to be able to assign shaders to different objects during runtime. Perhaps it is the same in the end?
0 x

gabbsson
Halfling
Posts: 59
Joined: Wed Aug 08, 2018 9:03 am
x 9

Re: [2.1] Associate renderable with different shader in runtime

Post by gabbsson » Thu Oct 18, 2018 10:42 am

After reading the source for HlmsUnlit::calculateHashForPreCreate I realized I was of course supposed to store the info in the datablock.
So this is basically solved.. But it does mean I need to create unique datablocks for clipping/not clipping. Is there a way where I dont have to create two versions of every datablock?

Edit:

Should probably explain, instead initializing shaders based on renderables I had to inherit the datablocks (unlit/pbs) and add a clip paramter in them. That way it can be detected when a new datablock is used and a new shader will be created if needed. I recommend reading the source for calculateHashForPreCreate in Unlit/PBS to get an idea.
0 x

Post Reply