ogre-next 学习笔记 - Day 7
通过之前的分析,知晓 hlms 的重要性。对hlms做一个详细的分析
hlms文件结构以及对象
从图中看出,hlms的文件不多,对象也不多,关系简单。
类图
能看懂就行,不求格式
对象大概能分为几类
- Hlms
- HlmsProperty
- HlmsDatablock
- StaticBlock
- HlmsJson
- 其他
每一种 hlms都有一个对应的property,这些property由一些const idString 标识它支持的属性。
例如
struct _OgreHlmsUnlitMobileExport UnlitMobileProp
{
static const IdString TexMatrixCount;
static const IdString TexMatrixCount0;
static const IdString TexMatrixCount1;
static const IdString TexMatrixCount2;
static const IdString TexMatrixCount3;
static const IdString TexMatrixCount4;
static const IdString TexMatrixCount5;
static const IdString TexMatrixCount6;
static const IdString TexMatrixCount7;
// ...
}
const IdString UnlitMobileProp::TexMatrixCount = IdString( "hlms_texture_matrix_count" );
const IdString UnlitMobileProp::TexMatrixCount0 = IdString( "hlms_texture_matrix_count0" );
const IdString UnlitMobileProp::TexMatrixCount1 = IdString( "hlms_texture_matrix_count1" );
const IdString UnlitMobileProp::TexMatrixCount2 = IdString( "hlms_texture_matrix_count2" );
const IdString UnlitMobileProp::TexMatrixCount3 = IdString( "hlms_texture_matrix_count3" );
const IdString UnlitMobileProp::TexMatrixCount4 = IdString( "hlms_texture_matrix_count4" );
const IdString UnlitMobileProp::TexMatrixCount5 = IdString( "hlms_texture_matrix_count5" );
const IdString UnlitMobileProp::TexMatrixCount6 = IdString( "hlms_texture_matrix_count6" );
const IdString UnlitMobileProp::TexMatrixCount7 = IdString( "hlms_texture_matrix_count7" );
每个hlms 都有一个 datablock
例如
class HlmsUnlitMobileDatablock : public HlmsDatablock
{
/** Valid parameters in params:
@param params
* diffuse [r g b [a]]
If absent, the values of mR, mG, mB & mA will be ignored by the pixel shader.
When present, the rgba values can be specified.
Default: Absent
Default (when present): diffuse 1 1 1 1
* diffuse_map [texture name] [#uv]
Name of the diffuse texture for the base image (optional, otherwise a dummy is set)
The #uv parameter is optional, and specifies the texcoord set that will
be used. Valid range is [0; 8)
If the Renderable doesn't have enough UV texcoords, HLMS will throw an exception.
Note: The UV set is evaluated when creating the Renderable cache.
* diffuse_map1 [texture name] [blendmode] [#uv]
Name of the diffuse texture that will be layered on top of the base image.
The #uv parameter is optional. Valid range is [0; 8)
The blendmode parameter is optional. Valid values are:
NormalNonPremul, NormalPremul, Add, Subtract, Multiply,
Multiply2x, Screen, Overlay, Lighten, Darken, GrainExtract,
GrainMerge, Difference
which are very similar to Photoshop/GIMP's blend modes.
See Samples/Media/Hlms/GuiMobile/GLSL/BlendModes_piece_ps.glsl for the exact math.
Default blendmode: NormalPremul
Default uv: 0
Example: diffuse_map1 myTexture.png Add 3
* diffuse_map2 through diffuse_map16
Same as diffuse_map1 but for subsequent layers to be applied on top of the previous
images. You can't leave gaps (i.e. specify diffuse_map0 & diffuse_map2 but not
diffuse_map1).
Note that not all mobile HW supports 16 textures at the same time, thus we will
just cut/ignore the extra textures that won't fit (we log a warning though).
* animate <#uv> [<#uv> <#uv> ... <#uv>]
Enables texture animation through a 4x4 matrix for the specified UV sets.
Default: All UV set animation/manipulation disabled.
Example: animate 0 1 2 3 4 5 6 7
* alpha_test [compare_func] [threshold]
When present, mAlphaTestThreshold is used.
compare_func is optional. Valid values are:
less, less_equal, equal, greater, greater_equal, not_equal
Threshold is optional, and a value in the range (0; 1)
Default: alpha_test less 0.5
Example: alpha_test equal 0.1
*/
}
这里通过注释的方式,把每个支持的数据都标出来了。通过之前的学习知道,这些数据可以来自script,也可以通过代码设置。
datablock里的数据与property里的是一一对应的,renderable持有了一个datablock,最终会把 datablock里的数据设置到property里。
void HlmsPbs::calculateHashForPreCreate( Renderable *renderable, PiecesMap *inOutPieces )
{
assert( dynamic_cast<HlmsPbsDatablock*>( renderable->getDatablock() ) );
HlmsPbsDatablock *datablock = static_cast<HlmsPbsDatablock*>(
renderable->getDatablock() );
const bool metallicWorkflow = datablock->getWorkflow() == HlmsPbsDatablock::MetallicWorkflow;
const bool fresnelWorkflow = datablock->getWorkflow() ==
HlmsPbsDatablock::SpecularAsFresnelWorkflow;
setProperty( PbsProperty::FresnelScalar, datablock->hasSeparateFresnel() || metallicWorkflow );
setProperty( PbsProperty::FresnelWorkflow, fresnelWorkflow );
setProperty( PbsProperty::MetallicWorkflow, metallicWorkflow );
// ...
}
已知的是,创建的时候是通过item->setDatablock(…)
void Item::setDatablock( HlmsDatablock *datablock )
{
SubItemVec::iterator itor = mSubItems.begin();
SubItemVec::iterator end = mSubItems.end();
while( itor != end )
{
itor->setDatablock( datablock );
++itor;
}
}
内部会调用 subItem->setDatablock(…)
void Renderable::setDatablock( HlmsDatablock *datablock )
{
// ...
}
class _OgreExport SubItem : public RenderableAnimated
class _OgreExport RenderableAnimated : public Renderable
SubItem 是 Renderable。
从material 到 hlms property,hlms 算走通了一半。设置完属性后,就应该设置往shader送数据了。
还有 hlms的几个cache没有涉及到
to be continue…