taking a screenshot and placing it on a quad

I am trying to take a screenshot and then place it on a quad. I have it working - sort of. Here’s what I have so far:

var quad = EntityManager.Instantiate(SystemAPI.GetSingleton<Config>().QuadPrefab);
var hybridRenderer = World.GetExistingSystemManaged<EntitiesGraphicsSystem>();
var screenShotMaterial = new Material(Shader.Find("HDRP/Unlit"));
//_squareImage simply makes the 16:9 screenshot square
var squareTexture = _squareImage(UnityEngine.ScreenCapture.CaptureScreenshotAsTexture());
squareTexture.Apply();
screenShotMaterial.mainTexture = squareTexture;
var materialID = hybridRenderer.RegisterMaterial(screenShotMaterial);
var mmi = EntityManager.GetComponentData<MaterialMeshInfo>(quad);
mmi.MaterialID = materialID;
var quadRma = EntityManager.GetSharedComponentManaged<RenderMeshArray>(quad);
var rmaMatList = quadRma.Materials.ToList();
rmaMatList.Add(screenShotMaterial);
var rma = new RenderMeshArray(rmaMatList.ToArray(), quadRma.Meshes);
var rmd = new RenderMeshDescription(UnityEngine.Rendering.ShadowCastingMode.Off, false);
RenderMeshUtility.AddComponents(quad, EntityManager, rmd, rma, mmi);

So this doesn’t work unless I add this line

UnityEngine.ScreenCapture.CaptureScreenshot("screen.png");

And even then, I have to run it twice as the first time through it doesn’t work.

So two problems:

why doesn’t ScreenCapture.CaptureScreenshotAsTexture() work without saving a copy to the disk?

Why do I get no result the first time I hit run but then it works the second? (I think this is due to the texture being on the CPU but not the GPU but I thought the Apply() method would copy it over.)

Not sure if this is the crux of the issue, but from the docs:

That was probably my issue with it as I can’t do that while in an ECS system.

I have come up with a solution that works though.

I’m no longer using the ScreenCapture function, I set up a second camera and a rendertexture, I’m then copying the texture from the rendertexture into a new material. I got the idea from this post:

So I set up everything according to the what mingwai did in that post and then I used this code to make the copy and place it on the texture

var quad = EntityManager.Instantiate(SystemAPI.GetSingleton<Config>().QuadPrefab);
var hybridRenderer = World.GetExistingSystemManaged<EntitiesGraphicsSystem>();
var mat = new Material(Shader.Find("HDRP/Unlit"));
var texture = new Texture2D(2048, 2048, TextureFormat.RGBA32, 1, false, false);
Graphics.CopyTexture(_material.mainTexture, texture);
mat.mainTexture = texture;
mat.name = "mat";// some unique name
var materialID = hybridRenderer.RegisterMaterial(mat);
var mmi = EntityManager.GetComponentData<MaterialMeshInfo>(quad);
mmi.MaterialID = materialID;
var quadRma = EntityManager.GetSharedComponentManaged<RenderMeshArray>(rawDataEntity); // this is one of my singleton entities that I put a quad on so I could get the RMA from it
var rmaMatList = quadRma.Materials.ToList();
maMatList.Add(mat);
var rma = new RenderMeshArray(rmaMatList.ToArray(), quadRma.Meshes);
var rmd = new RenderMeshDescription(UnityEngine.Rendering.ShadowCastingMode.Off, false);
RenderMeshUtility.AddComponents(quad, EntityManager, rmd, rma, mmi);
enderMeshUtility.AddComponents(rawDataEntity, EntityManager, rmd, rma, mmi);

the _material property is straight from what Mingwai did:

private Material _material;

protected override void OnStartRunning()
{
       Entities
           .WithoutBurst()
           .WithAll<AssignAssetToMaterialTag>()
           .ForEach((in MaterialMeshInfo mmi, in RenderMeshArray rma) =>
           {
               _material = rma.GetMaterial(mmi);
              _material.mainTexture = AssetRefForSubscene.static_renderTex;
           }).Run();
  }

finally works like I want it too