ShowFlag.Grain
ShowFlag.Grain
#Overview
name: ShowFlag.Grain
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Allows to override a specific showflag (works in editor and game, \
It is referenced in 7
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of ShowFlag.Grain is to control the visibility of film grain post-processing effect in Unreal Engine’s rendering system. This setting variable is part of the post-processing pipeline and affects the final visual output of the scene.
The Unreal Engine subsystems that rely on this setting variable are primarily the rendering system and the post-processing module. Based on the callsites, we can see that it’s used in the SceneRendering and SceneView components.
The value of this variable is set through the engine’s show flags system, which allows toggling various visual features on and off. It can be manipulated through the engine’s UI or programmatically.
The ShowFlag.Grain interacts with other variables, particularly:
- FinalPostProcessSettings.FilmGrainIntensity: If ShowFlag.Grain is false, FilmGrainIntensity is set to 0, effectively disabling the film grain effect.
- FinalPostProcessSettings.FilmGrainTexture: This texture is used when the grain effect is enabled.
Developers should be aware of the following when using this variable:
- It’s fixed in shipping builds, meaning it can’t be toggled at runtime in final game releases.
- It affects performance, as enabling grain requires additional post-processing.
- It’s part of the SFG_PostProcess group, indicating its role in post-processing effects.
Best practices when using this variable include:
- Use it judiciously, as film grain can significantly alter the visual style of your game.
- Consider performance implications, especially on lower-end devices.
- Ensure it aligns with your game’s artistic direction and target platform capabilities.
Regarding the associated variable ‘Grain’:
The purpose of the Grain variable varies depending on the context. In the MotoSynthEngine, it’s used in audio processing for granular synthesis. In the rendering context, it’s likely an internal representation of the ShowFlag.Grain setting.
The Grain variable is used in multiple Unreal Engine subsystems, including the experimental MotoSynth plugin for audio and the core rendering system.
The value of this variable is set and used differently in various contexts. In audio processing, it’s part of the grain pool in granular synthesis. In rendering, its value is typically derived from the ShowFlag.Grain setting.
Developers should be aware that the Grain variable has different meanings and usages in different parts of the engine. It’s crucial to understand the specific context when working with this variable.
Best practices include ensuring proper initialization and cleanup of Grain objects in audio processing, and correctly handling the grain effect in rendering based on the ShowFlag.Grain setting.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:47
Scope: file
Source code excerpt:
SHOWFLAG_ALWAYS_ACCESSIBLE(Vignette, SFG_PostProcess, NSLOCTEXT("UnrealEd", "VignetteSF", "Vignette"))
/** Fine film grain */
SHOWFLAG_FIXED_IN_SHIPPING(1, Grain, SFG_PostProcess, NSLOCTEXT("UnrealEd", "GrainSF", "Grain"))
/** Screen Space Ambient Occlusion, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(AmbientOcclusion, SFG_LightingComponents, NSLOCTEXT("UnrealEd", "AmbientOcclusionSF", "Ambient Occlusion"))
/** Decal rendering, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Decals, SFG_Normal, NSLOCTEXT("UnrealEd", "DecalsSF", "Decals"))
/** like bloom dirt mask */
SHOWFLAG_FIXED_IN_SHIPPING(1, CameraImperfections, SFG_PostProcess, NSLOCTEXT("UnrealEd", "CameraImperfectionsSF", "Camera Imperfections"))
#Associated Variable and Callsites
This variable is associated with another variable named Grain
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Plugins/Experimental/MotoSynth/Source/MotoSynth/Private/MotoSynthEngine.cpp:438
Scope (from outer to inner):
file
function void FMotoSynthEngine::GenerateGranularEngine
Source code excerpt:
{
int32 GrainIndex = ActiveGrains[ActiveGrainIndex];
FMotoSynthGrainRuntime& Grain = GrainPool[GrainIndex];
Grain.SetRPM(CurrentRPM);
if (bGranularEngineEnabled)
{
OutAudio[SampleIndex] += Grain.GenerateSample();
}
else
{
// Still need to generate the grain since envelope state is dependent on grain state
// TODO: if this is used at runtime, implement a virtual GenerateSample to update state but not do any audio work
// Currently the expectation is that this mode is only an editor-only mode (i.e. no pure synth engines shipped)
Grain.GenerateSample();
}
if (Grain.IsDone())
{
ActiveGrains.RemoveAtSwap(ActiveGrainIndex, 1, EAllowShrinking::No);
FreeGrains.Push(GrainIndex);
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SceneView.cpp:2118
Scope (from outer to inner):
file
function void FSceneView::EndFinalPostprocessSettings
Source code excerpt:
}
if(!Family->EngineShowFlags.Grain)
{
FinalPostProcessSettings.FilmGrainIntensity = 0.0f;
}
if(!Family->EngineShowFlags.CameraImperfections)
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:47
Scope: file
Source code excerpt:
SHOWFLAG_ALWAYS_ACCESSIBLE(Vignette, SFG_PostProcess, NSLOCTEXT("UnrealEd", "VignetteSF", "Vignette"))
/** Fine film grain */
SHOWFLAG_FIXED_IN_SHIPPING(1, Grain, SFG_PostProcess, NSLOCTEXT("UnrealEd", "GrainSF", "Grain"))
/** Screen Space Ambient Occlusion, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(AmbientOcclusion, SFG_LightingComponents, NSLOCTEXT("UnrealEd", "AmbientOcclusionSF", "Ambient Occlusion"))
/** Decal rendering, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(Decals, SFG_Normal, NSLOCTEXT("UnrealEd", "DecalsSF", "Decals"))
/** like bloom dirt mask */
SHOWFLAG_FIXED_IN_SHIPPING(1, CameraImperfections, SFG_PostProcess, NSLOCTEXT("UnrealEd", "CameraImperfectionsSF", "Camera Imperfections"))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneRendering.cpp:2705
Scope (from outer to inner):
file
function FSceneRenderer::FSceneRenderer
Source code excerpt:
// Handle the film grain texture
if (ViewInfo->FinalPostProcessSettings.FilmGrainIntensity > 0.0f &&
ViewFamily.EngineShowFlags.Grain &&
CVarFilmGrain.GetValueOnGameThread() != 0 &&
SupportsFilmGrain(ViewFamily.GetShaderPlatform()))
{
UTexture2D* FilmGrainTexture = ViewInfo->FinalPostProcessSettings.FilmGrainTexture;
if (FilmGrainTexture == nullptr)
{
#Loc: <Workspace>/Engine/Source/Runtime/SignalProcessing/Private/GrainDelay.cpp:96
Scope (from outer to inner):
file
namespace Audio
namespace GrainDelay
function void FGrainDelay::SetGrainBasePitchShiftRatio
Source code excerpt:
for (const int32 ActiveGrainId : ActiveGrains)
{
FGrain& Grain = GrainPool[ActiveGrainId];
// Set the pitch shift ratio of the grain.
// This function will take into account the initial random pitch offset
Grain.SetGrainPitchShiftRatio(InPitchRatioBase, SampleRate);
}
}
}
void FGrainDelay::SpawnGrain(const float InDelay, const float InDuration, const float InPitchShiftRatioOffset)
{
#Loc: <Workspace>/Engine/Source/Runtime/SignalProcessing/Private/GrainDelay.cpp:149
Scope (from outer to inner):
file
namespace Audio
namespace GrainDelay
function float FGrainDelay::SynthesizeFrame
Source code excerpt:
// Get the grain data
const int32 GrainId = ActiveGrains[ActiveGrainIndex];
FGrain& Grain = GrainPool[GrainId];
// Calculate the grain envelope
// should have never been added to the pool
check(!FMath::IsNearlyZero(Grain.DurationFrames));
const float Fraction = FMath::Min(Grain.NumFramesRendered / Grain.DurationFrames, 1.0f);
const float GrainVolume = Grain::GetValue(GrainEnvelope, Fraction);
const float PitchShiftedSample = Grain.PitchShifter.ReadDopplerShiftedTapFromDelay(InDelayLine, Grain.DelayTapPositionMilliseconds);
OutFrame += GrainVolume * PitchShiftedSample;
// Note we are tracking real frames rendered not frames consumed from the delay for grain duration
Grain.NumFramesRendered += 1.0f;
// Clean up the grain once it's done
if (Grain.NumFramesRendered >= Grain.DurationFrames)
{
// Pop back on this id so we can reuse it next time a grain is spawned
FreeGrains.Add(GrainId);
// Remove at swap allows us to clean up the active grain list while we loop through it
ActiveGrains.RemoveAtSwap(ActiveGrainIndex, 1, EAllowShrinking::No);