This time, I extended the functionality of my plugin, to let it become a PBR calibration plugin that can be used in editor to calibrate the albedo (brightness for dielectric materials\metallic materials), saturation, roughness range, metalness value.
When I’m working in the current PBR pipeline project, the huge amount of assets making the calibration very difficult, and not everyone reads the documentation or follows the documentation, besides it’s not easy to tell whether each gbuffer channel is in valid range or not by just eyeballing. It’s necessary to provide with a visualization tool that easily indicating which pixel is out of range. This calibration workflow should start from DCC (Substance Painter, Substance Designer) to engine. I’ve done some calibration within Substance Painter shader to give corresponding warning colors when PBR values are out of range, this time I’d like to try to use the plugin I was working on to make a PBR calibration tool to visualize the invalid PBR values showing in the editor view port.
Add a New Buffer to Save GBuffer Data
Diffuse color, roughness and metallic are all Gbuffer data, to get and compare the pixels from each, I need to pass them into an RDG pass using SHADER_PARAMETER_RDG_UNIFORM_BUFFER so that the shader can grab and use them:
Correspondingly, in CTSceneViewExtension.cpp, I need to grab SceneTextures that has gbuffer data to the shader.
*1 Inputs.SceneTextures is from FPostProcessingInputs:
FSceneTextureUniformParameters is a uniform buffer containing common scene textures used by materials or global shaders. In SceneTexturesConfig.h file it defines from scene color to depth, gbuffer, ssao, custom depth, etc.
Use GBuffer Data in the Global Shader
Now, in the .usf shader file, I can start to use the GBuffer data from the SceneTextures:
*1 GetGBufferData() is defined in /Engine/Private/DeferredShadingCommon.ush file, it contains:
Implement the Pixel Comparison
Then I can start to work on the calibration logic in my .usf file. Basically the logic is, for example “if diffuseColor’s brightness < x.xf, then debugPixels = red color”, so that the original pixels will be replaced by the debug pixels, to indicate this pixel is problematic:
Create an Editor Panel
In my last post, what I did to let the plugin work and add the render thread was I added an Actor, and after BeginPlay(), the render thread will be activated. Now because it’s a debug tool, I want it to be called in editor from several buttons. I haven’t ever wrote any UI in C++ in Unreal, but I remembered in plugin template there’s one can add the plugin into the menu:
Codes there can bring you a plugin button and a dock tab:
In the .cpp file it generated, there’s a function named onSpawnPluginTab() is where you can add your own Slate UI into the empty dock tab window.
Create Buttons and Call functions
So I added four buttons for my tool, and linked my FSceneViewExtensions with buttons:
Under each SButton, .OnClicked() function is the one can call a function after cliked the button. To be noticed, I can’t write OnClicked(this, &FCTLibModule::MyFunction) directly, instead I have to use OnClicked(FOnClicked::CreateRaw(this, &FCTLibModule::MyFunction)) , because FCTLibModule derived from IModuleInterface, it’s not a shared pointer, so have to specify the method to bind for OnCliked.
For functions that called by the button, it needs to use FReply class. This is its description: * A Reply is something that a Slate event returns to the system to notify it about certain aspect of how an event was handled. * For example, a widget may handle an OnMouseDown event by asking the system to give mouse capture to a specific Widget. * To do this, return FReply::CaptureMouse( NewMouseCapture ).
Through each fuction StartCalibration_Roughness, StartCalibration_Albedo, StartCalibration_Metallic, I alse passed a flag into the shader, so that my shader knows in what channel is debugging right now.
The Final Look
Below showing how the plugin works:
With Diffuse Color button, as what described in the button tooltip, those highlight color indicate: RED: Diffuse Color is too dark for dielectric materials; YELLOW: Diffuse Color is too bright for dielectric materials; BLUE: Diffuse Color is too dark for metal materials; MAGENTA: Diffuse Color is too saturated
With Roughness button, as what described in the button tooltip, those highlight color indicate: RED: Roughness is lower than 0.098f; YELLOW: Roughness is higher than 0.955f
With Metallic button, as what described in the button tooltip, those highlight color indicate: RED: Metalness has a grayscale value (Invalid Range: 0.039f ~ 0.9216f)
I believe there are more things can be added into this calibration tool in the future such as texel density, vertices warning, texture format\size warning, material properties check, etc. It’s gonna be interesting to extand it into a more versatile tool.