[2.1] a pretty way to change setProperty(),cull,depthWrite,etc (custom HLMS)

Problems building or running the engine, queries about how to use features etc.
Post Reply
hyyou
Gremlin
Posts: 173
Joined: Wed Feb 03, 2016 2:24 am
x 17
Contact:

[2.1] a pretty way to change setProperty(),cull,depthWrite,etc (custom HLMS)

Post by hyyou »

I am using a custom HLMS implementation.
Although it works nice and fast ( :D ), I feel that it is counter-intuitive to change setProperty()/cull/depthWrite/blendMode of a Ogre::item.

So far, I create a class MyItem (simplified):-

Code: Select all

class MyItem{
     Ogre::Item* item;
     BlendMode currentBlend,lastBlend;
     bool lastCull,currentCull ,lastDepthWrite,currentDepthWrite ;
     int setPropertyA,last_setPropertyA=0; //for Hlms::setProperty("A",setPropertyA);
     void update(){......}
};
Inside MyItem::update(), first, I check change in my custom shader setPropertyA , and prepare to flush:-

Code: Select all

 
bool flush=false;
if( last_setPropertyA!=setPropertyA ){
    last_setPropertyA=setPropertyA ;
    flush=true;  //= I need to call "flushRenderables()" later
}
Second, I check blend mode. If it changed, I will tell the datablock via setBlendblock():-

Code: Select all

 if(lastBlend!=currentBlend){
    flush=true;
    lastBlend=currentBlend;
    //"myBlendSolid","myBlendTrans","myBlendAdd"  are created as singleton at the first time-step
    switch(currentBlend){
        case MyBlend::SOLID : datablock->setBlendblock(myBlendSolid); break;
        case MyBlend::TRAN : datablock->setBlendblock(myBlendTrans); break;
        case MyBlend::ADD: datablock->setBlendblock(myBlendAdd); break;
    }
}
Next, I check culling. If it changed, I will tell the datablock via setMacroBlock().
However, setMacroBlock() is special, it calls flushRenderables(). In that case, I don't need to flush it again.

Code: Select all

 if(lastCull!=currentCull || lastDepthWrite!=currentDepthWrite ){
    lastCull=currentCull;
    lastDepthWrite=currentDepthWrite;
    //myMacro[0]= (cull=False, depthWrite = False), [1]=(F,T),[2]=(T,F),[3]=(T,T)
    if(!currentCull&&!currentDepthWrite){
    	datablock->setMacroBlock(myMacro[0]);
    	//it call "flushRenderables", so I don't need to flush again
    }else if(...){ ...
    }else{
        datablock->setMacroBlock(myMacro[3]);
    }
    flush=false;   //<-- mark that I don't need to flush it again, sigh.  (#4)
}
Finally, I flushed it if need :-

Code: Select all

if(flush){
    datablock->flushRenderables();
}
Everything works fine and fast, but my code is very dirty :-
1. I have to create Ogre::HlmsBlendblock* myBlendSolid,myBlendTrans,myBlendAdd,myMacro[4] at the first time step.
2. I have to check everything (all: setProperty,blendMode,CullMode,DepthWrite,etc.) against the previous time-step.
3. I have to remember to call datablock->flushRenderables(); as necessary, but not more than that because it is expensive.
4. datablock->setMacroBlock() sneakly call flushRenderables() (WTF). Thus, I don't have to flush it again, so I have to set flush=false. (ugly #4)

It is the way to go?
If yes, I will shut up.
If no, what is the more pretty approach?
Post Reply