Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HDRP][Compositor] Fix edge cases when cameras are missing or deleted #2700

Merged
merged 8 commits into from
Nov 23, 2020
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixes some labels being clipped in the Render Graph Viewer
- Fixed issue when decal projector material is none.
- Fixed the sampling of the normal buffer in the the forward transparent pass.
- Fixed issues with camera management in the graphics compositor (cases 1292548, 1292549).

## [10.2.0] - 2020-10-19

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ public float aspectRatio
{
get
{
if (m_Camera != null)
var compositor = CompositionManager.GetInstance();
if (compositor != null && compositor.outputCamera != null)
{
return (float)m_Camera.pixelWidth / m_Camera.pixelHeight;
return (float)compositor.outputCamera.pixelWidth / compositor.outputCamera.pixelHeight;
}
return 1.0f;
}
Expand Down Expand Up @@ -158,6 +159,9 @@ public static CompositorLayer CreateStackLayer(LayerType type = CompositorLayer.

if (newLayer.m_Type == LayerType.Image || newLayer.m_Type == LayerType.Video)
{
if (newLayer.m_Camera == null)
newLayer.m_Camera = CompositionManager.CreateCamera(layerName);

// Image and movie layers do not render any 3D objects
newLayer.m_OverrideCullingMask = true;
newLayer.m_CullingMask = 0;
Expand Down Expand Up @@ -200,10 +204,11 @@ public int pixelWidth
{
get
{
if (m_Camera)
var compositor = CompositionManager.GetInstance();
if (compositor && compositor.outputCamera)
{
float resScale = EnumToScale(m_ResolutionScale);
return (int)(resScale * m_Camera.pixelWidth);
return (int)(resScale * compositor.outputCamera.pixelWidth);
}
return 0;
}
Expand All @@ -212,10 +217,11 @@ public int pixelHeight
{
get
{
if (m_Camera)
var compositor = CompositionManager.GetInstance();
if (compositor && compositor.outputCamera)
{
float resScale = EnumToScale(m_ResolutionScale);
return (int)(resScale * m_Camera.pixelHeight);
return (int)(resScale * compositor.outputCamera.pixelHeight);
}
return 0;
}
Expand All @@ -227,13 +233,6 @@ public void Init(string layerID = "")
m_LayerName = layerID;
}

// Compositor output layers (that allocate the render targets) also need a reference camera, just to get the reference pixel width/height
// Note: Movie & image layers are rendered at the output resolution (and not the movie/image resolution). This is required to have post-processing effects like film grain at full res.
if (m_Camera == null)
{
m_Camera = CompositionManager.GetSceneCamera();
}

var compositor = CompositionManager.GetInstance();

// Create a new camera if necessary or use the one specified by the user
Expand All @@ -244,7 +243,7 @@ public void Init(string layerID = "")
// - is not shared between layers
// - is not used in an mage/video layer (in this case the camera is not exposed at all, so it makes sense to let the compositor manage it)
// - it does not force-clear the RT (the first layer of a stack, even if disabled by the user), still clears the RT
bool shouldClear = !enabled && m_LayerPositionInStack == 0;
bool shouldClear = !enabled && m_LayerPositionInStack == 0 && m_Camera;
bool isImageOrVideo = (m_Type == LayerType.Image || m_Type == LayerType.Video);
if (!isImageOrVideo && !hasLayerOverrides && !shouldClear && !compositor.IsThisCameraShared(m_Camera))
{
Expand Down Expand Up @@ -527,14 +526,17 @@ internal void CopyInternalCameraData()

// Copy/update the camera data (but preserve the camera depth/draw-order [case 1264552])
var drawOrder = m_LayerCamera.depth;
m_LayerCamera.CopyFrom(m_Camera);
m_LayerCamera.depth = drawOrder;

var cameraDataOrig = m_Camera.GetComponent<HDAdditionalCameraData>();
var cameraData = m_LayerCamera.GetComponent<HDAdditionalCameraData>();
if (cameraDataOrig)
if (m_Camera)
{
cameraDataOrig.CopyTo(cameraData);
m_LayerCamera.CopyFrom(m_Camera);
m_LayerCamera.depth = drawOrder;

var cameraDataOrig = m_Camera.GetComponent<HDAdditionalCameraData>();
var cameraData = m_LayerCamera.GetComponent<HDAdditionalCameraData>();
if (cameraDataOrig)
{
cameraDataOrig.CopyTo(cameraData);
}
}
}

Expand Down Expand Up @@ -606,15 +608,18 @@ public bool ValidateRTSize(int referenceWidth, int referenceHeight)

public void SetupClearColor()
{
m_LayerCamera.enabled = true;
m_LayerCamera.cullingMask = 0;
var cameraData = m_LayerCamera.GetComponent<HDAdditionalCameraData>();
var cameraDataOrig = m_Camera.GetComponent<HDAdditionalCameraData>();
if (m_LayerCamera && m_Camera)
{
m_LayerCamera.enabled = true;
m_LayerCamera.cullingMask = 0;
var cameraData = m_LayerCamera.GetComponent<HDAdditionalCameraData>();
var cameraDataOrig = m_Camera.GetComponent<HDAdditionalCameraData>();

cameraData.clearColorMode = cameraDataOrig.clearColorMode;
cameraData.clearDepth = true;
cameraData.clearColorMode = cameraDataOrig.clearColorMode;
cameraData.clearDepth = true;

m_ClearsBackGround = true;
m_ClearsBackGround = true;
}
}

public void AddInputFilter(CompositionFilter filter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ public bool enableOutput
{
layer.camera.enabled = value;
}
else
{
// The target texture was managed by the compositor, reset it so the user can se the camera output
if (layer.camera && value == false)
layer.camera.targetTexture = null;
}
}
}
}
Expand Down Expand Up @@ -107,9 +113,9 @@ public float aspectRatio
{
get
{
if (m_InputLayers.Count > 0)
if (m_OutputCamera)
{
return m_InputLayers[0].aspectRatio;
return (float)m_OutputCamera.pixelWidth / m_OutputCamera.pixelHeight;
}
return 1.0f;
}
Expand Down Expand Up @@ -257,7 +263,6 @@ bool ValidateAndFixRuntime()
{
if (m_OutputCamera == null)
{
Debug.Log("No camera was found");
return false;
}

Expand Down Expand Up @@ -434,10 +439,13 @@ public void SetupLayerPriorities()
public void OnAfterAssemblyReload()
{
// Bug? : After assembly reload, the customRender callback is dropped, so set it again
var cameraData = m_OutputCamera.GetComponent<HDAdditionalCameraData>();
if (cameraData && !cameraData.hasCustomRender)
if (m_OutputCamera)
{
cameraData.customRender += CustomRender;
var cameraData = m_OutputCamera.GetComponent<HDAdditionalCameraData>();
if (cameraData && !cameraData.hasCustomRender)
{
cameraData.customRender += CustomRender;
}
}
}

Expand Down Expand Up @@ -837,10 +845,22 @@ static public Camera GetSceneCamera()
return camera;
}
}
Debug.LogWarning("Camera not found");

return null;
}

static public Camera CreateCamera(string cameraName)
{
var newCameraGameObject = new GameObject(cameraName)
{
hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy | HideFlags.HideAndDontSave
};
var newCamera = newCameraGameObject.AddComponent<Camera>();
newCameraGameObject.AddComponent<HDAdditionalCameraData>();

return newCamera;
}

static public CompositionManager GetInstance() =>
s_CompositorInstance ?? (s_CompositorInstance = GameObject.FindObjectOfType(typeof(CompositionManager), true) as CompositionManager);

Expand Down