// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX.FrameInterpolation
{
///
/// Scriptable object containing all shader resources required by FidelityFX Frame Interpolation.
/// These can be stored in an asset file and referenced from a scene or prefab, avoiding the need to load the shaders from a Resources folder.
///
[CreateAssetMenu(fileName = "Frame Interpolation Assets", menuName = "FidelityFX/Frame Interpolation Assets", order = 1112)]
public class FrameInterpolationAssets : ScriptableObject
{
public FrameInterpolationShaders shaders;
#if UNITY_EDITOR
private void Reset()
{
shaders = new FrameInterpolationShaders
{
reconstructAndDilate = FindComputeShader("ffx_frameinterpolation_reconstruct_and_dilate_pass"),
setup = FindComputeShader("ffx_frameinterpolation_setup_pass"),
reconstructPreviousDepth = FindComputeShader("ffx_frameinterpolation_reconstruct_previous_depth_pass"),
gameMotionVectorField = FindComputeShader("ffx_frameinterpolation_game_motion_vector_field_pass"),
opticalFlowVectorField = FindComputeShader("ffx_frameinterpolation_optical_flow_vector_field_pass"),
disocclusionMask = FindComputeShader("ffx_frameinterpolation_disocclusion_mask_pass"),
interpolation = FindComputeShader("ffx_frameinterpolation_pass"),
inpaintingPyramid = FindComputeShader("ffx_frameinterpolation_compute_inpainting_pyramid_pass"),
inpainting = FindComputeShader("ffx_frameinterpolation_inpainting_pass"),
gameVectorFieldInpaintingPyramid = FindComputeShader("ffx_frameinterpolation_compute_game_vector_field_inpainting_pyramid_pass"),
debugView = FindComputeShader("ffx_frameinterpolation_debug_view_pass"),
};
}
private static ComputeShader FindComputeShader(string name)
{
string[] assetGuids = UnityEditor.AssetDatabase.FindAssets($"t:ComputeShader {name}");
if (assetGuids == null || assetGuids.Length == 0)
return null;
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assetGuids[0]);
return UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath);
}
#endif
}
///
/// All the compute shaders used by Frame Interpolation.
///
[System.Serializable]
public class FrameInterpolationShaders
{
///
/// The compute shader used by the reconstruct and dilate pass.
///
public ComputeShader reconstructAndDilate;
///
/// The compute shader used by the setup pass.
///
public ComputeShader setup;
///
/// The compute shader used by the reconstruct previous depth pass.
///
public ComputeShader reconstructPreviousDepth;
///
/// The compute shader used by the game motion vector field pass.
///
public ComputeShader gameMotionVectorField;
///
/// The compute shader used by the optical flow vector field pass.
///
public ComputeShader opticalFlowVectorField;
///
/// The compute shader used by the disocclusion mask pass.
///
public ComputeShader disocclusionMask;
///
/// The compute shader used by the interpolation pass.
///
public ComputeShader interpolation;
///
/// The compute shader used by the inpainting pyramid pass.
///
public ComputeShader inpaintingPyramid;
///
/// The compute shader used by the inpainting pass.
///
public ComputeShader inpainting;
///
/// The compute shader used by the game vector field inpainting pyramid pass.
///
public ComputeShader gameVectorFieldInpaintingPyramid;
///
/// The compute shader used by the debug view pass.
///
public ComputeShader debugView;
///
/// Returns a copy of this class and its contents.
///
public FrameInterpolationShaders Clone()
{
return (FrameInterpolationShaders)MemberwiseClone();
}
///
/// Returns a copy of this class with clones of all its shaders.
/// This can be useful if you're running multiple Frame Interpolation instances with different shader configurations.
/// Be sure to clean up these clones through Dispose once you're done with them.
///
public FrameInterpolationShaders DeepCopy()
{
return new FrameInterpolationShaders
{
reconstructAndDilate = Object.Instantiate(reconstructAndDilate),
setup = Object.Instantiate(setup),
reconstructPreviousDepth = Object.Instantiate(reconstructPreviousDepth),
gameMotionVectorField = Object.Instantiate(gameMotionVectorField),
opticalFlowVectorField = Object.Instantiate(opticalFlowVectorField),
disocclusionMask = Object.Instantiate(disocclusionMask),
interpolation = Object.Instantiate(interpolation),
inpaintingPyramid = Object.Instantiate(inpaintingPyramid),
inpainting = Object.Instantiate(inpainting),
gameVectorFieldInpaintingPyramid = Object.Instantiate(gameVectorFieldInpaintingPyramid),
debugView = Object.Instantiate(debugView),
};
}
///
/// Destroy all the shaders within this instance.
/// Use this only on clones created through DeepCopy.
///
public void Dispose()
{
Object.Destroy(debugView);
Object.Destroy(gameVectorFieldInpaintingPyramid);
Object.Destroy(inpainting);
Object.Destroy(inpaintingPyramid);
Object.Destroy(interpolation);
Object.Destroy(disocclusionMask);
Object.Destroy(opticalFlowVectorField);
Object.Destroy(gameMotionVectorField);
Object.Destroy(reconstructPreviousDepth);
Object.Destroy(setup);
Object.Destroy(reconstructAndDilate);
}
}
}