hlms template conditions

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


User avatar
bishopnator
Gnome
Posts: 327
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 15

hlms template conditions

Post by bishopnator »

Hi, I am trying to write a template shader for my custom hlms which will have multiple "sections". Basically I want to write couple of pieces and based on the Renderable's properties, only once piece will be inserted to the shader:

Code: Select all

@piece(PropertyA) @insertpiece(ShaderA) @end
@piece(PropertyB) @insertpiece(ShaderB) @end
@piece(PropertyC) @insertpiece(ShaderC) @end
@piece(!PropertyA && !PropertyB && !PropertyC) @insertpiece(DefaultShader) @end

This of course work, but I would like to write last part in more general way that if I insert new PropertyD, that I don't have to update the condition there. Something like this (but it doesn't work):

Code: Select all

@piece(PropertyA) @insertpiece(ShaderA) @set(ShaderSet, 1) @end
@piece(PropertyB) @insertpiece(ShaderB) @set(ShaderSet, 1) @end
@piece(PropertyC) @insertpiece(ShaderC) @set(ShaderSet, 1) @end
@piece(!ShaderSet) @insertpiece(DefaultShader) @end

From what I read in the documentation for HLMS I think I understand why it is not working - the @set is evaluated after the pieces are inserted, which is just too late. I tried it also with @pset, but this one is evaluated before any piece is inserted. Is there something more dynamic? There was description of something similar and recommended that it is possible to use HLSL/GLSL preprocessor macros with their own cons and pros. I would like to stick purely to HLMS preprocessing so if there is nothing else what I can do, I will stick to my original template code (with last part naming all properties).

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5476
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1359

Re: hlms template conditions

Post by dark_sylinc »

Since the Hlms parses files as individual units and in alphabetical order, you can workaround this by using two files:

Code: Select all

// 01.Script_piece_all.any
@property(PropertyA) @insertpiece(ShaderA) @set(ShaderSet, 1) @end
@property(PropertyB) @insertpiece(ShaderB) @set(ShaderSet, 1) @end
@property(PropertyC) @insertpiece(ShaderC) @set(ShaderSet, 1) @end

Code: Select all

// 02.Script_piece_all.any
@property(!ShaderSet) @insertpiece(DefaultShader) @end

This way 01.Script_piece_all.any will be parsed, the piece inserted and the property set.
Then 02.Script_piece_all.any gets parsed with ShaderSet already set.

Alternatively in C++, Hlms::notifyPropertiesMergedPreGenerationStep (or HlmsListener::propertiesMergedPreGenerationStep) can do the same evaluation, where you can check if Prop A, B or C have been set, then set/unset ShaderSet:

Code: Select all

void MyListener::propertiesMergedPreGenerationStep(
	Hlms *hlms, const HlmsCache &passCache, const HlmsPropertyVec &renderableCacheProperties,
	const PiecesMap renderableCachePieces[NumShaderTypes], const HlmsPropertyVec &properties,
	const QueuedRenderable &queuedRenderable, const size_t tid )
{
	if( hlms->_getProperty( tid, "A" ) != 0 ||
	    hlms->_getProperty( tid, "B" ) != 0 ||
    	    hlms->_getProperty( tid, "C" ) != 0 )
	{
	    hlms->_setProperty( tid, "ShaderSet", 1 );
	}
}
User avatar
bishopnator
Gnome
Posts: 327
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 15

Re: hlms template conditions

Post by bishopnator »

The approach with 2 files sounds better for me. However I need to wrap the "implementation" in a piece. So something like this:

Code: Select all

// 01.Script_piece_all.any
@piece(mainShaderBody)
@property(PropertyA) @insertpiece(ShaderA) @set(ShaderSet, 1) @end
@property(PropertyB) @insertpiece(ShaderB) @set(ShaderSet, 1) @end
@property(PropertyC) @insertpiece(ShaderC) @set(ShaderSet, 1) @end
@end

And in the second file:

Code: Select all

// 02.Script_piece_all.any
@insertpiece(mainShaderBody)
@property(!ShaderSet) @insertpiece(DefaultShader) @end

Without trying it, do you think it could work? I will experiment with it later as I am in the middle of shader implementation and I went for now with the solution of using all the conditions as mentioned in my first post.