I'm making a script that renders a scene frame by frame in Unity and overlays each frame on the previous one. It turns out motion blur. The frame is then saved. And the problem begins. Th problem is that after overlaying pictures, artifacts appear on the final image.
There are two frames in the picture below: on the left - a normal image consisting of one frame(1 iteration of motion blur), on the right - an image with an overlay of 10 previous frames (10 iterations of motion blur).
As if the color depth changes after overlays.
This is the code of the function that is responsible for overlaying frames:
//VFB is a video frame buffer. It is a type of Texture2D.
//It is clearing after storing each frame.
//MoBlur_Steps int, the number of motion blur iterations.
void Fill_VFB(Texture2D src)
{
UnityEngine.Color32[] src_pixels = src.GetPixels32();
UnityEngine.Color32[] dest_pixels = VFB.GetPixels32();
for (int i = 0; i < src_pixels.Length; i++)
{
dest_pixels[i].r = (byte)(dest_pixels[i].r + (float)src_pixels[i].r / MoBlur_Steps);
dest_pixels[i].g = (byte)(dest_pixels[i].g + (float)src_pixels[i].g / MoBlur_Steps);
dest_pixels[i].b = (byte)(dest_pixels[i].b + (float)src_pixels[i].b / MoBlur_Steps);
dest_pixels[i].a = (byte)(dest_pixels[i].a + (float)src_pixels[i].a / MoBlur_Steps);
}
VFB.SetPixels32(dest_pixels);
Render_Step++;
}
I tried to make this with type Color. Then I thought that it was a rounding error when dividing the color components and tried to do the same with type double for each component of color, but results was identical.
Need help :)
I think you should need to blend two pixels instead of add them. Another point to note is that converting a float to byte may overflow.
float f = 1f / MoBlur_Steps;
float t = dest_pixels[i].r * (1-f) + src_pixels[i].r * f;
dest_pixels[i].r = t >= 255f ? (byte)255 : (byte)t;
Blending alpha channel is a bit special, usually if the current pixel is opaque, you expect the pixel to keep opaque after blending, so your original method can work.
t = dest_pixels[i].a + src_pixels[i].a * f;
dest_pixels[i].a = t >= 255f ? (byte)255 : (byte)t;