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

Add camera property to ocean renderer #677

Merged
merged 5 commits into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions crest/Assets/Crest/Crest/Scripts/Helpers/Editor/EditorHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Crest Ocean System

// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)

#if UNITY_EDITOR

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace Crest
{
/// <summary>
/// Provides general helper functions for the editor.
/// </summary>
public static class EditorHelpers
{
static EditorWindow _lastGameOrSceneEditorWindow = null;

/// <summary>
/// Returns the scene view camera if the scene view is focused.
/// </summary>
public static Camera GetActiveSceneViewCamera()
{
Camera sceneCamera = null;

if (EditorWindow.focusedWindow != null && (EditorWindow.focusedWindow.titleContent.text == "Scene" ||
EditorWindow.focusedWindow.titleContent.text == "Game"))
{
_lastGameOrSceneEditorWindow = EditorWindow.focusedWindow;
}

// If scene view is focused, use its camera. This code is slightly ropey but seems to work ok enough.
if (_lastGameOrSceneEditorWindow != null && _lastGameOrSceneEditorWindow.titleContent.text == "Scene")
{
var sceneView = SceneView.lastActiveSceneView;
if (sceneView != null && !EditorApplication.isPlaying)
{
sceneCamera = sceneView.camera;
}
}

return sceneCamera;
}
}
}

#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class LodDataMgrShadow : LodDataMgr
public static bool s_processData = true;

Light _mainLight;
Camera _cameraMain;

// SRP version needs access to this externally, hence public get
public CommandBuffer BufCopyShadowMap { get; private set; }
Expand Down Expand Up @@ -90,9 +89,6 @@ public override void Start()
return;
}

// Setup the camera.
UpdateCameraMain();

#if UNITY_EDITOR
if (!OceanRenderer.Instance.OceanMaterial.IsKeywordEnabled("_SHADOWS_ON"))
{
Expand Down Expand Up @@ -188,12 +184,6 @@ public override void UpdateLodData()
return;
}

// Update the camera if it has changed.
if (_cameraMain.transform != OceanRenderer.Instance.Viewpoint)
{
UpdateCameraMain();
}

Swap(ref _sources, ref _targets);

BufCopyShadowMap.Clear();
Expand All @@ -210,6 +200,14 @@ public override void UpdateLodData()
TextureArrayHelpers.ClearToBlack(_targets);
}

// Cache the camera for further down.
var camera = OceanRenderer.Instance.ViewCamera;
if (camera == null)
{
// We want to return early after clear.
return;
}

{
// Run shadow update

Expand All @@ -218,14 +216,11 @@ public override void UpdateLodData()

_renderProperties.Initialise(BufCopyShadowMap, _updateShadowShader, krnl_UpdateShadow);

if (OceanRenderer.Instance.Viewpoint != null)
{
_renderProperties.SetVector(sp_CamPos, OceanRenderer.Instance.Viewpoint.position);
_renderProperties.SetVector(sp_CamForward, OceanRenderer.Instance.Viewpoint.forward);
}
_renderProperties.SetVector(sp_CamPos, camera.transform.position);
_renderProperties.SetVector(sp_CamForward, camera.transform.forward);

_renderProperties.SetVector(sp_JitterDiameters_CurrentFrameWeights, new Vector4(Settings._jitterDiameterSoft, Settings._jitterDiameterHard, Settings._currentFrameWeightSoft, Settings._currentFrameWeightHard));
_renderProperties.SetMatrix(sp_MainCameraProjectionMatrix, _cameraMain.projectionMatrix * _cameraMain.worldToCameraMatrix);
_renderProperties.SetMatrix(sp_MainCameraProjectionMatrix, camera.projectionMatrix * camera.worldToCameraMatrix);
_renderProperties.SetFloat(sp_SimDeltaTime, OceanRenderer.Instance.DeltaTimeDynamics);

_renderProperties.SetTexture(GetParamIdSampler(true), (Texture)_sources);
Expand Down Expand Up @@ -260,7 +255,7 @@ public override void UpdateLodData()
// Disable single pass double-wide stereo rendering for these commands since we are rendering to
// rendering texture. Otherwise, it will render double. Single pass instanced is broken here, but that
// appears to be a Unity bug only for the legacy VR system.
if (_cameraMain.stereoEnabled && XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePass)
if (camera.stereoEnabled && XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePass)
{
BufCopyShadowMap.SetSinglePassStereo(SinglePassStereoMode.None);
BufCopyShadowMap.DisableShaderKeyword("UNITY_SINGLE_PASS_STEREO");
Expand All @@ -274,7 +269,7 @@ public override void UpdateLodData()
}

// Restore single pass double-wide as we cannot rely on remaining pipeline to do it for us.
if (_cameraMain.stereoEnabled && XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePass)
if (camera.stereoEnabled && XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePass)
{
BufCopyShadowMap.SetSinglePassStereo(SinglePassStereoMode.SideBySide);
BufCopyShadowMap.EnableShaderKeyword("UNITY_SINGLE_PASS_STEREO");
Expand All @@ -285,19 +280,6 @@ public override void UpdateLodData()
Shader.SetGlobalTexture(GetParamIdSampler(), _targets);
}

void UpdateCameraMain()
{
var viewpoint = OceanRenderer.Instance.Viewpoint;
_cameraMain = viewpoint != null ? viewpoint.GetComponent<Camera>() : null;

if (_cameraMain == null)
{
Debug.LogError("Could not find main camera, disabling shadow data", _ocean);
enabled = false;
return;
}
}

public void ValidateSourceData()
{
#if UNITY_EDITOR
Expand Down
97 changes: 60 additions & 37 deletions crest/Assets/Crest/Crest/Scripts/OceanRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Crest
[ExecuteAlways, SelectionBase]
public partial class OceanRenderer : MonoBehaviour
{
[Tooltip("The viewpoint which drives the ocean detail. Defaults to main camera."), SerializeField]
[Tooltip("The viewpoint which drives the ocean detail. Defaults to the camera."), SerializeField]
Transform _viewpoint;
public Transform Viewpoint
{
Expand All @@ -33,20 +33,10 @@ public Transform Viewpoint
#if UNITY_EDITOR
if (_followSceneCamera)
{
if (EditorWindow.focusedWindow != null &&
(EditorWindow.focusedWindow.titleContent.text == "Scene" || EditorWindow.focusedWindow.titleContent.text == "Game"))
var sceneViewCamera = EditorHelpers.GetActiveSceneViewCamera();
if (sceneViewCamera != null)
{
_lastGameOrSceneEditorWindow = EditorWindow.focusedWindow;
}

// If scene view is focused, use its camera. This code is slightly ropey but seems to work ok enough.
if (_lastGameOrSceneEditorWindow != null && _lastGameOrSceneEditorWindow.titleContent.text == "Scene")
{
var sv = SceneView.lastActiveSceneView;
if (sv != null && !EditorApplication.isPlaying && sv.camera != null)
{
return sv.camera.transform;
}
return sceneViewCamera.transform;
}
}
#endif
Expand All @@ -55,9 +45,12 @@ public Transform Viewpoint
return _viewpoint;
}

if (Camera.main != null)
// Even with performance improvements, it is still good to cache whenever possible.
var camera = ViewCamera;

if (camera != null)
{
return Camera.main.transform;
return camera.transform;
}

return null;
Expand All @@ -68,12 +61,39 @@ public Transform Viewpoint
}
}

public Transform Root { get; private set; }

[Tooltip("The camera which drives the ocean data. Defaults to main camera."), SerializeField]
Camera _camera;
public Camera ViewCamera
{
get
{
#if UNITY_EDITOR
static EditorWindow _lastGameOrSceneEditorWindow = null;
if (_followSceneCamera)
{
var sceneViewCamera = EditorHelpers.GetActiveSceneViewCamera();
if (sceneViewCamera != null)
{
return sceneViewCamera;
}
}
#endif

if (_camera != null)
{
return _camera;
}

// Unity has greatly improved performance of this operation in 2019.4.9.
return Camera.main;
daleeidd marked this conversation as resolved.
Show resolved Hide resolved
}
set
{
_camera = value;
}
}

public Transform Root { get; private set; }

[Tooltip("Optional provider for time, can be used to hard-code time for automation, or provide server time. Defaults to local Unity time."), SerializeField]
TimeProviderBase _timeProvider = null;
TimeProviderDefault _timeProviderDefault = new TimeProviderDefault();
Expand Down Expand Up @@ -252,7 +272,7 @@ public enum DefaultClippingState
public int CurrentLodCount { get { return _lodTransform != null ? _lodTransform.LodCount : 0; } }

/// <summary>
/// Vertical offset of viewer vs water surface
/// Vertical offset of camera vs water surface.
/// </summary>
public float ViewerHeightAboveWater { get; private set; }

Expand Down Expand Up @@ -388,7 +408,7 @@ void OnEnable()

_commandbufferBuilder = new BuildCommandBuffer();

InitViewpoint();
ValidateViewpoint();

if (_attachDebugGUI && GetComponent<OceanDebugGUI>() == null)
{
Expand Down Expand Up @@ -634,19 +654,11 @@ bool VerifyRequirements()
return true;
}

void InitViewpoint()
void ValidateViewpoint()
{
if (Viewpoint == null)
{
var camMain = Camera.main;
if (camMain != null)
{
Viewpoint = camMain.transform;
}
else
{
Debug.LogError("Crest needs to know where to focus the ocean detail. Please set the Viewpoint property of the OceanRenderer component to the transform of the viewpoint/camera that the ocean should follow, or tag the primary camera as MainCamera.", this);
}
Debug.LogError("Crest needs to know where to focus the ocean detail. Please set the <i>ViewCamera</i> or the <i>Viewpoint</i> property that will render the ocean, or tag the primary camera as <i>MainCamera</i>.", this);
}
}

Expand Down Expand Up @@ -703,10 +715,7 @@ void RunUpdate()
var meshScaleLerp = needToBlendOutShape ? ViewerAltitudeLevelAlpha : 0f;
Shader.SetGlobalFloat(sp_meshScaleLerp, meshScaleLerp);

if (Viewpoint == null && Application.isPlaying)
{
Debug.LogError("Viewpoint is null, ocean update will fail.", this);
}
ValidateViewpoint();

if (_followViewpoint && Viewpoint != null)
{
Expand Down Expand Up @@ -832,11 +841,13 @@ void LateUpdateScale()

void LateUpdateViewerHeight()
{
_sampleHeightHelper.Init(Viewpoint.position, 0f, true);
var camera = ViewCamera;

_sampleHeightHelper.Init(camera.transform.position, 0f, true);

_sampleHeightHelper.Sample(out var waterHeight);

ViewerHeightAboveWater = Viewpoint.position.y - waterHeight;
ViewerHeightAboveWater = camera.transform.position.y - waterHeight;
}

void LateUpdateLods()
Expand Down Expand Up @@ -1102,6 +1113,18 @@ public bool Validate(OceanRenderer ocean, ValidatedHelper.ShowMessage showMessag
{
var isValid = true;

#if !UNITY_2019_4_9_OR_NEWER
if (_camera == null)
{
showMessage
(
"Not setting the camera property will result in using Camera.main which has a significant " +
"performance cost. This is improved in Unity 2019.4.9 and above.",
ValidatedHelper.MessageType.Warning, ocean
);
}
#endif

if (_material == null)
{
showMessage
Expand Down