Why has Bokeh been removed and Gaussian been made mobile only in 4.23?

Unless something has changed very recently, it *partially *works with temporal upsampling – the “slight out of focus” component doesn’t doesn’t work at all, but the downsampled portion does, so there’s a terrible-looking hard edge between the heavily-blurred area of the image and the rest that is fully sharp.

It’s possible to work around this to some extent using a post-process material to do the “slight out of focus” portion, using the DepthOfFieldFunction node (with value set to TDOF Circle of Confusion Radius) and some kind of blur function of your own (this custom node is a possible example):


//this is actually just the SpiralBlur node slightly adjusted to make a disc kernel

#include "/Engine/Private/SceneTexturesCommon.ush"

float3 CurColor;
float2 NewUV = BaseUV;
float StepSize = Distance / (int) DistanceSteps;
float CurDistance=0;
float2 CurOffset;
float TwoPi = 6.283185;
float Substep;
float2 ScenePixels=View.BufferSizeAndInvSize.xy*BaseUV;
ScenePixels+=View.TemporalAAParams.r;
float2 RandomSamp = ((uint)(ScenePixels.x) + 2 * (uint)(ScenePixels.y)) % 5;
RandomSamp+=Texture2DSample(Tex,TexSampler,ScenePixels);
RandomSamp/=5;
RandomSamp-=0.5;
TempAARotation*=RandomSamp;
TempAADistance*=StepSize*RandomSamp;


int i=0;
int TotalRadialSteps = 0;

if (DistanceSteps<1)
{
    return DecodeSceneColorForMaterialNode(NewUV);
}
else
{

    while ( i < (int) DistanceSteps)
    {
        //decrease the number of radial steps near center so that samples are distributed more uniformly
        int RadialStepsDistributed = ((float)RadialSteps)*(((float)i)/((float)DistanceSteps));

        for (int j = 0; j < (int) RadialStepsDistributed; j++)
        {
            CurOffset.x = cos(TwoPi*((TempAARotation+Substep) / RadialStepsDistributed));
            CurOffset.y = sin(TwoPi*((TempAARotation+Substep) / RadialStepsDistributed));
            CurOffset *=DistanceMask;
            NewUV.x = BaseUV.x + (CurOffset.x * (CurDistance+(RandomSamp*TempAADistance)));
            NewUV.y = BaseUV.y + (CurOffset.y * (CurDistance+(RandomSamp*TempAADistance)));
            CurColor += SceneTextureLookup(NewUV, 14, false);
            Substep++;
            TotalRadialSteps++;
        }
        CurDistance+=StepSize;
        Substep+=RadialOffset;
        i++;
    }
    CurColor = CurColor / ((int)TotalRadialSteps);
    return CurColor;
}

There are, of course, a few problems with doing it this way:

-Performing this blur in the “Before Tonemapping” location breaks the temporal reconstruction used for upsampling pretty badly, so you need to do your custom blur in “After Tonemapping” instead. You can perform your own gamma correction to compensate to some extent, but it still won’t be correct.

-You should avoid blurring the areas that are already handled by the diaphragm DOF so that they’re not double-blurred, but it’s impossible to determine exactly where the diaphragm DOF kicks in. Making your custom blur fade out or start to decrease in radius as the CoC reaches some threshold can at least hide the seam.

-It’s kind of slow, although the number of samples doesn’t need to be very high since we’re only blurring slightly.

-Directly using the DepthOfFieldFunction as the custom blur radius causes sharp edge artifacts, so you may want to perform a pre-blur on the CoC as well in the same material (which makes this even slower).

EDIT: I just noticed that I was setting the “BaseUV” to a value that’s not corrected for screen percentage, so you need to pass that in as a parameter as well.