ShowFlag.StereoRendering

ShowFlag.StereoRendering

#Overview

name: ShowFlag.StereoRendering

This variable is created as a Console Variable (cvar).

It is referenced in 20 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of ShowFlag.StereoRendering is to control whether stereoscopic 3D rendering is enabled in Unreal Engine. This setting is primarily used for virtual reality (VR) and other stereoscopic display applications.

Key points about ShowFlag.StereoRendering:

  1. It is part of the rendering system, specifically for stereoscopic rendering.

  2. Multiple Unreal Engine subsystems and plugins rely on this flag, including:

    • SimpleHMD plugin
    • PixelStreamingHMD plugin
    • OpenXRHMD plugin
    • XRBase plugin
    • Editor viewport system
    • Game viewport system
    • Mobile shading renderer
    • Post-processing system
    • Variable Rate Shading system
  3. The value is typically set based on the current rendering configuration, often determined by whether a VR headset is in use or if stereoscopic rendering is explicitly enabled.

  4. It interacts closely with other variables like HMDDistortion and VREditing.

  5. Developers should be aware that enabling this flag can significantly impact rendering performance and behavior, as it often requires rendering the scene twice (once for each eye).

  6. Best practices include:

    • Only enabling StereoRendering when actually using a stereoscopic display or VR headset.
    • Ensuring that your rendering pipeline and shaders are compatible with stereoscopic rendering when this flag is enabled.
    • Testing your application thoroughly in both stereo and non-stereo modes to ensure correct behavior.

Regarding the associated variable StereoRendering:

The purpose of StereoRendering is essentially the same as ShowFlag.StereoRendering. It’s used in various parts of the engine to determine if stereoscopic rendering is currently active. This variable is often set based on the result of calls to IsStereoEnabled() or similar functions, which check if stereoscopic rendering should be used for the current frame or view.

The StereoRendering variable is used in similar contexts to ShowFlag.StereoRendering, often controlling behavior in VR-related plugins, post-processing effects, and rendering systems. It’s important for developers to ensure consistency between ShowFlag.StereoRendering and any associated StereoRendering variables to avoid conflicts in rendering behavior.

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:313

Scope: file

Source code excerpt:

SHOWFLAG_ALWAYS_ACCESSIBLE(HMDDistortion, SFG_PostProcess, NSLOCTEXT("UnrealEd", "HMDDistortionSF", "HMD Distortion"))
/** Whether to render in stereoscopic 3d, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's used by StereoRendering */
SHOWFLAG_ALWAYS_ACCESSIBLE(StereoRendering, SFG_Hidden, NSLOCTEXT("UnrealEd", "StereoRenderingSF", "Stereoscopic Rendering"))
/** Show objects even if they should be distance culled, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(DistanceCulledPrimitives, SFG_Hidden, NSLOCTEXT("UnrealEd", "DistanceCulledPrimitivesSF", "Distance Culled Primitives"))
/** To visualize the culling in Tile Based Deferred Lighting, later for non tiled as well */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightCulling, SFG_Hidden, NSLOCTEXT("UnrealEd", "VisualizeLightCullingSF", "Light Culling"))
/** To disable precomputed visibility */
SHOWFLAG_FIXED_IN_SHIPPING(1, PrecomputedVisibility, SFG_Advanced, NSLOCTEXT("UnrealEd", "PrecomputedVisibilitySF", "Precomputed Visibility"))

#Associated Variable and Callsites

This variable is associated with another variable named StereoRendering. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Plugins/Experimental/SimpleHMD/Source/SimpleHMD/Private/SimpleHMD.cpp:277

Scope (from outer to inner):

file
function     void FSimpleHMD::SetupViewFamily

Source code excerpt:

	InViewFamily.EngineShowFlags.MotionBlur = 0;
	InViewFamily.EngineShowFlags.HMDDistortion = true;
	InViewFamily.EngineShowFlags.StereoRendering = IsStereoEnabled();

	if (UWorld* World = GWorld)
	{
		WorldToMeters = World->GetWorldSettings()->WorldToMeters;
	}
}

#Loc: <Workspace>/Engine/Plugins/Media/PixelStreaming/Source/PixelStreamingHMD/Private/PixelStreamingHMD.cpp:290

Scope (from outer to inner):

file
function     void FPixelStreamingHMD::SetupViewFamily

Source code excerpt:

	// Note: We do not want to apply any distortion on the UE side.
	InViewFamily.EngineShowFlags.HMDDistortion = false;
	InViewFamily.EngineShowFlags.StereoRendering = IsStereoEnabled();

	if (UWorld* World = GWorld)
	{
		WorldToMeters = World->GetWorldSettings()->WorldToMeters;
	}
}

#Loc: <Workspace>/Engine/Plugins/Runtime/OpenXR/Source/OpenXRHMD/Private/OpenXRHMD.cpp:1230

Scope (from outer to inner):

file
function     void FOpenXRHMD::SetupViewFamily

Source code excerpt:

	InViewFamily.EngineShowFlags.MotionBlur = 0;
	InViewFamily.EngineShowFlags.HMDDistortion = false;
	InViewFamily.EngineShowFlags.StereoRendering = IsStereoEnabled();

	const FPipelinedFrameState& FrameState = GetPipelinedFrameStateForThread();
	if (FrameState.Views.Num() > 2)
	{
		InViewFamily.EngineShowFlags.Vignette = 0;
		InViewFamily.EngineShowFlags.Bloom = 0;

#Loc: <Workspace>/Engine/Plugins/Runtime/XRBase/Source/XRBase/Private/DefaultXRCamera.cpp:218

Scope (from outer to inner):

file
function     void FDefaultXRCamera::SetupViewFamily

Source code excerpt:

		InViewFamily.EngineShowFlags.HMDDistortion = HMD != nullptr ? HMD->GetHMDDistortionEnabled(InViewFamily.Scene->GetShadingPath()) : false;
	}
	InViewFamily.EngineShowFlags.StereoRendering = bCurrentFrameIsStereoRendering;
	InViewFamily.EngineShowFlags.Rendering = HMD != nullptr ? !HMD->IsRenderingPaused() : true;
}

void FDefaultXRCamera::SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView)
{
	FQuat DeviceOrientation;

#Loc: <Workspace>/Engine/Plugins/Runtime/XRBase/Source/XRBase/Private/DefaultXRLoadingScreen.cpp:16

Scope (from outer to inner):

file
function     IStereoLayers* FDefaultXRLoadingScreen::GetStereoLayers

Source code excerpt:

{
	IStereoLayers* StereoLayers = nullptr;
	auto StereoRendering = TrackingSystem->GetStereoRenderingDevice();
	if (StereoRendering.IsValid())
	{
		StereoLayers = StereoRendering->GetStereoLayers();
		if (!StereoLayers || !StereoLayers->SupportsLayerState())
		{
			StereoLayers = nullptr;
			UE_LOG(LogHMD, Warning, TEXT("FDefaultXRLoadingScreen requires a working IStereoLayers implementation supporting IStereoLayers::Push/PopLayerState."));
		}
	}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorViewportClient.cpp:2901

Scope (from outer to inner):

file
function     EViewStatusForScreenPercentage FEditorViewportClient::GetViewStatusForScreenPercentage

Source code excerpt:

		return EViewStatusForScreenPercentage::PathTracer;
	}
	else if (EngineShowFlags.StereoRendering || EngineShowFlags.VREditing)
	{
		return EViewStatusForScreenPercentage::VR;
	}
	else if (!bIsRealtime)
	{
		return EViewStatusForScreenPercentage::NonRealtime;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameViewportClient.cpp:1352

Scope (from outer to inner):

file
function     EViewStatusForScreenPercentage UGameViewportClient::GetViewStatusForScreenPercentage

Source code excerpt:

		return EViewStatusForScreenPercentage::PathTracer;
	}
	else if (EngineShowFlags.StereoRendering)
	{
		return EViewStatusForScreenPercentage::VR;
	}
	else if (World && World->GetFeatureLevel() == ERHIFeatureLevel::ES3_1)
	{
		return EViewStatusForScreenPercentage::Mobile;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameViewportClient.cpp:1455

Scope (from outer to inner):

file
function     void UGameViewportClient::Draw

Source code excerpt:

		// Update stereo flag in viewport client so we can accurately run GetViewStatusForScreenPercentage()
		static bool bEmulateStereo = FParse::Param(FCommandLine::Get(), TEXT("emulatestereo"));
		EngineShowFlags.StereoRendering = bEmulateStereo ? true : ViewFamily.EngineShowFlags.StereoRendering;
	}

	ESplitScreenType::Type SplitScreenConfig = GetCurrentSplitscreenConfiguration();
	ViewFamily.ViewMode = EViewModeIndex(ViewModeIndex);
	EngineShowFlagOverride(ESFIM_Game, ViewFamily.ViewMode, ViewFamily.EngineShowFlags, false);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/LegacyScreenPercentageDriver.cpp:188

Scope (from outer to inner):

file
function     FStaticResolutionFractionHeuristic::FStaticResolutionFractionHeuristic

Source code excerpt:

FStaticResolutionFractionHeuristic::FStaticResolutionFractionHeuristic(const FEngineShowFlags& EngineShowFlags)
{
	Settings.bAllowDisplayBasedScreenPercentageMode = (EngineShowFlags.StereoRendering == 0) && (EngineShowFlags.VREditing == 0);
}

#if WITH_EDITOR
// static
bool FStaticResolutionFractionHeuristic::FUserSettings::EditorOverridePIESettings()
{

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/DynamicResolutionState.h:1

Scope: file

Source code excerpt:


/*=============================================================================
	StereoRendering.h: Abstract stereoscopic rendering interface
=============================================================================*/

#pragma once

#include "CoreMinimal.h"
#include "Engine/EngineTypes.h"
#include "DynamicRenderScaling.h"
#include "TemporalUpscaler.h"

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:312

Scope: file

Source code excerpt:

/** Distortion of output for HMD devices, SHOWFLAG_ALWAYS_ACCESSIBLE for now because USceneCaptureComponent needs that */
SHOWFLAG_ALWAYS_ACCESSIBLE(HMDDistortion, SFG_PostProcess, NSLOCTEXT("UnrealEd", "HMDDistortionSF", "HMD Distortion"))
/** Whether to render in stereoscopic 3d, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's used by StereoRendering */
SHOWFLAG_ALWAYS_ACCESSIBLE(StereoRendering, SFG_Hidden, NSLOCTEXT("UnrealEd", "StereoRenderingSF", "Stereoscopic Rendering"))
/** Show objects even if they should be distance culled, for now SHOWFLAG_ALWAYS_ACCESSIBLE because it's exposed in SceneCapture */
SHOWFLAG_ALWAYS_ACCESSIBLE(DistanceCulledPrimitives, SFG_Hidden, NSLOCTEXT("UnrealEd", "DistanceCulledPrimitivesSF", "Distance Culled Primitives"))
/** To visualize the culling in Tile Based Deferred Lighting, later for non tiled as well */
SHOWFLAG_FIXED_IN_SHIPPING(0, VisualizeLightCulling, SFG_Hidden, NSLOCTEXT("UnrealEd", "VisualizeLightCullingSF", "Light Culling"))
/** To disable precomputed visibility */
SHOWFLAG_FIXED_IN_SHIPPING(1, PrecomputedVisibility, SFG_Advanced, NSLOCTEXT("UnrealEd", "PrecomputedVisibilitySF", "Precomputed Visibility"))

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/StereoRendering.h:1

Scope: file

Source code excerpt:


/*=============================================================================
	StereoRendering.h: Abstract stereoscopic rendering interface
=============================================================================*/

#pragma once

#include "CoreMinimal.h"

class FSceneView;
class IStereoLayers;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/HairStrands/HairStrandsRendering.cpp:127

Scope (from outer to inner):

file
function     void RenderHairPrePass

Source code excerpt:

		if (IStereoRendering::IsStereoEyeView(View))
		{
			// nDisplay uses StereoRendering code path with a mono-view
			if (Views.Num() >= 2)
			{
				PreViewStereoCorrection = Views[0].ViewMatrices.GetPreViewTranslation() - Views[1].ViewMatrices.GetPreViewTranslation();
			}
			if (IStereoRendering::IsASecondaryView(View))
			{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:506

Scope (from outer to inner):

file
function     void FMobileSceneRenderer::InitViews

Source code excerpt:

	// For the most part this is not the case when using scene captures. Thus scene captures always render to scene color target.
	const bool bShouldCompositeEditorPrimitives = FSceneRenderer::ShouldCompositeEditorPrimitives(Views[0]);
	const bool bStereoRenderingAndHMD = ViewFamily.EngineShowFlags.StereoRendering && ViewFamily.EngineShowFlags.HMDDistortion;
	bRenderToSceneColor = !bGammaSpace 
						|| bStereoRenderingAndHMD 
						|| bRequiresUpscale 
						|| bShouldCompositeEditorPrimitives 
						|| Views[0].bIsSceneCapture 
						|| Views[0].bIsReflectionCapture 

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:496

Scope (from outer to inner):

file
function     void AddPostProcessingPasses

Source code excerpt:

	PassSequence.SetEnabled(EPass::PixelInspector, false);
#endif
	PassSequence.SetEnabled(EPass::HMDDistortion, EngineShowFlags.StereoRendering && EngineShowFlags.HMDDistortion);
	PassSequence.SetEnabled(EPass::HighResolutionScreenshotMask, IsHighResolutionScreenshotMaskEnabled(View));
#if UE_ENABLE_DEBUG_DRAWING
	PassSequence.SetEnabled(EPass::DebugPrimitive, FSceneRenderer::ShouldCompositeDebugPrimitivesInPostProcess(View));
#endif
	PassSequence.SetEnabled(EPass::PrimaryUpscale, PaniniConfig.IsEnabled() || (View.PrimaryScreenPercentageMethod == EPrimaryScreenPercentageMethod::SpatialUpscale && PrimaryViewRect.Size() != View.GetSecondaryViewRectSize()));
	PassSequence.SetEnabled(EPass::SecondaryUpscale, View.RequiresSecondaryUpscale() || View.Family->GetSecondarySpatialUpscalerInterface() != nullptr);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:2232

Scope (from outer to inner):

file
function     void AddMobilePostProcessingPasses

Source code excerpt:

	PassSequence.SetEnabled(EPass::Visualize, View.Family->EngineShowFlags.ShaderComplexity);

	PassSequence.SetEnabled(EPass::HMDDistortion, View.Family->EngineShowFlags.StereoRendering && View.Family->EngineShowFlags.HMDDistortion);

	// Always evaluate custom post processes
	// The scene color will be decoded at the first post-process material and output linear color space for the following passes
	// bMetalMSAAHDRDecode will be set to false if there is any post-process material exist

	auto AddPostProcessMaterialPass = [&GraphBuilder, &View, &Inputs, &SceneColor, &CustomDepth, &bMetalMSAAHDRDecode, &PassSequence](EBlendableLocation BlendableLocation, bool bLastPass)

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VariableRateShading/FoveatedImageGenerator.cpp:63

Scope: file

Source code excerpt:

{
	None = 0x0,
	StereoRendering = 0x1,
	SideBySideStereo = 0x2,
};

ENUM_CLASS_FLAGS(EVRSGenerationFlags);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VariableRateShading/FoveatedImageGenerator.cpp:113

Scope (from outer to inner):

file
class        class FComputeVariableRateShadingImageGeneration : public FGlobalShader
function     static void ModifyCompilationEnvironment

Source code excerpt:

		OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), kComputeGroupSize);

		OutEnvironment.SetDefine(TEXT("STEREO_RENDERING"), (uint32)EVRSGenerationFlags::StereoRendering);
		OutEnvironment.SetDefine(TEXT("SIDE_BY_SIDE_STEREO"), (uint32)EVRSGenerationFlags::SideBySideStereo);
	}
};

IMPLEMENT_GLOBAL_SHADER(FComputeVariableRateShadingImageGeneration, "/Engine/Private/VariableRateShading/VRSShadingRateFoveated.usf", "GenerateShadingRateTexture", SF_Compute);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/VariableRateShading/FoveatedImageGenerator.cpp:219

Scope (from outer to inner):

file
function     void FFoveatedImageGenerator::PrepareImages

Source code excerpt:

	if (IStereoRendering::IsStereoEyeView(*ViewFamily.Views[0]))
	{
		EnumAddFlags(GenFlags, EVRSGenerationFlags::StereoRendering);
		EnumAddFlags(GenFlags, EVRSGenerationFlags::SideBySideStereo); 

		// Adjust eyes for side-by-side stereo and/or quadview
		PassParameters->LeftEyeCenterPixelXY.X /= ViewFamily.Views.Num();;
		PassParameters->RightEyeCenterPixelXY.X = PassParameters->LeftEyeCenterPixelXY.X + Desc.Extent.X / ViewFamily.Views.Num();
	}