In my game I have the following:
- Material Parameter Collection (MPC) containing a scalar value “IrisSize”
- Material Function (MF_Gobos) which utilizes “IrisSize” as an input, used for various calculations.
- Material asset (M_LightCrossSection) which utilizes MF_Gobos to determine its emissive output.
- A C++ function responsible for copying the contents of the dynamic material instance of M_LightCrossSection into a UTextureRenderTarget2D.
Observed Behavior: When updating IrisSize’s default value in-editor, I do see the UTextureRenderTarget2D update as expected. However, during gameplay, when I update “IrisSize” via sequencer or C++, I do not see any changes to the Render Target take place. Regardless of approach, the rendering portion always seems to utilize IrisSize’s default value, ignoring subsequent changes. My main questions are:
-
Should I even be using MPCs in this context or is there a preferred approach?
-
If so, I believe the issue may be with the rendering call itself. I am wondering if the CanvasPass detailed below is somehow unaware of the updates to Iris Size, or if the Scene View options may be interfering. I have pasted a snippet below. Any insights appreciated. Thanks!
void AStageLight::QueueRender()
{
UMaterialInstanceDynamic* SafeMID = MID_LightCrossSection;
UTextureRenderTarget2D* SafeRenderTarget = RT_CrossSectionTexture;
UWorld* SafeWorld = GetWorld();
//Note: Calling GetWorld(), getting MPC object, and GetScalarParameterValues("IrisSize") here does print the correct value.
ENQUEUE_RENDER_COMMAND(RenderRDGToTarget)(
[SafeMID, SafeRenderTarget, SafeWorld, MyGameTime](FRHICommandListImmediate& RHICmdList)
{
FRDGBuilder GraphBuilder(RHICmdList);
FRHITexture* RHITexture = SafeRenderTarget->GetRenderTargetResource()->GetRenderTargetTexture();
FRDGTextureRef OutputRDG = GraphBuilder.RegisterExternalTexture(
CreateRenderTarget(RHITexture, TEXT("RT_CrossSectionTextureOutput"))
);
FScreenPassRenderTarget Output(OutputRDG, ERenderTargetLoadAction::EClear);
FSceneViewFamilyContext ViewFamily(
FSceneViewFamily::ConstructionValues(nullptr, SafeWorld->Scene,
FEngineShowFlags(ESFIM_Game)).SetTime(FGameTime::GetTimeSinceAppStart())); //FGameTime::GetTimeSinceAppStart();
FSceneViewInitOptions ViewInitOptions;
ViewInitOptions.ViewFamily = &ViewFamily;
ViewInitOptions.ViewOrigin = FVector::ZeroVector;
ViewInitOptions.ViewRotationMatrix = FMatrix::Identity;
ViewInitOptions.ProjectionMatrix = FMatrix::Identity;
//ViewInitOptions.SceneViewStateInterface = nullptr;
ViewInitOptions.SetViewRectangle(FIntRect(0, 0, SafeRenderTarget->SizeX, SafeRenderTarget->SizeY)); // Need this SetView call in 5.3
FSceneView* SceneView = new FSceneView(ViewInitOptions);
ViewFamily.Views.Add(SceneView);
// is this a different world?? without collection param?
AddDrawCanvasPass(
GraphBuilder,
RDG_EVENT_NAME("DrawMID_LightCrossSection"),
*SceneView,
Output,
[SafeMID, SafeRenderTarget](FCanvas& Canvas)
{
FCanvasTileItem Tile(FVector2D(0, 0), SafeMID->GetRenderProxy(), FVector2D(SafeRenderTarget->SizeX, SafeRenderTarget->SizeY));
Tile.BlendMode = SE_BLEND_Opaque;
Canvas.DrawItem(Tile);
}
);
GraphBuilder.Execute();
}
);
}