I very much appreciate that you provide me some content to read to further improve my skills. But let's take some smaller steps to be more safe.
I got it working and your post was helpful.
My first working draft is this.
900.OutlineShader_piece_all.any (I chose that name so I need only one file)
Code: Select all
@property( hlms_normal_thicken )
@undefpiece( DefaultBodyPS )
@piece( DefaultBodyPS )
outColour = vec4(0.0, 0.5, 0.0, 1.0);
@end
@end
@property( hlms_normal_thicken )
@piece( custom_vs_preTransform )
@property( hlms_normal || hlms_qtangent )
worldPos.xyz = worldPos.xyz + worldNorm * 0.01;
@end
@end
@end
I've deactivated the default implementation of the pixel shader and altered the vertex shader.
Of course this is nothing for an actual practical use as the color and the outline thickness is hard coded.
My current file looks like this: (For some reason the forum doesn't select the right language syntax highlighting here.)
Code: Select all
@property( hlms_normal_thicken )
// Pixel Shader Modify. Remove all lighting calculation. Shall only use emissive
@undefpiece( DoDirectionalLights )
@undefpiece( DoSpotLights )
@undefpiece( DoDirectionalShadowMaps )
// Vertex Shader Modify
// Diffuse Red Channel defines the width of the outline
@piece( custom_vs_preTransform )
@property( hlms_normal || hlms_qtangent )
ushort materialId = worldMaterialIdx[inVs_drawId].x & 0x1FFu;
#define material materialArray[materialId]
worldPos.xyz = worldPos.xyz + worldNorm * material.kD.x;
@end
@end
// Force that the Vertex shader also gets the Material data which is not standard for Pbs
@piece( custom_vs_uniformStructDeclaration)
@insertpiece( MaterialStructDecl )
@property( !(hlms_skeleton || hlms_shadowcaster || hlms_pose) )@insertpiece( InstanceStructDecl )@end
@end
@end
I've removed most of the pixel shader stuff and use only emissive colors as output.
The vertex shader uses the red channel of the diffuse color to define a factor applied to the normal.
While this solution might not be perfect as it depends on the direction of the normals and therefore the quality of the mesh, it currently is ok for me.
Some example code to use this:
Code: Select all
Ogre::Hlms* hlmsPbsOutline = hlmsManager->getHlms(Ogre::HLMS_USER0);
Ogre::HlmsMacroblock macroblock;
Ogre::HlmsBlendblock blendblock;
macroblock.mCullMode = Ogre::CULL_ANTICLOCKWISE;
Ogre::HlmsParamVec param;
redOutlineDataBlock = static_cast<Ogre::HlmsPbsDatablock*>(
hlmsPbsOutline->createDatablock("RedOutline", "RedOutline", macroblock, blendblock, param));
redOutlineDataBlock->setEmissive(Ogre::Vector3(0.0, 1.0, 0));
redOutlineDataBlock->setDiffuse(Ogre::Vector3(0.01, 0, 0));
redOutlineDataBlock->setSpecular(Ogre::Vector3(0, 0, 0));
For initialization I just duplicated some lines in GraphicsSystem.cpp:
Code: Select all
{
// Create & Register HlmsPbsOutline
HlmsPbsOutline::getDefaultPaths(mainFolderPath, libraryFoldersPaths);
std::cout << "mainFolderPath " << mainFolderPath << std::endl;
Ogre::Archive* archivePbs = archiveManager.load(rootHlmsFolder + mainFolderPath, archiveType, true);
// Get the library archive(s)
Ogre::ArchiveVec archivePbsLibraryFolders;
libraryFolderPathIt = libraryFoldersPaths.begin();
libraryFolderPathEn = libraryFoldersPaths.end();
while (libraryFolderPathIt != libraryFolderPathEn)
{
Ogre::Archive* archiveLibrary =
archiveManager.load(rootHlmsFolder + *libraryFolderPathIt, archiveType, true);
std::cout << "archiveLibrary " << archiveLibrary << std::endl;
std::cout << "libraryFolderPathIt " << *libraryFolderPathIt << std::endl;
archivePbsLibraryFolders.push_back(archiveLibrary);
++libraryFolderPathIt;
}
{
Ogre::Archive* archiveLibrary = archiveManager.load("HlmsPbsOutline", archiveType, true);
archivePbsLibraryFolders.push_back(archiveLibrary);
}
// Create and register
hlmsPbsOutline = OGRE_NEW HlmsPbsOutline(archivePbs, &archivePbsLibraryFolders);
Ogre::Root::getSingleton().getHlmsManager()->registerHlms(hlmsPbsOutline);
}
And then this custom class
Code: Select all
/*
* HlmsPbsOutline.h
*
* Created on: 08.05.2021
* Author: andre
*/
#ifndef HLMSPBSOUTLINE_H_
#define HLMSPBSOUTLINE_H_
#include "OgreHlmsPbs.h"
class HlmsPbsOutline : public Ogre::HlmsPbs
{
public:
HlmsPbsOutline(Ogre::Archive* dataFolder, Ogre::ArchiveVec* libraryFolders) : Ogre::HlmsPbs(dataFolder, libraryFolders)
{
mType = Ogre::HLMS_USER0;
mTypeName = "PbsOutline";
mTypeNameStr = "PbsOutline";
}
protected:
void calculateHashForPreCreate(Ogre::Renderable* renderable, Ogre::PiecesMap* inOutPieces) override
{
setProperty("hlms_normal_thicken", 1);
Ogre::HlmsPbs::calculateHashForPreCreate(renderable, inOutPieces);
}
};
#endif /* HLMSPBSOUTLINE_H_ */
That's all folks!