Vis
Vis
#Overview
name: Vis
This variable is created as a Console Variable (cvar).
- type:
Cmd
- help:
short version of visualizetexture
It is referenced in 9
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of Vis is to represent the visibility term in microfacet-based specular reflection calculations, specifically within the context of physically-based rendering (PBR) in Unreal Engine 5.
Vis is primarily used in the rendering system, particularly in shading and material calculations. Based on the callsites, it appears to be utilized in various subsystems and plugins, including:
- The AxFImporter plugin for enterprise-level material import
- The FractureEditor plugin for visualizing proximity in fractured geometry
- The core rendering pipeline, especially in specular reflection calculations
The value of Vis is typically calculated within shading functions rather than being set as a global variable. It’s often computed using different visibility functions, such as Smith-GGX or Smith-Joint approximations, depending on the specific use case and material model.
Vis interacts with other variables in the specular reflection equation, such as:
- NoV (Normal dot View)
- NoL (Normal dot Light)
- NoH (Normal dot Half-vector)
- VoH (View dot Half-vector)
- Roughness (often represented as ‘a’ or ‘a2’)
Developers should be aware that:
- Vis is a critical component in achieving physically accurate specular reflections.
- Different material models may use different visibility functions to calculate Vis.
- The accuracy of Vis calculation can significantly impact the visual quality of specular highlights.
Best practices when using Vis include:
- Ensure that the chosen visibility function is appropriate for the material model being used.
- Optimize the Vis calculation for performance while maintaining visual quality.
- Be consistent in the use of Vis across different shaders and materials to maintain a cohesive look.
- When implementing custom shading models, validate the Vis calculation against reference implementations or real-world measurements.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Enterprise/AxFImporter/Source/AxFImporter/Private/AxFImporter.cpp:774
Scope (from outer to inner):
file
class class FAxFFileImporter : public IAxFFileImporter
class class FUeGgxBRDF
function FVector SpecularGGX
Source code excerpt:
// Generalized microfacet specular
float D = D_GGX(a2, NoH) * Energy;
float Vis = Vis_SmithJointApprox(a2, NoV, NoL);
FVector F = F_Schlick(SpecularColor, VoH);
return (D * Vis) * F;
}
};
class FCarPaint2BRDF
{
#Loc: <Workspace>/Engine/Plugins/Experimental/ChaosEditor/Source/FractureEditor/Private/FractureToolProximity.cpp:114
Scope (from outer to inner):
file
function void UFractureToolProximity::UpdateVisualizations
Source code excerpt:
// Save the geometry collection component for rendering
int32 CollectionIdx = VisualizedCollections.Add(FractureContext.GetGeometryCollectionComponent());
FCollectionVisInfo& Vis = ProximityVisualizations.Emplace_GetRef();
Vis.CollectionIndex = CollectionIdx;
// Get proximity graph node positions as bounding box centers for each piece of geometry
Vis.GeoCenters.SetNum(Collection.NumElements(FGeometryCollection::GeometryGroup));
TArray<FTransform> GlobalTransformArray;
GeometryCollectionAlgo::GlobalMatrices(Collection.Transform, Collection.Parent, GlobalTransformArray);
for (int32 GeoIdx = 0; GeoIdx < Collection.NumElements(FGeometryCollection::GeometryGroup); ++GeoIdx)
{
int32 TransformIdx = Collection.TransformIndex[GeoIdx];
FVector BoxCenter = GlobalTransformArray[TransformIdx].TransformPosition(Collection.BoundingBox[GeoIdx].GetCenter());
Vis.GeoCenters[GeoIdx] = BoxCenter;
}
// Collect relevant proximity graph edges to render
auto AddEdgesForGeoIdx = [&Proximity, &Vis](int32 GeoIdx, bool bAddAll)
{
for (int32 GeoNbr : Proximity[GeoIdx])
{
if (bAddAll || GeoIdx < GeoNbr)
{
Vis.ProximityEdges.Add(FEdgeVisInfo{ GeoIdx, GeoNbr });
}
}
};
if (ProximitySettings->bOnlyShowForSelected)
{
TArray<int32> SelectedRigids;
#Loc: <Workspace>/Engine/Plugins/Experimental/ChaosEditor/Source/FractureEditor/Private/FractureToolProximity.cpp:170
Scope (from outer to inner):
file
function void UFractureToolProximity::Render
Source code excerpt:
if (ProximitySettings->bShowProximity)
{
for (const FCollectionVisInfo& Vis : ProximityVisualizations)
{
const FGeometryCollection& Collection = *VisualizedCollections[Vis.CollectionIndex]->GetRestCollection()->GetGeometryCollection();
const TManagedArray<FVector3f>* ExplodedVectors = Collection.FindAttributeTyped<FVector3f>("ExplodedVector", FGeometryCollection::TransformGroup);
auto GetExplodedOffset = [&ExplodedVectors, &Collection](int32 GeoIdx)
{
return ExplodedVectors ?
(FVector)(*ExplodedVectors)[Collection.TransformIndex[GeoIdx]] :
FVector::ZeroVector;
};
const FTransform WorldTransform = VisualizedCollections[Vis.CollectionIndex]->GetComponentTransform();
for (const FEdgeVisInfo& Edge : Vis.ProximityEdges)
{
FVector P1 = WorldTransform.TransformPosition(Vis.GeoCenters[Edge.A] + GetExplodedOffset(Edge.A));
FVector P2 = WorldTransform.TransformPosition(Vis.GeoCenters[Edge.B] + GetExplodedOffset(Edge.B));
PDI->DrawLine(P1, P2, ProximitySettings->LineColor, SDPG_Foreground, ProximitySettings->LineThickness, 0.001f);
}
for (int32 CenterIndex = 0; CenterIndex < Vis.GeoCenters.Num(); CenterIndex++)
{
// Draw centers for geometry (clusters can have geometry but it is not visible and won't be connected in the proximity graph)
if (Collection.SimulationType[Collection.TransformIndex[CenterIndex]] == FGeometryCollection::ESimulationTypes::FST_Rigid)
{
FVector P = WorldTransform.TransformPosition(Vis.GeoCenters[CenterIndex] + GetExplodedOffset(CenterIndex));
PDI->DrawPoint(P, ProximitySettings->CenterColor, ProximitySettings->CenterSize, SDPG_Foreground);
}
}
}
}
}
#Loc: <Workspace>/Engine/Plugins/Runtime/CommonUI/Source/CommonUI/Private/CommonButtonBase.cpp:723
Scope (from outer to inner):
file
function bool UCommonButtonBase::IsInteractionEnabled
Source code excerpt:
bool UCommonButtonBase::IsInteractionEnabled() const
{
ESlateVisibility Vis = GetVisibility(); // hidden or collapsed should have 'bInteractionEnabled' set false, but sometimes they don't :(
return GetIsEnabled() && bButtonEnabled && bInteractionEnabled && (Vis != ESlateVisibility::Collapsed) && (Vis != ESlateVisibility::Hidden);
}
bool UCommonButtonBase::IsHovered() const
{
return RootButton.IsValid() && RootButton->IsHovered();
}
#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/Widgets/SEventGraph.cpp:3353
Scope (from outer to inner):
file
function EVisibility SEventGraph::EventGraphViewMode_GetVisibility
Source code excerpt:
if( ViewMode == EEventGraphViewModes::FlatInclusiveCoalesced || ViewMode == EEventGraphViewModes::FlatExclusiveCoalesced )
{
const EVisibility Vis = FProfilerManager::GetSettings().bShowCoalescedViewModesInEventGraph ? EVisibility::Visible : EVisibility::Collapsed;
if (Vis == EVisibility::Collapsed && GetCurrentStateViewMode() == ViewMode)
{
// If view mode is not available event graph will switch to the hierarchical view mode.
SEventGraph* MutableThis = const_cast< SEventGraph* >( this );
MutableThis->EventGraphViewMode_OnCheckStateChanged( ECheckBoxState::Checked, EEventGraphViewModes::Hierarchical );
}
return Vis;
}
else
{
return EVisibility::Visible;
}
}
#Loc: <Workspace>/Engine/Source/Editor/AnimationEditorWidgets/Private/SchematicGraphPanel/SSchematicGraphPanel.cpp:461
Scope (from outer to inner):
file
function EVisibility SSchematicGraphNode::GetNodeVisibility
Source code excerpt:
if(SchematicGraphPanel && SchematicGraphPanel->GetSchematicGraph())
{
ESchematicGraphVisibility::Type Vis = SchematicGraphPanel->GetSchematicGraph()->GetVisibilityForNode(GetGuid());
if(Vis == ESchematicGraphVisibility::Hidden)
{
return EVisibility::Hidden;
}
}
return EVisibility::Visible;
#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/HAL/ConsoleManager.cpp:3353
Scope (from outer to inner):
file
function void CreateConsoleVariables
Source code excerpt:
// the following commands are common exec commands that should be added to auto completion (todo: read UnConsole list in ini, discover all exec commands)
IConsoleManager::Get().RegisterConsoleCommand(TEXT("VisualizeTexture"), TEXT("To visualize internal textures"), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("Vis"), TEXT("short version of visualizetexture"), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("VisRT"), TEXT("GUI for visualizetexture"), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("HighResShot"), TEXT("High resolution screenshots ResolutionX(int32)xResolutionY(int32) Or Magnification(float) [CaptureRegionX(int32) CaptureRegionY(int32) CaptureRegionWidth(int32) CaptureRegionHeight(int32) MaskEnabled(int32) DumpBufferVisualizationTargets(int32) CaptureHDR(int32)]\nExample: HighResShot 500x500 50 50 120 500 1 1 1"), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("DumpUnbuiltLightInteractions"), TEXT("Logs all lights and primitives that have an unbuilt interaction."), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("Stat MapBuildData"), TEXT(""), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("r.ResetViewState"), TEXT("Reset some state (e.g. TemporalAA index) to make rendering more deterministic (for automated screenshot verification)"), ECVF_Cheat);
IConsoleManager::Get().RegisterConsoleCommand(TEXT("r.RHI.Name"), TEXT("Show current RHI's name"), ECVF_Cheat);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Renderer.cpp:620
Scope (from outer to inner):
file
function static bool RendererExec
Source code excerpt:
{
#if SUPPORTS_VISUALIZE_TEXTURE
if (FParse::Command(&Cmd, TEXT("VisualizeTexture")) || FParse::Command(&Cmd, TEXT("Vis")))
{
VisualizeTextureExec(Cmd, Ar);
return true;
}
#endif //SUPPORTS_VISUALIZE_TEXTURE
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SystemTextures.cpp:489
Scope (from outer to inner):
file
function void FSystemTextures::InitializeFeatureLevelDependentTextures
Source code excerpt:
float Vis_SmithV = NoL * (NoV * (1 - m) + m);
float Vis_SmithL = NoV * (NoL * (1 - m) + m);
float Vis = 0.5f / (Vis_SmithV + Vis_SmithL);
float NoL_Vis_PDF = NoL * Vis * (4.0f * VoH / NoH);
float Fc = 1.0f - VoH;
Fc *= FMath::Square(Fc*Fc);
A += NoL_Vis_PDF * (1.0f - Fc);
B += NoL_Vis_PDF * Fc;
}
}