The overhead for SceneCaptureComponent2D is killing my ability to make a inventory UI where each item is displayed as a rotating 3D object in a large grid (think Breath of the Wild or Morrowind style but with the items rotating), and I’m wondering if I’m just missing something in my searches for lowering the cost/overhead.
The question isn’t how to do what I want, but how to do it better/more efficiently. I am able to accomplish the desired behavior I’m after already:
Create a blueprint with the desired mesh and a SceneCaptureComponent2D
Rotate the mesh within the blueprint on the event tick (which I’ve reduced to only tick at 20 times per sec by reducing the Tick Interval of the BP),
Capture the scene on the same event tick and render to a texture target
That texture is then used as a material for a UMG image in a grid box
This all works well and is doing what I want it to do.
However, even with 10 items (and thus, 10 SceneCaptureComponent2D), the typical game fps (which hovers around 90-120 fps) plummets to <30 fps. Increasing the items causes the fps to drop even more.
I’ve done the following “optimizations” to the SceneCaptureComponent2D:
Only capturing the mesh actor I want
Limiting the max distance view
Turning off every optional/additional show flag except for Static Meshes (under “General Show Flags”), Deferred Lighting (under “Advanced Show Flags”), Sky Lighting (under “Light Types Show Flags”), and Lighting (under “Hidden Show Flags”)
Capturing the scene 20 times per sec instead of at the game tick rate (I’ve tried even lower, but then the rotating effect looks really bad in the UI)
Is there something I’m missing? Are SceneCaptureComponents just that expensive? Is there a way to further optimize them so I could have 20+ without single digit fps? Alternatively, is there a way to achieve the UI effect/behavior I’m after without using SceneCaptureComponents?
Thanks in advance. I appreciate any and all feedback!
Yes, setting up and managing each render target is a lot of work for the system.
I would suggest putting the inventory objects into a real scene in front a real camera and rendering that as your inventory instead.
If that doesn’t work, make one screen-sized 2D capture, and array all the inventory items into that one scene capture, and put that into your UI, to reduce the per-scene-capture overhead down to 1.
Thanks for the reply! I expected that was unfortunately the answer, just glad to hear confirmation.
Funny enough, your 2nd suggestion is exactly what I started trying before I saw your reply; great idea! I’m using an orthographic camera in this case though to eliminate any weird parallax/distortion issues with objects on the edge. Any ideas how to accomplish it without an ortho camera? Perspective cam with a really small FOV?
As for the first suggestion (i.e. rending everything in a real scene in front of a real camera), similar question, any thought as to how to get around the parallax/distortion issue? Am I overthinking it?
I believe you can fake the perspective effect with a smart shader trick and still be using orthographic camera.
Below would be my approach just for reference, sorry for the rambling style.
I think just scaling local position of each vertex based on how close it to the camera plane should do the trick. But not affecting position’s “away from camera” component (Most likely Y if calculating in mesh local space). You’re model’s origin is the perceived camera look-at position for perspective effect. If it’s not in the middle, you’ll need to add an offset for origin point for scaling operation.
If you need them to rotate, it will somewhat complicate the method above. You may want to calculate in world space. or do everything in the shader including rotation of vertex positions (and normals!) etc.
There could be something I forgot and it’s not exactly like this, but in general it looks workable for me right now. I may give it a try someday, but probably not too soon.
I simplified shader by a bit. For instance instead of distance to the camera we can just use the positional data on an axis (here it’s on Z). I dropped fixing Z component after scaling, because it wasn’t too noticeable if you’re not scaling close to camera (so it may clip), but if you need to, MakeFloat3 can be connected to Substract in “A” input.
You may be overthinking it, but a narrow FOV and longer distance to the objects would work.
It kinda depends on what look you really want and really care about.
I’ve used ortho cameras in real scenes before, though; it’s handy for top-down minimaps and such.