I’m planning to share a custom planar reflections plugin which will give you full render target access but I need this clip plane support pr to be accepted in order for it to work properly.
Is there any this gets accepted for 4.13? pretty please? with sugar on top? (@ ? :p)
I got some real issues of performance with planar reflections. Is it possible to make the entire Folliage not to affect the planar reflections? Something like actor hidden in game but only for planar reflection?
Is there any way to adjust the roughness of the reflection? It looks awesome but for me the problem is that it is making the wood floor look too polished/wet.
I figured out that I can manually disable most of the expensive settings from planar reflections. This cut reflection pass cost about 60% for me. If you find others stuff that can be safely disabled let me know.
Edit: I noticed that these settings are visible from editor if you use planar reflection actor but hidden if you use planar reflection component.
I recently made big optimization for planar reflections that does not have infinite size. In our use case there are multiple reflection actors per level but those are quite small in size.(example swim pool or mirror). So I made system that construct frustum pyramid using 4 corner points of reflection actor and reflection camera position. From these 5 points I make 4 frustum planes and I make additional frustum culling check for all static objects. This is huge win for cases where planar reflection actor is not infinite. especially for mobile where occlusion culling is not helping at all. I also check object screenspace distance and cull objects that are too small. These usually cull about 70-80% of objects.
struct FStaticObjectActor
{
FVector pos;
float radius;
AActor* actor;
};
void DynamicPlanarReflectionCulling(const TArray<FStaticObjectActor> objects, UPlanarReflectionComponent* p, FVector reflectionCamPos)
{
p->HiddenActors.Reset();
// Planar reflection is rectangle at z plane. Construct portal from reflection camera and 4 corner points.
FVector min = p->Bounds.GetBox().Min;
FVector max = p->Bounds.GetBox().Max;
FVector corners[4] = { FVector(min.X, min.Y, max.Z), FVector(min.X, max.Y, max.Z), FVector(max.X, max.Y, max.Z), FVector(max.X, min.Y, max.Z) };
FPlane planes[4] = { FPlane(corners[0], corners[1], reflectionCamPos), FPlane(corners[1], corners[2], reflectionCamPos), FPlane(corners[2], corners[3], reflectionCamPos), FPlane(corners[3], corners[0], reflectionCamPos)};
for (const FStaticObjectActor& obj : objects)
{
// Hide objects that are outside of fitted frustum.
if ((planes[0].PlaneDot(obj.pos) > obj.radius) || (planes[1].PlaneDot(obj.pos) > obj.radius) || (planes[2].PlaneDot(obj.pos) > obj.radius) || (planes[3].PlaneDot(obj.pos) > obj.radius))
{
p->HiddenActors.Add(obj.actor);
}
else
{
// Hide objects that are too small from reflection camera perspective.
float d2 = FVector::DistSquared(reflectionCamPos, obj.pos);
//if (obj.radius / sqrt(d2) < 0.05)) // unoptimized
if (400.f * obj.radius * obj.radius < d2)
{
p->HiddenActors.Add(obj.actor);
}
}
}
}
This is quite simple and fast method for making planar reflections usable for us. It would be nice to see this kind of system to be integrated to actual engine code because this is bit duplicate checking and could be do much more efficient and general way withing engine. I also noticed that engine does not cull objects behind planar reflection. This also should be done always. Maybe frustum near plane could be swapped to culling plane without any additional cost with bit more efficient culling.
There is a performance hit even with no objects in the scene but culling should definitely help at least a little bit in heavy scenes.
But keep in mind that iterating over all the objects in the scene in order to cull them out could sometimes be bad for performance (if you are cpu-bound I guess).
Isn’t the clip plane supposed to take care of that?
Iterating all static objects in compact array is super fast. Around 1000 objects in our scene cost less than 0.1ms. Renderer always do normal frustum culling, so if engine would use this optimization then it wouldn’t cost anything extra.
Clip plane will cull objects but this culling happen after vertex shader. So all objects that are rendered that are behind clip plane will still cost extra draw calls and vertex shader performance. This could be fixed by easily by replacing frustum near plane with clipping plane.
Planar reflections could use some additional occlusion culling from main camera perspective. So after opaque pass render occlusion queries of bounding boxes projected to planar reflection plane using main camera depth buffer. So this would test if object reflection is even possible to see. These queries would be ready for next frame.