diff --git a/Assets/ResRaw/AnimEditor/player_umotion_project.asset b/Assets/ResRaw/AnimEditor/player_umotion_project.asset index 31cc4048b..f58abc9fb 100644 --- a/Assets/ResRaw/AnimEditor/player_umotion_project.asset +++ b/Assets/ResRaw/AnimEditor/player_umotion_project.asset @@ -14,7 +14,7 @@ MonoBehaviour: m_EditorClassIdentifier: UMotionEditor.dll::UMotionEditor.Model.FileFormats.Project.V01_02.UMotionProjectFileV01_02 EditorState: EditMode: - valueInternal: 1 + valueInternal: 0 MainTabIndex: valueInternal: 0 PoseToolPivotMode: @@ -28,7 +28,7 @@ MonoBehaviour: ConfigToolPivotMode: valueInternal: 0 ConfigToolMode: - valueInternal: 2 + valueInternal: 1 OpenedClipIndex: valueInternal: 1 SelectedFrame: @@ -38,9 +38,9 @@ MonoBehaviour: FramesScrollPosition: valueInternal: -40 FramesZoom: - valueInternal: 0.57544 + valueInternal: 0.57543993 PropertiesScrollPosition: - valueInternal: 707 + valueInternal: 0 PropertiesZoom: valueInternal: 1 CurveYScrollPosition: @@ -5102,7 +5102,7 @@ MonoBehaviour: valueInternal: 0 LocalPositionChannelList: - CurrentValue: - valueInternal: -1.5405825e-20 + valueInternal: 0.0123695675 ReferencePoseValue: valueInternal: -1.5405825e-20 PoseValueList: [] @@ -5113,10 +5113,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.5405825e-20 + valueInternal: 0.0123695675 newKeyListSerialized: 02000000000000000000baa94a3c0000000000000000abaaaa3eabaaaa3e00000000000100000000baa94a3c0000000000000000abaaaa3eabaaaa3e00000000 - CurrentValue: - valueInternal: -0.022808662 + valueInternal: -0.012674093 ReferencePoseValue: valueInternal: -0.022808662 PoseValueList: [] @@ -5127,10 +5127,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.022808662 + valueInternal: -0.012674093 newKeyListSerialized: 0200000000000000000000a74fbc0000000000000000abaaaa3eabaaaa3e0000000000010000000000a74fbc0000000000000000abaaaa3eabaaaa3e00000000 - CurrentValue: - valueInternal: 0.9589678 + valueInternal: 0.9561756 ReferencePoseValue: valueInternal: 0.9589678 PoseValueList: [] @@ -5141,7 +5141,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9589678 + valueInternal: 0.9561756 newKeyListSerialized: 02000000000000000000edc7743f0000000000000000abaaaa3eabaaaa3e00000000000100000000edc7743f0000000000000000abaaaa3eabaaaa3e00000000 LocalRotationSelected: valueInternal: 0 @@ -5150,7 +5150,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.02241497 + valueInternal: -0.002251485 ReferencePoseValue: valueInternal: -0.02241497 PoseValueList: [] @@ -5161,10 +5161,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.02241497 + valueInternal: -0.002251485 newKeyListSerialized: 02000000000000000000a68d13bb0000000000000000abaaaa3eabaaaa3e44010000000100000000a68d13bb0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7067514 + valueInternal: 0.7035268 ReferencePoseValue: valueInternal: 0.7067514 PoseValueList: [] @@ -5175,10 +5175,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7067514 + valueInternal: 0.7035268 newKeyListSerialized: 02000000000000000000551a343f0000000000000000abaaaa3eabaaaa3e44010000000100000000551a343f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.02241497 + valueInternal: -0.010654556 ReferencePoseValue: valueInternal: -0.02241497 PoseValueList: [] @@ -5189,10 +5189,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.02241497 + valueInternal: -0.010654556 newKeyListSerialized: 0200000000000000000072902ebc0000000000000000abaaaa3eabaaaa3e4401000000010000000072902ebc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7067514 + valueInternal: 0.71058553 ReferencePoseValue: valueInternal: 0.7067514 PoseValueList: [] @@ -5203,7 +5203,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7067514 + valueInternal: 0.71058553 newKeyListSerialized: 02000000000000000000efe8353f0000000000000000abaaaa3eabaaaa3e44010000000100000000efe8353f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -6226,7 +6226,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -2.6025898e-30 + valueInternal: -0.010361094 ReferencePoseValue: valueInternal: -2.6025898e-30 PoseValueList: [] @@ -6237,10 +6237,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.6025898e-30 + valueInternal: -0.010361094 newKeyListSerialized: 0200000000000000000094c129bc0000000000000000abaaaa3eabaaaa3e4401000000010000000094c129bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.1158186e-30 + valueInternal: 0.010265518 ReferencePoseValue: valueInternal: 1.1158186e-30 PoseValueList: [] @@ -6251,10 +6251,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.1158186e-30 + valueInternal: 0.010265518 newKeyListSerialized: 02000000000000000000b430283c0000000000000000abaaaa3eabaaaa3e44010000000100000000b430283c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.1258295 + valueInternal: 0.11083683 ReferencePoseValue: valueInternal: 0.1258295 PoseValueList: [] @@ -6265,10 +6265,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.1258295 + valueInternal: 0.11083683 newKeyListSerialized: 020000000000000000006cfee23d0000000000000000abaaaa3eabaaaa3e440100000001000000006cfee23d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9920519 + valueInternal: 0.9937317 ReferencePoseValue: valueInternal: 0.9920519 PoseValueList: [] @@ -6279,7 +6279,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9920519 + valueInternal: 0.9937317 newKeyListSerialized: 0200000000000000000033657e3f0000000000000000abaaaa3eabaaaa3e4401000000010000000033657e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -7302,7 +7302,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -2.0213553e-30 + valueInternal: -0.0036019208 ReferencePoseValue: valueInternal: -2.0213553e-30 PoseValueList: [] @@ -7313,10 +7313,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.0213553e-30 + valueInternal: -0.0036019208 newKeyListSerialized: 02000000000000000000340e6cbb0000000000000000abaaaa3eabaaaa3e44010000000100000000340e6cbb0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -7.24171e-31 + valueInternal: 0.008874873 ReferencePoseValue: valueInternal: -7.24171e-31 PoseValueList: [] @@ -7327,10 +7327,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -7.24171e-31 + valueInternal: 0.008874873 newKeyListSerialized: 02000000000000000000ea67113c0000000000000000abaaaa3eabaaaa3e44010000000100000000ea67113c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.09537736 + valueInternal: -0.122498155 ReferencePoseValue: valueInternal: -0.09537736 PoseValueList: [] @@ -7341,10 +7341,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.09537736 + valueInternal: -0.122498155 newKeyListSerialized: 0200000000000000000050e0fabd0000000000000000abaaaa3eabaaaa3e4401000000010000000050e0fabd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9954412 + valueInternal: 0.9924225 ReferencePoseValue: valueInternal: 0.9954412 PoseValueList: [] @@ -7355,7 +7355,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9954412 + valueInternal: 0.9924225 newKeyListSerialized: 02000000000000000000670f7e3f0000000000000000abaaaa3eabaaaa3e44010000000100000000670f7e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -8378,7 +8378,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.000003922817 + valueInternal: -0.0000039049896 ReferencePoseValue: valueInternal: -0.000003922817 PoseValueList: [] @@ -8389,10 +8389,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.000003922817 + valueInternal: -0.0000039049896 newKeyListSerialized: 020000000000000000009b0783b60000000000000000abaaaa3eabaaaa3e440100000001000000009b0783b60000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.000000023326137 + valueInternal: 0.000000014903577 ReferencePoseValue: valueInternal: -0.000000023326137 PoseValueList: [] @@ -8403,10 +8403,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.000000023326137 + valueInternal: 0.000000014903577 newKeyListSerialized: 02000000000000000000500580320000000000000000abaaaa3eabaaaa3e44010000000100000000500580320000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.005946209 + valueInternal: -0.005946233 ReferencePoseValue: valueInternal: -0.005946209 PoseValueList: [] @@ -8417,7 +8417,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.005946209 + valueInternal: -0.005946233 newKeyListSerialized: 020000000000000000009ed8c2bb0000000000000000abaaaa3eabaaaa3e440100000001000000009ed8c2bb0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0.99998236 @@ -8647,7 +8647,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.08327826 + valueInternal: 0.116074376 ReferencePoseValue: valueInternal: 0.08327826 PoseValueList: [] @@ -8658,10 +8658,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.08327826 + valueInternal: 0.116074376 newKeyListSerialized: 0200000000000000000067b8ed3d0000000000000000abaaaa3eabaaaa3e4401000000010000000067b8ed3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.7545604 + valueInternal: -0.7172705 ReferencePoseValue: valueInternal: -0.7545604 PoseValueList: [] @@ -8672,10 +8672,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.7545604 + valueInternal: -0.7172705 newKeyListSerialized: 020000000000000000000a9f37bf0000000000000000abaaaa3eabaaaa3e440100000001000000000a9f37bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.041289933 + valueInternal: 0.007625906 ReferencePoseValue: valueInternal: 0.041289933 PoseValueList: [] @@ -8686,10 +8686,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.041289933 + valueInternal: 0.007625906 newKeyListSerialized: 02000000000000000000bce2f93b0000000000000000abaaaa3eabaaaa3e44010000000100000000bce2f93b0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.6496141 + valueInternal: 0.6870165 ReferencePoseValue: valueInternal: 0.6496141 PoseValueList: [] @@ -8700,7 +8700,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.6496141 + valueInternal: 0.6870165 newKeyListSerialized: 0200000000000000000050e02f3f0000000000000000abaaaa3eabaaaa3e4401000000010000000050e02f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -8916,7 +8916,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.01994785 + valueInternal: -0.15612495 ReferencePoseValue: valueInternal: -0.01994785 PoseValueList: [] @@ -8927,10 +8927,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.01994785 + valueInternal: -0.15612495 newKeyListSerialized: 0200000000000000000038df1fbe0000000000000000abaaaa3eabaaaa3e4401000000010000000038df1fbe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.39173076 + valueInternal: -0.47788846 ReferencePoseValue: valueInternal: -0.39173076 PoseValueList: [] @@ -8941,10 +8941,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.39173076 + valueInternal: -0.47788846 newKeyListSerialized: 02000000000000000000ccadf4be0000000000000000abaaaa3eabaaaa3e44010000000100000000ccadf4be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.020190157 + valueInternal: 0.48425734 ReferencePoseValue: valueInternal: 0.020190157 PoseValueList: [] @@ -8955,10 +8955,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.020190157 + valueInternal: 0.48425734 newKeyListSerialized: 0200000000000000000094f0f73e0000000000000000abaaaa3eabaaaa3e4401000000010000000094f0f73e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.91964203 + valueInternal: 0.7160604 ReferencePoseValue: valueInternal: 0.91964203 PoseValueList: [] @@ -8969,7 +8969,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.91964203 + valueInternal: 0.7160604 newKeyListSerialized: 02000000000000000000bc4f373f0000000000000000abaaaa3eabaaaa3e44010000000100000000bc4f373f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -9185,7 +9185,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.3674641e-17 + valueInternal: -0.07595502 ReferencePoseValue: valueInternal: 1.3674641e-17 PoseValueList: [] @@ -9196,10 +9196,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.3674641e-17 + valueInternal: -0.07595502 newKeyListSerialized: 020000000000000000004e8e9bbd0000000000000000abaaaa3eabaaaa3e440100000001000000004e8e9bbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 2.1093738e-16 + valueInternal: 0.012259677 ReferencePoseValue: valueInternal: 2.1093738e-16 PoseValueList: [] @@ -9210,10 +9210,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 2.1093738e-16 + valueInternal: 0.012259677 newKeyListSerialized: 02000000000000000000d0dc483c0000000000000000abaaaa3eabaaaa3e44010000000100000000d0dc483c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.33363262 + valueInternal: 0.43630737 ReferencePoseValue: valueInternal: 0.33363262 PoseValueList: [] @@ -9224,10 +9224,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.33363262 + valueInternal: 0.43630737 newKeyListSerialized: 02000000000000000000ae63df3e0000000000000000abaaaa3eabaaaa3e44010000000100000000ae63df3e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9427032 + valueInternal: 0.8965024 ReferencePoseValue: valueInternal: 0.9427032 PoseValueList: [] @@ -9238,7 +9238,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9427032 + valueInternal: 0.8965024 newKeyListSerialized: 020000000000000000002e81653f0000000000000000abaaaa3eabaaaa3e440100000001000000002e81653f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -9454,7 +9454,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.55758685 + valueInternal: -0.63309926 ReferencePoseValue: valueInternal: -0.55758685 PoseValueList: [] @@ -9465,10 +9465,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.55758685 + valueInternal: -0.63309926 newKeyListSerialized: 02000000000000000000cb1222bf0000000000000000abaaaa3eabaaaa3e44010000000100000000cb1222bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.0016783397 + valueInternal: 0.17619902 ReferencePoseValue: valueInternal: -0.0016783397 PoseValueList: [] @@ -9479,10 +9479,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.0016783397 + valueInternal: 0.17619902 newKeyListSerialized: 02000000000000000000846d343e0000000000000000abaaaa3eabaaaa3e44010000000100000000846d343e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.020560935 + valueInternal: -0.12625034 ReferencePoseValue: valueInternal: -0.020560935 PoseValueList: [] @@ -9493,10 +9493,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.020560935 + valueInternal: -0.12625034 newKeyListSerialized: 02000000000000000000c54701be0000000000000000abaaaa3eabaaaa3e44010000000100000000c54701be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.82986224 + valueInternal: 0.7431017 ReferencePoseValue: valueInternal: 0.82986224 PoseValueList: [] @@ -9507,7 +9507,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.82986224 + valueInternal: 0.7431017 newKeyListSerialized: 02000000000000000000ea3b3e3f0000000000000000abaaaa3eabaaaa3e44010000000100000000ea3b3e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -9992,7 +9992,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -2.4834257e-17 + valueInternal: -0.12077076 ReferencePoseValue: valueInternal: -2.4834257e-17 PoseValueList: [] @@ -10003,10 +10003,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.4834257e-17 + valueInternal: -0.12077076 newKeyListSerialized: 02000000000000000000a956f7bd0000000000000000abaaaa3eabaaaa3e44010000000100000000a956f7bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -5.15494e-17 + valueInternal: -0.09062012 ReferencePoseValue: valueInternal: -5.15494e-17 PoseValueList: [] @@ -10017,10 +10017,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -5.15494e-17 + valueInternal: -0.09062012 newKeyListSerialized: 020000000000000000000b97b9bd0000000000000000abaaaa3eabaaaa3e440100000001000000000b97b9bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.20255657 + valueInternal: -0.45609194 ReferencePoseValue: valueInternal: -0.20255657 PoseValueList: [] @@ -10031,10 +10031,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.20255657 + valueInternal: -0.45609194 newKeyListSerialized: 02000000000000000000e284e9be0000000000000000abaaaa3eabaaaa3e44010000000100000000e284e9be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9792706 + valueInternal: 0.87703097 ReferencePoseValue: valueInternal: 0.9792706 PoseValueList: [] @@ -10045,7 +10045,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9792706 + valueInternal: 0.87703097 newKeyListSerialized: 020000000000000000001a85603f0000000000000000abaaaa3eabaaaa3e440100000001000000001a85603f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -10261,7 +10261,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 9.335562e-17 + valueInternal: -0.029060753 ReferencePoseValue: valueInternal: 9.335562e-17 PoseValueList: [] @@ -10272,10 +10272,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 9.335562e-17 + valueInternal: -0.029060753 newKeyListSerialized: 02000000000000000000d110eebc0000000000000000abaaaa3eabaaaa3e44010000000100000000d110eebc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 7.177344e-17 + valueInternal: -0.04188049 ReferencePoseValue: valueInternal: 7.177344e-17 PoseValueList: [] @@ -10286,10 +10286,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 7.177344e-17 + valueInternal: -0.04188049 newKeyListSerialized: 02000000000000000000e08a2bbd0000000000000000abaaaa3eabaaaa3e44010000000100000000e08a2bbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.12959665 + valueInternal: -0.30216303 ReferencePoseValue: valueInternal: -0.12959665 PoseValueList: [] @@ -10300,10 +10300,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.12959665 + valueInternal: -0.30216303 newKeyListSerialized: 020000000000000000001db59abe0000000000000000abaaaa3eabaaaa3e440100000001000000001db59abe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99156684 + valueInternal: 0.9518924 ReferencePoseValue: valueInternal: 0.99156684 PoseValueList: [] @@ -10314,7 +10314,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99156684 + valueInternal: 0.9518924 newKeyListSerialized: 0200000000000000000038af733f0000000000000000abaaaa3eabaaaa3e4401000000010000000038af733f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -10530,7 +10530,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -5.157263e-16 + valueInternal: -0.02733975 ReferencePoseValue: valueInternal: -5.157263e-16 PoseValueList: [] @@ -10541,10 +10541,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -5.157263e-16 + valueInternal: -0.02733975 newKeyListSerialized: 020000000000000000009df7dfbc0000000000000000abaaaa3eabaaaa3e440100000001000000009df7dfbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -4.1811757e-16 + valueInternal: -0.043023072 ReferencePoseValue: valueInternal: -4.1811757e-16 PoseValueList: [] @@ -10555,10 +10555,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -4.1811757e-16 + valueInternal: -0.043023072 newKeyListSerialized: 02000000000000000000f63830bd0000000000000000abaaaa3eabaaaa3e44010000000100000000f63830bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.109009154 + valueInternal: -0.31209376 ReferencePoseValue: valueInternal: -0.109009154 PoseValueList: [] @@ -10569,10 +10569,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.109009154 + valueInternal: -0.31209376 newKeyListSerialized: 02000000000000000000c1ca9fbe0000000000000000abaaaa3eabaaaa3e44010000000100000000c1ca9fbe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9940407 + valueInternal: 0.94868314 ReferencePoseValue: valueInternal: 0.9940407 PoseValueList: [] @@ -10583,7 +10583,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9940407 + valueInternal: 0.94868314 newKeyListSerialized: 02000000000000000000e6dc723f0000000000000000abaaaa3eabaaaa3e44010000000100000000e6dc723f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -11068,7 +11068,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.9713317e-16 + valueInternal: 0.032478023 ReferencePoseValue: valueInternal: 1.9713317e-16 PoseValueList: [] @@ -11079,10 +11079,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.9713317e-16 + valueInternal: 0.032478023 newKeyListSerialized: 02000000000000000000ad07053d0000000000000000abaaaa3eabaaaa3e44010000000100000000ad07053d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 5.964157e-17 + valueInternal: 0.038706884 ReferencePoseValue: valueInternal: 5.964157e-17 PoseValueList: [] @@ -11093,10 +11093,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 5.964157e-17 + valueInternal: 0.038706884 newKeyListSerialized: 020000000000000000001c8b1e3d0000000000000000abaaaa3eabaaaa3e440100000001000000001c8b1e3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.27205086 + valueInternal: -0.665601 ReferencePoseValue: valueInternal: -0.27205086 PoseValueList: [] @@ -11107,10 +11107,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.27205086 + valueInternal: -0.665601 newKeyListSerialized: 02000000000000000000d4642abf0000000000000000abaaaa3eabaaaa3e44010000000100000000d4642abf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9622829 + valueInternal: 0.7445958 ReferencePoseValue: valueInternal: 0.9622829 PoseValueList: [] @@ -11121,7 +11121,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9622829 + valueInternal: 0.7445958 newKeyListSerialized: 02000000000000000000d59d3e3f0000000000000000abaaaa3eabaaaa3e44010000000100000000d59d3e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -11337,7 +11337,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -7.404477e-18 + valueInternal: -0.009772375 ReferencePoseValue: valueInternal: -7.404477e-18 PoseValueList: [] @@ -11348,10 +11348,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -7.404477e-18 + valueInternal: -0.009772375 newKeyListSerialized: 02000000000000000000501c20bc0000000000000000abaaaa3eabaaaa3e44010000000100000000501c20bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.4244586e-16 + valueInternal: -0.010720067 ReferencePoseValue: valueInternal: 1.4244586e-16 PoseValueList: [] @@ -11362,10 +11362,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.4244586e-16 + valueInternal: -0.010720067 newKeyListSerialized: 0200000000000000000038a32fbc0000000000000000abaaaa3eabaaaa3e4401000000010000000038a32fbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.18025488 + valueInternal: -0.6784182 ReferencePoseValue: valueInternal: -0.18025488 PoseValueList: [] @@ -11376,10 +11376,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.18025488 + valueInternal: -0.6784182 newKeyListSerialized: 02000000000000000000d1ac2dbf0000000000000000abaaaa3eabaaaa3e44010000000100000000d1ac2dbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.98362 + valueInternal: 0.7345338 ReferencePoseValue: valueInternal: 0.98362 PoseValueList: [] @@ -11390,7 +11390,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.98362 + valueInternal: 0.7345338 newKeyListSerialized: 02000000000000000000680a3c3f0000000000000000abaaaa3eabaaaa3e44010000000100000000680a3c3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -11606,7 +11606,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -3.940056e-17 + valueInternal: -0.009234358 ReferencePoseValue: valueInternal: -3.940056e-17 PoseValueList: [] @@ -11617,10 +11617,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -3.940056e-17 + valueInternal: -0.009234358 newKeyListSerialized: 02000000000000000000b44b17bc0000000000000000abaaaa3eabaaaa3e44010000000100000000b44b17bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -5.227609e-17 + valueInternal: -0.011186738 ReferencePoseValue: valueInternal: -5.227609e-17 PoseValueList: [] @@ -11631,10 +11631,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -5.227609e-17 + valueInternal: -0.011186738 newKeyListSerialized: 02000000000000000000944837bc0000000000000000abaaaa3eabaaaa3e44010000000100000000944837bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.087155744 + valueInternal: -0.66367507 ReferencePoseValue: valueInternal: -0.087155744 PoseValueList: [] @@ -11645,10 +11645,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.087155744 + valueInternal: -0.66367507 newKeyListSerialized: 020000000000000000009ce629bf0000000000000000abaaaa3eabaaaa3e440100000001000000009ce629bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9961947 + valueInternal: 0.74788064 ReferencePoseValue: valueInternal: 0.9961947 PoseValueList: [] @@ -11659,7 +11659,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9961947 + valueInternal: 0.74788064 newKeyListSerialized: 020000000000000000001b753f3f0000000000000000abaaaa3eabaaaa3e440100000001000000001b753f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -12144,7 +12144,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.08998402 + valueInternal: 0.07243729 ReferencePoseValue: valueInternal: 0.08998402 PoseValueList: [] @@ -12155,10 +12155,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.08998402 + valueInternal: 0.07243729 newKeyListSerialized: 02000000000000000000005a943d0000000000000000abaaaa3eabaaaa3e44010000000100000000005a943d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.017015995 + valueInternal: 0.045979954 ReferencePoseValue: valueInternal: -0.017015995 PoseValueList: [] @@ -12169,10 +12169,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.017015995 + valueInternal: 0.045979954 newKeyListSerialized: 020000000000000000007a553c3d0000000000000000abaaaa3eabaaaa3e440100000001000000007a553c3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.1280659 + valueInternal: -0.6749333 ReferencePoseValue: valueInternal: -0.1280659 PoseValueList: [] @@ -12183,10 +12183,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.1280659 + valueInternal: -0.6749333 newKeyListSerialized: 020000000000000000006ec82cbf0000000000000000abaaaa3eabaaaa3e440100000001000000006ec82cbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.98752844 + valueInternal: 0.7328741 ReferencePoseValue: valueInternal: 0.98752844 PoseValueList: [] @@ -12197,7 +12197,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.98752844 + valueInternal: 0.7328741 newKeyListSerialized: 02000000000000000000a39d3b3f0000000000000000abaaaa3eabaaaa3e44010000000100000000a39d3b3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -12413,7 +12413,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 2.1858013e-16 + valueInternal: 0.028632885 ReferencePoseValue: valueInternal: 2.1858013e-16 PoseValueList: [] @@ -12424,10 +12424,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 2.1858013e-16 + valueInternal: 0.028632885 newKeyListSerialized: 02000000000000000000838fea3c0000000000000000abaaaa3eabaaaa3e44010000000100000000838fea3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -2.1052669e-16 + valueInternal: 0.09171413 ReferencePoseValue: valueInternal: -2.1052669e-16 PoseValueList: [] @@ -12438,10 +12438,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.1052669e-16 + valueInternal: 0.09171413 newKeyListSerialized: 020000000000000000009ed4bb3d0000000000000000abaaaa3eabaaaa3e440100000001000000009ed4bb3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.18469755 + valueInternal: -0.67084634 ReferencePoseValue: valueInternal: -0.18469755 PoseValueList: [] @@ -12452,10 +12452,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.18469755 + valueInternal: -0.67084634 newKeyListSerialized: 0200000000000000000096bc2bbf0000000000000000abaaaa3eabaaaa3e4401000000010000000096bc2bbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9827954 + valueInternal: 0.7353461 ReferencePoseValue: valueInternal: 0.9827954 PoseValueList: [] @@ -12466,7 +12466,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9827954 + valueInternal: 0.7353461 newKeyListSerialized: 02000000000000000000a43f3c3f0000000000000000abaaaa3eabaaaa3e44010000000100000000a43f3c3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -12682,7 +12682,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -4.2619093e-16 + valueInternal: 0.028107585 ReferencePoseValue: valueInternal: -4.2619093e-16 PoseValueList: [] @@ -12693,10 +12693,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -4.2619093e-16 + valueInternal: 0.028107585 newKeyListSerialized: 02000000000000000000e141e63c0000000000000000abaaaa3eabaaaa3e44010000000100000000e141e63c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.433138e-16 + valueInternal: 0.091876276 ReferencePoseValue: valueInternal: 1.433138e-16 PoseValueList: [] @@ -12707,10 +12707,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.433138e-16 + valueInternal: 0.091876276 newKeyListSerialized: 02000000000000000000a129bc3d0000000000000000abaaaa3eabaaaa3e44010000000100000000a129bc3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.042895757 + valueInternal: -0.62340605 ReferencePoseValue: valueInternal: -0.042895757 PoseValueList: [] @@ -12721,10 +12721,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.042895757 + valueInternal: -0.62340605 newKeyListSerialized: 020000000000000000008a971fbf0000000000000000abaaaa3eabaaaa3e440100000001000000008a971fbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9990796 + valueInternal: 0.7759725 ReferencePoseValue: valueInternal: 0.9990796 PoseValueList: [] @@ -12735,7 +12735,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9990796 + valueInternal: 0.7759725 newKeyListSerialized: 0200000000000000000022a6463f0000000000000000abaaaa3eabaaaa3e4401000000010000000022a6463f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -13220,7 +13220,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.054216176 + valueInternal: 0.04786189 ReferencePoseValue: valueInternal: 0.054216176 PoseValueList: [] @@ -13231,10 +13231,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.054216176 + valueInternal: 0.04786189 newKeyListSerialized: 02000000000000000000d40a443d0000000000000000abaaaa3eabaaaa3e44010000000100000000d40a443d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.01317727 + valueInternal: 0.07530979 ReferencePoseValue: valueInternal: -0.01317727 PoseValueList: [] @@ -13245,10 +13245,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.01317727 + valueInternal: 0.07530979 newKeyListSerialized: 02000000000000000000053c9a3d0000000000000000abaaaa3eabaaaa3e44010000000100000000053c9a3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.25353977 + valueInternal: -0.70363027 ReferencePoseValue: valueInternal: -0.25353977 PoseValueList: [] @@ -13259,10 +13259,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.25353977 + valueInternal: -0.70363027 newKeyListSerialized: 020000000000000000001d2134bf0000000000000000abaaaa3eabaaaa3e440100000001000000001d2134bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9657145 + valueInternal: 0.70494175 ReferencePoseValue: valueInternal: 0.9657145 PoseValueList: [] @@ -13273,7 +13273,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9657145 + valueInternal: 0.70494175 newKeyListSerialized: 020000000000000000001077343f0000000000000000abaaaa3eabaaaa3e440100000001000000001077343f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -13489,7 +13489,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.6304381e-16 + valueInternal: 0.014484646 ReferencePoseValue: valueInternal: 1.6304381e-16 PoseValueList: [] @@ -13500,10 +13500,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.6304381e-16 + valueInternal: 0.014484646 newKeyListSerialized: 0200000000000000000002516d3c0000000000000000abaaaa3eabaaaa3e4401000000010000000002516d3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -4.4933213e-16 + valueInternal: 0.026761495 ReferencePoseValue: valueInternal: -4.4933213e-16 PoseValueList: [] @@ -13514,10 +13514,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -4.4933213e-16 + valueInternal: 0.026761495 newKeyListSerialized: 02000000000000000000ec3adb3c0000000000000000abaaaa3eabaaaa3e44010000000100000000ec3adb3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.16473773 + valueInternal: -0.6596887 ReferencePoseValue: valueInternal: -0.16473773 PoseValueList: [] @@ -13528,10 +13528,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.16473773 + valueInternal: -0.6596887 newKeyListSerialized: 020000000000000000005ce128bf0000000000000000abaaaa3eabaaaa3e440100000001000000005ce128bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9863374 + valueInternal: 0.7509233 ReferencePoseValue: valueInternal: 0.9863374 PoseValueList: [] @@ -13542,7 +13542,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9863374 + valueInternal: 0.7509233 newKeyListSerialized: 02000000000000000000823c403f0000000000000000abaaaa3eabaaaa3e44010000000100000000823c403f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -13758,7 +13758,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -3.7109125e-16 + valueInternal: 0.013737011 ReferencePoseValue: valueInternal: -3.7109125e-16 PoseValueList: [] @@ -13769,10 +13769,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -3.7109125e-16 + valueInternal: 0.013737011 newKeyListSerialized: 020000000000000000003311613c0000000000000000abaaaa3eabaaaa3e440100000001000000003311613c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 3.6388872e-16 + valueInternal: 0.027153153 ReferencePoseValue: valueInternal: 3.6388872e-16 PoseValueList: [] @@ -13783,10 +13783,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 3.6388872e-16 + valueInternal: 0.027153153 newKeyListSerialized: 020000000000000000004a70de3c0000000000000000abaaaa3eabaaaa3e440100000001000000004a70de3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.07992057 + valueInternal: -0.6652811 ReferencePoseValue: valueInternal: -0.07992057 PoseValueList: [] @@ -13797,10 +13797,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.07992057 + valueInternal: -0.6652811 newKeyListSerialized: 02000000000000000000dd4f2abf0000000000000000abaaaa3eabaaaa3e44010000000100000000dd4f2abf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99680126 + valueInternal: 0.74597275 ReferencePoseValue: valueInternal: 0.99680126 PoseValueList: [] @@ -13811,7 +13811,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99680126 + valueInternal: 0.74597275 newKeyListSerialized: 0200000000000000000012f83e3f0000000000000000abaaaa3eabaaaa3e4401000000010000000012f83e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -14027,7 +14027,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.50519353 + valueInternal: 0.46131757 ReferencePoseValue: valueInternal: 0.50519353 PoseValueList: [] @@ -14038,10 +14038,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.50519353 + valueInternal: 0.46131757 newKeyListSerialized: 02000000000000000000d131ec3e0000000000000000abaaaa3eabaaaa3e44010000000100000000d131ec3e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.3691297 + valueInternal: -0.44174165 ReferencePoseValue: valueInternal: -0.3691297 PoseValueList: [] @@ -14052,10 +14052,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.3691297 + valueInternal: -0.44174165 newKeyListSerialized: 02000000000000000000f62be2be0000000000000000abaaaa3eabaaaa3e44010000000100000000f62be2be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.06703917 + valueInternal: -0.053030174 ReferencePoseValue: valueInternal: 0.06703917 PoseValueList: [] @@ -14066,10 +14066,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.06703917 + valueInternal: -0.053030174 newKeyListSerialized: 020000000000000000002b3659bd0000000000000000abaaaa3eabaaaa3e440100000001000000002b3659bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7771927 + valueInternal: 0.76761913 ReferencePoseValue: valueInternal: 0.7771927 PoseValueList: [] @@ -14080,7 +14080,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7771927 + valueInternal: 0.76761913 newKeyListSerialized: 02000000000000000000b082443f0000000000000000abaaaa3eabaaaa3e44010000000100000000b082443f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -14296,7 +14296,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.03356521 + valueInternal: 0.014754489 ReferencePoseValue: valueInternal: 0.03356521 PoseValueList: [] @@ -14307,10 +14307,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.03356521 + valueInternal: 0.014754489 newKeyListSerialized: 02000000000000000000d0bc713c0000000000000000abaaaa3eabaaaa3e44010000000100000000d0bc713c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.01030245 + valueInternal: 0.076458216 ReferencePoseValue: valueInternal: 0.01030245 PoseValueList: [] @@ -14321,10 +14321,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.01030245 + valueInternal: 0.076458216 newKeyListSerialized: 0200000000000000000020969c3d0000000000000000abaaaa3eabaaaa3e4401000000010000000020969c3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.20185572 + valueInternal: -0.18701956 ReferencePoseValue: valueInternal: -0.20185572 PoseValueList: [] @@ -14335,10 +14335,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.20185572 + valueInternal: -0.18701956 newKeyListSerialized: 020000000000000000000e823fbe0000000000000000abaaaa3eabaaaa3e440100000001000000000e823fbe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.97878575 + valueInternal: 0.97926515 ReferencePoseValue: valueInternal: 0.97878575 PoseValueList: [] @@ -14349,7 +14349,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.97878575 + valueInternal: 0.97926515 newKeyListSerialized: 020000000000000000001fb17a3f0000000000000000abaaaa3eabaaaa3e440100000001000000001fb17a3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -14565,7 +14565,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -9.193674e-17 + valueInternal: -0.024934556 ReferencePoseValue: valueInternal: -9.193674e-17 PoseValueList: [] @@ -14576,10 +14576,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -9.193674e-17 + valueInternal: -0.024934556 newKeyListSerialized: 020000000000000000008e43ccbc0000000000000000abaaaa3eabaaaa3e440100000001000000008e43ccbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 6.376662e-17 + valueInternal: 0.044454366 ReferencePoseValue: valueInternal: 6.376662e-17 PoseValueList: [] @@ -14590,10 +14590,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 6.376662e-17 + valueInternal: 0.044454366 newKeyListSerialized: 02000000000000000000c815363d0000000000000000abaaaa3eabaaaa3e44010000000100000000c815363d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.087155744 + valueInternal: -0.1885523 ReferencePoseValue: valueInternal: -0.087155744 PoseValueList: [] @@ -14604,10 +14604,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.087155744 + valueInternal: -0.1885523 newKeyListSerialized: 02000000000000000000db1341be0000000000000000abaaaa3eabaaaa3e44010000000100000000db1341be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9961947 + valueInternal: 0.9807396 ReferencePoseValue: valueInternal: 0.9961947 PoseValueList: [] @@ -14618,7 +14618,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9961947 + valueInternal: 0.9807396 newKeyListSerialized: 02000000000000000000c0117b3f0000000000000000abaaaa3eabaaaa3e44010000000100000000c0117b3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -16179,7 +16179,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.7545604 + valueInternal: 0.71628493 ReferencePoseValue: valueInternal: 0.7545604 PoseValueList: [] @@ -16190,10 +16190,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7545604 + valueInternal: 0.71628493 newKeyListSerialized: 02000000000000000000735e373f0000000000000000abaaaa3eabaaaa3e44010000000100000000735e373f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.0832783 + valueInternal: 0.08777306 ReferencePoseValue: valueInternal: 0.0832783 PoseValueList: [] @@ -16204,10 +16204,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.0832783 + valueInternal: 0.08777306 newKeyListSerialized: 020000000000000000005dc2b33d0000000000000000abaaaa3eabaaaa3e440100000001000000005dc2b33d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.6496141 + valueInternal: 0.69136405 ReferencePoseValue: valueInternal: 0.6496141 PoseValueList: [] @@ -16218,10 +16218,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.6496141 + valueInternal: 0.69136405 newKeyListSerialized: 020000000000000000003cfd303f0000000000000000abaaaa3eabaaaa3e440100000001000000003cfd303f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.041289967 + valueInternal: -0.0353217 ReferencePoseValue: valueInternal: -0.041289967 PoseValueList: [] @@ -16232,7 +16232,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.041289967 + valueInternal: -0.0353217 newKeyListSerialized: 020000000000000000007dad10bd0000000000000000abaaaa3eabaaaa3e440100000001000000007dad10bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -16448,7 +16448,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.01994785 + valueInternal: -0.16102028 ReferencePoseValue: valueInternal: -0.01994785 PoseValueList: [] @@ -16459,10 +16459,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.01994785 + valueInternal: -0.16102028 newKeyListSerialized: 0200000000000000000080e224be0000000000000000abaaaa3eabaaaa3e4401000000010000000080e224be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.39173076 + valueInternal: -0.43316105 ReferencePoseValue: valueInternal: -0.39173076 PoseValueList: [] @@ -16473,10 +16473,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.39173076 + valueInternal: -0.43316105 newKeyListSerialized: 0200000000000000000049c7ddbe0000000000000000abaaaa3eabaaaa3e4401000000010000000049c7ddbe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.020190157 + valueInternal: 0.54169196 ReferencePoseValue: valueInternal: 0.020190157 PoseValueList: [] @@ -16487,10 +16487,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.020190157 + valueInternal: 0.54169196 newKeyListSerialized: 0200000000000000000053ac0a3f0000000000000000abaaaa3eabaaaa3e4401000000010000000053ac0a3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.91964203 + valueInternal: 0.70214945 ReferencePoseValue: valueInternal: 0.91964203 PoseValueList: [] @@ -16501,7 +16501,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.91964203 + valueInternal: 0.70214945 newKeyListSerialized: 0200000000000000000011c0333f0000000000000000abaaaa3eabaaaa3e4401000000010000000011c0333f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -16717,7 +16717,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -9.217045e-17 + valueInternal: -0.18839227 ReferencePoseValue: valueInternal: -9.217045e-17 PoseValueList: [] @@ -16728,10 +16728,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -9.217045e-17 + valueInternal: -0.18839227 newKeyListSerialized: 02000000000000000000e7e940be0000000000000000abaaaa3eabaaaa3e44010000000100000000e7e940be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -2.3871787e-16 + valueInternal: -0.045563564 ReferencePoseValue: valueInternal: -2.3871787e-16 PoseValueList: [] @@ -16742,10 +16742,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.3871787e-16 + valueInternal: -0.045563564 newKeyListSerialized: 02000000000000000000dca03abd0000000000000000abaaaa3eabaaaa3e44010000000100000000dca03abd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.33363262 + valueInternal: 0.3312921 ReferencePoseValue: valueInternal: 0.33363262 PoseValueList: [] @@ -16756,10 +16756,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.33363262 + valueInternal: 0.3312921 newKeyListSerialized: 020000000000000000001e9fa93e0000000000000000abaaaa3eabaaaa3e440100000001000000001e9fa93e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9427032 + valueInternal: 0.92340565 ReferencePoseValue: valueInternal: 0.9427032 PoseValueList: [] @@ -16770,7 +16770,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9427032 + valueInternal: 0.92340565 newKeyListSerialized: 0200000000000000000050646c3f0000000000000000abaaaa3eabaaaa3e4401000000010000000050646c3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -16986,7 +16986,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.55758685 + valueInternal: -0.75300705 ReferencePoseValue: valueInternal: -0.55758685 PoseValueList: [] @@ -16997,10 +16997,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.55758685 + valueInternal: -0.75300705 newKeyListSerialized: 0200000000000000000012c540bf0000000000000000abaaaa3eabaaaa3e4401000000010000000012c540bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.001678249 + valueInternal: 0.09807466 ReferencePoseValue: valueInternal: -0.001678249 PoseValueList: [] @@ -17011,10 +17011,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.001678249 + valueInternal: 0.09807466 newKeyListSerialized: 020000000000000000005edbc83d0000000000000000abaaaa3eabaaaa3e440100000001000000005edbc83d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.02056061 + valueInternal: -0.006336633 ReferencePoseValue: valueInternal: -0.02056061 PoseValueList: [] @@ -17025,10 +17025,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.02056061 + valueInternal: -0.006336633 newKeyListSerialized: 0200000000000000000088a3cfbb0000000000000000abaaaa3eabaaaa3e4401000000010000000088a3cfbb0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.82986224 + valueInternal: 0.65063167 ReferencePoseValue: valueInternal: 0.82986224 PoseValueList: [] @@ -17039,7 +17039,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.82986224 + valueInternal: 0.65063167 newKeyListSerialized: 02000000000000000000cc8f263f0000000000000000abaaaa3eabaaaa3e44010000000100000000cc8f263f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -17524,7 +17524,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -4.451975e-16 + valueInternal: -0.042171586 ReferencePoseValue: valueInternal: -4.451975e-16 PoseValueList: [] @@ -17535,10 +17535,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -4.451975e-16 + valueInternal: -0.042171586 newKeyListSerialized: 020000000000000000001dbc2cbd0000000000000000abaaaa3eabaaaa3e440100000001000000001dbc2cbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.7711591e-16 + valueInternal: -0.02520001 ReferencePoseValue: valueInternal: 1.7711591e-16 PoseValueList: [] @@ -17549,10 +17549,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.7711591e-16 + valueInternal: -0.02520001 newKeyListSerialized: 020000000000000000004070cebc0000000000000000abaaaa3eabaaaa3e440100000001000000004070cebc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.20255657 + valueInternal: 0.5554784 ReferencePoseValue: valueInternal: -0.20255657 PoseValueList: [] @@ -17563,10 +17563,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.20255657 + valueInternal: 0.5554784 newKeyListSerialized: 02000000000000000000d5330e3f0000000000000000abaaaa3eabaaaa3e44010000000100000000d5330e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9792706 + valueInternal: -0.8300789 ReferencePoseValue: valueInternal: 0.9792706 PoseValueList: [] @@ -17577,7 +17577,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9792706 + valueInternal: -0.8300789 newKeyListSerialized: 020000000000000000000d8054bf0000000000000000abaaaa3eabaaaa3e440100000001000000000d8054bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -17793,7 +17793,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 3.178986e-16 + valueInternal: 0.037751526 ReferencePoseValue: valueInternal: 3.178986e-16 PoseValueList: [] @@ -17804,10 +17804,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 3.178986e-16 + valueInternal: 0.037751526 newKeyListSerialized: 0200000000000000000058a11a3d0000000000000000abaaaa3eabaaaa3e4401000000010000000058a11a3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -4.0544026e-16 + valueInternal: 0.08755188 ReferencePoseValue: valueInternal: -4.0544026e-16 PoseValueList: [] @@ -17818,10 +17818,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -4.0544026e-16 + valueInternal: 0.08755188 newKeyListSerialized: 02000000000000000000664eb33d0000000000000000abaaaa3eabaaaa3e44010000000100000000664eb33d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.12959665 + valueInternal: 0.6126037 ReferencePoseValue: valueInternal: -0.12959665 PoseValueList: [] @@ -17832,10 +17832,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.12959665 + valueInternal: 0.6126037 newKeyListSerialized: 0200000000000000000099d31c3f0000000000000000abaaaa3eabaaaa3e4401000000010000000099d31c3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99156684 + valueInternal: -0.7846186 ReferencePoseValue: valueInternal: 0.99156684 PoseValueList: [] @@ -17846,7 +17846,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99156684 + valueInternal: -0.7846186 newKeyListSerialized: 02000000000000000000c4dc48bf0000000000000000abaaaa3eabaaaa3e44010000000100000000c4dc48bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -18062,7 +18062,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -3.590716e-16 + valueInternal: 0.05484819 ReferencePoseValue: valueInternal: -3.590716e-16 PoseValueList: [] @@ -18073,10 +18073,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -3.590716e-16 + valueInternal: 0.05484819 newKeyListSerialized: 020000000000000000007fa8603d0000000000000000abaaaa3eabaaaa3e440100000001000000007fa8603d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.5106462e-16 + valueInternal: 0.07798502 ReferencePoseValue: valueInternal: 1.5106462e-16 PoseValueList: [] @@ -18087,10 +18087,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.5106462e-16 + valueInternal: 0.07798502 newKeyListSerialized: 020000000000000000009cb69f3d0000000000000000abaaaa3eabaaaa3e440100000001000000009cb69f3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.109009154 + valueInternal: 0.40683824 ReferencePoseValue: valueInternal: -0.109009154 PoseValueList: [] @@ -18101,10 +18101,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.109009154 + valueInternal: 0.40683824 newKeyListSerialized: 020000000000000000001a4dd03e0000000000000000abaaaa3eabaaaa3e440100000001000000001a4dd03e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9940407 + valueInternal: -0.9085112 ReferencePoseValue: valueInternal: 0.9940407 PoseValueList: [] @@ -18115,7 +18115,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9940407 + valueInternal: -0.9085112 newKeyListSerialized: 02000000000000000000319468bf0000000000000000abaaaa3eabaaaa3e44010000000100000000319468bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -18600,7 +18600,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 7.238114e-18 + valueInternal: -0.014290191 ReferencePoseValue: valueInternal: 7.238114e-18 PoseValueList: [] @@ -18611,10 +18611,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 7.238114e-18 + valueInternal: -0.014290191 newKeyListSerialized: 0200000000000000000068216abc0000000000000000abaaaa3eabaaaa3e4401000000010000000068216abc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -2.0395058e-16 + valueInternal: -0.024388462 ReferencePoseValue: valueInternal: -2.0395058e-16 PoseValueList: [] @@ -18625,10 +18625,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.0395058e-16 + valueInternal: -0.024388462 newKeyListSerialized: 0200000000000000000050cac7bc0000000000000000abaaaa3eabaaaa3e4401000000010000000050cac7bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.27205086 + valueInternal: 0.63642806 ReferencePoseValue: valueInternal: -0.27205086 PoseValueList: [] @@ -18639,10 +18639,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.27205086 + valueInternal: 0.63642806 newKeyListSerialized: 02000000000000000000f3ec223f0000000000000000abaaaa3eabaaaa3e44010000000100000000f3ec223f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9622829 + valueInternal: -0.7708189 ReferencePoseValue: valueInternal: 0.9622829 PoseValueList: [] @@ -18653,7 +18653,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9622829 + valueInternal: -0.7708189 newKeyListSerialized: 02000000000000000000635445bf0000000000000000abaaaa3eabaaaa3e44010000000100000000635445bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -18869,7 +18869,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.3949614e-16 + valueInternal: 0.022887217 ReferencePoseValue: valueInternal: 1.3949614e-16 PoseValueList: [] @@ -18880,10 +18880,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.3949614e-16 + valueInternal: 0.022887217 newKeyListSerialized: 02000000000000000000f97dbb3c0000000000000000abaaaa3eabaaaa3e44010000000100000000f97dbb3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 2.8483206e-16 + valueInternal: 0.0030220088 ReferencePoseValue: valueInternal: 2.8483206e-16 PoseValueList: [] @@ -18894,10 +18894,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 2.8483206e-16 + valueInternal: 0.0030220088 newKeyListSerialized: 02000000000000000000e50c463b0000000000000000abaaaa3eabaaaa3e44010000000100000000e50c463b0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.18025488 + valueInternal: 0.6331344 ReferencePoseValue: valueInternal: -0.18025488 PoseValueList: [] @@ -18908,10 +18908,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.18025488 + valueInternal: 0.6331344 newKeyListSerialized: 020000000000000000001915223f0000000000000000abaaaa3eabaaaa3e440100000001000000001915223f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.98362 + valueInternal: -0.77369773 ReferencePoseValue: valueInternal: 0.98362 PoseValueList: [] @@ -18922,7 +18922,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.98362 + valueInternal: -0.77369773 newKeyListSerialized: 020000000000000000000e1146bf0000000000000000abaaaa3eabaaaa3e440100000001000000000e1146bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -19138,7 +19138,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.2200574e-16 + valueInternal: 0.023069648 ReferencePoseValue: valueInternal: 1.2200574e-16 PoseValueList: [] @@ -19149,10 +19149,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.2200574e-16 + valueInternal: 0.023069648 newKeyListSerialized: 020000000000000000008ffcbc3c0000000000000000abaaaa3eabaaaa3e440100000001000000008ffcbc3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -3.8535718e-17 + valueInternal: 0.0007349544 ReferencePoseValue: valueInternal: -3.8535718e-17 PoseValueList: [] @@ -19163,10 +19163,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -3.8535718e-17 + valueInternal: 0.0007349544 newKeyListSerialized: 02000000000000000000f4a9403a0000000000000000abaaaa3eabaaaa3e44010000000100000000f4a9403a0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.087155744 + valueInternal: 0.4942548 ReferencePoseValue: valueInternal: -0.087155744 PoseValueList: [] @@ -19177,10 +19177,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.087155744 + valueInternal: 0.4942548 newKeyListSerialized: 02000000000000000000f70efd3e0000000000000000abaaaa3eabaaaa3e44010000000100000000f70efd3e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9961947 + valueInternal: -0.8690106 ReferencePoseValue: valueInternal: 0.9961947 PoseValueList: [] @@ -19191,7 +19191,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9961947 + valueInternal: -0.8690106 newKeyListSerialized: 020000000000000000007b775ebf0000000000000000abaaaa3eabaaaa3e440100000001000000007b775ebf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -19676,7 +19676,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.08998402 + valueInternal: -0.11173194 ReferencePoseValue: valueInternal: 0.08998402 PoseValueList: [] @@ -19687,10 +19687,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.08998402 + valueInternal: -0.11173194 newKeyListSerialized: 02000000000000000000b7d3e4bd0000000000000000abaaaa3eabaaaa3e44010000000100000000b7d3e4bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.017015995 + valueInternal: -0.05399457 ReferencePoseValue: valueInternal: -0.017015995 PoseValueList: [] @@ -19701,10 +19701,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.017015995 + valueInternal: -0.05399457 newKeyListSerialized: 0200000000000000000069295dbd0000000000000000abaaaa3eabaaaa3e4401000000010000000069295dbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.1280659 + valueInternal: 0.34303504 ReferencePoseValue: valueInternal: -0.1280659 PoseValueList: [] @@ -19715,10 +19715,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.1280659 + valueInternal: 0.34303504 newKeyListSerialized: 020000000000000000004aa2af3e0000000000000000abaaaa3eabaaaa3e440100000001000000004aa2af3e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.98752844 + valueInternal: -0.9310898 ReferencePoseValue: valueInternal: 0.98752844 PoseValueList: [] @@ -19729,7 +19729,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.98752844 + valueInternal: -0.9310898 newKeyListSerialized: 02000000000000000000e75b6ebf0000000000000000abaaaa3eabaaaa3e44010000000100000000e75b6ebf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -19945,7 +19945,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -2.4258357e-16 + valueInternal: 0.016319372 ReferencePoseValue: valueInternal: -2.4258357e-16 PoseValueList: [] @@ -19956,10 +19956,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -2.4258357e-16 + valueInternal: 0.016319372 newKeyListSerialized: 0200000000000000000034b0853c0000000000000000abaaaa3eabaaaa3e4401000000010000000034b0853c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -1.0973908e-16 + valueInternal: -0.14385234 ReferencePoseValue: valueInternal: -1.0973908e-16 PoseValueList: [] @@ -19970,10 +19970,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.0973908e-16 + valueInternal: -0.14385234 newKeyListSerialized: 02000000000000000000074e13be0000000000000000abaaaa3eabaaaa3e44010000000100000000074e13be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.18469755 + valueInternal: 0.66374105 ReferencePoseValue: valueInternal: -0.18469755 PoseValueList: [] @@ -19984,10 +19984,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.18469755 + valueInternal: 0.66374105 newKeyListSerialized: 02000000000000000000efea293f0000000000000000abaaaa3eabaaaa3e44010000000100000000efea293f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9827954 + valueInternal: -0.73381835 ReferencePoseValue: valueInternal: 0.9827954 PoseValueList: [] @@ -19998,7 +19998,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9827954 + valueInternal: -0.73381835 newKeyListSerialized: 0200000000000000000085db3bbf0000000000000000abaaaa3eabaaaa3e4401000000010000000085db3bbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -20214,7 +20214,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.000000014887448 + valueInternal: -0.13972063 ReferencePoseValue: valueInternal: 0.000000014887448 PoseValueList: [] @@ -20225,10 +20225,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.000000014887448 + valueInternal: -0.13972063 newKeyListSerialized: 02000000000000000000ed120fbe0000000000000000abaaaa3eabaaaa3e44010000000100000000ed120fbe0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -6.391964e-10 + valueInternal: -0.0859377 ReferencePoseValue: valueInternal: -6.391964e-10 PoseValueList: [] @@ -20239,10 +20239,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -6.391964e-10 + valueInternal: -0.0859377 newKeyListSerialized: 020000000000000000001b00b0bd0000000000000000abaaaa3eabaaaa3e440100000001000000001b00b0bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.042895757 + valueInternal: 0.4454335 ReferencePoseValue: valueInternal: -0.042895757 PoseValueList: [] @@ -20253,10 +20253,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.042895757 + valueInternal: 0.4454335 newKeyListSerialized: 02000000000000000000dc0fe43e0000000000000000abaaaa3eabaaaa3e44010000000100000000dc0fe43e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9990796 + valueInternal: -0.8801609 ReferencePoseValue: valueInternal: 0.9990796 PoseValueList: [] @@ -20267,7 +20267,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9990796 + valueInternal: -0.8801609 newKeyListSerialized: 020000000000000000003a5261bf0000000000000000abaaaa3eabaaaa3e440100000001000000003a5261bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -20752,7 +20752,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.054216176 + valueInternal: -0.034832343 ReferencePoseValue: valueInternal: 0.054216176 PoseValueList: [] @@ -20763,10 +20763,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.054216176 + valueInternal: -0.034832343 newKeyListSerialized: 020000000000000000005cac0ebd0000000000000000abaaaa3eabaaaa3e440100000001000000005cac0ebd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.01317727 + valueInternal: -0.08704354 ReferencePoseValue: valueInternal: -0.01317727 PoseValueList: [] @@ -20777,10 +20777,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.01317727 + valueInternal: -0.08704354 newKeyListSerialized: 02000000000000000000e243b2bd0000000000000000abaaaa3eabaaaa3e44010000000100000000e243b2bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.25353977 + valueInternal: 0.6287977 ReferencePoseValue: valueInternal: -0.25353977 PoseValueList: [] @@ -20791,10 +20791,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.25353977 + valueInternal: 0.6287977 newKeyListSerialized: 02000000000000000000e3f8203f0000000000000000abaaaa3eabaaaa3e44010000000100000000e3f8203f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9657145 + valueInternal: -0.7718961 ReferencePoseValue: valueInternal: 0.9657145 PoseValueList: [] @@ -20805,7 +20805,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9657145 + valueInternal: -0.7718961 newKeyListSerialized: 02000000000000000000fc9a45bf0000000000000000abaaaa3eabaaaa3e44010000000100000000fc9a45bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -21021,7 +21021,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -1.5397508e-16 + valueInternal: -0.006810576 ReferencePoseValue: valueInternal: -1.5397508e-16 PoseValueList: [] @@ -21032,10 +21032,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.5397508e-16 + valueInternal: -0.006810576 newKeyListSerialized: 02000000000000000000412bdfbb0000000000000000abaaaa3eabaaaa3e44010000000100000000412bdfbb0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -3.4010369e-16 + valueInternal: -0.037440967 ReferencePoseValue: valueInternal: -3.4010369e-16 PoseValueList: [] @@ -21046,10 +21046,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -3.4010369e-16 + valueInternal: -0.037440967 newKeyListSerialized: 02000000000000000000b35b19bd0000000000000000abaaaa3eabaaaa3e44010000000100000000b35b19bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.16473773 + valueInternal: 0.6595794 ReferencePoseValue: valueInternal: -0.16473773 PoseValueList: [] @@ -21060,10 +21060,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.16473773 + valueInternal: 0.6595794 newKeyListSerialized: 0200000000000000000032da283f0000000000000000abaaaa3eabaaaa3e4401000000010000000032da283f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9863374 + valueInternal: -0.75067097 ReferencePoseValue: valueInternal: 0.9863374 PoseValueList: [] @@ -21074,7 +21074,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9863374 + valueInternal: -0.75067097 newKeyListSerialized: 02000000000000000000f92b40bf0000000000000000abaaaa3eabaaaa3e44010000000100000000f92b40bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -21290,7 +21290,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -1.8648887e-16 + valueInternal: -0.0153708225 ReferencePoseValue: valueInternal: -1.8648887e-16 PoseValueList: [] @@ -21301,10 +21301,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.8648887e-16 + valueInternal: -0.0153708225 newKeyListSerialized: 02000000000000000000e7d57bbc0000000000000000abaaaa3eabaaaa3e44010000000100000000e7d57bbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -6.858181e-17 + valueInternal: -0.034813665 ReferencePoseValue: valueInternal: -6.858181e-17 PoseValueList: [] @@ -21315,10 +21315,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -6.858181e-17 + valueInternal: -0.034813665 newKeyListSerialized: 02000000000000000000c6980ebd0000000000000000abaaaa3eabaaaa3e44010000000100000000c6980ebd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.07992057 + valueInternal: 0.46977198 ReferencePoseValue: valueInternal: -0.07992057 PoseValueList: [] @@ -21329,10 +21329,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.07992057 + valueInternal: 0.46977198 newKeyListSerialized: 02000000000000000000f485f03e0000000000000000abaaaa3eabaaaa3e44010000000100000000f485f03e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99680126 + valueInternal: -0.8819676 ReferencePoseValue: valueInternal: 0.99680126 PoseValueList: [] @@ -21343,7 +21343,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99680126 + valueInternal: -0.8819676 newKeyListSerialized: 02000000000000000000a1c861bf0000000000000000abaaaa3eabaaaa3e44010000000100000000a1c861bf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -21559,7 +21559,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.5051934 + valueInternal: 0.58969223 ReferencePoseValue: valueInternal: 0.5051934 PoseValueList: [] @@ -21570,10 +21570,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.5051934 + valueInternal: 0.58969223 newKeyListSerialized: 0200000000000000000012f6163f0000000000000000abaaaa3eabaaaa3e4401000000010000000012f6163f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.36912975 + valueInternal: -0.43866277 ReferencePoseValue: valueInternal: -0.36912975 PoseValueList: [] @@ -21584,10 +21584,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.36912975 + valueInternal: -0.43866277 newKeyListSerialized: 020000000000000000006898e0be0000000000000000abaaaa3eabaaaa3e440100000001000000006898e0be0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.06703907 + valueInternal: 0.3540516 ReferencePoseValue: valueInternal: 0.06703907 PoseValueList: [] @@ -21598,10 +21598,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.06703907 + valueInternal: 0.3540516 newKeyListSerialized: 020000000000000000004046b53e0000000000000000abaaaa3eabaaaa3e440100000001000000004046b53e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7771928 + valueInternal: 0.5783472 ReferencePoseValue: valueInternal: 0.7771928 PoseValueList: [] @@ -21612,7 +21612,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7771928 + valueInternal: 0.5783472 newKeyListSerialized: 02000000000000000000900e143f0000000000000000abaaaa3eabaaaa3e44010000000100000000900e143f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -21828,7 +21828,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.03356521 + valueInternal: -0.017112667 ReferencePoseValue: valueInternal: 0.03356521 PoseValueList: [] @@ -21839,10 +21839,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.03356521 + valueInternal: -0.017112667 newKeyListSerialized: 02000000000000000000dd2f8cbc0000000000000000abaaaa3eabaaaa3e44010000000100000000dd2f8cbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.01030245 + valueInternal: -0.024984494 ReferencePoseValue: valueInternal: 0.01030245 PoseValueList: [] @@ -21853,10 +21853,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.01030245 + valueInternal: -0.024984494 newKeyListSerialized: 0200000000000000000048acccbc0000000000000000abaaaa3eabaaaa3e4401000000010000000048acccbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.20185572 + valueInternal: 0.06675618 ReferencePoseValue: valueInternal: -0.20185572 PoseValueList: [] @@ -21867,10 +21867,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.20185572 + valueInternal: 0.06675618 newKeyListSerialized: 0200000000000000000077b7883d0000000000000000abaaaa3eabaaaa3e4401000000010000000077b7883d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.97878575 + valueInternal: -0.99731016 ReferencePoseValue: valueInternal: 0.97878575 PoseValueList: [] @@ -21881,7 +21881,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.97878575 + valueInternal: -0.99731016 newKeyListSerialized: 02000000000000000000b84f7fbf0000000000000000abaaaa3eabaaaa3e44010000000100000000b84f7fbf0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -22097,7 +22097,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -1.2891824e-16 + valueInternal: -0.01246169 ReferencePoseValue: valueInternal: -1.2891824e-16 PoseValueList: [] @@ -22108,10 +22108,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.2891824e-16 + valueInternal: -0.01246169 newKeyListSerialized: 020000000000000000001e2c4cbc0000000000000000abaaaa3eabaaaa3e440100000001000000001e2c4cbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 3.9140483e-17 + valueInternal: 0.021071797 ReferencePoseValue: valueInternal: 3.9140483e-17 PoseValueList: [] @@ -22122,10 +22122,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 3.9140483e-17 + valueInternal: 0.021071797 newKeyListSerialized: 02000000000000000000c39eac3c0000000000000000abaaaa3eabaaaa3e44010000000100000000c39eac3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.087155744 + valueInternal: -0.045577236 ReferencePoseValue: valueInternal: -0.087155744 PoseValueList: [] @@ -22136,10 +22136,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.087155744 + valueInternal: -0.045577236 newKeyListSerialized: 0200000000000000000032af3abd0000000000000000abaaaa3eabaaaa3e4401000000010000000032af3abd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9961947 + valueInternal: 0.9986612 ReferencePoseValue: valueInternal: 0.9961947 PoseValueList: [] @@ -22150,7 +22150,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9961947 + valueInternal: 0.9986612 newKeyListSerialized: 0200000000000000000043a87f3f0000000000000000abaaaa3eabaaaa3e4401000000010000000043a87f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -23711,7 +23711,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 2.331743e-26 + valueInternal: 0.020986166 ReferencePoseValue: valueInternal: 2.331743e-26 PoseValueList: [] @@ -23722,10 +23722,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 2.331743e-26 + valueInternal: 0.020986166 newKeyListSerialized: 020000000000000000002eebab3c0000000000000000abaaaa3eabaaaa3e440100000001000000002eebab3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 1.0188271e-27 + valueInternal: -0.00033505866 ReferencePoseValue: valueInternal: 1.0188271e-27 PoseValueList: [] @@ -23736,10 +23736,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.0188271e-27 + valueInternal: -0.00033505866 newKeyListSerialized: 02000000000000000000d0aaafb90000000000000000abaaaa3eabaaaa3e44010000000100000000d0aaafb90000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.20730051 + valueInternal: 0.20824216 ReferencePoseValue: valueInternal: 0.20730051 PoseValueList: [] @@ -23750,10 +23750,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.20730051 + valueInternal: 0.20824216 newKeyListSerialized: 020000000000000000006f3d553e0000000000000000abaaaa3eabaaaa3e440100000001000000006f3d553e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9782773 + valueInternal: 0.9778521 ReferencePoseValue: valueInternal: 0.9782773 PoseValueList: [] @@ -23764,7 +23764,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9782773 + valueInternal: 0.9778521 newKeyListSerialized: 0200000000000000000084547a3f0000000000000000abaaaa3eabaaaa3e4401000000010000000084547a3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -24518,7 +24518,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.0000029681603 + valueInternal: 0.004810615 ReferencePoseValue: valueInternal: 0.0000029681603 PoseValueList: [] @@ -24529,10 +24529,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.0000029681603 + valueInternal: 0.004810615 newKeyListSerialized: 020000000000000000005da29d3b0000000000000000abaaaa3eabaaaa3e440100000001000000005da29d3b0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.00000030712667 + valueInternal: -0.0015895684 ReferencePoseValue: valueInternal: 0.00000030712667 PoseValueList: [] @@ -24543,10 +24543,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.00000030712667 + valueInternal: -0.0015895684 newKeyListSerialized: 020000000000000000001159d0ba0000000000000000abaaaa3eabaaaa3e440100000001000000001159d0ba0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.10705551 + valueInternal: -0.06290296 ReferencePoseValue: valueInternal: -0.10705551 PoseValueList: [] @@ -24557,10 +24557,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.10705551 + valueInternal: -0.06290296 newKeyListSerialized: 0200000000000000000044d380bd0000000000000000abaaaa3eabaaaa3e4401000000010000000044d380bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99425304 + valueInternal: 0.9980068 ReferencePoseValue: valueInternal: 0.99425304 PoseValueList: [] @@ -24571,7 +24571,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99425304 + valueInternal: 0.9980068 newKeyListSerialized: 02000000000000000000607d7f3f0000000000000000abaaaa3eabaaaa3e44010000000100000000607d7f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -36086,7 +36086,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 0.07240499 + valueInternal: 0.11358028 ReferencePoseValue: valueInternal: 0.07240499 PoseValueList: [] @@ -36097,10 +36097,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.07240499 + valueInternal: 0.11358028 newKeyListSerialized: 02000000000000000000c79ce83d0000000000000000abaaaa3eabaaaa3e44010000000100000000c79ce83d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.029462025 + valueInternal: 0.06169392 ReferencePoseValue: valueInternal: 0.029462025 PoseValueList: [] @@ -36111,10 +36111,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.029462025 + valueInternal: 0.06169392 newKeyListSerialized: 02000000000000000000c4b27c3d0000000000000000abaaaa3eabaaaa3e44010000000100000000c4b27c3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.02896951 + valueInternal: -0.035066895 ReferencePoseValue: valueInternal: 0.02896951 PoseValueList: [] @@ -36125,10 +36125,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.02896951 + valueInternal: -0.035066895 newKeyListSerialized: 020000000000000000004ea20fbd0000000000000000abaaaa3eabaaaa3e440100000001000000004ea20fbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9965191 + valueInternal: 0.9909913 ReferencePoseValue: valueInternal: 0.9965191 PoseValueList: [] @@ -36139,7 +36139,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9965191 + valueInternal: 0.9909913 newKeyListSerialized: 020000000000000000009bb17d3f0000000000000000abaaaa3eabaaaa3e440100000001000000009bb17d3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -36355,7 +36355,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -1.7330692e-18 + valueInternal: -0.017116316 ReferencePoseValue: valueInternal: -1.7330692e-18 PoseValueList: [] @@ -36366,10 +36366,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.7330692e-18 + valueInternal: -0.017116316 newKeyListSerialized: 0200000000000000000084378cbc0000000000000000abaaaa3eabaaaa3e4401000000010000000084378cbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -7.5740844e-20 + valueInternal: -0.014065158 ReferencePoseValue: valueInternal: -7.5740844e-20 PoseValueList: [] @@ -36380,10 +36380,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -7.5740844e-20 + valueInternal: -0.014065158 newKeyListSerialized: 020000000000000000008c7166bc0000000000000000abaaaa3eabaaaa3e440100000001000000008c7166bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.043661624 + valueInternal: 0.085640594 ReferencePoseValue: valueInternal: 0.043661624 PoseValueList: [] @@ -36394,10 +36394,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.043661624 + valueInternal: 0.085640594 newKeyListSerialized: 020000000000000000005664af3d0000000000000000abaaaa3eabaaaa3e440100000001000000005664af3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9990464 + valueInternal: 0.9960798 ReferencePoseValue: valueInternal: 0.9990464 PoseValueList: [] @@ -36408,7 +36408,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9990464 + valueInternal: 0.9960798 newKeyListSerialized: 0200000000000000000016ff7e3f0000000000000000abaaaa3eabaaaa3e4401000000010000000016ff7e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -37162,7 +37162,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.00066565565 + valueInternal: -0.018234238 ReferencePoseValue: valueInternal: -0.00066565565 PoseValueList: [] @@ -37173,10 +37173,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.00066565565 + valueInternal: -0.018234238 newKeyListSerialized: 02000000000000000000f85f95bc0000000000000000abaaaa3eabaaaa3e44010000000100000000f85f95bc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.026877109 + valueInternal: -0.050366934 ReferencePoseValue: valueInternal: -0.026877109 PoseValueList: [] @@ -37187,10 +37187,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.026877109 + valueInternal: -0.050366934 newKeyListSerialized: 020000000000000000008f4d4ebd0000000000000000abaaaa3eabaaaa3e440100000001000000008f4d4ebd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.023239296 + valueInternal: -0.021035478 ReferencePoseValue: valueInternal: -0.023239296 PoseValueList: [] @@ -37201,10 +37201,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.023239296 + valueInternal: -0.021035478 newKeyListSerialized: 020000000000000000009852acbc0000000000000000abaaaa3eabaaaa3e440100000001000000009852acbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99936837 + valueInternal: 0.99834275 ReferencePoseValue: valueInternal: 0.99936837 PoseValueList: [] @@ -37215,7 +37215,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99936837 + valueInternal: 0.99834275 newKeyListSerialized: 0200000000000000000064937f3f0000000000000000abaaaa3eabaaaa3e4401000000010000000064937f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -37431,7 +37431,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 1.7128753e-17 + valueInternal: -0.000000011001248 ReferencePoseValue: valueInternal: 1.7128753e-17 PoseValueList: [] @@ -37442,10 +37442,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 1.7128753e-17 + valueInternal: -0.000000011001248 newKeyListSerialized: 0200000000000000000000003db20000000000000000abaaaa3eabaaaa3e4401000000010000000000003db20000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -1.7811548e-17 + valueInternal: -0.000000024097972 ReferencePoseValue: valueInternal: -1.7811548e-17 PoseValueList: [] @@ -37456,10 +37456,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -1.7811548e-17 + valueInternal: -0.000000024097972 newKeyListSerialized: 020000000000000000000000cfb20000000000000000abaaaa3eabaaaa3e440100000001000000000000cfb20000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7071068 + valueInternal: 0.7071067 ReferencePoseValue: valueInternal: 0.7071068 PoseValueList: [] @@ -37470,10 +37470,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7071068 + valueInternal: 0.7071067 newKeyListSerialized: 02000000000000000000f204353f0000000000000000abaaaa3eabaaaa3e44010000000100000000f204353f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7071068 + valueInternal: 0.70710695 ReferencePoseValue: valueInternal: 0.7071068 PoseValueList: [] @@ -37484,7 +37484,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7071068 + valueInternal: 0.70710695 newKeyListSerialized: 02000000000000000000f604353f0000000000000000abaaaa3eabaaaa3e44010000000100000000f604353f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -38238,7 +38238,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.029462025 + valueInternal: -0.054058768 ReferencePoseValue: valueInternal: -0.029462025 PoseValueList: [] @@ -38249,10 +38249,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.029462025 + valueInternal: -0.054058768 newKeyListSerialized: 02000000000000000000ba6c5dbd0000000000000000abaaaa3eabaaaa3e44010000000100000000ba6c5dbd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.07240499 + valueInternal: 0.15511884 ReferencePoseValue: valueInternal: 0.07240499 PoseValueList: [] @@ -38263,10 +38263,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.07240499 + valueInternal: 0.15511884 newKeyListSerialized: 0200000000000000000079d71e3e0000000000000000abaaaa3eabaaaa3e4401000000010000000079d71e3e0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9965191 + valueInternal: 0.9859836 ReferencePoseValue: valueInternal: 0.9965191 PoseValueList: [] @@ -38277,10 +38277,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9965191 + valueInternal: 0.9859836 newKeyListSerialized: 020000000000000000006c697c3f0000000000000000abaaaa3eabaaaa3e440100000001000000006c697c3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.02896951 + valueInternal: 0.029193554 ReferencePoseValue: valueInternal: -0.02896951 PoseValueList: [] @@ -38291,7 +38291,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.02896951 + valueInternal: 0.029193554 newKeyListSerialized: 020000000000000000005227ef3c0000000000000000abaaaa3eabaaaa3e440100000001000000005227ef3c0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -38507,7 +38507,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: 4.6144585e-18 + valueInternal: 0.04654016 ReferencePoseValue: valueInternal: 4.6144585e-18 PoseValueList: [] @@ -38518,10 +38518,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 4.6144585e-18 + valueInternal: 0.04654016 newKeyListSerialized: 02000000000000000000e5a03e3d0000000000000000abaaaa3eabaaaa3e44010000000100000000e5a03e3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 3.6744256e-18 + valueInternal: -0.015302908 ReferencePoseValue: valueInternal: 3.6744256e-18 PoseValueList: [] @@ -38532,10 +38532,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 3.6744256e-18 + valueInternal: -0.015302908 newKeyListSerialized: 020000000000000000000cb97abc0000000000000000abaaaa3eabaaaa3e440100000001000000000cb97abc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.043661624 + valueInternal: 0.091519535 ReferencePoseValue: valueInternal: 0.043661624 PoseValueList: [] @@ -38546,10 +38546,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.043661624 + valueInternal: 0.091519535 newKeyListSerialized: 02000000000000000000986ebb3d0000000000000000abaaaa3eabaaaa3e44010000000100000000986ebb3d0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.9990464 + valueInternal: 0.9945975 ReferencePoseValue: valueInternal: 0.9990464 PoseValueList: [] @@ -38560,7 +38560,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.9990464 + valueInternal: 0.9945975 newKeyListSerialized: 02000000000000000000f19d7e3f0000000000000000abaaaa3eabaaaa3e44010000000100000000f19d7e3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -39314,7 +39314,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -0.00066565565 + valueInternal: 0.0014848111 ReferencePoseValue: valueInternal: -0.00066565565 PoseValueList: [] @@ -39325,10 +39325,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.00066565565 + valueInternal: 0.0014848111 newKeyListSerialized: 02000000000000000000fe9dc23a0000000000000000abaaaa3eabaaaa3e44010000000100000000fe9dc23a0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.026877109 + valueInternal: -0.060889628 ReferencePoseValue: valueInternal: -0.026877109 PoseValueList: [] @@ -39339,10 +39339,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.026877109 + valueInternal: -0.060889628 newKeyListSerialized: 02000000000000000000676779bd0000000000000000abaaaa3eabaaaa3e44010000000100000000676779bd0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: -0.023239296 + valueInternal: -0.009740293 ReferencePoseValue: valueInternal: -0.023239296 PoseValueList: [] @@ -39353,10 +39353,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -0.023239296 + valueInternal: -0.009740293 newKeyListSerialized: 02000000000000000000c0951fbc0000000000000000abaaaa3eabaaaa3e44010000000100000000c0951fbc0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.99936837 + valueInternal: 0.9980959 ReferencePoseValue: valueInternal: 0.99936837 PoseValueList: [] @@ -39367,7 +39367,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.99936837 + valueInternal: 0.9980959 newKeyListSerialized: 0200000000000000000037837f3f0000000000000000abaaaa3eabaaaa3e4401000000010000000037837f3f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 @@ -39583,7 +39583,7 @@ MonoBehaviour: - valueInternal: 0 LocalRotationChannelList: - CurrentValue: - valueInternal: -5.6719134e-18 + valueInternal: -0.000000081956394 ReferencePoseValue: valueInternal: -5.6719134e-18 PoseValueList: [] @@ -39594,10 +39594,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: -5.6719134e-18 + valueInternal: -0.000000081956394 newKeyListSerialized: 020000000000000000000100b0b30000000000000000abaaaa3eabaaaa3e440100000001000000000100b0b30000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 4.4740276e-18 + valueInternal: -0.000000037252907 ReferencePoseValue: valueInternal: 4.4740276e-18 PoseValueList: [] @@ -39608,10 +39608,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 4.4740276e-18 + valueInternal: -0.000000037252907 newKeyListSerialized: 02000000000000000000010020b30000000000000000abaaaa3eabaaaa3e44010000000100000000010020b30000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7071068 + valueInternal: 0.7071065 ReferencePoseValue: valueInternal: 0.7071068 PoseValueList: [] @@ -39622,10 +39622,10 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7071068 + valueInternal: 0.7071065 newKeyListSerialized: 02000000000000000000ee04353f0000000000000000abaaaa3eabaaaa3e44010000000100000000ee04353f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: - valueInternal: 0.7071068 + valueInternal: 0.7071072 ReferencePoseValue: valueInternal: 0.7071068 PoseValueList: [] @@ -39636,7 +39636,7 @@ MonoBehaviour: newKeyListSerialized: 00000000 - LayerList: - CurrentOriginalValue: - valueInternal: 0.7071068 + valueInternal: 0.7071072 newKeyListSerialized: 02000000000000000000fa04353f0000000000000000abaaaa3eabaaaa3e44010000000100000000fa04353f0000000000000000abaaaa3eabaaaa3e44010000 - CurrentValue: valueInternal: 0 diff --git a/Assets/ResRaw/Maps/Map1/Map1.unity b/Assets/ResRaw/Maps/Map1/Map1.unity index 68fe3d034..1172a4563 100644 --- a/Assets/ResRaw/Maps/Map1/Map1.unity +++ b/Assets/ResRaw/Maps/Map1/Map1.unity @@ -26,7 +26,7 @@ RenderSettings: m_AmbientIntensity: 0.8050667 m_AmbientMode: 0 m_SubtractiveShadowColor: {r: 0.8679245, g: 0.8679245, b: 0.8679245, a: 1} - m_SkyboxMaterial: {fileID: 1558624448} + m_SkyboxMaterial: {fileID: 1670076013} m_HaloStrength: 0.5 m_FlareStrength: 1 m_FlareFadeSpeed: 3 @@ -556,65 +556,78 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: WaveHarmonic.Crest::WaveHarmonic.Crest.WaterRenderer - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 10 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, type: 3} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 10 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 4604655935489310866 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 - _Slices: 7 + _Slices: 9 _Resolution: 384 _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 100 _AnimatedWavesLod: - rid: 4604655776581025792 + rid: 4604655935489310867 _DepthLod: - rid: 4604655776581025793 + rid: 4604655935489310868 _LevelLod: - rid: 4604655776581025794 + rid: 4604655935489310869 _FoamLod: - rid: 4604655776581025795 + rid: 4604655935489310870 _DynamicWavesLod: - rid: 4604655776581025796 + rid: 4604655935489310871 _FlowLod: - rid: 4604655776581025797 + rid: 4604655935489310872 _ShadowLod: - rid: 4604655776581025798 + rid: 4604655935489310873 _AbsorptionLod: - rid: 4604655776581025799 + rid: 4604655935489310874 _ScatteringLod: - rid: 4604655776581025800 + rid: 4604655935489310875 _ClipLod: - rid: 4604655776581025801 + rid: 4604655935489310876 _AlbedoLod: - rid: 4604655776581025802 + rid: 4604655935489310877 _Reflections: - rid: 4604655776581025803 + rid: 4604655935489310878 _Underwater: - rid: 4604655776581025804 + rid: 4604655935489310879 + _Meniscus: + rid: 4604655935489310880 _Portals: - rid: 4604655776581025805 + rid: 4604655935489310881 _ShowWaterProxyPlane: 0 _EditModeFrameRate: 30 _FollowSceneCamera: 1 @@ -627,13 +640,29 @@ MonoBehaviour: _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: version: 2 RefIds: - - rid: 4604655776581025792 + - rid: 4604655935489310866 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 07f640ada75ec1a47aefdbab1c7cd068, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 1fa5bda715b77f44ab384955ea0b6e4f, type: 3} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 4604655935489310867 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 1 @@ -648,7 +677,7 @@ MonoBehaviour: _CollisionLayers: -1 _MaximumQueryCount: 4096 _BakedWaveData: {fileID: 0} - - rid: 4604655776581025793 + - rid: 4604655935489310868 type: {class: DepthLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 1 @@ -656,8 +685,9 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 1 _EnableSignedDistanceFields: 1 - - rid: 4604655776581025794 + - rid: 4604655935489310869 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -665,10 +695,10 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 300 _TextureFormat: 45 - - rid: 4604655776581025795 + - rid: 4604655935489310870 type: {class: FoamLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: - _Enabled: 1 + _Enabled: 0 _OverrideResolution: 1 _Resolution: 256 _TextureFormatMode: 100 @@ -676,7 +706,7 @@ MonoBehaviour: _SimulationFrequency: 30 _Prewarm: 1 _Settings: {fileID: 0} - - rid: 4604655776581025796 + - rid: 4604655935489310871 type: {class: DynamicWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -687,7 +717,7 @@ MonoBehaviour: _SimulationFrequency: 60 _AttenuationInShallows: 1 _Settings: {fileID: 0} - - rid: 4604655776581025797 + - rid: 4604655935489310872 type: {class: FlowLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -695,7 +725,7 @@ MonoBehaviour: _Resolution: 128 _TextureFormatMode: 100 _TextureFormat: 46 - - rid: 4604655776581025798 + - rid: 4604655935489310873 type: {class: ShadowLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 1 @@ -703,6 +733,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -711,7 +742,7 @@ MonoBehaviour: _CurrentFrameWeightHard: 0.15 _AllowNullLight: 0 _AllowNoShadows: 0 - - rid: 4604655776581025799 + - rid: 4604655935489310874 type: {class: AbsorptionLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -723,7 +754,7 @@ MonoBehaviour: _ShorelineColor: {r: 0.513, g: 1, b: 1, a: 0.153} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 - - rid: 4604655776581025800 + - rid: 4604655935489310875 type: {class: ScatteringLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -735,7 +766,7 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1, a: 1} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 - - rid: 4604655776581025801 + - rid: 4604655935489310876 type: {class: ClipLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -744,7 +775,7 @@ MonoBehaviour: _TextureFormatMode: 100 _TextureFormat: 5 _DefaultClippingState: 0 - - rid: 4604655776581025802 + - rid: 4604655935489310877 type: {class: AlbedoLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Enabled: 0 @@ -752,15 +783,15 @@ MonoBehaviour: _Resolution: 768 _TextureFormatMode: 100 _TextureFormat: 8 - - rid: 4604655776581025803 + - rid: 4604655935489310878 type: {class: WaterReflections, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Version: 0 - _Enabled: 1 + _Enabled: 0 _Mode: 1 _Layers: serializedVersion: 2 - m_Bits: 4294967295 + m_Bits: 1 _Resolution: 256 _RenderOnlySingleCamera: 0 _Sky: 1 @@ -787,7 +818,7 @@ MonoBehaviour: _Debug: _ShowHiddenObjects: 0 _DisableRecursiveRendering: 0 - - rid: 4604655776581025804 + - rid: 4604655935489310879 type: {class: UnderwaterRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: _Version: 0 @@ -797,10 +828,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -812,7 +839,13 @@ MonoBehaviour: _DisableHeightAboveWaterOptimization: 0 _DisableArtifactCorrection: 0 _OnlyReflectionCameras: 0 - - rid: 4604655776581025805 + - rid: 4604655935489310880 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} + - rid: 4604655935489310881 type: {class: PortalRenderer, ns: WaveHarmonic.Crest.Portals, asm: WaveHarmonic.Crest} data: --- !u!1 &862991151 @@ -1354,7 +1387,7 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!21 &1558624448 +--- !u!21 &1670076013 Material: serializedVersion: 8 m_ObjectHideFlags: 0 diff --git a/Assets/ResRaw/Water/Water Chunk1.prefab b/Assets/ResRaw/Water/Chunk 1.prefab similarity index 93% rename from Assets/ResRaw/Water/Water Chunk1.prefab rename to Assets/ResRaw/Water/Chunk 1.prefab index 1107697e9..a7964c7a6 100644 --- a/Assets/ResRaw/Water/Water Chunk1.prefab +++ b/Assets/ResRaw/Water/Chunk 1.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 5573293823876610619} - component: {fileID: 6121422689720352427} m_Layer: 4 - m_Name: Water Chunk1 + m_Name: Chunk 1 m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -49,9 +49,6 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 - m_RayTracingAccelStructBuildFlagsOverride: 0 - m_RayTracingAccelStructBuildFlags: 1 - m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: [] diff --git a/Assets/ResRaw/Water/Water Chunk1.prefab.meta b/Assets/ResRaw/Water/Chunk 1.prefab.meta similarity index 74% rename from Assets/ResRaw/Water/Water Chunk1.prefab.meta rename to Assets/ResRaw/Water/Chunk 1.prefab.meta index d1e84331a..297bdbdec 100644 --- a/Assets/ResRaw/Water/Water Chunk1.prefab.meta +++ b/Assets/ResRaw/Water/Chunk 1.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e4b1708c3e7d90f4ab48ff0a501d57f4 +guid: 1fa5bda715b77f44ab384955ea0b6e4f PrefabImporter: externalObjects: {} userData: diff --git a/Assets/ResRaw/Water/Water 1.mat b/Assets/ResRaw/Water/Water 1.mat new file mode 100644 index 000000000..670aa7119 --- /dev/null +++ b/Assets/ResRaw/Water/Water 1.mat @@ -0,0 +1,107 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-5994654682710206810 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 13 + hdPluginSubTargetMaterialVersions: + m_Keys: [] + m_Values: +--- !u!114 &-4042563326011365698 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Water 1 + m_Shader: {fileID: -6465566751694194690, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3} + m_Parent: {fileID: -876546973899608171, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - _ALPHATEST_ON + - _BUILTIN_ALPHATEST_ON + - _BUILTIN_AlphaClip + - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS + - _DOUBLESIDED_ON + - _ENABLE_FOG_ON_TRANSPARENT + - _SURFACE_TYPE_TRANSPARENT + - _TRANSPARENT_WRITES_MOTION_VEC + m_InvalidKeywords: [] + m_LightmapFlags: 2 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 1 + m_CustomRenderQueue: 3000 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPostpass + - TransparentBackface + - RayTracingPrepass + - MOTIONVECTORS + - SHADOWCASTER + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: [] + m_Floats: + - _AlphaDstBlend: 10 + - _BUILTIN_DstBlend: 10 + - _BUILTIN_QueueControl: 0 + - _BUILTIN_SrcBlend: 5 + - _BUILTIN_ZWrite: 1 + - _Crest_FoamEnabled: 1 + - _Crest_PlanarReflectionsEnabled: 1 + - _Crest_SSSEnabled: 0 + - _CullMode: 0 + - _CullModeForward: 0 + - _DstBlend: 10 + - _QueueControl: 0 + - _RefractionModel: 0 + - _SrcBlend: 5 + - _ZTestGBuffer: 3 + m_Colors: + - _Crest_Absorption: {r: 0.49963623, g: 0.49033588, b: 0.497967, a: 1} + - _Crest_AbsorptionColor: {r: 0.46502313, g: 0.4716981, b: 0.4662141, a: 0.1019608} + - _Crest_Scattering: {r: 0.11320752, g: 0.11320752, b: 0.11320752, a: 1} + - _DoubleSidedConstants: {r: 1, g: 1, b: 1, a: 0} + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &4748330692745026848 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 0 diff --git a/Assets/ResRaw/Water/Water1.mat.meta b/Assets/ResRaw/Water/Water 1.mat.meta similarity index 79% rename from Assets/ResRaw/Water/Water1.mat.meta rename to Assets/ResRaw/Water/Water 1.mat.meta index 491f6aaaf..8329b2b5d 100644 --- a/Assets/ResRaw/Water/Water1.mat.meta +++ b/Assets/ResRaw/Water/Water 1.mat.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1911984e2b778d241869f62e89b400fe +guid: 07f640ada75ec1a47aefdbab1c7cd068 NativeFormatImporter: externalObjects: {} mainObjectFileID: 2100000 diff --git a/Assets/ResRaw/Water/Water1.mat b/Assets/ResRaw/Water/Water1.mat deleted file mode 100644 index 901e4f98a..000000000 --- a/Assets/ResRaw/Water/Water1.mat +++ /dev/null @@ -1,250 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 8 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: Water1 - m_Shader: {fileID: -6465566751694194690, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3} - m_Parent: {fileID: 0} - m_ModifiedSerializedProperties: 0 - m_ValidKeywords: - - _ALPHATEST_ON - - _DOUBLESIDED_ON - - _ENABLE_FOG_ON_TRANSPARENT - - _MATERIAL_FEATURE_SPECULAR_COLOR - - _REFRACTION_PLANE - - _SPECULAR_SETUP - - _SURFACE_TYPE_TRANSPARENT - - _TRANSPARENT_WRITES_MOTION_VEC - m_InvalidKeywords: [] - m_LightmapFlags: 2 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 1 - m_CustomRenderQueue: 3000 - stringTagMap: - MotionVector: User - RenderType: Transparent - disabledShaderPasses: - - SHADOWCASTER - - MOTIONVECTORS - - TransparentDepthPostpass - - TransparentBackface - - RayTracingPrepass - m_LockedProperties: - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _Crest_CausticsDistortionTexture: - m_Texture: {fileID: 2800000, guid: 7aa3f69cfb40b429a865c45a7271c5f5, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _Crest_CausticsTexture: - m_Texture: {fileID: 2800000, guid: 1407209016967410da2ae6fdd4d97fc6, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _Crest_FoamTexture: - m_Texture: {fileID: 2800000, guid: 959dd0505e2c54585865f51257daa0e3, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _Crest_NormalMapTexture: - m_Texture: {fileID: 2800000, guid: 7aa3f69cfb40b429a865c45a7271c5f5, type: 3} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - unity_Lightmaps: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - unity_LightmapsInd: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - unity_ShadowMasks: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Ints: [] - m_Floats: - - CREST_FLOW: 0 - - _AddPrecomputedVelocity: 0 - - _AlphaClip: 1 - - _AlphaCutoffEnable: 1 - - _AlphaDstBlend: 10 - - _AlphaSrcBlend: 1 - - _AlphaToMask: 0 - - _BUILTIN_AlphaClip: 1 - - _BUILTIN_Blend: 0 - - _BUILTIN_CullMode: 0 - - _BUILTIN_DstBlend: 10 - - _BUILTIN_QueueControl: 0 - - _BUILTIN_QueueOffset: 0 - - _BUILTIN_SrcBlend: 5 - - _BUILTIN_Surface: 1 - - _BUILTIN_ZTest: 4 - - _BUILTIN_ZWrite: 1 - - _BUILTIN_ZWriteControl: 1 - - _Blend: 0 - - _BlendMode: 0 - - _BlendModePreserveSpecular: 0 - - _CastShadows: 0 - - _ConservativeDepthOffsetEnable: 0 - - _Crest_AlbedoEnabled: 0 - - _Crest_AlbedoIgnoreFoam: 1 - - _Crest_AmbientTerm: 1 - - _Crest_Anisotropy: 0.5 - - _Crest_CausticsDepthOfField: 6 - - _Crest_CausticsDistortionScale: 250 - - _Crest_CausticsDistortionStrength: 0.173 - - _Crest_CausticsEnabled: 1 - - _Crest_CausticsFocalDepth: 2 - - _Crest_CausticsMotionBlur: 1 - - _Crest_CausticsScrollSpeed: 1 - - _Crest_CausticsStrength: 1.61 - - _Crest_CausticsTextureAverage: 0.07 - - _Crest_CausticsTextureScale: 50.6 - - _Crest_DirectTerm: 1 - - _Crest_FoamEnabled: 1 - - _Crest_FoamFeather: 0.75 - - _Crest_FoamIntensityAlbedo: 1 - - _Crest_FoamNormalStrength: 1 - - _Crest_FoamScale: 5 - - _Crest_FoamScrollSpeed: 1 - - _Crest_FoamSmoothness: 0.7 - - _Crest_MinimumReflectionDirectionY: 0 - - _Crest_NormalMapEnabled: 1 - - _Crest_NormalMapScale: 10.8 - - _Crest_NormalMapScrollSpeed: 1 - - _Crest_NormalMapStrength: 0.33 - - _Crest_NormalsStrengthOverall: 0.197 - - _Crest_Occlusion: 1 - - _Crest_OcclusionUnderwater: 0 - - _Crest_PlanarReflectionsDistortion: 1 - - _Crest_PlanarReflectionsEnabled: 1 - - _Crest_PlanarReflectionsIntensity: 1 - - _Crest_PlanarReflectionsRoughness: 1 - - _Crest_RefractionStrength: 1 - - _Crest_RefractiveIndexOfWater: 1.646 - - _Crest_SSSDirectionalFalloff: 2 - - _Crest_SSSEnabled: 1 - - _Crest_SSSIntensity: 10 - - _Crest_SSSPinchFalloff: 1.5 - - _Crest_SSSPinchMaximum: 1.67 - - _Crest_SSSPinchMinimum: 0.57 - - _Crest_ShadowCasterThreshold: 0.5 - - _Crest_ShadowsAffectsAmbientFactor: 0.5 - - _Crest_ShadowsEnabled: 1 - - _Crest_Smoothness: 0.9 - - _Crest_SmoothnessFalloff: 0.5 - - _Crest_SmoothnessFar: 0.4 - - _Crest_SmoothnessFarDistance: 4000 - - _Crest_Specular: 0.25 - - _Crest_TotalInternalReflectionIntensity: 1 - - _Crest_Version: 0 - - _Cull: 0 - - _CullMode: 0 - - _CullModeForward: 0 - - _DepthOffsetEnable: 0 - - _DoubleSidedEnable: 1 - - _DoubleSidedGIMode: 0 - - _DoubleSidedNormalMode: 2 - - _DstBlend: 10 - - _DstBlend2: 10 - - _EnableBlendModePreserveSpecularLighting: 0 - - _EnableFogOnTransparent: 1 - - _ExcludeFromTUAndAA: 0 - - _MaterialID: 4 - - _MaterialTypeMask: 16 - - _OpaqueCullMode: 2 - - _PerPixelSorting: 0 - - _QueueControl: 0 - - _QueueOffset: 0 - - _RayTracing: 0 - - _ReceiveShadows: 1 - - _ReceivesSSR: 1 - - _ReceivesSSRTransparent: 1 - - _RefractionModel: 1 - - _RenderQueueType: 3 - - _RequireSplitLighting: 0 - - _SrcBlend: 5 - - _StencilRef: 0 - - _StencilRefDepth: 24 - - _StencilRefDistortionVec: 4 - - _StencilRefGBuffer: 10 - - _StencilRefMV: 40 - - _StencilWriteMask: 6 - - _StencilWriteMaskDepth: 25 - - _StencilWriteMaskDistortionVec: 4 - - _StencilWriteMaskGBuffer: 15 - - _StencilWriteMaskMV: 41 - - _SupportDecals: 1 - - _Surface: 1 - - _SurfaceType: 1 - - _TransmissionEnable: 1 - - _TransparentBackfaceEnable: 0 - - _TransparentCullMode: 2 - - _TransparentDepthPostpassEnable: 0 - - _TransparentDepthPrepassEnable: 0 - - _TransparentSortPriority: 0 - - _TransparentWritingMotionVec: 1 - - _TransparentZWrite: 1 - - _UseShadowThreshold: 0 - - _WorkflowMode: 0 - - _ZTest: 4 - - _ZTestDepthEqualForOpaque: 4 - - _ZTestGBuffer: 3 - - _ZTestTransparent: 4 - - _ZWrite: 1 - - _ZWriteControl: 1 - m_Colors: - - _Crest_Absorption: {r: 7.7473936, g: 6.665305, b: 9.93459, a: 1} - - _Crest_AbsorptionColor: {r: 0.29803923, g: 0.3529412, b: 0.21176471, a: 1} - - _Crest_Scattering: {r: 0.19378929, g: 0.3207547, b: 0, a: 1} - - _DoubleSidedConstants: {r: 1, g: 1, b: 1, a: 0} - - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} - m_BuildTextureStacks: [] - m_AllowLocking: 1 ---- !u!114 &5834112337178765781 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 9 ---- !u!114 &6553897719873794358 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 0 ---- !u!114 &8806993520622682055 -MonoBehaviour: - m_ObjectHideFlags: 11 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: da692e001514ec24dbc4cca1949ff7e8, type: 3} - m_Name: - m_EditorClassIdentifier: - version: 13 - hdPluginSubTargetMaterialVersions: - m_Keys: [] - m_Values: diff --git a/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatScene.prefab b/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatScene.prefab index 10faead71..e2c22122a 100644 --- a/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatScene.prefab +++ b/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatScene.prefab @@ -1643,28 +1643,38 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 150 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, type: 3} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 150 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 1002 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 _Slices: 7 @@ -1672,6 +1682,7 @@ MonoBehaviour: _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -1701,6 +1712,8 @@ MonoBehaviour: rid: 162836781179600905 _Underwater: rid: 162836781179600906 + _Meniscus: + rid: 1003 _Portals: rid: 162836781179600907 _ShowWaterProxyPlane: 0 @@ -1712,15 +1725,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 - _DisableChunks: 0 - _UniformTiles: 0 - _DisableSkirt: 0 _DrawLodOutline: 0 _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -1750,6 +1759,30 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 1002 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, + type: 3} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 1003 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 162836781179600896 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: @@ -1773,6 +1806,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 162836781179600898 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -1820,6 +1854,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -1890,10 +1925,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -2197,12 +2228,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: 4fde516347f8f410cb7bf7ec2b66c163, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -2212,7 +2245,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatsScene.prefab b/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatsScene.prefab index 2db0ec690..884ef5fd6 100644 --- a/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatsScene.prefab +++ b/Assets/Samples/Crest/5.4.2/Boats/Prefabs/Boats_BoatsScene.prefab @@ -45,28 +45,38 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 150 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, type: 3} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 150 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 1002 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 _Slices: 7 @@ -74,6 +84,7 @@ MonoBehaviour: _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -103,6 +114,8 @@ MonoBehaviour: rid: 162836781179600921 _Underwater: rid: 162836781179600922 + _Meniscus: + rid: 1003 _Portals: rid: 162836781179600923 _ShowWaterProxyPlane: 0 @@ -114,15 +127,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 - _DisableChunks: 0 - _UniformTiles: 0 - _DisableSkirt: 0 _DrawLodOutline: 0 _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -152,6 +161,30 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 1002 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, + type: 3} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 1003 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 162836781179600912 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: @@ -175,6 +208,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 162836781179600914 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -222,6 +256,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -292,10 +327,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -370,12 +401,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: 28a29b5ef0c644735b5d7ba47d2863d4, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 180 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 32 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: 32 @@ -385,7 +418,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Materials/Examples_Water.mat b/Assets/Samples/Crest/5.4.2/Examples/Materials/Examples_Water.mat index 7d66bfdcd..3b706e5d1 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Materials/Examples_Water.mat +++ b/Assets/Samples/Crest/5.4.2/Examples/Materials/Examples_Water.mat @@ -59,9 +59,9 @@ Material: - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_InvalidKeywords: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Examples_Scenes.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Examples_Scenes.prefab index 4e778741b..03c3ebd93 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Examples_Scenes.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Examples_Scenes.prefab @@ -314,12 +314,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: e13a1902b10e34e9fb08e1d09e39b5d4, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 32 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.35 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -329,7 +331,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: @@ -1365,27 +1367,37 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 10 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: d82d92d8d8f214cd0b8bf7c185b2c341, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 0} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 10 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 1013 _ScaleRange: {x: 8, y: 8} _DropDetailHeightBasedOnWaves: 0.081 _Slices: 7 @@ -1393,6 +1405,7 @@ MonoBehaviour: _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 2613380069347621712} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -1422,6 +1435,8 @@ MonoBehaviour: rid: 1009 _Underwater: rid: 1010 + _Meniscus: + rid: 1014 _Portals: rid: 1011 _ShowWaterProxyPlane: 0 @@ -1433,15 +1448,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 - _DisableChunks: 0 - _UniformTiles: 0 - _DisableSkirt: 0 _DrawLodOutline: 0 _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -1467,6 +1478,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 1002 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -1514,6 +1526,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -1584,10 +1597,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -1618,6 +1627,29 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 1013 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: d82d92d8d8f214cd0b8bf7c185b2c341, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 0} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 1014 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 5163698739167625228 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_OverrideGlobalWaves.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_OverrideGlobalWaves.prefab index ac7a3238b..e78afeda2 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_OverrideGlobalWaves.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_OverrideGlobalWaves.prefab @@ -56,12 +56,14 @@ MonoBehaviour: _Spectrum: {fileID: 0} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 1 _WindSpeed: 3 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -71,7 +73,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: @@ -80,6 +82,7 @@ MonoBehaviour: data: _Input: {fileID: 5261791568129114886} _Texture: {fileID: 2800000, guid: b922f588948724e039eadd46288af89d, type: 3} + _Multiplier: {x: 1, y: 1, z: 1, w: 1} _NegativeValues: 1 --- !u!1001 &5419066683695935889 PrefabInstance: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_ShaderGraphInput.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_ShaderGraphInput.prefab index cfb078dac..f25c83fca 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_ShaderGraphInput.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_ShaderGraphInput.prefab @@ -179,51 +179,6 @@ PrefabInstance: propertyPath: m_AnchorMin.x value: 1 objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: m_Enabled - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.size - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_Mode - value: 6 - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_Target - value: - objectReference: {fileID: 8893367339784545046} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_CallState - value: 2 - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName - value: SetActive - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName - value: UnityEngine.GameObject, UnityEngine - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_BoolArgument - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 5628891711212661418, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - propertyPath: _OnHighDefinitionPipeline.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName - value: UnityEngine.Object, UnityEngine - objectReference: {fileID: 0} - target: {fileID: 5655619906866042202, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, type: 3} propertyPath: m_LocalPosition.x @@ -299,9 +254,3 @@ Transform: type: 3} m_PrefabInstance: {fileID: 7420766973803980796} m_PrefabAsset: {fileID: 0} ---- !u!1 &8893367339784545046 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 2130284292857808106, guid: 8b98a14ae91dd498d8f577f0f8f4aff1, - type: 3} - m_PrefabInstance: {fileID: 7420766973803980796} - m_PrefabAsset: {fileID: 0} diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_TrochoidalWaves.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_TrochoidalWaves.prefab index 3a1d9aca6..cd14769e6 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_TrochoidalWaves.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_TrochoidalWaves.prefab @@ -56,16 +56,19 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: 6b50b5218dbe2488fb5d00db49d15dae, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 1 _WindSpeed: 150 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _Swell: 0 _ReverseWaveWeight: 0 _ComponentsPerOctave: 8 _RandomSeed: 0 - _Version: 1 + _ManualGeneration: 0 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WaveComparison.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WaveComparison.prefab index 6406cfb41..163512eed 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WaveComparison.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WaveComparison.prefab @@ -212,16 +212,19 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: e13a1902b10e34e9fb08e1d09e39b5d4, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: -58.00273 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _Swell: 0 _ReverseWaveWeight: 0.5 _ComponentsPerOctave: 8 _RandomSeed: 0 - _Version: 1 + _ManualGeneration: 0 + _Version: 2 references: version: 2 RefIds: @@ -422,12 +425,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: e13a1902b10e34e9fb08e1d09e39b5d4, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -437,7 +442,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WavePatch.prefab b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WavePatch.prefab index 924409b03..76134212f 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WavePatch.prefab +++ b/Assets/Samples/Crest/5.4.2/Examples/Prefabs/Scenes/Examples_WavePatch.prefab @@ -58,12 +58,14 @@ MonoBehaviour: _Spectrum: {fileID: 0} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 0 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 32 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -73,7 +75,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples.unity b/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples.unity index 8d30d77e2..28105ef42 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples.unity +++ b/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 9 + serializedVersion: 10 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -42,8 +42,8 @@ RenderSettings: --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 + serializedVersion: 13 + m_BakeOnSceneLoad: 1 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -66,9 +66,6 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 1 @@ -96,9 +93,8 @@ LightmapSettings: m_ExportTrainingData: 0 m_TrainingDataDestination: TrainingData m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 4890085278179872738, guid: 6e72aca972f324f7886200f86939d735, - type: 2} + m_LightingDataAsset: {fileID: 112000000, guid: be61fd374ee0fad46a337d78e0ed01ae, type: 2} + m_LightingSettings: {fileID: 4890085278179872738, guid: 6e72aca972f324f7886200f86939d735, type: 2} --- !u!196 &4 NavMeshSettings: serializedVersion: 2 @@ -771,28 +767,17 @@ MonoBehaviour: m_MoveRepeatDelay: 0.5 m_MoveRepeatRate: 0.1 m_XRTrackingOrigin: {fileID: 0} - m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_PointAction: {fileID: 1054132383583890850, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_MoveAction: {fileID: 3710738434707379630, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_SubmitAction: {fileID: 2064916234097673511, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_CancelAction: {fileID: -1967631576421560919, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_LeftClickAction: {fileID: 8056856818456041789, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_MiddleClickAction: {fileID: 3279352641294131588, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_RightClickAction: {fileID: 3837173908680883260, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_ScrollWheelAction: {fileID: 4502412055082496612, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_TrackedDevicePositionAction: {fileID: 4754684134866288074, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} - m_TrackedDeviceOrientationAction: {fileID: 1025543830046995696, guid: ca9f5fa95ffab41fb9a615ab714db018, - type: 3} + m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_PointAction: {fileID: 1054132383583890850, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MoveAction: {fileID: 3710738434707379630, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_SubmitAction: {fileID: 2064916234097673511, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_CancelAction: {fileID: -1967631576421560919, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_LeftClickAction: {fileID: 8056856818456041789, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MiddleClickAction: {fileID: 3279352641294131588, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_RightClickAction: {fileID: 3837173908680883260, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_ScrollWheelAction: {fileID: 4502412055082496612, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDevicePositionAction: {fileID: 4754684134866288074, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDeviceOrientationAction: {fileID: 1025543830046995696, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} m_DeselectOnBackgroundClick: 1 m_PointerBehavior: 0 m_CursorLockBehavior: 0 @@ -882,6 +867,11 @@ MeshRenderer: m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -903,6 +893,7 @@ MeshRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 @@ -938,58 +929,47 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1845454492} m_Modifications: - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalRotation.w value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalRotation.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalRotation.y value: 0.9063079 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalRotation.z value: -0.42261827 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 105 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 15 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 5304508333967466499, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + - target: {fileID: 5304508333967466499, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} propertyPath: m_Name value: Sun objectReference: {fileID: 0} @@ -1000,8 +980,7 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} --- !u!4 &1364867124 stripped Transform: - m_CorrespondingSourceObject: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, - type: 3} + m_CorrespondingSourceObject: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} m_PrefabInstance: {fileID: 1364867123} m_PrefabAsset: {fileID: 0} --- !u!1 &1682107712 @@ -1093,58 +1072,47 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1845454492} m_Modifications: - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalRotation.x value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalRotation.y value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalRotation.z value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 2942909709672342223, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + - target: {fileID: 2942909709672342223, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} propertyPath: m_Name value: Atmosphere objectReference: {fileID: 0} @@ -1155,8 +1123,7 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} --- !u!4 &1734491900 stripped Transform: - m_CorrespondingSourceObject: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, - type: 3} + m_CorrespondingSourceObject: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} m_PrefabInstance: {fileID: 1734491899} m_PrefabAsset: {fileID: 0} --- !u!1 &1835631273 @@ -1304,58 +1271,47 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1845454492} m_Modifications: - - target: {fileID: 963553959586484309, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 963553959586484309, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_Name value: Lighting objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalRotation.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalRotation.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalRotation.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -1366,8 +1322,7 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} --- !u!4 &1886939755 stripped Transform: - m_CorrespondingSourceObject: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, - type: 3} + m_CorrespondingSourceObject: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} m_PrefabInstance: {fileID: 1886939754} m_PrefabAsset: {fileID: 0} --- !u!1 &2128464135 diff --git a/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples/LightingData.asset b/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples/LightingData.asset index f567fd78e..46eda0b3d 100644 Binary files a/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples/LightingData.asset and b/Assets/Samples/Crest/5.4.2/Examples/Scenes/Examples/LightingData.asset differ diff --git a/Assets/Samples/Crest/5.4.2/Examples/Shaders/Sine Wave.shadergraph b/Assets/Samples/Crest/5.4.2/Examples/Shaders/Sine Wave.shadergraph index d0846debc..c477183ea 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Shaders/Sine Wave.shadergraph +++ b/Assets/Samples/Crest/5.4.2/Examples/Shaders/Sine Wave.shadergraph @@ -36,12 +36,6 @@ { "m_Id": "cd0f156c542b4619b7281770039836b5" }, - { - "m_Id": "f4c1405668a94fcea48969bdf227848c" - }, - { - "m_Id": "0c7cf37480bc4ef0b974856817777a03" - }, { "m_Id": "98621ce2e8384650a727003ac9fe6ae3" }, @@ -273,12 +267,6 @@ "m_Blocks": [ { "m_Id": "7adbe727b57a468eaafd52267fc097d2" - }, - { - "m_Id": "f4c1405668a94fcea48969bdf227848c" - }, - { - "m_Id": "0c7cf37480bc4ef0b974856817777a03" } ] }, @@ -301,10 +289,7 @@ "m_Id": "1b9d4d1e66054d0f8c6930b3fa52d986" }, { - "m_Id": "666e5ce71520453f886b902afbe47d67" - }, - { - "m_Id": "a7a5bf24ad3d443f911d872cdffa4e6c" + "m_Id": "d844ace01485410e80662a30ebca0fe0" } ] } @@ -324,21 +309,6 @@ "m_Labels": [] } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", - "m_ObjectId": "0399ec53adad4e459c8dcbc7631a3d5b", - "m_Id": 0, - "m_DisplayName": "Alpha", - "m_SlotType": 0, - "m_Hidden": false, - "m_ShaderOutputName": "Alpha", - "m_StageCapability": 2, - "m_Value": 1.0, - "m_DefaultValue": 1.0, - "m_Labels": [] -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.BlockNode", @@ -397,40 +367,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.BlockNode", - "m_ObjectId": "0c7cf37480bc4ef0b974856817777a03", - "m_Group": { - "m_Id": "" - }, - "m_Name": "SurfaceDescription.Alpha", - "m_DrawState": { - "m_Expanded": true, - "m_Position": { - "serializedVersion": "2", - "x": 0.0, - "y": 0.0, - "width": 0.0, - "height": 0.0 - } - }, - "m_Slots": [ - { - "m_Id": "0399ec53adad4e459c8dcbc7631a3d5b" - } - ], - "synonyms": [], - "m_Precision": 0, - "m_PreviewExpanded": true, - "m_DismissedVersion": 0, - "m_PreviewMode": 0, - "m_CustomColors": { - "m_SerializableColors": [] - }, - "m_SerializedDescriptor": "SurfaceDescription.Alpha" -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", @@ -479,39 +415,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", - "m_ObjectId": "0f03685dd1484a778c8ad3dbf87e9719", - "m_MaterialNeedsUpdateHash": 0, - "m_SurfaceType": 0, - "m_RenderingPass": 1, - "m_BlendMode": 0, - "m_ZTest": 4, - "m_ZWrite": false, - "m_TransparentCullMode": 2, - "m_OpaqueCullMode": 2, - "m_SortPriority": 0, - "m_AlphaTest": false, - "m_ExcludeFromTUAndAA": false, - "m_TransparentDepthPrepass": false, - "m_TransparentDepthPostpass": false, - "m_SupportLodCrossFade": false, - "m_DoubleSidedMode": 0, - "m_DOTSInstancing": false, - "m_CustomVelocity": false, - "m_Tessellation": false, - "m_TessellationMode": 0, - "m_TessellationFactorMinDistance": 20.0, - "m_TessellationFactorMaxDistance": 50.0, - "m_TessellationFactorTriangleSize": 100.0, - "m_TessellationShapeFactor": 0.75, - "m_TessellationBackFaceCullEpsilon": -0.25, - "m_TessellationMaxDisplacement": 0.009999999776482582, - "m_Version": 1, - "inspectorFoldoutMask": 0 -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", @@ -527,6 +430,12 @@ "m_Labels": [] } +{ + "m_SGVersion": 2, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget", + "m_ObjectId": "186d62d80d5342778df6756e00152eb0" +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", @@ -569,8 +478,8 @@ }, "m_AllowMaterialOverride": false, "m_SurfaceType": 0, - "m_ZWriteControl": 0, - "m_ZTestMode": 4, + "m_ZWriteControl": 2, + "m_ZTestMode": 8, "m_AlphaMode": 0, "m_RenderFace": 2, "m_AlphaClip": false, @@ -772,12 +681,6 @@ } } -{ - "m_SGVersion": 2, - "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalUnlitSubTarget", - "m_ObjectId": "4beb3457ecff455e81b2a38737480fde" -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", @@ -899,14 +802,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitData", - "m_ObjectId": "56cb2ffc93b44d849bf40c5e58b2f9c3", - "m_EnableShadowMatte": false, - "m_DistortionOnly": false -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", @@ -1091,29 +986,6 @@ "m_Labels": [] } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDTarget", - "m_ObjectId": "666e5ce71520453f886b902afbe47d67", - "m_ActiveSubTarget": { - "m_Id": "ad6b12314a1a4bfdab2f7dc03c885480" - }, - "m_Datas": [ - { - "m_Id": "86dc2941a072419a906d1d9d771faa2e" - }, - { - "m_Id": "0f03685dd1484a778c8ad3dbf87e9719" - }, - { - "m_Id": "56cb2ffc93b44d849bf40c5e58b2f9c3" - } - ], - "m_CustomEditorGUI": "", - "m_SupportVFX": false, - "m_SupportComputeForVertexSetup": false -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInUnlitSubTarget", @@ -1454,25 +1326,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.BuiltinData", - "m_ObjectId": "86dc2941a072419a906d1d9d771faa2e", - "m_Distortion": false, - "m_DistortionMode": 0, - "m_DistortionDepthTest": true, - "m_AddPrecomputedVelocity": false, - "m_TransparentWritesMotionVec": false, - "m_DepthOffset": false, - "m_ConservativeDepthOffset": false, - "m_TransparencyFog": true, - "m_AlphaTestShadow": false, - "m_BackThenFrontRendering": false, - "m_TransparentDepthPrepass": false, - "m_TransparentDepthPostpass": false, - "m_SupportLodCrossFade": false -} - { "m_SGVersion": 1, "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", @@ -1501,36 +1354,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot", - "m_ObjectId": "8ed07cb6ee9245b195f845215e00d7ed", - "m_Id": 0, - "m_DisplayName": "Emission", - "m_SlotType": 0, - "m_Hidden": false, - "m_ShaderOutputName": "Emission", - "m_StageCapability": 2, - "m_Value": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "m_DefaultValue": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "m_Labels": [], - "m_ColorMode": 1, - "m_DefaultColor": { - "r": 0.0, - "g": 0.0, - "b": 0.0, - "a": 1.0 - } -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", @@ -1678,34 +1501,6 @@ } } -{ - "m_SGVersion": 1, - "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", - "m_ObjectId": "a7a5bf24ad3d443f911d872cdffa4e6c", - "m_Datas": [], - "m_ActiveSubTarget": { - "m_Id": "4beb3457ecff455e81b2a38737480fde" - }, - "m_AllowMaterialOverride": false, - "m_SurfaceType": 0, - "m_ZTestMode": 4, - "m_ZWriteControl": 0, - "m_AlphaMode": 0, - "m_RenderFace": 2, - "m_AlphaClip": false, - "m_CastShadows": true, - "m_ReceiveShadows": true, - "m_SupportsLODCrossFade": false, - "m_CustomEditorGUI": "", - "m_SupportVFX": false -} - -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDUnlitSubTarget", - "m_ObjectId": "ad6b12314a1a4bfdab2f7dc03c885480" -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.DynamicValueMaterialSlot", @@ -2037,6 +1832,28 @@ } } +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget", + "m_ObjectId": "d844ace01485410e80662a30ebca0fe0", + "m_Datas": [], + "m_ActiveSubTarget": { + "m_Id": "186d62d80d5342778df6756e00152eb0" + }, + "m_AllowMaterialOverride": false, + "m_SurfaceType": 0, + "m_ZTestMode": 8, + "m_ZWriteControl": 2, + "m_AlphaMode": 0, + "m_RenderFace": 2, + "m_AlphaClip": false, + "m_CastShadows": false, + "m_ReceiveShadows": true, + "m_SupportsLODCrossFade": false, + "m_CustomEditorGUI": "", + "m_SupportVFX": false +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", @@ -2181,40 +1998,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.BlockNode", - "m_ObjectId": "f4c1405668a94fcea48969bdf227848c", - "m_Group": { - "m_Id": "" - }, - "m_Name": "SurfaceDescription.Emission", - "m_DrawState": { - "m_Expanded": true, - "m_Position": { - "serializedVersion": "2", - "x": 0.0, - "y": 0.0, - "width": 0.0, - "height": 0.0 - } - }, - "m_Slots": [ - { - "m_Id": "8ed07cb6ee9245b195f845215e00d7ed" - } - ], - "synonyms": [], - "m_Precision": 0, - "m_PreviewExpanded": true, - "m_DismissedVersion": 0, - "m_PreviewMode": 0, - "m_CustomColors": { - "m_SerializableColors": [] - }, - "m_SerializedDescriptor": "SurfaceDescription.Emission" -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.UVNode", diff --git a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowLeft.png.meta b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowLeft.png.meta index 8d2bc67fa..f1ad98103 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowLeft.png.meta +++ b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowLeft.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowRight.png.meta b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowRight.png.meta index 64b38620d..9cb24c9c2 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowRight.png.meta +++ b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/ArrowRight.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/Flask.png.meta b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/Flask.png.meta index 48736e608..c224b9c7f 100644 --- a/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/Flask.png.meta +++ b/Assets/Samples/Crest/5.4.2/Examples/Sprites/MaterialIcons/Flask.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Assets/Samples/Crest/5.4.2/Main/Materials/Main_Water.mat b/Assets/Samples/Crest/5.4.2/Main/Materials/Main_Water.mat index cf1f7b701..7ef763cb9 100644 --- a/Assets/Samples/Crest/5.4.2/Main/Materials/Main_Water.mat +++ b/Assets/Samples/Crest/5.4.2/Main/Materials/Main_Water.mat @@ -29,9 +29,9 @@ Material: - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_InvalidKeywords: [] diff --git a/Assets/Samples/Crest/5.4.2/Main/Prefabs/Main_Scene.prefab b/Assets/Samples/Crest/5.4.2/Main/Prefabs/Main_Scene.prefab index 2a5ca3572..ab059e4ab 100644 --- a/Assets/Samples/Crest/5.4.2/Main/Prefabs/Main_Scene.prefab +++ b/Assets/Samples/Crest/5.4.2/Main/Prefabs/Main_Scene.prefab @@ -56,12 +56,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: ce5a3f1aff978418c90b45d58f574528, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 0 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: 180 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -71,7 +73,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: @@ -296,34 +298,45 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 150 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: d340825b528984c3ea62563460223aa4, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 0} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 150 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 1010 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 - _Slices: 7 + _Slices: 9 _Resolution: 384 _GeometryDownSampleFactor: 4 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -353,6 +366,8 @@ MonoBehaviour: rid: 1720327093404827649 _Underwater: rid: 1720327093404827648 + _Meniscus: + rid: 1011 _Portals: rid: 7000983677634084867 _ShowWaterProxyPlane: 0 @@ -364,15 +379,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 - _DisableChunks: 0 - _UniformTiles: 0 - _DisableSkirt: 0 _DrawLodOutline: 0 _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -401,6 +412,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 1002 type: {class: FoamLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -440,6 +452,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -489,6 +502,29 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 1010 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: d340825b528984c3ea62563460223aa4, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 0} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 1011 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 1720327093404827648 type: {class: UnderwaterRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: @@ -499,10 +535,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -519,7 +551,7 @@ MonoBehaviour: data: _Version: 0 _Enabled: 0 - _Mode: 0 + _Mode: 1 _Layers: serializedVersion: 2 m_Bits: 2147483649 diff --git a/Assets/Samples/Crest/5.4.2/Main/Scenes/Main/LightingData.asset b/Assets/Samples/Crest/5.4.2/Main/Scenes/Main/LightingData.asset index f8e84d15d..ecd3a7f70 100644 Binary files a/Assets/Samples/Crest/5.4.2/Main/Scenes/Main/LightingData.asset and b/Assets/Samples/Crest/5.4.2/Main/Scenes/Main/LightingData.asset differ diff --git a/Assets/Samples/Crest/5.4.2/Ripples/Materials/Ripples_Water.mat b/Assets/Samples/Crest/5.4.2/Ripples/Materials/Ripples_Water.mat index fd0e9f818..0edb6e5c8 100644 --- a/Assets/Samples/Crest/5.4.2/Ripples/Materials/Ripples_Water.mat +++ b/Assets/Samples/Crest/5.4.2/Ripples/Materials/Ripples_Water.mat @@ -45,9 +45,9 @@ Material: - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_InvalidKeywords: [] diff --git a/Assets/Samples/Crest/5.4.2/Ripples/Scenes/Ripples.unity b/Assets/Samples/Crest/5.4.2/Ripples/Scenes/Ripples.unity index 71f34508c..0b9995719 100644 --- a/Assets/Samples/Crest/5.4.2/Ripples/Scenes/Ripples.unity +++ b/Assets/Samples/Crest/5.4.2/Ripples/Scenes/Ripples.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 10 + serializedVersion: 9 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -42,8 +42,8 @@ RenderSettings: --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 13 - m_BakeOnSceneLoad: 1 + serializedVersion: 12 + m_GIWorkflowMode: 1 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -66,6 +66,9 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 1 @@ -93,8 +96,9 @@ LightmapSettings: m_ExportTrainingData: 0 m_TrainingDataDestination: TrainingData m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 112000000, guid: 2fb19c05f04ea8c4fad841f42065b207, type: 2} - m_LightingSettings: {fileID: 4890085278179872738, guid: 6e72aca972f324f7886200f86939d735, type: 2} + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 4890085278179872738, guid: 6e72aca972f324f7886200f86939d735, + type: 2} --- !u!196 &4 NavMeshSettings: serializedVersion: 2 @@ -160,47 +164,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1737612588} m_Modifications: - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalRotation.x value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalRotation.y value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalRotation.z value: -0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 2942909709672342223, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + - target: {fileID: 2942909709672342223, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} propertyPath: m_Name value: Atmosphere objectReference: {fileID: 0} @@ -211,7 +226,8 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} --- !u!4 &849648606 stripped Transform: - m_CorrespondingSourceObject: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, type: 3} + m_CorrespondingSourceObject: {fileID: 2272289698115174340, guid: 63a4b7e65d06948649ac3e10077d8c2e, + type: 3} m_PrefabInstance: {fileID: 849648605} m_PrefabAsset: {fileID: 0} --- !u!1001 &1305144322 @@ -222,47 +238,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 204793448} m_Modifications: - - target: {fileID: 6079220456006713144, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 6079220456006713144, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_Name value: PostProcessing objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalRotation.x value: -0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalRotation.y value: -0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalRotation.z value: -0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + - target: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -273,7 +300,8 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} --- !u!4 &1305144323 stripped Transform: - m_CorrespondingSourceObject: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, type: 3} + m_CorrespondingSourceObject: {fileID: 9013060131419009103, guid: 5e01cffb9e8324147affb8e08fd5ed13, + type: 3} m_PrefabInstance: {fileID: 1305144322} m_PrefabAsset: {fileID: 0} --- !u!1 &1713053106 @@ -318,47 +346,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 204793448} m_Modifications: - - target: {fileID: 2452750316707852747, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852747, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_Name value: Camera objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalPosition.x value: -12.755484 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalPosition.y value: 3.9116275 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalPosition.z value: -0.47643661 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalRotation.w value: 0.6911961 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalRotation.x value: 0.1276672 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalRotation.y value: 0.6994695 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalRotation.z value: -0.12919533 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + - target: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -369,7 +408,8 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} --- !u!4 &1730370255 stripped Transform: - m_CorrespondingSourceObject: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, type: 3} + m_CorrespondingSourceObject: {fileID: 2452750316707852748, guid: c26fe2b4fef6c484089497b549dd6b04, + type: 3} m_PrefabInstance: {fileID: 1730370254} m_PrefabAsset: {fileID: 0} --- !u!1 &1737612587 @@ -414,47 +454,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1737612588} m_Modifications: - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalRotation.w value: -0.6898038 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalRotation.x value: -0.28572607 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalRotation.y value: 0.6145928 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalRotation.z value: -0.25457266 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 45 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 276.6 objectReference: {fileID: 0} - - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 5304508333967466499, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + - target: {fileID: 5304508333967466499, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} propertyPath: m_Name value: Sun objectReference: {fileID: 0} @@ -465,7 +516,8 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} --- !u!4 &1745844464 stripped Transform: - m_CorrespondingSourceObject: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, type: 3} + m_CorrespondingSourceObject: {fileID: 1399345652565587599, guid: 774ab582b39374a7e9d5dac8e31b9a5a, + type: 3} m_PrefabInstance: {fileID: 1745844463} m_PrefabAsset: {fileID: 0} --- !u!1001 &1773514258 @@ -476,47 +528,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 1737612588} m_Modifications: - - target: {fileID: 963553959586484309, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 963553959586484309, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_Name value: Lighting objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalRotation.w value: 1 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalRotation.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalRotation.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalRotation.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + - target: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} @@ -527,7 +590,8 @@ PrefabInstance: m_SourcePrefab: {fileID: 100100000, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} --- !u!4 &1773514259 stripped Transform: - m_CorrespondingSourceObject: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, type: 3} + m_CorrespondingSourceObject: {fileID: 6033288213199496986, guid: bece9afbf3ddd49059dd73ba2cc986f6, + type: 3} m_PrefabInstance: {fileID: 1773514258} m_PrefabAsset: {fileID: 0} --- !u!1 &1887373152 @@ -574,27 +638,38 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 10 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: aa74fe26a90564079a48cdae97645f7b, type: 2} _VolumeMaterial: {fileID: 0} - _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, type: 3} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, + type: 3} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 10 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 4199187345983668226 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 _Slices: 7 @@ -602,6 +677,7 @@ MonoBehaviour: _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -631,6 +707,8 @@ MonoBehaviour: rid: 9154139594981113868 _Underwater: rid: 9154139594981113869 + _Meniscus: + rid: 9040549687677943810 _Portals: rid: 9154139594981113870 _ShowWaterProxyPlane: 0 @@ -642,10 +720,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 + _DrawLodOutline: 0 + _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -675,6 +754,30 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 4199187345983668226 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: aa74fe26a90564079a48cdae97645f7b, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, + type: 3} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 9040549687677943810 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 9154139594981113859 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: @@ -698,6 +801,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 9154139594981113861 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -745,6 +849,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -815,10 +920,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -832,7 +933,11 @@ MonoBehaviour: _OnlyReflectionCameras: 0 - rid: 9154139594981113870 type: {class: PortalRenderer, ns: WaveHarmonic.Crest.Portals, asm: WaveHarmonic.Crest} - data: + data: + _Enabled: 0 + _Mode: 2 + _Geometry: {fileID: 0} + _Invert: 0 --- !u!1001 &2904561123747805697 PrefabInstance: m_ObjectHideFlags: 0 @@ -841,47 +946,58 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 0} m_Modifications: - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalPosition.x value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalPosition.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalPosition.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalRotation.w value: 0.7071068 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalRotation.x value: 0.7071068 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalRotation.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalRotation.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalEulerAnglesHint.x value: 90 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalEulerAnglesHint.y value: 0 objectReference: {fileID: 0} - - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 873869071320452477, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} - - target: {fileID: 6920241850790494902, guid: 178ae2ae1dc4f4224a165b75c017acfa, type: 3} + - target: {fileID: 6920241850790494902, guid: 178ae2ae1dc4f4224a165b75c017acfa, + type: 3} propertyPath: m_Name value: Ripple Generator objectReference: {fileID: 0} diff --git a/Assets/Samples/Crest/5.4.2/Ripples/Scripts/RippleGenerator.cs b/Assets/Samples/Crest/5.4.2/Ripples/Scripts/RippleGenerator.cs index 0a48f2b89..8671800ff 100644 --- a/Assets/Samples/Crest/5.4.2/Ripples/Scripts/RippleGenerator.cs +++ b/Assets/Samples/Crest/5.4.2/Ripples/Scripts/RippleGenerator.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Assets/Samples/Crest/5.4.2/Wakes/Materials/Wakes_Water.mat b/Assets/Samples/Crest/5.4.2/Wakes/Materials/Wakes_Water.mat index f9c2f883b..a790dc027 100644 --- a/Assets/Samples/Crest/5.4.2/Wakes/Materials/Wakes_Water.mat +++ b/Assets/Samples/Crest/5.4.2/Wakes/Materials/Wakes_Water.mat @@ -45,9 +45,9 @@ Material: - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_InvalidKeywords: [] diff --git a/Assets/Samples/Crest/5.4.2/Wakes/Prefabs/Wakes_Scene.prefab b/Assets/Samples/Crest/5.4.2/Wakes/Prefabs/Wakes_Scene.prefab index 078606e63..37146bccf 100644 --- a/Assets/Samples/Crest/5.4.2/Wakes/Prefabs/Wakes_Scene.prefab +++ b/Assets/Samples/Crest/5.4.2/Wakes/Prefabs/Wakes_Scene.prefab @@ -270,35 +270,46 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: e64c239f69eea46778ded6dcc3427a34, type: 3} m_Name: m_EditorClassIdentifier: - _Version: 0 - _Camera: {fileID: 0} - _TimeProvider: {fileID: 0} - _OverrideRenderHDR: 0 - _RenderHDR: 1 - _WindSpeed: 150 - _OverrideGravity: 0 - _GravityOverride: -9.8 - _GravityMultiplier: 1 - _PrimaryLight: {fileID: 0} _Layer: 4 _Material: {fileID: 2100000, guid: d6e4d43be817745be8c654fe12d10077, type: 2} _VolumeMaterial: {fileID: 0} _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, type: 3} _CastShadows: 0 - _WriteMotionVectors: 1 - _WriteToDepthTexture: 1 _WaterBodyCulling: 1 _TimeSliceBoundsUpdateFrameCount: 1 _SurfaceSelfIntersectionFixMode: 4 _AllowRenderQueueSorting: 0 + _Version: 1 + _Camera: {fileID: 0} + _TimeProvider: {fileID: 0} + _WindZone: {fileID: 0} + _OverrideWindZoneWindSpeed: 0 + _WindSpeed: 150 + _OverrideWindZoneWindDirection: 0 + _WindDirection: 0 + _OverrideWindZoneWindTurbulence: 0 + _WindTurbulence: 0.145 + _OverrideGravity: 0 + _GravityOverride: -9.8 + _GravityMultiplier: 1 + _PrimaryLight: {fileID: 0} + _InjectionPoint: 0 + _WriteToColorTexture: 1 + _WriteToDepthTexture: 1 + _WriteMotionVectors: 1 + _OverrideRenderHDR: 0 + _RenderHDR: 1 + _Surface: + rid: 1002 _ScaleRange: {x: 4, y: 256} _DropDetailHeightBasedOnWaves: 0.2 - _Slices: 7 + _Slices: 9 _Resolution: 384 _GeometryDownSampleFactor: 2 _ExtentsSizeMultiplier: 100 _Viewpoint: {fileID: 0} + _CenterOfDetailDisplacementCorrection: 1 _SampleTerrainHeightForScale: 1 _ForceScaleChangeSmoothing: 0 _TeleportThreshold: 10 @@ -328,6 +339,8 @@ MonoBehaviour: rid: 162836781179600933 _Underwater: rid: 162836781179600934 + _Meniscus: + rid: 1003 _Portals: rid: 162836781179600935 _ShowWaterProxyPlane: 0 @@ -339,15 +352,11 @@ MonoBehaviour: _ShowHiddenObjects: 0 _DisableFollowViewpoint: 0 _DestroyResourcesInOnDisable: 0 - _DisableChunks: 0 - _UniformTiles: 0 - _DisableSkirt: 0 _DrawLodOutline: 0 _ShowDebugInformation: 0 _LogScaleChange: 0 _PauseOnScaleChange: 0 _IgnoreWavesForScaleChange: 0 - _ForceBatchMode: 0 _ForceNoGraphics: 0 _Resources: {fileID: 11400000, guid: 0817af17dea584e5382e6216db162d4a, type: 2} references: @@ -377,6 +386,30 @@ MonoBehaviour: _ShorelineColor: {r: 0, g: 0.588, b: 1.2, a: 6} _ShorelineColorMaximumDistance: 10 _ShorelineColorFalloff: 2 + - rid: 1002 + type: {class: SurfaceRenderer, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Version: 0 + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: d6e4d43be817745be8c654fe12d10077, type: 2} + _VolumeMaterial: {fileID: 0} + _ChunkTemplate: {fileID: 1516456258233481520, guid: 17840562212c147d6bdb5144d35bc442, + type: 3} + _CastShadows: 0 + _WaterBodyCulling: 1 + _TimeSliceBoundsUpdateFrameCount: 1 + _SurfaceSelfIntersectionFixMode: 4 + _AllowRenderQueueSorting: 0 + _Debug: + _UniformTiles: 0 + _DisableSkirt: 0 + - rid: 1003 + type: {class: Meniscus, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} + data: + _Enabled: 1 + _Layer: 4 + _Material: {fileID: 2100000, guid: 238e45299a5ec46308e9bf99ddf67963, type: 2} - rid: 162836781179600924 type: {class: AnimatedWavesLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} data: @@ -400,6 +433,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 46 + _IncludeTerrainHeight: 0 _EnableSignedDistanceFields: 1 - rid: 162836781179600926 type: {class: LevelLod, ns: WaveHarmonic.Crest, asm: WaveHarmonic.Crest} @@ -447,6 +481,7 @@ MonoBehaviour: _Resolution: 256 _TextureFormatMode: 100 _TextureFormat: 6 + _SimulationFrequency: 60 _DynamicSoftShadows: 1 _SoftJitterExtinctionFactor: 0.75 _JitterDiameterSoft: 15 @@ -517,10 +552,6 @@ MonoBehaviour: _EnvironmentalLightingEnable: 0 _EnvironmentalLightingWeight: 1 _EnvironmentalLightingVolumeProfile: {fileID: 0} - _EnableShaderAPI: 0 - _TransparentObjectLayers: - serializedVersion: 2 - m_Bits: 0 _AllCameras: 0 _CopyWaterMaterialParametersEachFrame: 1 _FarPlaneMultiplier: 0.68 @@ -650,12 +681,14 @@ MonoBehaviour: _Spectrum: {fileID: 11400000, guid: 30151f29a777a41f39698cb262ee599b, type: 2} _EvaluateSpectrumAtRunTimeEveryFrame: 1 _RespectShallowWaterAttenuation: 1 + _OverrideGlobalWindDirection: 1 _WaveDirectionHeadingAngle: -90 _OverrideGlobalWindSpeed: 0 _WindSpeed: 20 _Resolution: 128 _DrawSlicesInEditor: 0 _AlphaSource: 0 + _OverrideGlobalWindTurbulence: 1 _WindTurbulence: 0.145 _WindAlignment: 0 _TimeLoopLength: Infinity @@ -665,7 +698,7 @@ MonoBehaviour: _TimeResolution: 4 _SmallestWavelengthRequired: 2 _BakedTimeLoopLength: 32 - _Version: 1 + _Version: 2 references: version: 2 RefIds: diff --git a/Assets/UMotionEditor/Data/EditorUndoStackPointer.asset b/Assets/UMotionEditor/Data/EditorUndoStackPointer.asset index bb1905923..89c022166 100644 --- a/Assets/UMotionEditor/Data/EditorUndoStackPointer.asset +++ b/Assets/UMotionEditor/Data/EditorUndoStackPointer.asset @@ -12,5 +12,5 @@ MonoBehaviour: m_Script: {fileID: -1063058285, guid: 448d62fcada76fd4ab5702190add98fd, type: 3} m_Name: EditorUndoStackPointer m_EditorClassIdentifier: "UMotionEditor.dll::\u0389\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u038A\u038A\u038A\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u0389\u0389\u0389\u0389\u038A" - "\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u0389\u038A\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u038A": 1.29p03 - "\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389": 176 + "\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u038A\u0389\u0389\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u0389\u038A\u038A\u0389\u0389\u038A\u0389\u038A\u038A\u0389\u038A": + "\u038A\u038A\u0389\u038A\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u038A\u0389\u038A\u0389\u038A\u038A\u038A\u038A\u038A\u0389\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389\u0389\u038A\u038A\u0389\u038A\u0389\u0389\u0389": -1 diff --git a/Packages/com.waveharmonic.crest/Documentation~/API.pdf b/Packages/com.waveharmonic.crest/Documentation~/API.pdf index b7e06e2be..a2cee0112 100644 Binary files a/Packages/com.waveharmonic.crest/Documentation~/API.pdf and b/Packages/com.waveharmonic.crest/Documentation~/API.pdf differ diff --git a/Packages/com.waveharmonic.crest/Documentation~/Manual.pdf b/Packages/com.waveharmonic.crest/Documentation~/Manual.pdf index 3e2bfb4fd..a3cd4cb39 100644 Binary files a/Packages/com.waveharmonic.crest/Documentation~/Manual.pdf and b/Packages/com.waveharmonic.crest/Documentation~/Manual.pdf differ diff --git a/Packages/com.waveharmonic.crest/Editor/Icons/Logomark.png.meta b/Packages/com.waveharmonic.crest/Editor/Icons/Logomark.png.meta index 7df6548cd..aa39df1ef 100644 --- a/Packages/com.waveharmonic.crest/Editor/Icons/Logomark.png.meta +++ b/Packages/com.waveharmonic.crest/Editor/Icons/Logomark.png.meta @@ -93,6 +93,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/BuildProcessor.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/BuildProcessor.cs index 4882df301..89bb5ed90 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/BuildProcessor.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/BuildProcessor.cs @@ -29,6 +29,8 @@ namespace WaveHarmonic.Crest.Editor.Build false; #endif + static readonly string[] s_ShadowCollectorKeywords = { "SHADOWS_SINGLE_CASCADE", "SHADOWS_SPLIT_SPHERES", "SHADOWS_SOFT" }; + public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList data) { // Not one of our shaders. @@ -49,6 +51,8 @@ namespace WaveHarmonic.Crest.Editor.Build return; } + // NOTE: There is no point checking against sub-shader count. + _VariantCount += data.Count; // Strip BIRP sub-shader if not using BIRP, as Unity only strips HDRP/URP sub-shaders. @@ -61,34 +65,36 @@ namespace WaveHarmonic.Crest.Editor.Build for (var i = data.Count - 1; i >= 0; --i) { + var strip = false; var keywords = data[i].shaderKeywordSet.GetShaderKeywords(); + var isLightingPass = snippet.passType is PassType.ForwardBase or PassType.ForwardAdd; var isTransparent = keywords.Any(x => x.name == "_BUILTIN_SURFACE_TYPE_TRANSPARENT"); + var isTransparentShadowReceiver = keywords.Any(x => x.name == "_BUILTIN_TRANSPARENT_RECEIVES_SHADOWS"); - foreach (var keyword in keywords) + // Invalid combination. + if (isLightingPass && !isTransparent && isTransparentShadowReceiver) { - var name = keyword.name; - var strip = - // Main light shadows. Never used. - name.StartsWithNoAlloc("_MAIN_LIGHT_") || - // Additional lights. Never used. Although, vertex lighting keyword is set. - name.StartsWithNoAlloc("_ADDITIONAL_LIGHT") || - // Never used. Used in deferred pass, but not defined in deferred pass. - keyword.name is "LIGHTMAP_SHADOW_MIXING" or "SHADOWS_SHADOWMASK" || - // Never used. - keyword.name is "_SCREEN_SPACE_OCCLUSION" or "_SHADOWS_SOFT" or "_CASTING_PUNCTUAL_LIGHT_SHADOW" || - // BIRP does not support this feature (URP does). - keyword.name is "_GBUFFER_NORMALS_OCT" || - // TODO: check LightMode instead of pass name. - // Shadow keywords are not enabled for transparent objects, except if casting. - isTransparent && snippet.passName == "ShadowCaster" && keyword.name.Contains("SHADOW"); + strip = true; + } - if (strip) + if (!strip) + { + foreach (var keyword in keywords) { - _VariantCountStripped++; - data.RemoveAt(i); - break; + var name = keyword.name; + strip = + // Invalid combination. + isLightingPass && (!isTransparent || !isTransparentShadowReceiver) && s_ShadowCollectorKeywords.Contains(keyword.name); + + if (strip) break; } } + + if (strip) + { + _VariantCountStripped++; + data.RemoveAt(i); + } } } @@ -217,6 +223,14 @@ namespace WaveHarmonic.Crest.Editor.Build } } + if (!RenderPipelineHelper.IsLegacy) + { + if (shader.name.StartsWithNoAlloc("Hidden/Crest/Legacy/")) + { + return true; + } + } + return false; } @@ -273,8 +287,8 @@ namespace WaveHarmonic.Crest.Editor.Build return false; } - // There will be at least three sub-shaders if one per render pipeline. - if (shader.subshaderCount <= 2) + // There will be at least two sub-shaders if other render pipelines. + if (shader.subshaderCount <= 1) { return false; } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Editors.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Editors.cs index 833fab3ac..03f19beaf 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Editors.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Editors.cs @@ -10,10 +10,14 @@ namespace WaveHarmonic.Crest.Editor [CustomEditor(typeof(WaterRenderer))] sealed class WaterRendererEditor : Inspector { + // Whether validation was triggered by user request, which should never skip console logging. + internal static bool ManualValidation { get; private set; } + WaterRenderer _Target; - void OnEnable() + protected override void OnEnable() { + base.OnEnable(); _Target = (WaterRenderer)target; } @@ -65,9 +69,9 @@ namespace WaveHarmonic.Crest.Editor if (i < target.LodLevels - 1) message += "\n\n"; } - if (target.Material.HasVector(WaterRenderer.ShaderIDs.s_Absorption)) + if (target.Surface.Material.HasVector(WaterRenderer.ShaderIDs.s_Absorption)) { - message += $"\n\nDepth Fog Density: {target.Material.GetVector(WaterRenderer.ShaderIDs.s_Absorption)}"; + message += $"\n\nDepth Fog Density: {target.Surface.Material.GetVector(WaterRenderer.ShaderIDs.s_Absorption)}"; } EditorGUILayout.HelpBox(message, MessageType.None); @@ -98,6 +102,8 @@ namespace WaveHarmonic.Crest.Editor if (GUILayout.Button("Validate Setup")) { + ManualValidation = true; + ValidatedHelper.ExecuteValidators(target, ValidatedHelper.DebugLog); foreach (var component in FindObjectsByType(FindObjectsSortMode.None)) @@ -107,6 +113,8 @@ namespace WaveHarmonic.Crest.Editor } Debug.Log("Crest: Validation complete!", target); + + ManualValidation = false; } } } @@ -128,8 +136,10 @@ namespace WaveHarmonic.Crest.Editor _HostComponentType = hostComponentType; } - void OnEnable() + protected override void OnEnable() { + base.OnEnable(); + Undo.undoRedoEvent -= OnUndoRedo; Undo.undoRedoEvent += OnUndoRedo; } @@ -297,7 +307,8 @@ namespace WaveHarmonic.Crest.Editor switch (spectrumModel) { case WaveSpectrum.SpectrumModel.PiersonMoskowitz: - spec.ApplyPiersonMoskowitzSpectrum(); + var water = WaterRenderer.Instance; + spec.ApplyPiersonMoskowitzSpectrum(water != null ? water.Gravity : Mathf.Abs(Physics.gravity.y)); break; } } @@ -383,7 +394,7 @@ namespace WaveHarmonic.Crest.Editor var canBake = !onDemand && !Application.isPlaying; var canPopulate = Application.isPlaying ? onDemand : target.Type != DepthProbeMode.Baked; - if (target.SavedTexture != null && isBaked ? GUILayout.Button("Switch to Real-Time") : GUILayout.Button("Switch to Baked")) + if (isBaked ? GUILayout.Button("Switch to Real-Time") : target.SavedTexture != null && GUILayout.Button("Switch to Baked")) { Undo.RecordObject(target, isBaked ? "Switch to Real-Time" : "Switch to Baked"); target.Type = isBaked ? DepthProbeMode.RealTime : DepthProbeMode.Baked; @@ -451,6 +462,10 @@ namespace WaveHarmonic.Crest.Editor settings.singleChannelComponent = TextureImporterSingleChannelComponent.Red; ti.SetTextureSettings(settings); } + else + { + ti.textureType = TextureImporterType.Default; + } // Set format. { diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Gizmos.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Gizmos.cs index c27c61edc..c29972f89 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Gizmos.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Gizmos.cs @@ -16,6 +16,12 @@ namespace WaveHarmonic.Crest.Editor : s_VisualizeMaterial = new(Shader.Find("Local/Debug/Visualize Signed Texture")); #endif + static void DrawLine(Vector3 start, Vector3 end, Color color, float _) + { + Gizmos.color = color; + Gizmos.DrawLine(start, end); + } + [DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)] static void DrawGizmos(WaterRenderer target, GizmoType type) { @@ -51,12 +57,12 @@ namespace WaveHarmonic.Crest.Editor // Create proxy if not present already, and proxy enabled if (target._ProxyPlane == null && target._ShowWaterProxyPlane) { - target._ProxyPlane = GameObject.CreatePrimitive(PrimitiveType.Plane); + target._ProxyPlane = GameObject.CreatePrimitive(PrimitiveType.Quad); Helpers.Destroy(target._ProxyPlane.GetComponent()); target._ProxyPlane.hideFlags = HideFlags.HideAndDontSave; target._ProxyPlane.transform.parent = target.transform; - target._ProxyPlane.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - target._ProxyPlane.transform.localScale = 4000f * Vector3.one; + target._ProxyPlane.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.Euler(90f, 0f, 0f)); + target._ProxyPlane.transform.localScale = 1000000f * Vector3.one; target._ProxyPlane.GetComponent().sharedMaterial = new(Shader.Find(WaterRenderer.k_ProxyShader)); } @@ -70,11 +76,6 @@ namespace WaveHarmonic.Crest.Editor EditorWindow view = EditorWindow.GetWindow(); view.Repaint(); } - - if (target.Root != null) - { - target.Root.gameObject.SetActive(!target._ShowWaterProxyPlane); - } } [DrawGizmo(GizmoType.Selected)] @@ -87,7 +88,8 @@ namespace WaveHarmonic.Crest.Editor var rect = target.Rect; if (rect != Rect.zero) { - var height = WaterRenderer.Instance ? WaterRenderer.Instance.SeaLevel : target.transform.position.y; + var water = WaterRenderer.Instance; + var height = water ? water.SeaLevel : target.transform.position.y; Gizmos.color = Color.magenta; Gizmos.DrawWireCube ( @@ -146,7 +148,8 @@ namespace WaveHarmonic.Crest.Editor var rect = target.Rect; if (rect != Rect.zero) { - var height = WaterRenderer.Instance ? WaterRenderer.Instance.SeaLevel : target.transform.position.y; + var water = WaterRenderer.Instance; + var height = water ? water.SeaLevel : target.transform.position.y; Gizmos.color = Color.magenta; Gizmos.DrawWireCube ( @@ -209,6 +212,14 @@ namespace WaveHarmonic.Crest.Editor } } + [DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)] + static void DrawGizmos(CollisionAreaVisualizer target, GizmoType type) + { + var water = WaterRenderer.Instance; + if (water == null) return; + target.Render(water, DrawLine); + } + [DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)] static void DrawGizmos(DepthProbe target, GizmoType type) { diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations.meta new file mode 100644 index 000000000..2e9e01034 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 76bb1904a4c3377478b2e551e16f2d59 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia.meta new file mode 100644 index 000000000..77a6a129b --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a5b1db7ccbfeda46871d9c365e6a914 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs new file mode 100644 index 000000000..758e48398 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs @@ -0,0 +1,6 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// Define empty namespaces for when assemblies are not present. + +namespace WaveHarmonic.Crest.ShallowWater { } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs.meta new file mode 100644 index 000000000..ed25b2979 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/Assembly.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1364267b3de043daae23dda97c99063 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs new file mode 100644 index 000000000..273ca1658 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs @@ -0,0 +1,259 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE) + +using Gaia; +using UnityEditor; +using UnityEngine; +using WaveHarmonic.Crest.ShallowWater; + +namespace WaveHarmonic.Crest +{ + sealed class GRC_Crest : GaiaRuntimeComponent + { + [SerializeField] + bool _Wind = true; + + [SerializeField] + bool _Swell = true; + + [SerializeField] + bool _ShallowWater = true; + + GUIContent _HelpLink; + GUIContent _PanelLabel; + + /// + public override GUIContent PanelLabel + { + get + { + if (_PanelLabel == null || _PanelLabel.text == "") + { + _PanelLabel = new GUIContent("Crest Water", "Adds Crest Water to your scene."); + } + + return _PanelLabel; + } + } + + /// + public override void Initialize() + { + // Order components appear in the UI. Try to keep in alphabetical order. + m_orderNumber = 210; + + if (_HelpLink == null || _HelpLink.text == "") + { + _HelpLink = new GUIContent("Crest Online documentation", "Opens the documentation for the Crest Water System in your browser."); + } + } + + /// + public override void DrawUI() + { + // Displays "?" help button. + DisplayHelp + ( + "This module adds the Crest Water System to your scene. Please visit the link to learn more:", + _HelpLink, + "https://docs.crest.waveharmonic.com/About/Introduction.html" + ); + + EditorGUI.BeginChangeCheck(); + + { + _Swell = EditorGUILayout.Toggle("Swell Waves", _Swell); + DisplayHelp("Whether to add swell waves to the scene. Swell waves will come from conditions far away from the scene. Modify the component after creation to customize."); + + _Wind = EditorGUILayout.Toggle("Wind Waves", _Wind); + DisplayHelp("Whether to add wind waves to the scene. These waves are based on local wind conditions. Requires Gaia's Wind Zone (note that the defaul wind value will produce no waves). Modify the component after creation to customize."); + +#if d_WaveHarmonic_Crest_ShallowWater + _ShallowWater = EditorGUILayout.Toggle("Shoreline Simulation", _ShallowWater); + DisplayHelp("Whether to add a shoreline shallow water simulation to the scene. Modify the component after creation to customize."); +#endif + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Remove")) RemoveFromScene(); + GUILayout.Space(15); + if (GUILayout.Button("Apply")) AddToScene(); + GUILayout.EndHorizontal(); + } + + if (EditorGUI.EndChangeCheck()) + { + EditorUtility.SetDirty(this); + } + } + + /// Called when either "Apply" or "Create Runtime" is pressed. + /// + public override void AddToScene() + { + // Re-initialize to keep user's changes. + var water = FindFirstObjectByType(FindObjectsInactive.Include); + + if (water == null) + { + water = new GameObject("Water").AddComponent(); + } + + // Sea level is height above terrain bottom. + var seaLevel = GaiaAPI.GetSeaLevel(); + + water.transform.position = new Vector3(0f, seaLevel, 0f); + + var managed = water.transform.Find("Managed"); + + if (managed == null) + { + managed = new GameObject("Managed").transform; + } + + managed.SetParent(water.transform, worldPositionStays: false); + + // Wind + if (_Wind) + { + var wind = FindFirstObjectByType(); + + if (wind != null) + { + water.WindZone = wind.GetComponent(); + } + } + + // Depth + water.DepthLod.IncludeTerrainHeight = false; + + foreach (var terrain in FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None)) + { + var dp = terrain.GetComponentInChildren(includeInactive: true); + + if (dp == null) + { + dp = new GameObject("WaterDepthProbe").AddComponent(); + } + + dp.gameObject.layer = water.Surface.Layer; + dp.transform.SetParent(terrain.transform, worldPositionStays: false); + dp.transform.localPosition = terrain.terrainData.size * 0.5f; + var position = dp.transform.position; + position.y = seaLevel; + dp.transform.position = position; + dp.transform.localScale = new(terrain.terrainData.size.x, 1f, terrain.terrainData.size.z); + dp.Layers = 1 << terrain.gameObject.layer; + // 1m below terrain bottom to 1m above maximum terrain height. + dp.CaptureRange = new(-seaLevel + -1f, terrain.terrainData.size.y - seaLevel + 1); + dp.Resolution = terrain.terrainData.heightmapResolution - 1; + dp.Populate(); + } + + // Wind Waves + if (_Wind && water.WindZone != null) + { + GetOrAddComponentToScene(managed, "WaterWindWaves", out _); + } + else + { + RemoveComponentFromScene(managed); + } + + // Swell Waves + if (_Swell) + { + GetOrAddComponentToScene(managed, "WaterSwellWaves", out var waves); + + waves.OverrideGlobalWindDirection = true; + waves.OverrideGlobalWindSpeed = true; + waves.ReverseWaveWeight = 0; + waves.Swell = true; + + if (!waves.TryGetComponent(out var fft)) + { + fft = waves.gameObject.AddComponent(); + fft.Spectrum = AssetDatabase.LoadAssetAtPath("Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset"); + } + + fft.OverrideGlobalWindDirection = true; + fft.OverrideGlobalWindSpeed = true; + fft.OverrideGlobalWindTurbulence = true; + fft.WindAlignment = 0.5f; + } + else + { + RemoveComponentFromScene(managed); + } + +#if d_WaveHarmonic_Crest_ShallowWater + if (_ShallowWater) + { + water.FlowLod.Enabled = true; + + if (GetOrAddComponentToScene(managed, "ShorelineSimulation", out var sws)) + { + water.Surface.Material = AssetDatabase.LoadAssetAtPath("Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat"); + sws.Width = 256; + } + + if (!sws.TryGetComponent(out var dp)) + { + dp = sws.gameObject.AddComponent(); + } + + dp.GenerateSignedDistanceField = false; + + sws.Preset = ShallowWaterSimulationPreset.Shoreline; + sws.Placement = Placement.Viewpoint; + sws.DynamicSeabed = true; + } + else + { + RemoveComponentFromScene(managed); + } +#endif + } + + bool GetOrAddComponentToScene(Transform managed, string name, out T component) where T : MonoBehaviour + { + component = managed.GetComponentInChildren(); + + var create = component == null; + + if (create) + { + component = new GameObject(name).AddComponent(); + component.transform.SetParent(managed.transform, worldPositionStays: false); + } + + return create; + } + + void RemoveComponentFromScene(Transform managed) where T : MonoBehaviour + { + var component = managed.GetComponentInChildren(); + + if (component != null) + { + DestroyImmediate(component.gameObject); + } + } + + /// Called when "Remove" is pressed. + /// + public override void RemoveFromScene() + { + var water = FindFirstObjectByType(FindObjectsInactive.Include); + if (water != null) DestroyImmediate(water.gameObject); + + foreach (var terrain in FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None)) + { + var depthCache = terrain.GetComponentInChildren(includeInactive: true); + if (depthCache != null) DestroyImmediate(depthCache.gameObject); + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs.meta new file mode 100644 index 000000000..1bcd3fdcf --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/GRC_Crest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f9d5fab14f7242db80be581a62d53c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef new file mode 100644 index 000000000..554564d43 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef @@ -0,0 +1,32 @@ +{ + "name": "WaveHarmonic.Crest.Integration.Gaia", + "rootNamespace": "", + "references": [ + "GUID:532136e3ad79fba44b9e7d74f4e53abe", + "GUID:cc49c744ac0d6fa459f6fb20f0066991", + "GUID:7c347618730f5467f86a58f333ce21df", + "GUID:98db37baed0fc4b73a47a9d66f791aae", + "GUID:056ff2a5b2f124d468c6655552acdca5", + "GUID:d365b04c036e04304a59ef9aa90b3924" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_2022_3_OR_NEWER", + "GAIA_2023" + ], + "versionDefines": [ + { + "name": "com.waveharmonic.crest.shallow-water", + "expression": "", + "define": "d_WaveHarmonic_Crest_ShallowWater" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef.meta new file mode 100644 index 000000000..3e117d4fa --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Integrations/Gaia/WaveHarmonic.Crest.Integration.Gaia.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1c4070cb1d689471b80e17ee7aa518e6 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialDrawers.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialDrawers.cs index 3a81dc21d..c9fe8f827 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialDrawers.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialDrawers.cs @@ -25,7 +25,7 @@ namespace WaveHarmonic.Crest.Editor internal static readonly Dictionary> s_Grouped = new() { { - "Crest/Underwater", new() + UnderwaterRenderer.k_ShaderNameEffect, new() { { "_Crest_DataSliceOffset", new() { _IntegerRange = new(0, Lod.k_MaximumSlices - 2) } }, } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialTooltips.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialTooltips.cs index aec8fe30c..38eebcb7d 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialTooltips.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/MaterialTooltips.cs @@ -50,7 +50,7 @@ namespace WaveHarmonic.Crest.Editor } }, { - "Crest/Underwater", new() + UnderwaterRenderer.k_ShaderNameEffect, new() { { "_Crest_ExtinctionMultiplier", "Scales the depth fog density. Useful to reduce the intensity of the depth fog when underwater only" }, { "_Crest_SunBoost", "Boost the intensity of the sun scattering" }, @@ -149,7 +149,26 @@ namespace WaveHarmonic.Crest.Editor internal static MaterialProperty[] FilterProperties(MaterialProperty[] properties) { - return properties.Where(x => x.name != "_Crest_Absorption").ToArray(); + // Show specular control. + var specular = true; + + if (!RenderPipelineHelper.IsHighDefinition) + { + specular = properties + .First(x => x.name == (RenderPipelineHelper.IsLegacy ? "_BUILTIN_WorkflowMode" : "_WorkflowMode")).floatValue == 0; + } +#if UNITY_6000_0_OR_NEWER + else + { + // Always show specular control for U5, as it cannot be overriden by the material. + specular = properties + .First(x => x.name == "_MaterialID").floatValue == 4; + } +#endif + + return properties + .Where(x => (specular || x.name != "_Crest_Specular") && x.name != "_Crest_Absorption") + .ToArray(); } } @@ -175,7 +194,11 @@ namespace WaveHarmonic.Crest.Editor foreach (var property in properties) { +#if UNITY_6000_2_OR_NEWER if ((property.propertyFlags & UnityEngine.Rendering.ShaderPropertyFlags.HideInInspector) != 0) continue; +#else + if ((property.flags & MaterialProperty.PropFlags.HideInInspector) != 0) continue; +#endif var name = property.name; s_Label.text = property.displayName; @@ -187,7 +210,7 @@ namespace WaveHarmonic.Crest.Editor } #if d_UnityShaderGraph - class LegacyCustomShaderGUI : UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInBaseShaderGUI + class LegacyCustomShaderGUI : ShaderGraph.CustomBuiltInLitGUI { MaterialEditor _Editor; MaterialProperty[] _Properties; diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Previews.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Previews.cs index 58910e10c..ef39fdb18 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Previews.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Previews.cs @@ -1,6 +1,7 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. +using System.Reflection; using UnityEditor; using UnityEngine; @@ -21,7 +22,17 @@ namespace WaveHarmonic.Crest.Editor { get { - if (!Lod.Enabled || !((WaterRenderer)target).isActiveAndEnabled) return null; + var water = (WaterRenderer)target; + + if ((!Application.isPlaying && !water.runInEditMode) || !water.isActiveAndEnabled) + { + return null; + } + + if (!Lod.Enabled) + { + return null; + } var texture = Lod.DataTexture; @@ -245,21 +256,41 @@ namespace WaveHarmonic.Crest.Editor sealed class WaterLevelDepthPreview : TexturePreview { public override GUIContent GetPreviewTitle() => new("Water Level Screen-Space Depth"); - protected override Texture OriginalTexture => (target as WaterRenderer).WaterLevelDepthTexture; + protected override Texture OriginalTexture => (target as WaterRenderer).Surface.WaterLevelDepthTexture; + } + + [CustomPreview(typeof(WaterRenderer))] + sealed class WaterLinePreview : TexturePreview + { + public override GUIContent GetPreviewTitle() => new("Pre-Computed Displacement"); + protected override Texture OriginalTexture => (target as WaterRenderer).Surface.HeightRT; } [CustomPreview(typeof(WaterRenderer))] sealed class WaterVolumeMaskPreview : TexturePreview { public override GUIContent GetPreviewTitle() => new("Water Volume Mask"); - protected override Texture OriginalTexture => RenderPipelineHelper.IsLegacy && (target as WaterRenderer)._Underwater._MaskRT && (target as WaterRenderer)._Underwater._MaskRT.width > 0 ? (target as WaterRenderer)._Underwater._MaskRT : null; + protected override Texture OriginalTexture + { + get + { + var target = this.target as WaterRenderer; + return target._Mask?.ColorT != null && target._Mask?.ColorT.width > 0 + ? target._Mask.ColorT + : null; + } + } } #endif [CustomPreview(typeof(WaterRenderer))] sealed class ReflectionPreview : TexturePreview { + static readonly PropertyInfo s_DefaultReflection = typeof(RenderSettings).GetProperty("defaultReflection", BindingFlags.NonPublic | BindingFlags.Static); + public override GUIContent GetPreviewTitle() => new("Water Reflections"); - protected override Texture OriginalTexture => (target as WaterRenderer)._Reflections._Enabled ? (target as WaterRenderer)._Reflections.ReflectionTexture : null; + protected override Texture OriginalTexture => (target as WaterRenderer)._Reflections._Enabled + ? (target as WaterRenderer)._Reflections.ReflectionTexture + : s_DefaultReflection?.GetValue(null) as Texture; } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/ProjectSettings.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/ProjectSettings.cs index 7158d75c3..7697c5737 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/ProjectSettings.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/ProjectSettings.cs @@ -2,6 +2,8 @@ // Copyright © 2024 Wave Harmonic. All rights reserved. using System.IO; +using System.Linq; +using System.Reflection; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; @@ -41,9 +43,13 @@ namespace WaveHarmonic.Crest.Editor.Settings [@DecoratedField, SerializeField] bool _FullPrecisionDisplacementOnHalfPrecisionPlatforms = true; - [Tooltip("Whether to sample shadow maps for built-in renderer.")] + [Tooltip("Whether to render atmospheric scattering (ie fog) for pixels receiving aquatic scattering (underwater only).\n\nWhen disabled, if a pixel is receiving aquatic scattering, then it will not receive atmospheric scattering.")] [@DecoratedField, SerializeField] - bool _BuiltInRendererSampleShadowMaps = true; + bool _RenderAtmosphericScatteringWhenUnderWater; + + [Tooltip("Renders the underwater effect after transparency and uses the more expensive mask.\n\nYou may need this if rendering the underwater to multiple cameras. The other benefit is that transparent objects will be fogged (albeit incorrectly).\n\nThe downsides are that there can be artifacts if waves are very choppy, has a less impressive meniscus, and generally more expensive to execute.")] + [@DecoratedField, SerializeField] + bool _LegacyUnderwater; #pragma warning restore IDE0032 // Use auto property @@ -63,7 +69,8 @@ namespace WaveHarmonic.Crest.Editor.Settings internal bool LogStrippedVariants => _DebugEnableStrippingLogging && !_DebugOnlyLogRemainingVariants; internal bool LogKeptVariants => _DebugEnableStrippingLogging && _DebugOnlyLogRemainingVariants; internal bool FullPrecisionDisplacementOnHalfPrecisionPlatforms => _FullPrecisionDisplacementOnHalfPrecisionPlatforms; - internal bool BuiltInRendererSampleShadowMaps => _BuiltInRendererSampleShadowMaps; + internal bool RenderAtmosphericScatteringWhenUnderWater => _RenderAtmosphericScatteringWhenUnderWater; + internal bool LegacyUnderwater => _LegacyUnderwater; void OnEnable() @@ -83,12 +90,83 @@ namespace WaveHarmonic.Crest.Editor.Settings { switch (path) { - case nameof(_BuiltInRendererSampleShadowMaps): case nameof(_FullPrecisionDisplacementOnHalfPrecisionPlatforms): - ShaderSettingsGenerator.Generate(); + case nameof(_RenderAtmosphericScatteringWhenUnderWater): + case nameof(_LegacyUnderwater): + UpdateSymbols(); break; } } + + void UpdateScriptingSymbols() + { + ScriptingSymbols.Set(ProjectSymbols.k_LegacyUnderwaterScriptingSymbol, _LegacyUnderwater); + } + + void UpdateSymbols() + { + UpdateScriptingSymbols(); + ShaderSettingsGenerator.Generate(); + } + + sealed class ProjectSymbols : AssetModificationProcessor + { + public const string k_LegacyUnderwaterScriptingSymbol = "d_Crest_LegacyUnderwater"; + + static FileSystemWatcher s_Watcher; + + // Will run on load and recompile preventing symbol removal in player settings. + [InitializeOnLoadMethod] + static void OnLoad() + { + if (Instance != null) + { + Instance.UpdateScriptingSymbols(); + } + + Directory.CreateDirectory(Path.GetDirectoryName(k_Path)); + + s_Watcher = new(Path.GetDirectoryName(k_Path)) + { + Filter = Path.GetFileName(k_Path), + NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size, + EnableRaisingEvents = true + }; + + s_Watcher.Changed -= OnChanged; + s_Watcher.Changed += OnChanged; + } + + // Handle external edits. Possibly unreliable, but not important if fails. + static void OnChanged(object sender, FileSystemEventArgs e) + { + EditorApplication.delayCall += () => + { + // Destroy instance to reflect changes. + Helpers.Destroy(Instance); + typeof(ScriptableSingleton) + .GetField("s_Instance", BindingFlags.Static | BindingFlags.NonPublic) + .SetValue(null, null); + Instance.UpdateSymbols(); + }; + } + + static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options) + { + // Only remove symbols if this file is deleted. + if (Path.GetFullPath(path) == GetCurrentFileName()) + { + ScriptingSymbols.Remove(ScriptingSymbols.Symbols.Where(x => x.StartsWith("d_Crest_")).ToArray()); + } + + return AssetDeleteResult.DidNotDelete; + } + + static string GetCurrentFileName([System.Runtime.CompilerServices.CallerFilePath] string fileName = null) + { + return fileName; + } + } } sealed class SettingsProvider : UnityEditor.SettingsProvider diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Requirements/WaveHarmonic.Crest.Editor.Requirements.asmdef b/Packages/com.waveharmonic.crest/Editor/Scripts/Requirements/WaveHarmonic.Crest.Editor.Requirements.asmdef index 8dd5e1a09..74ef8cfd2 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Requirements/WaveHarmonic.Crest.Editor.Requirements.asmdef +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Requirements/WaveHarmonic.Crest.Editor.Requirements.asmdef @@ -14,37 +14,37 @@ "versionDefines": [ { "name": "com.waveharmonic.crest.cpu-queries", - "expression": "(,1.0.4)", + "expression": "(,1.0.8)", "define": "d_UpdateCPUQueries" }, { "name": "com.waveharmonic.crest.paint", - "expression": "(,1.2.0)", + "expression": "(,1.2.3)", "define": "d_UpdatePaint" }, { "name": "com.waveharmonic.crest.portals", - "expression": "(,1.2.1)", + "expression": "(,1.2.8)", "define": "d_UpdatePortals" }, { "name": "com.waveharmonic.crest.shallow-water", - "expression": "(,1.3.1)", + "expression": "(,1.3.3)", "define": "d_UpdateShallowWater" }, { "name": "com.waveharmonic.crest.shifting-origin", - "expression": "(,1.2.1)", + "expression": "(,1.3.0)", "define": "d_UpdateShiftingOrigin" }, { "name": "com.waveharmonic.crest.splines", - "expression": "(,1.3.2)", + "expression": "(,1.4.4)", "define": "d_UpdateSplines" }, { "name": "com.waveharmonic.crest.whirlpool", - "expression": "(,1.0.1)", + "expression": "(,1.0.3)", "define": "d_UpdateWhirlpool" } ], diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/ShaderSettings.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/ShaderSettings.cs index e4c548cde..6c37e2566 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/ShaderSettings.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/ShaderSettings.cs @@ -26,6 +26,11 @@ namespace WaveHarmonic.Crest.Editor return; } + if (EditorApplication.isUpdating) + { + return; + } + EditorApplication.update -= GenerateAfterReloadScripts; // Generate HLSL from C#. Only targets WaveHarmonic.Crest assemblies. @@ -46,6 +51,8 @@ namespace WaveHarmonic.Crest.Editor sealed class AssetPostProcessor : AssetPostprocessor { + const string k_SettingsPath = "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"; + static async void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] movedTo, string[] movedFrom, bool domainReload) { // Unused. @@ -53,12 +60,32 @@ namespace WaveHarmonic.Crest.Editor if (EditorApplication.isCompiling) { +#if CREST_DEBUG + if (imported.Contains(k_SettingsPath)) + { + UnityEngine.Debug.Log($"Crest: Settings.Crest.hlsl changed during compilation!"); + } +#endif + return; + } + + if (EditorApplication.isUpdating) + { +#if CREST_DEBUG + if (imported.Contains(k_SettingsPath)) + { + UnityEngine.Debug.Log($"Crest: Settings.Crest.hlsl changed during asset database update!"); + } +#endif return; } // Regenerate if file changed like re-importing. - if (imported.Contains("Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl")) + if (imported.Contains(k_SettingsPath)) { +#if CREST_DEBUG + UnityEngine.Debug.Log($"Crest: Settings.Crest.hlsl changed!"); +#endif // Generate HLSL from C#. Only targets WaveHarmonic.Crest assemblies. await ShaderGeneratorUtility.GenerateAll(); AssetDatabase.Refresh(); @@ -70,6 +97,19 @@ namespace WaveHarmonic.Crest.Editor [GenerateHLSL(sourcePath = "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest")] sealed class ShaderSettings { + // These two are here for compute shaders. + public static int s_CrestPackageHDRP = 0 +#if d_UnityHDRP + + 1 +#endif + ; + + public static int s_CrestPackageURP = 0 +#if d_UnityURP + + 1 +#endif + ; + public static int s_CrestPortals = #if d_CrestPortals 1 @@ -86,7 +126,10 @@ namespace WaveHarmonic.Crest.Editor #endif ; - public static int s_CrestShadowsBuiltInRenderPipeline = ProjectSettings.Instance.BuiltInRendererSampleShadowMaps ? 1 : 0; public static int s_CrestFullPrecisionDisplacement = ProjectSettings.Instance.FullPrecisionDisplacementOnHalfPrecisionPlatforms ? 1 : 0; + + public static int s_CrestDiscardAtmosphericScattering = ProjectSettings.Instance.RenderAtmosphericScatteringWhenUnderWater ? 0 : 1; + + public static int s_CrestLegacyUnderwater = ProjectSettings.Instance.LegacyUnderwater ? 1 : 0; } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Attributes.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Attributes.cs index b86708537..ea7139604 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Attributes.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Attributes.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Adapted from: @@ -619,6 +619,44 @@ namespace WaveHarmonic.Crest } } + sealed class InlineToggle : DecoratedProperty + { + // Add extra y offset. Needed for foldouts in foldouts so far. + readonly bool _Fix; + + public InlineToggle(bool fix = false) + { + _Fix = fix; + } + + internal override bool NeedsControlRectangle(SerializedProperty property) + { + return false; + } + + internal override void OnGUI(Rect position, SerializedProperty property, GUIContent label, DecoratedDrawer drawer) + { + var r = position; + r.x -= 16f; + // Align with Space offset. + if (drawer.Space > 0) r.y += drawer.Space + 2f; + if (_Fix) r.y += EditorGUIUtility.singleLineHeight + 2f; + // Seems to be needed. + r.width = 16f * (1f + EditorGUI.indentLevel); + r.height = EditorGUIUtility.singleLineHeight; + label.text = ""; + + using (new EditorGUI.PropertyScope(r, label, property)) + { + EditorGUI.BeginProperty(r, label, property); + // Passing a tooltip to Toggle does nothing. + GUI.Label(r, label); + property.boolValue = EditorGUI.Toggle(r, property.boolValue); + EditorGUI.EndProperty(); + } + } + } + /// /// Allows an enum to render only a subset of options in subclasses. /// @@ -793,6 +831,9 @@ namespace WaveHarmonic.Crest case SerializedPropertyType.Float: EditorGUILayout.FloatField(label, (float)_PropertyInfo.GetValue(_Target)); break; + case SerializedPropertyType.Integer: + EditorGUILayout.IntField(label, (int)_PropertyInfo.GetValue(_Target)); + break; case SerializedPropertyType.Enum: _EnumValues ??= Enum.GetValues(_PropertyInfo.PropertyType); EditorGUILayout.Popup(label, Array.IndexOf(_EnumValues, _PropertyInfo.GetValue(_Target)), property.enumDisplayNames); @@ -886,7 +927,7 @@ namespace WaveHarmonic.Crest /// sealed class Space : Decorator { - readonly float _Height; + public readonly float _Height; readonly bool _AlwaysVisible; public Space(float height, bool isAlwaysVisible = false) @@ -978,13 +1019,13 @@ namespace WaveHarmonic.Crest } } - sealed class AttachMaterialEditor : Decorator + sealed class AttachMaterialEditor : Attribute { - public override bool AlwaysVisible => true; + public int Order { get; private set; } - internal override void Decorate(Rect position, SerializedProperty property, GUIContent label, DecoratedDrawer drawer) + public AttachMaterialEditor(int order = 0) { - Inspector.Current._Materials.Add((Material)property.objectReferenceValue); + Order = order; } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Embedded.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Embedded.cs index 67a45c596..7c954746b 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Embedded.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Embedded.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEditor; @@ -11,17 +11,19 @@ namespace WaveHarmonic.Crest sealed class Embedded : DecoratedProperty { internal EmbeddedAssetEditor _Editor; - readonly int _BottomMargin; + public int BottomMargin { get; private set; } + public string DefaultPropertyName { get; private set; } - public Embedded(int margin = 0) + public Embedded(int margin = 0, string defaultPropertyName = null) { _Editor = new(); - _BottomMargin = margin; + BottomMargin = margin; + DefaultPropertyName = defaultPropertyName; } internal override void OnGUI(Rect position, SerializedProperty property, GUIContent label, DecoratedDrawer drawer) { - _Editor.DrawEditorCombo(label, drawer, property, "asset", _BottomMargin); + _Editor.DrawEditorCombo(this, label, drawer, property, "asset"); } internal override bool NeedsControlRectangle(SerializedProperty property) => false; diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/HelpBox.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/HelpBox.cs index c4c92f585..77ea34c3e 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/HelpBox.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/HelpBox.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEditor; diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Layer.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Layer.cs index 26601c70b..bbbeaae37 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Layer.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Layer.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEditor; diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Predicated.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Predicated.cs index c3ffae915..79f7c2884 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Predicated.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Attributes/Predicated.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System; @@ -51,6 +51,12 @@ namespace WaveHarmonic.Crest _Member = _Type.GetMember(member, Helpers.s_AnyMethod)[0]; } + /// + public Predicated(Type type, string member, bool inverted = false, bool hide = false) : this(type, member, true, inverted, hide) + { + + } + /// /// Enable/Disable field depending on the current type of the component. /// @@ -165,11 +171,11 @@ namespace WaveHarmonic.Crest if (_Member is PropertyInfo autoProperty) { // == operator does not work. - enabled = autoProperty.GetValue(@object).Equals(_DisableValue); + enabled = !autoProperty.GetValue(@object).Equals(_DisableValue); } else if (_Member is MethodInfo method) { - enabled = method.Invoke(@object, new object[] { }).Equals(_DisableValue); + enabled = !method.Invoke(@object, new object[] { }).Equals(_DisableValue); } if (_Inverted) enabled = !enabled; diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/DecoratedDrawer.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/DecoratedDrawer.cs index 9aa60c592..48088bb08 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/DecoratedDrawer.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/DecoratedDrawer.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Adapted from: @@ -27,6 +27,8 @@ namespace WaveHarmonic.Crest.Editor public static bool s_TemporaryColor; public static Color s_PreviousColor; + public float Space { get; private set; } + List _Decorators = null; List Decorators { @@ -84,6 +86,16 @@ namespace WaveHarmonic.Crest.Editor attribute.Decorate(position, property, label, this); } + Space = 0; + + // Execute all labels + for (var index = 0; index < Decorators.Count; index++) + { + var attribute = (Decorator)Decorators[index]; + if (attribute is Space space) Space = space._Height; + label = attribute.BuildLabel(label); + } + if (!s_HideInInspector && (!s_IsFoldout || s_IsFoldoutOpen)) { // Execute all visual attributes. @@ -91,7 +103,6 @@ namespace WaveHarmonic.Crest.Editor { var attribute = (Decorator)Decorators[index]; if (attribute.AlwaysVisible) continue; - label = attribute.BuildLabel(label); attribute.Decorate(position, property, label, this); } @@ -101,6 +112,7 @@ namespace WaveHarmonic.Crest.Editor : position; // Call for labels again as EditorGUI.GetPropertyHeight will revert them. + // Specifically for nested classes where the label will revert once opened. for (var index = 0; index < Decorators.Count; index++) { var attribute = (Decorator)Decorators[index]; @@ -163,7 +175,7 @@ namespace WaveHarmonic.Crest.Editor var targetType = target.GetType(); var isActive = true; - if (property.serializedObject.targetObject is Internal.EditorBehaviour c && !c.isActiveAndEnabled) + if (property.serializedObject.targetObject is Crest.Internal.EditorBehaviour c && !c.isActiveAndEnabled) { isActive = false; } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/EmbeddedAssetHelpers.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/EmbeddedAssetHelpers.cs index 348402057..319d41ca8 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/EmbeddedAssetHelpers.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/EmbeddedAssetHelpers.cs @@ -7,9 +7,10 @@ // Lovingly adapted from Cinemachine: // https://github.com/Unity-Technologies/com.unity.cinemachine/blob/593fa283bee378322337e5d9f5a7b91331a45799/Editor/Utility/EmbeddedAssetHelpers.cs -using UnityEngine; +using System.Reflection; using UnityEditor; using UnityEditor.VersionControl; +using UnityEngine; namespace WaveHarmonic.Crest.Editor { @@ -66,23 +67,24 @@ namespace WaveHarmonic.Crest.Editor System.Type _Type; Object _DefaultTarget; + FieldInfo _DefaultTargetField; const int k_IndentOffset = 3; - public void DrawEditorCombo(GUIContent label, PropertyDrawer drawer, SerializedProperty property, string extension, int bottomMargin = 0) + public void DrawEditorCombo(Embedded embedded, GUIContent label, PropertyDrawer drawer, SerializedProperty property, string extension) { _Type = drawer.fieldInfo.FieldType; DrawEditorCombo ( + embedded, label, $"Create {property.displayName} Asset", $"{property.displayName.Replace(' ', '_')}", extension, string.Empty, false, - property, - bottomMargin + property ); } @@ -92,17 +94,17 @@ namespace WaveHarmonic.Crest.Editor /// public void DrawEditorCombo ( + Embedded embedded, GUIContent label, string title, string defaultName, string extension, string message, bool indent, - SerializedProperty property, - int bottomMargin + SerializedProperty property ) { - UpdateEditor(property); + UpdateEditor(property, embedded); EditorGUI.BeginChangeCheck(); var rect = AssetField(label, property, title, defaultName, extension, message); @@ -110,7 +112,7 @@ namespace WaveHarmonic.Crest.Editor if (EditorGUI.EndChangeCheck()) { property.serializedObject.ApplyModifiedProperties(); - UpdateEditor(property); + UpdateEditor(property, embedded); } // Display embedded editor. @@ -145,9 +147,9 @@ namespace WaveHarmonic.Crest.Editor EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); - if (bottomMargin > 0) + if (embedded.BottomMargin > 0) { - EditorGUILayout.Space(bottomMargin); + EditorGUILayout.Space(embedded.BottomMargin); } } @@ -201,14 +203,31 @@ namespace WaveHarmonic.Crest.Editor } } - public void UpdateEditor(SerializedProperty property) + public void UpdateEditor(SerializedProperty property, Embedded embedded) { var target = property.objectReferenceValue; + var hasDefaultField = !string.IsNullOrEmpty(embedded.DefaultPropertyName); - if (target == null && _DefaultTarget == null) + if (target == null) { - _DefaultTarget = ScriptableObject.CreateInstance(_Type); - _DefaultTarget.hideFlags = HideFlags.DontSave | HideFlags.NotEditable; + if (!hasDefaultField) + { + if (_DefaultTarget == null) + { + _DefaultTarget = ScriptableObject.CreateInstance(_Type); + _DefaultTarget.hideFlags = HideFlags.DontSave | HideFlags.NotEditable; + } + } + else + { + if (_DefaultTargetField == null) + { + _DefaultTargetField = property.serializedObject.targetObject.GetType().GetField(embedded.DefaultPropertyName, Helpers.s_AnyMethod); + } + + // Always call, as it is dynamic. + _DefaultTarget = (Object)_DefaultTargetField.GetValue(property.serializedObject.targetObject); + } } if (target == null) diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Helpers.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Helpers.cs index 637c91561..7464fbd5d 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Helpers.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Helpers.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System.Diagnostics.CodeAnalysis; @@ -15,7 +15,7 @@ namespace WaveHarmonic.Crest.Editor /// /// Provides general helper functions for the editor. /// - static class EditorHelpers + static partial class EditorHelpers { internal static ComputeShader s_VisualizeNegativeValuesShader; internal static ComputeShader VisualizeNegativeValuesShader @@ -227,27 +227,6 @@ namespace WaveHarmonic.Crest.Editor UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene()); } } - - static readonly MethodInfo s_ButtonWithDropdownList = typeof(EditorGUI).GetMethod - ( - "ButtonWithDropdownList", - BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, - null, - new System.Type[] { typeof(GUIContent), typeof(string[]), typeof(GenericMenu.MenuFunction2), typeof(GUILayoutOption[]) }, - null - ); - - static readonly GUILayoutOption[] s_GUILayoutOptionsZero; - - public static bool ButtonWithDropdownList(GUIContent name, string[] names, GenericMenu.MenuFunction2 callback) - { - if (names == null) - { - return GUILayout.Button(name); - } - - return (bool)s_ButtonWithDropdownList.Invoke(null, new object[] { name, names, callback, s_GUILayoutOptionsZero }); - } } static partial class Extensions @@ -269,4 +248,241 @@ namespace WaveHarmonic.Crest.Editor return tag.name; } } + + static partial class EditorHelpers + { + const int k_ButtonDropDownWidth = 15; + + static readonly GUIContent s_ButtonDropDownIcon = new(EditorGUIUtility.FindTexture("icon dropdown@2x")); + static readonly PropertyInfo s_TopLevel = typeof(GUILayoutUtility).GetProperty("topLevel", BindingFlags.NonPublic | BindingFlags.Static); + static readonly MethodInfo s_GetLast = typeof(GUILayoutUtility).Assembly.GetType("UnityEngine.GUILayoutGroup").GetMethod("GetLast", BindingFlags.Public | BindingFlags.Instance); + + // Only way to identify the caller is its rect. + static Rect s_ButtonChooser; + static int s_ButtonChoice = -2; + + // Normal button or split button with dropdown. + public static bool Button + ( + GUIContent label, + out int choice, + string[] labels, + bool disableMain = false, + bool disableDropDown = false, + bool centerLabel = false, + bool expandWidth = true, + int minimumWidth = 0 + ) + { + choice = -2; + var chosen = false; + + var hasDropDown = labels?.Length > 0; + var skin = GUI.skin.button; + + using (new EditorGUI.DisabledGroupScope(disableMain)) + { + var style = new GUIStyle(hasDropDown ? EditorStyles.miniButtonLeft : EditorStyles.miniButton) + { + padding = skin.padding, + stretchHeight = skin.stretchHeight, + fixedHeight = skin.fixedHeight + }; + + var width = style.CalcSize(label).x + style.padding.left + + style.padding.right + style.border.left + style.border.right; + width = Mathf.Max(width, minimumWidth); + // TODO: Add option to disable this (consistent width). + if (!hasDropDown && minimumWidth > 0) width += k_ButtonDropDownWidth; + if (centerLabel && hasDropDown) style.padding.left += k_ButtonDropDownWidth; + + if (GUILayout.Button(label, style, expandWidth ? GUILayout.ExpandWidth(true) : GUILayout.Width(width))) + { + choice = -1; + chosen = true; + } + } + + if (hasDropDown) + { + using (new EditorGUI.DisabledGroupScope(disableDropDown)) + { + // TODO: color interior border same as exterior (lighten). + var style = new GUIStyle(EditorStyles.miniButtonRight) + { + padding = new(1, 1, 3, 3), + stretchHeight = skin.stretchHeight, + fixedHeight = skin.fixedHeight + }; + + var rect = (Rect)s_GetLast.Invoke(s_TopLevel.GetValue(null), null); + rect.width += k_ButtonDropDownWidth; + + if (s_ButtonChoice > -1 && s_ButtonChooser == rect) + { + choice = s_ButtonChoice; + chosen = true; + s_ButtonChoice = -2; + s_ButtonChooser = Rect.zero; + } + + if (GUILayout.Button(s_ButtonDropDownIcon, style, GUILayout.Width(k_ButtonDropDownWidth), GUILayout.ExpandHeight(true))) + { + var menu = new GenericMenu(); + + for (var i = 0; i < labels.Length; i++) + { + menu.AddItem(new(labels[i]), false, x => { s_ButtonChoice = (int)x; s_ButtonChooser = rect; }, i); + } + + menu.DropDown(rect); + } + } + } + + return chosen; + } + } + + static partial class EditorHelpers + { + // Adapted from (public API may support this in future): + // com.unity.splines@2.7.2/Editor/Components/SplineContainerEditor.cs + static GUIStyle s_HelpLabelStyle; + static GUIStyle HelpLabelStyle => s_HelpLabelStyle ??= new(EditorStyles.label) + { + wordWrap = EditorStyles.helpBox.wordWrap, + fontSize = EditorStyles.helpBox.fontSize, + padding = new(-2, 0, 0, 0), + richText = true, + }; + + static readonly MethodInfo s_GetHelpIcon = typeof(EditorGUIUtility).GetMethod("GetHelpIcon", BindingFlags.Static | BindingFlags.NonPublic); + + internal static int? HelpBox + ( + GUIContent message, + MessageType type, + GUIContent button = null, + string[] buttons = null, + bool buttonCenterLabel = false, + int buttonMinimumWidth = 0 + ) + { + return HelpBox + ( + message, + new GUIContent((Texture2D)s_GetHelpIcon.Invoke(null, new object[] { type })), + button, + buttons, + buttonCenterLabel, + buttonMinimumWidth + ); + } + + internal static int? HelpBox + ( + GUIContent message, + GUIContent icon, + GUIContent button = null, + string[] buttons = null, + bool buttonCenterLabel = false, + int buttonMinimumWidth = 0 + ) + { + int? result = null; + + // Box + EditorGUILayout.BeginHorizontal(EditorStyles.helpBox); + + // Icon + EditorGUIUtility.SetIconSize(new(32f, 32f)); + EditorGUILayout.LabelField(icon, GUILayout.Width(34), GUILayout.MinHeight(34), GUILayout.ExpandHeight(true)); + EditorGUIUtility.SetIconSize(Vector2.zero); + + // Text + EditorGUILayout.LabelField(message, HelpLabelStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); + + // Button + if (button != null) + { + GUILayout.FlexibleSpace(); + + EditorGUILayout.BeginVertical(); + GUILayout.FlexibleSpace(); + + EditorGUILayout.BeginHorizontal(); + + if (Button(button, out var choice, buttons, centerLabel: buttonCenterLabel, minimumWidth: buttonMinimumWidth, expandWidth: false)) + { + result = choice; + } + + EditorGUILayout.EndHorizontal(); + + GUILayout.FlexibleSpace(); + EditorGUILayout.EndVertical(); + + } + + EditorGUILayout.EndHorizontal(); + + return result; + } + } + + namespace Internal + { + static class Extensions + { + // Recursively find the field owner (instance). + public static bool FindOwner(this FieldInfo field, ref object target) + { + if (field.DeclaringType.IsAssignableFrom(target.GetType())) + { + return true; + } + + return field.FindOwnerInFields(ref target); + } + + public static bool FindOwnerInFields(this FieldInfo targetField, ref object target) + { + if (target == null) + { + return false; + } + + var fields = target.GetType() + .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + foreach (var field in fields) + { + if (field.GetCustomAttribute() == null) + { + continue; + } + + var value = field.GetValue(target); + if (value == null) + { + continue; + } + + if (targetField.DeclaringType.IsAssignableFrom(value.GetType())) + { + target = value; + return true; + } + + if (FindOwnerInFields(targetField, ref value)) + { + return true; + } + } + + return false; + } + } + } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.Validation.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.Validation.cs index f56859f06..914108340 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.Validation.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.Validation.cs @@ -9,16 +9,12 @@ namespace WaveHarmonic.Crest.Editor { partial class Inspector { - static readonly bool s_GroupMessages = false; - static GUIContent s_JumpButtonContent = null; - static GUIContent s_FixButtonContent = null; + static readonly string[] s_FixButtonDropDown = { "Inspect" }; + static readonly GUIContent s_FixButtonContent = new("Fix"); + static readonly GUIContent s_InspectButtonContent = new("Inspect", "Jump to object to resolve issue."); protected virtual void RenderValidationMessages() { - // Enable rich text in help boxes. Store original so we can revert since this might be a "hack". - var styleRichText = GUI.skin.GetStyle("HelpBox").richText; - GUI.skin.GetStyle("HelpBox").richText = true; - // This is a static list so we need to clear it before use. Not sure if this will ever be a threaded // operation which would be an issue. foreach (var messages in ValidatedHelper.s_Messages) @@ -30,7 +26,43 @@ namespace WaveHarmonic.Crest.Editor // We only want space before and after the list of help boxes. We don't want space between. var needsSpaceAbove = true; - var needsSpaceBelow = false; + + // Work out if button label needs aligning. + var needsAlignment = false; + var hasBoth = false; + var hasEither = false; + for (var messageTypeIndex = 0; messageTypeIndex < ValidatedHelper.s_Messages.Length; messageTypeIndex++) + { + var messages = ValidatedHelper.s_Messages[messageTypeIndex]; + + if (messages.Count > 0) + { + var messageType = (MessageType)ValidatedHelper.s_Messages.Length - messageTypeIndex; + + foreach (var message in messages) + { + var hasFix = message._Action != null; + var hasInspect = false; + + if (message._Object != null) + { + var casted = message._Object as MonoBehaviour; + + if (Selection.activeObject != message._Object && (casted == null || casted.gameObject != Selection.activeObject)) + { + hasInspect = true; + } + } + + if (hasFix && hasInspect) hasBoth = true; + if (hasInspect != hasFix) hasEither = true; + if (hasBoth && hasEither) goto exit; + } + } + } + + exit: + needsAlignment = hasBoth && hasEither; // We loop through in reverse order so errors appears at the top. for (var messageTypeIndex = 0; messageTypeIndex < ValidatedHelper.s_Messages.Length; messageTypeIndex++) @@ -41,118 +73,87 @@ namespace WaveHarmonic.Crest.Editor { if (needsSpaceAbove) { - // Double space looks good at top. EditorGUILayout.Space(); - // EditorGUILayout.Space(); needsSpaceAbove = false; } - needsSpaceBelow = true; - // Map Validated.MessageType to HelpBox.MessageType. var messageType = (MessageType)ValidatedHelper.s_Messages.Length - messageTypeIndex; - if (s_GroupMessages) + foreach (var message in messages) { - // We join the messages together to reduce vertical space since HelpBox has padding, borders etc. - var joinedMessage = messages[0]._Message; - // Format as list if we have more than one message. - if (messages.Count > 1) joinedMessage = $"- {joinedMessage}"; + EditorGUILayout.BeginHorizontal(); - for (var messageIndex = 1; messageIndex < messages.Count; messageIndex++) + var originalGUIEnabled = GUI.enabled; + + if ((message._Action == ValidatedHelper.FixAddMissingMathPackage || message._Action == ValidatedHelper.FixAddMissingBurstPackage) && PackageManagerHelpers.IsBusy) { - joinedMessage += $"\n- {messages[messageIndex]}"; + GUI.enabled = false; } - EditorGUILayout.HelpBox(joinedMessage, messageType); - } - else - { - foreach (var message in messages) + if (message._FixDescription != null) { - EditorGUILayout.BeginHorizontal(); - - var fixDescription = message._FixDescription; - var originalGUIEnabled = GUI.enabled; - - if (message._Action != null) - { - fixDescription += " Click the fix/repair button on the right to fix."; - - if ((message._Action == ValidatedHelper.FixAddMissingMathPackage || message._Action == ValidatedHelper.FixAddMissingBurstPackage) && PackageManagerHelpers.IsBusy) - { - GUI.enabled = false; - } - } - - EditorGUILayout.HelpBox($"{message._Message} {fixDescription}", messageType); - - // Jump to object button. - if (message._Object != null) - { - // Selection.activeObject can be message._object.gameObject instead of the component - // itself. We soft cast to MonoBehaviour to get the gameObject for comparison. - // Alternatively, we could always pass gameObject instead of "this". - var casted = message._Object as MonoBehaviour; - - if (Selection.activeObject != message._Object && (casted == null || casted.gameObject != Selection.activeObject)) - { - s_JumpButtonContent ??= new(EditorGUIUtility.FindTexture("scenepicking_pickable_hover@2x"), "Jump to object to resolve issue"); - - if (GUILayout.Button(s_JumpButtonContent, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true))) - { - Selection.activeObject = message._Object; - } - } - } - - // Fix the issue button. - if (message._Action != null) - { - s_FixButtonContent ??= new(EditorGUIUtility.FindTexture("SceneViewTools")); - - if (message._FixDescription != null) - { - var sanitisedFixDescr = Regex.Replace(message._FixDescription, @"<[^<>]*>", "'"); - s_FixButtonContent.tooltip = $"Apply fix: {sanitisedFixDescr}"; - } - else - { - s_FixButtonContent.tooltip = "Fix issue"; - } - - if (GUILayout.Button(s_FixButtonContent, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true))) - { - // Run fix function - var serializedObject = new SerializedObject(message._Object); - // Property is optional. - var property = message._PropertyPath != null ? serializedObject?.FindProperty(message._PropertyPath) : null; - var oldValue = property?.boxedValue; - message._Action.Invoke(serializedObject, property); - if (serializedObject.ApplyModifiedProperties()) - { - // SerializedObject does this for us, but gives the history item a nicer label. - Undo.RecordObject(message._Object, s_FixButtonContent.tooltip); - DecoratedDrawer.OnChange(property, oldValue); - } - } - } - - GUI.enabled = originalGUIEnabled; - - EditorGUILayout.EndHorizontal(); + var sanitized = Regex.Replace(message._FixDescription, @"<[^<>]*>", "'"); + s_FixButtonContent.tooltip = $"Fix: {sanitized}"; } + else + { + s_FixButtonContent.tooltip = "Fix issue"; + } + + var canFix = message._Action != null; + var canInspect = false; + + // Jump to object button. + if (message._Object != null) + { + // Selection.activeObject can be message._object.gameObject instead of the component + // itself. We soft cast to MonoBehaviour to get the gameObject for comparison. + // Alternatively, we could always pass gameObject instead of "this". + var casted = message._Object as MonoBehaviour; + + if (Selection.activeObject != message._Object && (casted == null || casted.gameObject != Selection.activeObject)) + { + canInspect = true; + } + } + + var result = EditorHelpers.HelpBox + ( + new($"{message._Message} {message._FixDescription}"), + messageType, + canFix ? s_FixButtonContent : canInspect ? s_InspectButtonContent : null, + buttons: canInspect && canFix ? s_FixButtonDropDown : null, + buttonCenterLabel: needsAlignment, + buttonMinimumWidth: 72 + ); + + if (canFix && result == -1) + { + // Run fix function. + var serializedObject = new SerializedObject(message._Object); + // Property is optional. + var property = message._PropertyPath != null ? serializedObject?.FindProperty(message._PropertyPath) : null; + var oldValue = property?.boxedValue; + message._Action.Invoke(serializedObject, property); + if (serializedObject.ApplyModifiedProperties()) + { + // SerializedObject does this for us, but gives the history item a nicer label. + Undo.RecordObject(message._Object, s_FixButtonContent.tooltip); + DecoratedDrawer.OnChange(property, oldValue); + } + } + else if (canInspect && result != null) + { + Selection.activeObject = message._Object; + } + + GUI.enabled = originalGUIEnabled; + + EditorGUILayout.EndHorizontal(); } } } - - if (needsSpaceBelow) - { - // EditorGUILayout.Space(); - } - - // Revert skin since it persists. - GUI.skin.GetStyle("HelpBox").richText = styleRichText; } } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.cs index 508ff883b..c8a6eaf78 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Inspector.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using UnityEditor; using UnityEngine; +using WaveHarmonic.Crest.Editor.Internal; using WaveHarmonic.Crest.Internal; namespace WaveHarmonic.Crest.Editor @@ -21,15 +23,32 @@ namespace WaveHarmonic.Crest.Editor internal static Inspector Current { get; private set; } + readonly Dictionary _MaterialOwners = new(); readonly Dictionary _MaterialEditors = new(); - public override bool RequiresConstantRepaint() => TexturePreview.AnyActivePreviews; + public override bool RequiresConstantRepaint() => TexturePreview.s_ActiveInstance?.Open == true; - // Set this from a decorator to enable the material editor. - internal List _Materials = new(); + static readonly IOrderedEnumerable s_AttachMaterialEditors = TypeCache + .GetFieldsWithAttribute() + .OrderBy(x => x.GetCustomAttribute().Order); readonly Utility.SortedList _Properties = new(Helpers.DuplicateComparison); + protected virtual void OnEnable() + { + _MaterialOwners.Clear(); + + foreach (var field in s_AttachMaterialEditors) + { + var target = (object)this.target; + + if (field.FindOwner(ref target)) + { + _MaterialOwners.Add(field, target); + } + } + } + public override void OnInspectorGUI() { // Reset foldout values. @@ -61,7 +80,7 @@ namespace WaveHarmonic.Crest.Editor } } - protected void RenderBeforeInspectorGUI() + protected virtual void RenderBeforeInspectorGUI() { if (this.target is EditorBehaviour target && target._IsPrefabStageInstance) { @@ -143,13 +162,14 @@ namespace WaveHarmonic.Crest.Editor protected virtual void RenderAfterInspectorGUI() { - foreach (var material in _Materials) + foreach (var mapping in _MaterialOwners) { - if (material == null) continue; - DrawMaterialEditor(material); + var material = (Material)mapping.Key.GetValue(mapping.Value); + if (material != null) + { + DrawMaterialEditor(material); + } } - - _Materials.Clear(); } // Adapted from: http://answers.unity.com/answers/975894/view.html diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs new file mode 100644 index 000000000..f904cef78 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs @@ -0,0 +1,75 @@ + +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System.Linq; +using UnityEditor; +using UnityEditor.Build; + +namespace WaveHarmonic.Crest.Editor.Settings +{ + static class ScriptingSymbols + { + static NamedBuildTarget CurrentNamedBuildTarget + { + get + { +#if UNITY_SERVER + return NamedBuildTarget.Server; +#else + return NamedBuildTarget.FromBuildTargetGroup(BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget)); +#endif + } + } + + public static string[] Symbols => PlayerSettings.GetScriptingDefineSymbols(CurrentNamedBuildTarget).Split(';'); + + public static void Add(string[] symbols) + { + // We remove our symbols from the list first to prevent duplicates - just to be safe. + SetScriptingDefineSymbols(Symbols.Except(symbols).Concat(symbols).ToArray()); + } + + public static void Add(string symbol) + { + Add(new string[] { symbol }); + } + + public static void Remove(string[] symbols) + { + SetScriptingDefineSymbols(Symbols.Except(symbols).ToArray()); + } + + public static void Remove(string symbol) + { + Remove(new string[] { symbol }); + } + + public static void Set(string[] symbols, bool enable) + { + if (enable) + { + Add(symbols); + } + else + { + Remove(symbols); + } + } + + public static void Set(string symbol, bool enable) + { + Set(new string[] { symbol }, enable); + } + + static void SetScriptingDefineSymbols(string[] symbols) + { + SetScriptingDefineSymbols(string.Join(";", symbols)); + } + + static void SetScriptingDefineSymbols(string symbols) + { + PlayerSettings.SetScriptingDefineSymbols(CurrentNamedBuildTarget, symbols); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs.meta new file mode 100644 index 000000000..66bd5bc96 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ScriptingSymbols.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c03a1671f6a84ed4ac42813e95a07d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs new file mode 100644 index 000000000..989b0784f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs @@ -0,0 +1,739 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEditor.Rendering.BuiltIn; +using UnityEditor.Rendering.BuiltIn.ShaderGraph; +using UnityEditor.ShaderGraph; +using UnityEngine; +using UnityEngine.Rendering; + +#if UNITY_2022_3_OR_NEWER +using UnityEngine.UIElements; +#else +using UnityEngine.UIElements; +using UnityEditor.UIElements; +#endif + +using UnityBuiltInLitSubTarget = UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInLitSubTarget; + +namespace WaveHarmonic.Crest.Editor.ShaderGraph +{ + sealed class MaterialModificationProcessor : AssetModificationProcessor + { + static void OnWillCreateAsset(string asset) + { + if (!asset.ToLowerInvariant().EndsWith(".mat")) + { + return; + } + + MaterialPostProcessor.s_CreatedAssets.Add(asset); + } + } + + sealed class MaterialPostProcessor : AssetPostprocessor + { + public override int GetPostprocessOrder() + { + return 1; + } + + internal static readonly List s_CreatedAssets = new(); + + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + { + foreach (var asset in importedAssets) + { + // We only care about materials + if (!asset.EndsWith(".mat", System.StringComparison.InvariantCultureIgnoreCase)) + { + continue; + } + + // Load the material and look for it's BuiltIn ShaderID. + // We only care about versioning materials using a known BuiltIn ShaderID. + // This skips any materials that only target other render pipelines, are user shaders, + // or are shaders we don't care to version + var material = (Material)AssetDatabase.LoadAssetAtPath(asset, typeof(Material)); + var shaderID = ShaderUtils.GetShaderID(material.shader); + if (shaderID == ShaderUtils.ShaderID.Unknown) + { + continue; + } + + if (material.shader == null || material.shader.name != "Crest/Water") + { + continue; + } + + // Look for the BuiltIn AssetVersion + AssetVersion assetVersion = null; + var allAssets = AssetDatabase.LoadAllAssetsAtPath(asset); + foreach (var subAsset in allAssets) + { + if (subAsset is AssetVersion sub) + { + assetVersion = sub; + } + } + + if (!assetVersion) + { + if (s_CreatedAssets.Contains(asset)) + { + s_CreatedAssets.Remove(asset); + CustomBuiltInLitGUI.UpdateMaterial(material); + } + } + } + } + } + + class CustomBuiltInLitGUI : BuiltInLitGUI + { + MaterialEditor _MaterialEditor; + MaterialProperty[] _Properties; + + static readonly GUIContent s_WorkflowModeText = EditorGUIUtility.TrTextContent + ( + "Workflow Mode", + "Select a workflow that fits your textures. Choose between Metallic or Specular." + ); + + static readonly GUIContent s_TransparentReceiveShadowsText = EditorGUIUtility.TrTextContent + ( + "Receives Shadows", + "When enabled, other GameObjects can cast shadows onto this GameObject." + ); + + public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) + { + _MaterialEditor = materialEditor; + _Properties = properties; + + base.OnGUI(materialEditor, properties); + } + + public override void ValidateMaterial(Material material) + { + base.ValidateMaterial(material); + UpdateMaterial(material); + } + + public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) + { + base.AssignNewShaderToMaterial(material, oldShader, newShader); + UpdateMaterial(material); + } + + protected override void DrawSurfaceOptions(Material material) + { + var materialEditor = _MaterialEditor; + var properties = _Properties; + + var workflowProperty = FindProperty(Property.SpecularWorkflowMode(), properties, false); + if (workflowProperty != null) + { + DoPopup(s_WorkflowModeText, materialEditor, workflowProperty, System.Enum.GetNames(typeof(WorkflowMode))); + } + + base.DrawSurfaceOptions(material); + + var surfaceTypeProp = FindProperty(Property.Surface(), properties, false); + if (surfaceTypeProp != null && (SurfaceType)surfaceTypeProp.floatValue == SurfaceType.Transparent) + { + var trsProperty = FindProperty(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty, properties, false); + DrawFloatToggleProperty(s_TransparentReceiveShadowsText, trsProperty); + } + } + + // Should be called by ShaderGraphMaterialsUpdater, but we will never upgrade. + public static new void UpdateMaterial(Material material) + { + if (material.HasProperty(Property.SpecularWorkflowMode())) + { + var workflow = (WorkflowMode)material.GetFloat(Property.SpecularWorkflowMode()); + CoreUtils.SetKeyword(material, BuiltInLitSubTarget.LitDefines.s_SpecularSetup.referenceName, workflow == WorkflowMode.Specular); + } + + if (material.HasProperty(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty)) + { + var receive = material.GetFloat(BuiltInLitSubTarget.s_TransparentReceiveShadowsProperty) == 1f; + CoreUtils.SetKeyword(material, BuiltInLitSubTarget.LitDefines.s_TransparentReceivesShadows.referenceName, receive); + } + } + } + + sealed class BuiltInLitSubTarget : BuiltInSubTarget + { + const string k_ShaderPath = "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy"; + const string k_TemplatePath = "Packages/com.waveharmonic.crest/Editor/Shaders/Templates"; + + readonly UnityBuiltInLitSubTarget _BuiltInLitSubTarget; + +#pragma warning disable IDE0032, IDE1006 + [SerializeField] + WorkflowMode m_WorkflowMode = WorkflowMode.Metallic; + + [SerializeField] + NormalDropOffSpace m_NormalDropOffSpace = NormalDropOffSpace.Tangent; + + [SerializeField] + bool m_TransparentReceiveShadows = true; +#pragma warning restore IDE0032, IDE1006 + + public static readonly string s_TransparentReceiveShadowsProperty = "_BUILTIN_TransparentReceiveShadows"; + + public BuiltInLitSubTarget() + { + _BuiltInLitSubTarget = new(); + displayName = _BuiltInLitSubTarget.displayName; + } + + protected override ShaderUtils.ShaderID shaderID => ShaderUtils.ShaderID.SG_Lit; + public override bool IsActive() => true; + + WorkflowMode WorkflowMode + { + get => m_WorkflowMode; + set => m_WorkflowMode = value; + } + + NormalDropOffSpace NormalDropOffSpace + { + get => m_NormalDropOffSpace; + set => m_NormalDropOffSpace = value; + } + + bool TransparentReceiveShadows + { + get => m_TransparentReceiveShadows; + set => m_TransparentReceiveShadows = value; + } + +#if UNITY_2022_3_OR_NEWER + static FieldInfo s_CustomEditorForRenderPipelines; + static FieldInfo CustomEditorForRenderPipelines => s_CustomEditorForRenderPipelines ??= typeof(TargetSetupContext).GetField("customEditorForRenderPipelines", BindingFlags.NonPublic | BindingFlags.Instance); +#endif + + public override void Setup(ref TargetSetupContext context) + { + _BuiltInLitSubTarget.target = target; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + _BuiltInLitSubTarget.Setup(ref context); + + // Caused a crash: !context.HasCustomEditorForRenderPipeline(null) + if (string.IsNullOrEmpty(target.customEditorGUI)) + { +#if UNITY_2022_3_OR_NEWER + var editors = (List)CustomEditorForRenderPipelines.GetValue(context); + if (editors.Count > 0) + { + editors.RemoveAt(editors.Count - 1); + } + + context.AddCustomEditorForRenderPipeline(typeof(CustomBuiltInLitGUI).FullName, ""); +#else + if (context.customEditorForRenderPipelines.Count > 0) + { + context.customEditorForRenderPipelines.RemoveAt(context.customEditorForRenderPipelines.Count - 1); + } + + context.customEditorForRenderPipelines.Add((typeof(CustomBuiltInLitGUI).FullName, "")); +#endif + } + + context.subShaders.RemoveAt(0); + context.AddSubShader(SubShaders.Lit(this)); + } + + public override void ProcessPreviewMaterial(Material material) + { + _BuiltInLitSubTarget.target = target; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + _BuiltInLitSubTarget.ProcessPreviewMaterial(material); + CustomBuiltInLitGUI.UpdateMaterial(material); + } + + public override void GetFields(ref TargetFieldContext context) + { + _BuiltInLitSubTarget.target = target; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + _BuiltInLitSubTarget.GetFields(ref context); + // Do not use this, as we handle this properly. + context.AddField(BuiltInFields.SpecularSetup, false); + } + + public override void GetActiveBlocks(ref TargetActiveBlockContext context) + { + _BuiltInLitSubTarget.target = target; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + _BuiltInLitSubTarget.GetActiveBlocks(ref context); + + context.activeBlocks.Remove(BlockFields.SurfaceDescription.Metallic); + var insertion = context.activeBlocks.FindIndex(x => x == BlockFields.SurfaceDescription.Occlusion) + 1; + + if ((WorkflowMode == WorkflowMode.Specular) || target.allowMaterialOverride) + { + context.activeBlocks.Insert(insertion, BlockFields.SurfaceDescription.Specular); + } + + if ((WorkflowMode == WorkflowMode.Metallic) || target.allowMaterialOverride) + { + context.activeBlocks.Insert(insertion, BlockFields.SurfaceDescription.Metallic); + } + } + + public override void CollectShaderProperties(PropertyCollector collector, GenerationMode generationMode) + { + if (target.allowMaterialOverride) + { + collector.AddFloatProperty(Property.SpecularWorkflowMode(), (float)WorkflowMode); + } + + _BuiltInLitSubTarget.target = target; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + _BuiltInLitSubTarget.CollectShaderProperties(collector, generationMode); + + if (target.allowMaterialOverride) + { + collector.AddFloatProperty(s_TransparentReceiveShadowsProperty, TransparentReceiveShadows ? 1f : 0f); + } + + // LEqual + collector.AddFloatProperty(SubShaders.k_ShadowCasterZTest, 4, UnityEditor.ShaderGraph.Internal.HLSLDeclaration.UnityPerMaterial); + } + + public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, System.Action onChange, System.Action registerUndo) + { + target.AddDefaultMaterialOverrideGUI(ref context, onChange, registerUndo); + + context.AddProperty("Workflow", new EnumField(WorkflowMode.Metallic) { value = WorkflowMode }, (evt) => + { + if (Equals(WorkflowMode, evt.newValue)) + return; + + registerUndo("Change Workflow"); + WorkflowMode = (WorkflowMode)evt.newValue; + onChange(); + }); + + target.GetDefaultSurfacePropertiesGUI(ref context, onChange, registerUndo); + + context.AddProperty("Transparent Receives Shadows", new Toggle() { value = TransparentReceiveShadows }, (evt) => + { + if (Equals(TransparentReceiveShadows, evt.newValue)) + return; + + registerUndo("Change Transparent Receives Shadows"); + TransparentReceiveShadows = evt.newValue; + onChange(); + }); + + context.AddProperty("Fragment Normal Space", new EnumField(NormalDropOffSpace.Tangent) { value = NormalDropOffSpace }, (evt) => + { + if (Equals(NormalDropOffSpace, evt.newValue)) + return; + + registerUndo("Change Fragment Normal Space"); + NormalDropOffSpace = (NormalDropOffSpace)evt.newValue; + _BuiltInLitSubTarget.normalDropOffSpace = NormalDropOffSpace; + onChange(); + }); + } + + static class SubShaders + { + static readonly string s_ShaderPathDefines = $"{k_ShaderPath}/Defines.hlsl"; + static readonly string s_ShaderPathBuilding = $"{k_ShaderPath}/LegacyBuilding.hlsl"; + + // SetShaderPassEnabled on ShadowCaster pass does not work for BIRP. We set ZTest + // to Never which is the best we can do. We are still incurring the draw call cost. + // This is an issue because of the way we trigger motion vectors, but is a bug with + // Unity and should be reported. + internal const string k_ShadowCasterZTest = "_Crest_BUILTIN_ShadowCasterZTest"; + + internal static System.Type s_SubShadersType; + internal static System.Type SubShadersType => s_SubShadersType ??= typeof(UnityBuiltInLitSubTarget).GetNestedType("SubShaders", BindingFlags.Static | BindingFlags.NonPublic); + internal static MethodInfo s_LitMethod; + internal static MethodInfo LitMethod => s_LitMethod ??= SubShadersType.GetMethod("Lit", BindingFlags.Static | BindingFlags.Public); + + static void PatchIncludes(ref PassDescriptor result) + { + var includes = new IncludeCollection(); + + includes.Add(s_ShaderPathDefines, IncludeLocation.Pregraph); + includes.Add("Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/ShaderPass.hlsl", IncludeLocation.Pregraph); + + foreach (var include in result.includes) + { + includes.AddInternal(include.guid, include.path, include.location, include.fieldConditions); + } + + result.includes = includes; + } + + static void PatchSpecularIncludes(ref PassDescriptor result, string file) + { + var ic = new IncludeCollection(); + foreach (var include in result.includes) + { + if (include.path.EndsWith(file)) + { + ic.Add(s_ShaderPathBuilding, include.location); + ic.AddInternal(include.guid, include.path, include.location, include.fieldConditions); + } + else + { + ic.AddInternal(include.guid, include.path, include.location, include.fieldConditions); + } + } + + result.includes = ic; + } + + static readonly Dictionary s_Mappings = new() + { + { "SHADERPASS_FORWARD", "PBRForwardPass.hlsl" }, + { "SHADERPASS_FORWARD_ADD", "PBRForwardAddPass.hlsl" }, + { "SHADERPASS_DEFERRED", "PBRDeferredPass.hlsl" }, + }; + + static readonly string[] s_SkipVariants = new string[] + { + "LIGHTMAP_ON", + "LIGHTMAP_SHADOW_MIXING", + "DIRLIGHTMAP_COMBINED", + "DYNAMICLIGHTMAP_ON", + "SHADOWS_SHADOWMASK", + }; + + public static SubShaderDescriptor Lit(BuiltInLitSubTarget subtarget) + { + var target = subtarget.target; + var ssd = (SubShaderDescriptor)LitMethod.Invoke(null, new object[] { target, target.renderType, target.renderQueue }); + + PassCollection passes = new(); + + foreach (var item in ssd.passes) + { + // Many artifacts in U6 if our Write Depth enabled. + // Caused by _SURFACE_TYPE_TRANSPARENT in m_ValidKeywords. + if (item.descriptor.referenceName == "SceneSelectionPass") + { + continue; + } + + var result = item.descriptor; + + var keywords = new KeywordCollection(); + + foreach (var keyword in result.keywords) + { + // All others are either duplicate or unused. + if (!keyword.descriptor.referenceName.StartsWith("_BUILTIN_")) + { + continue; + } + + keywords.Add(keyword.descriptor, keyword.fieldConditions); + } + + result.keywords = keywords; + + switch (item.descriptor.referenceName) + { + case "SHADERPASS_FORWARD": + case "SHADERPASS_FORWARD_ADD": + case "SHADERPASS_DEFERRED": + AddWorkflowModeControlToPass(ref result, target, subtarget.WorkflowMode); + PatchSpecularIncludes(ref result, s_Mappings[item.descriptor.referenceName]); + + var pragmas = new PragmaCollection(); + foreach (var pragma in result.pragmas) + { + // For UAVs (RWStructuredBuffer). + if (pragma.descriptor.value.StartsWithNoAlloc("target")) + { + pragmas.Add(Pragma.Target(ShaderModel.Target45)); + continue; + } + + if (pragma.descriptor.value.StartsWithNoAlloc("vertex")) + { + pragmas.Add(Pragma.SkipVariants(s_SkipVariants)); + } + + pragmas.Add(pragma.descriptor, pragma.fieldConditions); + } + result.pragmas = pragmas; + + goto default; + default: + PatchIncludes(ref result); + break; + } + + switch (item.descriptor.referenceName) + { + case "SHADERPASS_FORWARD": + case "SHADERPASS_FORWARD_ADD": + AddReceivesShadowsControlToPass(ref result, target, subtarget.TransparentReceiveShadows); + break; + case "SHADERPASS_SHADOWCASTER": + var states = new RenderStateCollection(); + foreach (var state in result.renderStates) + { + if (state.descriptor.type == RenderStateType.ZTest) + { + states.Add(RenderState.ZTest($"[{k_ShadowCasterZTest}]")); + continue; + } + + states.Add(state.descriptor, state.fieldConditions); + } + + result.renderStates = states; + break; + } + + // Add missing cull render state. + if (item.descriptor.referenceName == "SHADERPASS_FORWARD_ADD") + { + CoreRenderStates.AddUberSwitchedCull(target, result.renderStates); + } + + // Inject MV before DO pass. + if (item.descriptor.referenceName == "SHADERPASS_DEPTHONLY") + { + var mv = LitPasses.MotionVectors(target); + PatchIncludes(ref mv); + passes.Add(mv); + } + + // Fix XR SPI. + if (result.requiredFields != null) + { + var found = false; + + foreach (var collection in result.requiredFields) + { + if (collection.field == StructFields.Attributes.instanceID) + { + found = true; + break; + } + } + + if (!found) + { + result.requiredFields.Add(StructFields.Attributes.instanceID); + } + } + + passes.Add(result); + } + + ssd.passes = passes; + + return ssd; + } + + static void AddWorkflowModeControlToPass(ref PassDescriptor pass, BuiltInTarget target, WorkflowMode workflowMode) + { + if (target.allowMaterialOverride) + { + pass.keywords.Add(LitDefines.s_SpecularSetup); + } + else if (workflowMode == WorkflowMode.Specular) + { + pass.defines.Add(LitDefines.s_SpecularSetup, 1); + } + } + + static void AddReceivesShadowsControlToPass(ref PassDescriptor pass, BuiltInTarget target, bool receives) + { + if (target.allowMaterialOverride) + { + pass.keywords.Add(LitDefines.s_TransparentReceivesShadows); + pass.keywords.Add(LitDefines.s_ShadowsSingleCascade); + pass.keywords.Add(LitDefines.s_ShadowsSplitSpheres); + pass.keywords.Add(LitDefines.s_ShadowsSoft); + } + else if (receives) + { + pass.defines.Add(LitDefines.s_TransparentReceivesShadows, 1); + pass.keywords.Add(LitDefines.s_ShadowsSingleCascade); + pass.keywords.Add(LitDefines.s_ShadowsSplitSpheres); + pass.keywords.Add(LitDefines.s_ShadowsSoft); + } + } + } + + static class LitPasses + { + static readonly string s_ShaderPathMotionVectorCommon = $"{k_ShaderPath}/MotionVectorCommon.hlsl"; + static readonly string s_ShaderPathMotionVectorPass = $"{k_ShaderPath}/MotionVectorPass.hlsl"; + + public static RenderStateDescriptor UberSwitchedCullRenderState(BuiltInTarget target) + { + if (target.allowMaterialOverride) + { + return RenderState.Cull(CoreRenderStates.Uniforms.cullMode); + } + else + { + return RenderState.Cull(CoreRenderStates.RenderFaceToCull(target.renderFace)); + } + } + + public static PassDescriptor MotionVectors(BuiltInTarget target) + { + var result = new PassDescriptor() + { + // Definition + displayName = "BuiltIn MotionVectors", + referenceName = "SHADERPASS_MOTION_VECTORS", + lightMode = "MotionVectors", + useInPreview = false, + + // Template + passTemplatePath = BuiltInTarget.kTemplatePath, + sharedTemplateDirectories = BuiltInTarget.kSharedTemplateDirectories.Union + ( + new string[] + { + k_TemplatePath, + "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph" + } + ).ToArray(), + + // Port Mask + validVertexBlocks = new BlockFieldDescriptor[] + { + BlockFields.VertexDescription.Position, + }, + validPixelBlocks = CoreBlockMasks.FragmentAlphaOnly, + + // Fields + structs = CoreStructCollections.Default, + requiredFields = new() + { + // Needed for XR, but not sure if correct. + StructFields.Attributes.instanceID, + }, + fieldDependencies = CoreFieldDependencies.Default, + + // Conditional State + renderStates = new() + { + { RenderState.ZTest(ZTest.LEqual) }, + { RenderState.ZWrite(ZWrite.On) }, + { UberSwitchedCullRenderState(target) }, + // MVs write to the depth buffer causing z-fighting. Luckily, the depth texture has + // already been updated, and will not be updated before water renders. + { RenderState.ColorMask("ColorMask RG\nOffset 1, 1") }, + }, + + pragmas = new() + { + { Pragma.Target(ShaderModel.Target35) }, // NOTE: SM 2.0 only GL + { Pragma.MultiCompileInstancing }, + { Pragma.Vertex("vert") }, + { Pragma.Fragment("frag") }, + }, + + defines = new() { CoreDefines.BuiltInTargetAPI }, + keywords = new(), + includes = new() + { + // Pre-graph + { CoreIncludes.CorePregraph }, + { CoreIncludes.ShaderGraphPregraph }, + + // Post-graph + { s_ShaderPathMotionVectorCommon, IncludeLocation.Postgraph }, + { CoreIncludes.CorePostgraph }, + { s_ShaderPathMotionVectorPass, IncludeLocation.Postgraph }, + }, + + // Custom Interpolator Support + customInterpolators = CoreCustomInterpDescriptors.Common, + }; + + // Only support time for now. + result.defines.Add(LitDefines.s_AutomaticTimeBasedMotionVectors, 1); + + CorePasses.AddAlphaClipControlToPass(ref result, target); + return result; + } + } + + internal static class LitDefines + { + public static readonly KeywordDescriptor s_AutomaticTimeBasedMotionVectors = new() + { + displayName = "Automatic Time-Based Motion Vectors", + referenceName = "AUTOMATIC_TIME_BASED_MOTION_VECTORS", + type = KeywordType.Boolean, + definition = KeywordDefinition.Predefined, + scope = KeywordScope.Local, + stages = KeywordShaderStage.Vertex, + }; + + public static readonly KeywordDescriptor s_SpecularSetup = new() + { + displayName = "Specular Setup", + referenceName = "_BUILTIN_SPECULAR_SETUP", + type = KeywordType.Boolean, + definition = KeywordDefinition.ShaderFeature, + scope = KeywordScope.Local, + stages = KeywordShaderStage.Fragment + }; + + public static readonly KeywordDescriptor s_TransparentReceivesShadows = new() + { + displayName = "Transparent Receives Shadows", + referenceName = "_BUILTIN_TRANSPARENT_RECEIVES_SHADOWS", + type = KeywordType.Boolean, + definition = KeywordDefinition.ShaderFeature, + scope = KeywordScope.Local, + stages = KeywordShaderStage.Fragment + }; + + public static readonly KeywordDescriptor s_ShadowsSingleCascade = new() + { + displayName = "Single Cascade Shadows", + referenceName = "SHADOWS_SINGLE_CASCADE", + type = KeywordType.Boolean, + definition = KeywordDefinition.MultiCompile, + scope = KeywordScope.Global, + stages = KeywordShaderStage.All, + }; + + public static readonly KeywordDescriptor s_ShadowsSoft = new() + { + displayName = "Soft Shadows", + referenceName = "SHADOWS_SOFT", + type = KeywordType.Boolean, + definition = KeywordDefinition.MultiCompile, + scope = KeywordScope.Global, + stages = KeywordShaderStage.All, + }; + + public static readonly KeywordDescriptor s_ShadowsSplitSpheres = new() + { + displayName = "Stable Fit Shadows", + referenceName = "SHADOWS_SPLIT_SPHERES", + type = KeywordType.Boolean, + definition = KeywordDefinition.MultiCompile, + scope = KeywordScope.Global, + stages = KeywordShaderStage.All, + }; + } + } +} diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs.meta b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs.meta new file mode 100644 index 000000000..1ef0bb2d8 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/ShaderGraphLegacySubTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4c99fd6915934b21a43efb6ca9915f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/TexturePreview.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/TexturePreview.cs index 0c425d3ad..4abbc215f 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/TexturePreview.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/TexturePreview.cs @@ -10,7 +10,8 @@ namespace WaveHarmonic.Crest.Editor { abstract class TexturePreview : ObjectPreview { - public static bool AnyActivePreviews { get; private set; } + public static TexturePreview s_ActiveInstance; + public bool Open { get; private set; } UnityEditor.Editor _Editor; RenderTexture _RenderTexture; @@ -34,7 +35,11 @@ namespace WaveHarmonic.Crest.Editor public override bool HasPreviewGUI() { - AnyActivePreviews = false; + if (Event.current != null && Event.current.type == EventType.Layout) + { + Open = false; + } + return OriginalTexture; } @@ -61,7 +66,8 @@ namespace WaveHarmonic.Crest.Editor public override void OnPreviewGUI(Rect rect, GUIStyle background) { - AnyActivePreviews = true; + s_ActiveInstance = this; + Open = true; // This check is in original. if (Event.current.type == EventType.Repaint) @@ -69,6 +75,18 @@ namespace WaveHarmonic.Crest.Editor background.Draw(rect, false, false, false, false); } + if (Texture is Cubemap) + { + if (_Editor == null || _Editor.target != Texture) + { + Object.DestroyImmediate(_Editor); + _Editor = UnityEditor.Editor.CreateEditor(Texture); + } + + _Editor.DrawPreview(rect); + return; + } + var descriptor = Texture.GetDescriptor(); if (Helpers.RenderTextureNeedsUpdating(descriptor, _OriginalDescriptor)) @@ -111,6 +129,11 @@ namespace WaveHarmonic.Crest.Editor { OnPreviewGUI(rect, background); + if (Texture is Cubemap) + { + return; + } + // Show pixel value in preview. _Slice = Development.Utility.GetPreviewSlice(_Editor, Texture); var color = Development.Utility.InspectPixel(rect, OriginalTexture, Flipped, _Slice); diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Validation.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Validation.cs index 7d3c1c95b..3220fa210 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Validation.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/Validation.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // How to use: @@ -79,7 +79,7 @@ namespace WaveHarmonic.Crest.Editor s_Messages[(int)type].Add(new() { _Message = message, _FixDescription = fixDescription, _Object = @object, _Action = action, _PropertyPath = property }); } - public static void Suppressed(string message, string fixDescription, MessageType type, Object @object = null, FixValidation action = null, string property = null) + public static void Suppressed(string _0, string _1, MessageType _2, Object _3 = null, FixValidation _4 = null, string _5 = null) { } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/Validators.cs b/Packages/com.waveharmonic.crest/Editor/Scripts/Validators.cs index ed45d2deb..c16869d59 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/Validators.cs +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/Validators.cs @@ -6,6 +6,7 @@ using System.Reflection; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; using UnityEngine.Rendering.Universal; using WaveHarmonic.Crest.Internal; using WaveHarmonic.Crest.Watercraft; @@ -17,7 +18,11 @@ namespace WaveHarmonic.Crest.Editor { static class Validators { + // HDRP sub-shader always first. + const int k_SubShaderIndexHDRP = 0; internal static WaterRenderer Water => Utility.Water; + static readonly System.Collections.Generic.List s_Terrains = new(); + static readonly ShaderTagId s_RenderPipelineShaderTagID = new("RenderPipeline"); [Validator(typeof(LodInput))] static bool ValidateTextureInput(LodInput target, ShowMessage messenger) @@ -94,6 +99,7 @@ namespace WaveHarmonic.Crest.Editor { var material = materials[i]; if (material == null) continue; + if (material.shader == null) continue; if (data._OverrideShaderPass && data._ShaderPassIndex > material.shader.passCount - 1) { @@ -119,6 +125,22 @@ namespace WaveHarmonic.Crest.Editor ); } } + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + if (AssetDatabase.GetAssetPath(material.shader).EndsWith(".shadergraph") && material.shader.FindSubshaderTagValue(k_SubShaderIndexHDRP, s_RenderPipelineShaderTagID).name == "HDRenderPipeline") + { + messenger + ( + "It appears you are using Shader Graph with the HDRP target. " + + "Make sure to use the Built-In target instead for your Shader Graph to work.", + "Remove the HDRP target and add the Built-In target.", + MessageType.Warning, material.shader + ); + } + } +#endif } return isValid; @@ -126,18 +148,18 @@ namespace WaveHarmonic.Crest.Editor static bool ValidateRendererLayer(GameObject gameObject, ShowMessage messenger, WaterRenderer water) { - if (water != null && gameObject.layer != water.Layer) + if (water != null && gameObject.layer != water.Surface.Layer) { - var layerName = LayerMask.LayerToName(water.Layer); + var layerName = LayerMask.LayerToName(water.Surface.Layer); messenger ( - $"The layer is not the same as the {nameof(WaterRenderer)}.{nameof(WaterRenderer.Layer)} ({layerName}) which can cause problems if the {layerName} layer is excluded from any culling masks.", + $"The layer is not the same as the {nameof(WaterRenderer)}.{nameof(WaterRenderer.Surface)}.{nameof(SurfaceRenderer.Layer)} ({layerName}) which can cause problems if the {layerName} layer is excluded from any culling masks.", $"Set layer to {layerName}.", MessageType.Warning, gameObject, (_, _) => { Undo.RecordObject(gameObject, $"Change Layer to {layerName}"); - gameObject.layer = water.Layer; + gameObject.layer = water.Surface.Layer; } ); } @@ -155,7 +177,7 @@ namespace WaveHarmonic.Crest.Editor return isValid; } - var material = water.Material; + var material = water.Surface.Material; if (material != null) { @@ -231,9 +253,38 @@ namespace WaveHarmonic.Crest.Editor return isValid; } - if (water != null && water.Material != null) +#if !d_Crest_LegacyUnderwater + if (target.AllCameras) { - var material = water.Material; + messenger + ( + "All Cameras requires Legacy Underwater to be enabled.", + "Either disable All Cameras or enable Project Settings > Crest > Legacy Underwater.", + MessageType.Warning, water + ); + } +#endif + + if (target.Material != null) + { + var material = target.Material; + + if (material.shader.name.StartsWithNoAlloc("Crest/") && material.shader.name != "Crest/Underwater") + { + messenger + ( + $"The material {material.name} assigned to Underwater has the wrong shader ({material.shader.name}).", + "Use a material with the correct shader (Crest/Underwater).", + MessageType.Error, water + ); + + isValid = false; + } + } + + if (water != null && water.Surface.Material != null) + { + var material = water.Surface.Material; var cullModeName = #if d_UnityURP @@ -290,6 +341,34 @@ namespace WaveHarmonic.Crest.Editor return isValid; } + static bool Validate(Meniscus target, ShowMessage messenger, WaterRenderer water) + { + var isValid = true; + + if (!target._Enabled) + { + return isValid; + } + + if (target._Material == null) + { + messenger + ( + "The meniscus material is missing. The meniscus will not render.", + "Add the default material or your own.", + MessageType.Warning, + water, + (so, sp) => + { + sp.objectReferenceValue = AssetDatabase.LoadAssetAtPath(Meniscus.k_MaterialPath); + }, + $"{nameof(WaterRenderer._Meniscus)}.{nameof(Meniscus._Material)}" + ); + } + + return isValid; + } + [Validator(typeof(WaterRenderer))] static bool Validate(WaterRenderer target, ShowMessage messenger) { @@ -299,6 +378,7 @@ namespace WaveHarmonic.Crest.Editor isValid = isValid && Validate(target._Underwater, messenger, target); isValid = isValid && Validate(target._Reflections, messenger, target); + isValid = isValid && Validate(target._Meniscus, messenger, target); isValid = isValid && ValidateNoRotation(target, target.transform, messenger); isValid = isValid && ValidateNoScale(target, target.transform, messenger); @@ -326,7 +406,7 @@ namespace WaveHarmonic.Crest.Editor isValid = false; } - if (target.Material == null) + if (target.Surface.Material == null) { messenger ( @@ -339,33 +419,33 @@ namespace WaveHarmonic.Crest.Editor } else { - isValid = ValidateWaterMaterial(target, messenger, water, target.Material) && isValid; + isValid = ValidateWaterMaterial(target, messenger, water, target.Surface.Material) && isValid; - if (RenderPipelineHelper.IsHighDefinition && target.Material.GetFloat("_RefractionModel") > 0) + if (RenderPipelineHelper.IsHighDefinition && target.Surface.Material.GetFloat("_RefractionModel") > 0) { messenger ( - $"Refraction Model is not None for {target.Material}. " + + $"Refraction Model is not None for {target.Surface.Material}. " + "This is set by default so it is available in the inspector, " + "but it incurs an overhead and will produce a dark edge at the edge of the viewport (see Screen Space Refraction > Screen Weight Distance). " + "Enabling the refraction model is only useful to allow volumetric clouds to render over the water surface when view from above. " + "The refraction model has no effect on refractions.", $"Set Refraction Model to None.", - MessageType.Info, target.Material + MessageType.Info, target.Surface.Material ); } - if (RenderPipelineHelper.IsHighDefinition && target.Material.HasFloat("_TransparentWritingMotionVec") && target.WriteMotionVectors != (target.Material.GetFloat("_TransparentWritingMotionVec") == 1f)) + if (RenderPipelineHelper.IsHighDefinition && target.Surface.Material.HasFloat("_TransparentWritingMotionVec") && target.WriteMotionVectors != (target.Surface.Material.GetFloat("_TransparentWritingMotionVec") == 1f)) { messenger ( - $"Water Renderer > Surface Renderer > Motion Vectors and Transparent Writes Motion Vectors on {target.Material} do not match. ", + $"Water Renderer > Surface Renderer > Motion Vectors and Transparent Writes Motion Vectors on {target.Surface.Material} do not match. ", $"Either disable or enable both Water Renderer > Surface Renderer > Motion Vectors and Transparent Writes Motion Vectors", - MessageType.Info, target.Material + MessageType.Info, target.Surface.Material ); } - ValidateMaterialParent(target._VolumeMaterial, target.Material, messenger); + ValidateMaterialParent(target.Surface.VolumeMaterial, target.Surface.Material, messenger); } if (Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None).Length > 1) @@ -403,13 +483,13 @@ namespace WaveHarmonic.Crest.Editor } // We need to find hidden probes too, but do not include assets. - if (Resources.FindObjectsOfTypeAll().Where(x => !EditorUtility.IsPersistent(x)).Count() > 0) + if (Resources.FindObjectsOfTypeAll().Count(x => !EditorUtility.IsPersistent(x)) > 0) { messenger ( "There are reflection probes in the scene. These can cause tiling to appear on the water surface if not set up correctly.", "For reflections probes that affect the water, they will either need to cover the visible water tiles or water tiles need to ignore reflection probes (can done done with Water Tile Prefab field). " + - $"For all reflection probles that include the {LayerMask.LayerToName(target.Layer)} layer, make sure they are above the water surface as underwater reflections are not supported.", + $"For all reflection probles that include the {LayerMask.LayerToName(target.Surface.Layer)} layer, make sure they are above the water surface as underwater reflections are not supported.", MessageType.Info, target ); } @@ -470,7 +550,7 @@ namespace WaveHarmonic.Crest.Editor } // For safety. - if (target != null && target.Material != null) + if (target != null && target.Surface.Material != null) { foreach (var simulation in target.Simulations) { @@ -488,7 +568,7 @@ namespace WaveHarmonic.Crest.Editor ); } - if (target.Viewer == null) + if (target.Viewer == null && !target.IsRunningWithoutGraphics) { messenger ( @@ -503,7 +583,10 @@ namespace WaveHarmonic.Crest.Editor #if d_UnityHDRP if (RenderPipelineHelper.IsHighDefinition) { - var hdAsset = GraphicsSettings.currentRenderPipeline as UnityEngine.Rendering.HighDefinition.HDRenderPipelineAsset; + var material = target.Surface.Material; + var camera = target._Camera != null ? target._Camera : Camera.main; + var hdCamera = camera != null ? HDCamera.GetOrCreate(camera) : null; + var hdAsset = GraphicsSettings.currentRenderPipeline as HDRenderPipelineAsset; var mvs = hdAsset.currentPlatformRenderPipelineSettings.supportMotionVectors; // Only check the RP asset for now. @@ -518,6 +601,50 @@ namespace WaveHarmonic.Crest.Editor MessageType.Info, target ); } + + if (!hdAsset.currentPlatformRenderPipelineSettings.supportCustomPass) + { + messenger + ( + "Custom passes are disabled. Underwater and other features require them to work.", + "Enabled them on the global asset.", + MessageType.Error, hdCamera.camera + ); + } + + if (target.RenderBeforeTransparency && WaterRenderer.s_CameraMSAA) + { + messenger + ( + $"The water injection point is before transparency and MSAA is enabled for a camera. This combination is not currently supported for HDRP.", + "Disable MSAA or change the water injection point.", + MessageType.Error, target + ); + } + + // Seems that logging is too early for these. And edit mode has false positives. + if (Application.isPlaying && messenger == ValidatedHelper.HelpBox) + { + if (hdCamera?.frameSettings.IsEnabled(FrameSettingsField.CustomPass) == false) + { + messenger + ( + $"Custom passes are disabled for the primary camera ({camera}). Underwater and other features require them to work.", + "Enable them in the camera frame settings on the camera or the default frame settings in the global settings.", + MessageType.Error, hdCamera.camera + ); + } + + if (hdCamera?.frameSettings.IsEnabled(FrameSettingsField.Refraction) == false && material != null && SurfaceRenderer.IsTransparent(material)) + { + messenger + ( + "Refraction is disabled. Transparency requires it to work.", + "Enable it in the camera frame settings on the camera, or the default frame settings in the global settings.", + MessageType.Error, hdCamera.camera + ); + } + } } #endif // d_UnityHDRP @@ -541,11 +668,11 @@ namespace WaveHarmonic.Crest.Editor } #endif // d_UnityURP - if (!RenderPipelineHelper.IsHighDefinition && target.Material != null) + if (!RenderPipelineHelper.IsHighDefinition && target.Surface.Material != null) { - if (!target.AllowRenderQueueSorting && !System.Enum.IsDefined(typeof(RenderQueue), target.Material.renderQueue)) + if (!target.Surface.AllowRenderQueueSorting && !System.Enum.IsDefined(typeof(RenderQueue), target.Surface.Material.renderQueue)) { - var field = nameof(WaterRenderer.AllowRenderQueueSorting).Pretty().Italic(); + var field = nameof(SurfaceRenderer.AllowRenderQueueSorting).Pretty().Italic(); messenger ( $"The render queue has a sub-sort applied, but {field} is not enabled. Sub-sorting will not work.", @@ -563,11 +690,13 @@ namespace WaveHarmonic.Crest.Editor { var isValid = true; + var water = Water; + if (Object.FindObjectsByType(FindObjectsInactive.Include, FindObjectsSortMode.None).Length == 0) { messenger ( - $"Water body {target.gameObject.name} requires an water renderer component to be present.", + $"Water body {target.gameObject.name} requires a {nameof(WaterRenderer)} component to be present.", $"Create a separate GameObject and add an {nameof(WaterRenderer)} component to it.", MessageType.Error, target ); @@ -595,6 +724,25 @@ namespace WaveHarmonic.Crest.Editor isValid = isValid && ValidateNoRotation(target, target.transform, messenger); + if (target.Clipped && water != null) + { + // Validate main material, then overriden material. + ValidateLod(OptionalLod.Get(typeof(ClipLod)), messenger, water); + ValidateLod(OptionalLod.Get(typeof(ClipLod)), messenger, water, material: target._Material); + + if (water.ClipLod.DefaultClippingState == DefaultClippingState.NothingClipped) + { + messenger + ( + $"The {nameof(ClipLod.DefaultClippingState)} on the {nameof(WaterRenderer)} is set to {DefaultClippingState.NothingClipped}. " + + $"The {nameof(WaterBody.Clipped)} option will have no effect.", + $"Disable {nameof(WaterBody.Clipped)} or set {nameof(ClipLod.DefaultClippingState)} to {DefaultClippingState.NothingClipped}.", + MessageType.Warning, + water + ); + } + } + return isValid; } @@ -602,7 +750,7 @@ namespace WaveHarmonic.Crest.Editor /// /// Does validation for a feature on the water component and on the material /// - internal static bool ValidateLod(OptionalLod target, ShowMessage messenger, WaterRenderer water, string dependent = null) + internal static bool ValidateLod(OptionalLod target, ShowMessage messenger, WaterRenderer water, string dependent = null, Material material = null, Object context = null) { var isValid = true; @@ -620,7 +768,7 @@ namespace WaveHarmonic.Crest.Editor dependentClause = $", as {dependent} needs it."; } - if (!simulation._Enabled) + if (!simulation._Enabled && material == null) { messenger ( @@ -645,7 +793,10 @@ namespace WaveHarmonic.Crest.Editor isValid = false; } - var material = water.Material; + if (material == null) + { + material = water.Surface.Material; + } if (target.HasMaterialToggle && material != null) { @@ -709,7 +860,7 @@ namespace WaveHarmonic.Crest.Editor } // These checks are not necessary for our material but there may be custom materials. - if (!water.Material.HasProperty(target.MaterialProperty)) + if (!water.Surface.Material.HasProperty(target.MaterialProperty)) { return true; } @@ -717,14 +868,14 @@ namespace WaveHarmonic.Crest.Editor var feature = target.GetLod(water); // There is only a problem if there is a mismatch. - if (feature.Enabled == (water.Material.GetFloat(target.MaterialProperty) == 1f)) + if (feature._Enabled == (water.Surface.Material.GetFloat(target.MaterialProperty) == 1f)) { return true; } - if (feature.Enabled) + if (feature._Enabled) { - ShowMaterialValidationMessage(target, water.Material, messenger); + ShowMaterialValidationMessage(target, water.Surface.Material, messenger); } else if (messenger != DebugLog) { @@ -756,7 +907,7 @@ namespace WaveHarmonic.Crest.Editor ); } - if (target.Blend == LodInputBlend.AlphaClip && target.Mode is not LodInputMode.Texture or LodInputMode.Paint) + if (target.Blend == LodInputBlend.AlphaClip && target.Mode is not (LodInputMode.Texture or LodInputMode.Paint)) { messenger ( @@ -999,19 +1150,20 @@ namespace WaveHarmonic.Crest.Editor { var isValid = true; - var camera = target._Camera; - if (camera != null && camera.targetTexture != null && target.RealtimeTexture != null) + messenger + ( + "If you see an error RenderTexture color format cannot be set to a depth/stencil format or RenderTexture.Create failed, this is likely a bug with Unity (grab pass) or third-party, as they may be registered to execute a custom pass to the DepthProbe camera.", "", MessageType.Info, target + ); + + if (target.Outdated && (messenger != DebugLog || WaterRendererEditor.ManualValidation)) { - if (target.Outdated) - { - messenger - ( - "Depth Probe is outdated.", - "Click Populate or re-bake the probe to bring the probe up-to-date with component changes.", - MessageType.Warning, target, - (_, _) => target.Populate() - ); - } + messenger + ( + "Depth Probe is outdated.", + "Click Populate or re-bake the probe to bring the probe up-to-date with component changes.", + MessageType.Warning, target, + (_, _) => target.Populate() + ); } if (target.Type == DepthProbeMode.Baked) @@ -1042,12 +1194,34 @@ namespace WaveHarmonic.Crest.Editor messenger ( "No layers specified for rendering into depth probe.", - "Specify one or may layers using the Layers field.", + "Specify one or many layers using the Layers field.", MessageType.Error, target ); isValid = false; } +#if d_Unity_Terrain + else + { + Terrain.GetActiveTerrains(s_Terrains); + foreach (var terrain in s_Terrains) + { + if (Helpers.MaskIncludesLayer(target.Layers, terrain.gameObject.layer)) + { + continue; + } + + messenger + ( + $"There are terrains on a layer that is not in {nameof(DepthProbe)}.{nameof(DepthProbe.Layers)}.", + "This is typically mistake leading to no data (ie no shorelines). Please ignore if intentional.", + MessageType.Info, target + ); + + break; + } + } +#endif // d_Unity_Terrain if (target._Debug._ForceAlwaysUpdateDebug) { @@ -1196,6 +1370,19 @@ namespace WaveHarmonic.Crest.Editor { isValid = isValid && ValidateSignedDistanceFieldsLod(messenger, water, "Generate Signed Distance Field"); } + + if (water.DepthLod.IncludeTerrainHeight && Object.FindAnyObjectByType(FindObjectsInactive.Include) != null) + { + messenger + ( + "The Water Depth data is configured to automatically include terrain height via Include Terrain Height. " + + "Using a DepthProbe is still valid to capture non-terrain details like rocks. " + + "But typically, if you are using a DepthProbe, it is best to capture the terrain too, as it is more accurate. " + + "One reason to use a DepthProbe together with the auto capture is for better real-time/on-demand depth capture performance.", + string.Empty, + MessageType.Info, water + ); + } } diff --git a/Packages/com.waveharmonic.crest/Editor/Scripts/WaveHarmonic.Crest.Editor.asmdef b/Packages/com.waveharmonic.crest/Editor/Scripts/WaveHarmonic.Crest.Editor.asmdef index 86b226451..ed39db94f 100644 --- a/Packages/com.waveharmonic.crest/Editor/Scripts/WaveHarmonic.Crest.Editor.asmdef +++ b/Packages/com.waveharmonic.crest/Editor/Scripts/WaveHarmonic.Crest.Editor.asmdef @@ -31,6 +31,11 @@ "expression": "", "define": "d_ModuleUnityDirector" }, + { + "name": "com.unity.modules.terrain", + "expression": "", + "define": "d_Unity_Terrain" + }, { "name": "com.unity.postprocessing", "expression": "", diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/Templates.meta b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates.meta new file mode 100644 index 000000000..c1dcc114c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d8df6c721738dc4e9406af4d13e5e63 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl new file mode 100644 index 000000000..0a9d7cdcc --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl @@ -0,0 +1,6 @@ +// Shader Graph Complete +// Copyright © 2025 Wave Harmonic. All rights reserved. + +$include("Templates/SharedCode.template.hlsl") + +$VertexDescriptionInputs.TimeParameters: #define GRAPH_VERTEX_USES_TIME_PARAMETERS_INPUT diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl.meta b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl.meta new file mode 100644 index 000000000..0dc2682ba --- /dev/null +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/Templates/SharedCode.template.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ee5a966d356084782a3e3e78ec78b8e3 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/VisualizeNegativeValues.compute b/Packages/com.waveharmonic.crest/Editor/Shaders/VisualizeNegativeValues.compute index 9f23f4a92..1c7ca254a 100644 --- a/Packages/com.waveharmonic.crest/Editor/Shaders/VisualizeNegativeValues.compute +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/VisualizeNegativeValues.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #pragma kernel CrestVisualizeNegativeValues_Scalar diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/WaterLevel.shader b/Packages/com.waveharmonic.crest/Editor/Shaders/WaterLevel.shader index dcf0708b1..388051dfb 100644 --- a/Packages/com.waveharmonic.crest/Editor/Shaders/WaterLevel.shader +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/WaterLevel.shader @@ -62,10 +62,7 @@ Shader "Hidden/Crest/Editor/Water Level (Depth)" #pragma vertex Vertex #pragma fragment Fragment - #include "UnityCG.cginc" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" #include "Packages/com.waveharmonic.crest/Editor/Shaders/WaterLevel.hlsl" ENDHLSL diff --git a/Packages/com.waveharmonic.crest/Editor/Shaders/WaterProxy.shader b/Packages/com.waveharmonic.crest/Editor/Shaders/WaterProxy.shader index ffa242f57..13fd1aad9 100644 --- a/Packages/com.waveharmonic.crest/Editor/Shaders/WaterProxy.shader +++ b/Packages/com.waveharmonic.crest/Editor/Shaders/WaterProxy.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. Shader "Hidden/Crest/Editor/WaterProxy" @@ -8,6 +8,7 @@ Shader "Hidden/Crest/Editor/WaterProxy" Tags { "RenderType"="Transparent" "Queue"="Transparent"} Blend SrcAlpha OneMinusSrcAlpha ZWrite Off + Cull Off Pass { diff --git a/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset b/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset new file mode 100644 index 000000000..9503d9c34 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset @@ -0,0 +1,67 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3} + m_Name: WavesSwell + m_EditorClassIdentifier: + _Version: 0 + _WaveDirectionVariance: 90 + _GravityScale: 1 + _Multiplier: 1 + _PowerLogarithmicScales: + - -7.10794 + - -6.42794 + - -5.93794 + - -5.27794 + - -4.67794 + - -3.71794 + - -3.17794 + - -2.60794 + - -1.93794 + - -1.11794 + - -0.85794 + - -0.36794 + - 0.04206 + - -8 + _PowerDisabled: 0101010101010101000000000000 + _ChopScales: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + _GravityScales: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + _Chop: 1.6 + _ShowAdvancedControls: 0 + _Model: 0 diff --git a/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset.meta b/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset.meta new file mode 100644 index 000000000..2e59737a1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Data/WaveSpectra/WavesSwell.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efa03f442951949c7bbfadb22765f653 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat b/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat new file mode 100644 index 000000000..da2e532e3 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Meniscus + m_Shader: {fileID: 4800000, guid: ec7c774912c6f4b3cb6d73444cdedeca, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: + - d_Crest_Lighting + - d_Crest_Refraction + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: + - _Crest_LightingEnabled: 1 + - _Crest_RefractionEnabled: 1 + m_Floats: + - _Crest_Radius: 0.01 + - _Crest_RefractionStrength: 0.2 + m_Colors: [] + m_BuildTextureStacks: [] diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat.meta b/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat.meta new file mode 100644 index 000000000..df80d51d2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 238e45299a5ec46308e9bf99ddf67963 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat b/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat new file mode 100644 index 000000000..d3ba6b877 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat @@ -0,0 +1,92 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-3046556431833965186 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 0 +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Water (Flow) + m_Shader: {fileID: -6465566751694194690, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3} + m_Parent: {fileID: 2100000, guid: 8ab064b6606504a55b489af2787350c2, type: 2} + m_ModifiedSerializedProperties: 26 + m_ValidKeywords: + - CREST_FLOW_ON + - _ALPHATEST_ON + - _BUILTIN_ALPHATEST_ON + - _BUILTIN_AlphaClip + - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS + - _DOUBLESIDED_ON + - _ENABLE_FOG_ON_TRANSPARENT + - _SURFACE_TYPE_TRANSPARENT + - _TRANSPARENT_WRITES_MOTION_VEC + m_InvalidKeywords: + - _EMISSION + m_LightmapFlags: 2 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 1 + m_CustomRenderQueue: 3000 + stringTagMap: + MotionVector: User + RenderType: Transparent + disabledShaderPasses: + - TransparentDepthPostpass + - TransparentBackface + - RayTracingPrepass + - MOTIONVECTORS + - SHADOWCASTER + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: [] + m_Floats: + - CREST_FLOW: 1 + - _SrcBlend: 5 + m_Colors: [] + m_BuildTextureStacks: [] + m_AllowLocking: 1 +--- !u!114 &84831097882938775 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: da692e001514ec24dbc4cca1949ff7e8, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 13 + hdPluginSubTargetMaterialVersions: + m_Keys: [] + m_Values: +--- !u!114 &8072045821928201339 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 10 diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat.meta b/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat.meta new file mode 100644 index 000000000..976aa5c0c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Water (Flow).mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4b26ad6c6869b4091881e76c99363dac +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Water Volume.mat b/Packages/com.waveharmonic.crest/Runtime/Materials/Water Volume.mat index 81df789dc..6783ed774 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Materials/Water Volume.mat +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Water Volume.mat @@ -12,16 +12,16 @@ Material: m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 m_ValidKeywords: + - d_Crest_NoMaskDepth - d_Dithering - - d_Meniscus m_InvalidKeywords: - _ALPHATEST_ON - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_LightmapFlags: 4 @@ -45,7 +45,6 @@ Material: m_Ints: - _Crest_DataSliceOffset: 13 - _Crest_DitheringEnabled: 1 - - _Crest_MeniscusEnabled: 1 - _Crest_Version: 0 m_Floats: - CREST_FLOW: 0 @@ -69,7 +68,7 @@ Material: - _Crest_ShadowsAffectsAmbientFactor: 0.5 - _Crest_SunBoost: 2 m_Colors: - - _Crest_AbsorptionColor: {r: 0.34162676, g: 0.6954546, b: 0.85, a: 0.1019608} - - _Crest_Scattering: {r: 0, g: 0.09803919, b: 0.19999996, a: 1} + - _Crest_AbsorptionColor: {r: 0.46502313, g: 0.4716981, b: 0.4662141, a: 0.1019608} + - _Crest_Scattering: {r: 0.11320752, g: 0.11320752, b: 0.11320752, a: 1} m_BuildTextureStacks: [] m_AllowLocking: 1 diff --git a/Packages/com.waveharmonic.crest/Runtime/Materials/Water.mat b/Packages/com.waveharmonic.crest/Runtime/Materials/Water.mat index 6ab1506d8..b27826ec3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Materials/Water.mat +++ b/Packages/com.waveharmonic.crest/Runtime/Materials/Water.mat @@ -45,9 +45,9 @@ Material: - _BUILTIN_ALPHATEST_ON - _BUILTIN_AlphaClip - _BUILTIN_SURFACE_TYPE_TRANSPARENT + - _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS - _DOUBLESIDED_ON - _ENABLE_FOG_ON_TRANSPARENT - - _SPECULAR_SETUP - _SURFACE_TYPE_TRANSPARENT - _TRANSPARENT_WRITES_MOTION_VEC m_InvalidKeywords: [] @@ -70,29 +70,20 @@ Material: m_TexEnvs: [] m_Ints: [] m_Floats: - - CREST_FLOW: 0 - - _AlphaClip: 1 - _AlphaDstBlend: 10 - _BUILTIN_DstBlend: 10 - _BUILTIN_QueueControl: 0 - _BUILTIN_SrcBlend: 5 - _BUILTIN_ZWrite: 1 - - _Crest_AlbedoEnabled: 0 - - _Crest_CausticsEnabled: 1 - - _Crest_FoamEnabled: 1 - - _Crest_NormalMapEnabled: 1 + - _Crest_FoamEnabled: 0 - _Crest_PlanarReflectionsEnabled: 1 - - _Crest_RefractionStrength: 1 - _Crest_SSSEnabled: 0 - - _Crest_ShadowsEnabled: 1 - _CullMode: 0 - _CullModeForward: 0 - _DstBlend: 10 - _QueueControl: 0 - - _ReceiveShadows: 1 - _RefractionModel: 0 - _SrcBlend: 5 - - _WorkflowMode: 0 - _ZTestGBuffer: 3 m_Colors: - _DoubleSidedConstants: {r: 1, g: 1, b: 1, a: 0} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Constants.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Constants.cs index 479a118e3..c32e32fdc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Constants.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Constants.cs @@ -1,6 +1,8 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. +// 9160b2d47f1cb3d7559ed4fafa79e52b9448ef2a6d863948fe3c4eeddcd958da + namespace WaveHarmonic.Crest { static class Constants diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AbsorptionLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AbsorptionLod.cs index 51690a7ee..3721fa329 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AbsorptionLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AbsorptionLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -32,10 +32,11 @@ namespace WaveHarmonic.Crest get { var color = Color.clear; + var surface = _Water.Surface; - if (_Water.Material != null) + if (surface.Material != null && surface.Material.HasVector(WaterRenderer.ShaderIDs.s_Absorption)) { - color = _Water.Material.GetVector(WaterRenderer.ShaderIDs.s_Absorption); + color = surface.Material.GetVector(WaterRenderer.ShaderIDs.s_Absorption); color.a = 0f; } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AlbedoLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AlbedoLod.cs index 65fcbee1a..a6510b944 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AlbedoLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AlbedoLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AnimatedWavesLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AnimatedWavesLod.cs index 49b9c082c..d93462789 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AnimatedWavesLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/AnimatedWavesLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -20,55 +20,39 @@ namespace WaveHarmonic.Crest /// /// The source of collisions (ie water shape). /// + [@GenerateDoc] public enum CollisionSource { - /// - /// No collision source. Flat water. - /// + /// + [Tooltip("No collision source. Flat water.")] None = 0, // GerstnerWavesCPU = 1, - /// - /// Uses AsyncGPUReadback to retrieve data from GPU to CPU. - /// - /// - /// This is the most optimal approach. - /// + /// + [Tooltip("Uses AsyncGPUReadback to retrieve data from GPU to CPU.\n\nThis is the most optimal approach.")] GPU = 2, - /// - /// Computes data entirely on the CPU. - /// + /// + [Tooltip("Computes data entirely on the CPU.")] CPU = 3, } /// /// The pass to render displacement into. /// + [@GenerateDoc] public enum DisplacementPass { - /// - /// Displacement that is dependent on an LOD (eg waves). - /// - /// - /// Uses filtering to determine which LOD to write to. - /// + /// [Tooltip("Displacement that is dependent on an LOD (eg waves).\n\nUses filtering to determine which LOD to write to.")] LodDependent, - /// - /// Renders to all LODs. - /// + /// [Tooltip("Renders to all LODs.")] LodIndependent, - /// - /// Renders to all LODs, but as a separate pass. - /// - /// - /// Typically used to render visual displacement which does not affect collisions. - /// + /// [Tooltip("Renders to all LODs, but as a separate pass.\n\nTypically used to render visual displacement which does not affect collisions.")] [InspectorName("Lod Independent (Last)")] LodIndependentLast, @@ -78,35 +62,24 @@ namespace WaveHarmonic.Crest /// Flags to enable extra collsion layers. /// [System.Flags] + [@GenerateDoc] public enum CollisionLayers { // NOTE: numbers must be in order for defaults to work (everything first). - /// - /// All layers. - /// + /// [Tooltip("All layers.")] Everything = -1, - /// - /// No extra layers (ie single layer). - /// + /// [Tooltip("No extra layers (ie single layer).")] Nothing, - /// - /// Separate layer for dynamic waves. - /// - /// - /// Dynamic waves are normally combined together for efficiency. By enabling this - /// layer, dynamic waves are combined and added in a separate pass. - /// + /// [Tooltip("Separate layer for dynamic waves.\n\nDynamic waves are normally combined together for efficiency. By enabling this layer, dynamic waves are combined and added in a separate pass.")] DynamicWaves = 1 << 1, - /// - /// Extra displacement layer for visual displacement. - /// + /// [Tooltip("Extra displacement layer for visual displacement.")] Displacement = 1 << 2, } @@ -180,6 +153,9 @@ namespace WaveHarmonic.Crest internal BakedWaveData _BakedWaveData; + const string k_DrawCombine = "Combine"; + + internal static new partial class ShaderIDs { public static readonly int s_WaveBuffer = Shader.PropertyToID("_Crest_WaveBuffer"); @@ -201,7 +177,6 @@ namespace WaveHarmonic.Crest private protected override bool NeedToReadWriteTextureData => true; private protected override Color ClearColor => Color.black; internal override int BufferCount => _Water.WriteMotionVectors ? 2 : 1; - internal override bool RunsInHeadless => true; // NOTE: Tried RGB111110Float but errors becomes visible. One option would be to use a UNORM setup. private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch @@ -259,7 +234,7 @@ namespace WaveHarmonic.Crest internal override void BuildCommandBuffer(WaterRenderer water, CommandBuffer buffer) { - buffer.BeginSample(Name); + buffer.BeginSample(ID); FlipBuffers(); @@ -267,8 +242,7 @@ namespace WaveHarmonic.Crest // Get temporary buffer to store waves. They will be copied in the combine pass. buffer.GetTemporaryRT(ShaderIDs.s_WaveBuffer, DataTexture.descriptor); - buffer.SetRenderTarget(ShaderIDs.s_WaveBuffer, 0, CubemapFace.Unknown, -1); - buffer.ClearRenderTarget(false, true, ClearColor); + CoreUtils.SetRenderTarget(buffer, ShaderIDs.s_WaveBuffer, ClearFlag.Color, ClearColor); // LOD dependent data. // Write to per-octave _WaveBuffers. Not the same as _AnimatedWaves. @@ -304,7 +278,7 @@ namespace WaveHarmonic.Crest } } - buffer.BeginSample("Combine"); + buffer.BeginSample(k_DrawCombine); // Combine waves. for (var slice = lastSlice; slice >= 0; slice--) @@ -327,7 +301,7 @@ namespace WaveHarmonic.Crest wrapper.Dispatch(threadSize, threadSize, 1); } - buffer.EndSample("Combine"); + buffer.EndSample(k_DrawCombine); } buffer.ReleaseTemporaryRT(ShaderIDs.s_WaveBuffer); @@ -372,16 +346,22 @@ namespace WaveHarmonic.Crest // Query collisions including only Animated Waves. // Requires copying the water level. - Provider.UpdateQueries(_Water, CollisionLayer.AfterAnimatedWaves); + // Guard not required, as Query already does this check before returning the + // correct provider, thus nothing would be reqistered nor dispatched. But seems + // right to do so anyhow. + if (_CollisionLayers != CollisionLayers.Nothing) + { + Provider.UpdateQueries(_Water, CollisionLayer.AfterAnimatedWaves); + } // Transfer Dynamic Waves to Animated Waves. if (_CollisionLayers.HasFlag(CollisionLayers.DynamicWaves) && _Water._DynamicWavesLod.Enabled) { - buffer.BeginSample("Combine"); + buffer.BeginSample(k_DrawCombine); // Clearing not required as we overwrite enter texture. buffer.GetTemporaryRT(ShaderIDs.s_DynamicWavesTarget, DataTexture.descriptor); - var wrapper = new PropertyWrapperCompute(buffer, _CombineShader, 8); + var wrapper = new PropertyWrapperCompute(buffer, _CombineShader, 9); wrapper.SetTexture(ShaderIDs.s_DynamicWavesTarget, ShaderIDs.s_DynamicWavesTarget); @@ -392,22 +372,28 @@ namespace WaveHarmonic.Crest { wrapper.SetInteger(Lod.ShaderIDs.s_LodIndex, slice); wrapper.Dispatch(threadSize, threadSize, 1); + + // Change to kernel with combine enabled. + if (slice == lastSlice) + { + wrapper = new(buffer, _CombineShader, 8); + } } // Copy Dynamic Waves displacement into Animated Waves. { - wrapper = new PropertyWrapperCompute(buffer, _CombineShader, 9); + wrapper = new(buffer, _CombineShader, 10); wrapper.SetTexture(ShaderIDs.s_AnimatedWavesTarget, DataTexture); wrapper.SetTexture(ShaderIDs.s_DynamicWavesTarget, ShaderIDs.s_DynamicWavesTarget); wrapper.Dispatch(threadSize, threadSize, Slices); } buffer.ReleaseTemporaryRT(ShaderIDs.s_DynamicWavesTarget); - buffer.EndSample("Combine"); + buffer.EndSample(k_DrawCombine); // Query collisions including Dynamic Waves. // Does not require copying the water level as they are added with zero alpha. - _Water.CollisionProvider.UpdateQueries(_Water, CollisionLayer.AfterDynamicWaves); + Provider.UpdateQueries(_Water, CollisionLayer.AfterDynamicWaves); } if (_CollisionLayers.HasFlag(CollisionLayers.Displacement)) @@ -429,7 +415,12 @@ namespace WaveHarmonic.Crest Shader.SetGlobalTexture(_TextureShaderID, DataTexture); } - buffer.EndSample(Name); + buffer.EndSample(ID); + } + + internal override void AfterExecute() + { + Provider.SendReadBack(_Water, _CollisionLayers); } /// diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ClipLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ClipLod.cs index 1b1ebcb53..45babc546 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ClipLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ClipLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -11,16 +11,15 @@ namespace WaveHarmonic.Crest /// /// The default state for clipping. /// + [@GenerateDoc] public enum DefaultClippingState { - /// - /// By default, nothing is clipped. Use clip inputs to remove water. - /// + /// + [Tooltip("By default, nothing is clipped. Use clip inputs to remove water.")] NothingClipped, - /// - /// By default, everything is clipped. Use clip inputs to add water. - /// + /// + [Tooltip("By default, everything is clipped. Use clip inputs to add water.")] EverythingClipped, } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ColorLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ColorLod.cs index 399df336c..1d0a965cb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ColorLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ColorLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -10,21 +10,19 @@ namespace WaveHarmonic.Crest /// /// The source of depth color. /// + [@GenerateDoc] public enum ShorelineVolumeColorSource { - /// - /// No depth color. - /// + /// + [Tooltip("No depth color.")] None, - /// - /// Depth color based on water depth. - /// + /// + [Tooltip("Depth color based on water depth.")] Depth, - /// - /// Depth color based on shoreline distance. - /// + /// + [Tooltip("Depth color based on shoreline distance.")] Distance, } @@ -32,6 +30,7 @@ namespace WaveHarmonic.Crest /// Contains shared functionality for and . /// [FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)] + [System.Serializable] public abstract partial class ColorLod : Lod { [@Space(10f)] diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DepthLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DepthLod.cs index da061407d..87a7f47cb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DepthLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DepthLod.cs @@ -1,8 +1,10 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering; +using WaveHarmonic.Crest.Internal; using WaveHarmonic.Crest.Utility; namespace WaveHarmonic.Crest @@ -13,6 +15,13 @@ namespace WaveHarmonic.Crest [FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)] public sealed partial class DepthLod : Lod { + [@Space(10)] + + [Tooltip("Whether to include the terrain height automatically.\n\nThis will not include terrain details, nor will it produce a signed-distance field. There may also be a slight deviation due to differences in height data and terrain mesh. In these cases, please use the DepthProbe.")] + [@GenerateAPI] + [@DecoratedField, SerializeField] + internal bool _IncludeTerrainHeight = true; + [Tooltip("Support signed distance field data generated from the depth probes.\n\nRequires a two component texture format.")] [@GenerateAPI(Setter.Custom)] [@DecoratedField, SerializeField] @@ -30,7 +39,6 @@ namespace WaveHarmonic.Crest internal override Color GizmoColor => s_GizmoColor; private protected override Color ClearColor => s_NullColor; private protected override bool NeedToReadWriteTextureData => true; - internal override bool RunsInHeadless => true; private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch { @@ -89,6 +97,76 @@ namespace WaveHarmonic.Crest ReAllocate(); } +#if d_Unity_Terrain + TerrainDepthInput _TerrainDepthInput; + + internal override void Enable() + { + base.Enable(); + + if (Enabled) + { + _TerrainDepthInput ??= new(this); + Inputs.Add(_TerrainDepthInput.Queue, _TerrainDepthInput); + } + } + + internal override void Disable() + { + base.Disable(); + + Inputs.Remove(_TerrainDepthInput); + } + + sealed class TerrainDepthInput : ILodInput + { + public bool Enabled => _DepthLod._IncludeTerrainHeight; + public bool IsCompute => true; + public int Queue => int.MinValue; + public int Pass => -1; + public Rect Rect => Rect.zero; + public MonoBehaviour Component => null; + public float Filter(WaterRenderer water, int slice) => 1f; + + readonly DepthLod _DepthLod; + readonly System.Collections.Generic.List _Terrains = new(); + + public TerrainDepthInput(DepthLod lod) + { + _DepthLod = lod; + } + + public void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slices = -1) + { + var resources = WaterResources.Instance; + var wrapper = new PropertyWrapperCompute(buffer, resources.Compute._DepthTexture, 0); + + var threads = lod.Resolution / k_ThreadGroupSize; + + wrapper.SetTexture(Crest.ShaderIDs.s_Target, target); + wrapper.SetVector(Crest.ShaderIDs.s_TextureRotation, new(0, 1)); + wrapper.SetBoolean(DepthLodInput.ShaderIDs.s_SDF, false); + wrapper.SetKeyword(resources.Keywords.DepthTextureSDF, lod._Water._DepthLod._EnableSignedDistanceFields); + + Terrain.GetActiveTerrains(_Terrains); + foreach (var terrain in _Terrains) + { + var data = terrain.terrainData; + if (data == null) continue; + var size = data.size; + var position = terrain.GetPosition(); + + wrapper.SetFloat(DepthLodInput.ShaderIDs.s_HeightOffset, position.y); + wrapper.SetVector(Crest.ShaderIDs.s_Multiplier, new(size.y * 2f, 1, 1, 1)); + wrapper.SetVector(Crest.ShaderIDs.s_TexturePosition, position.XZ() + (size.XZ() * 0.5f)); + wrapper.SetVector(Crest.ShaderIDs.s_TextureSize, size.XZ()); + wrapper.SetTexture(Crest.ShaderIDs.s_Texture, data.heightmapTexture); + wrapper.Dispatch(threads, threads, slices); + } + } + } +#endif // d_Unity_Terrain + #if UNITY_EDITOR [@OnChange] private protected override void OnChange(string propertyPath, object previousValue) diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DynamicWavesLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DynamicWavesLod.cs index fb85024e4..0c3e1c5fc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DynamicWavesLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/DynamicWavesLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -41,7 +41,6 @@ namespace WaveHarmonic.Crest internal override string Name => "Dynamic Waves"; internal override Color GizmoColor => s_GizmoColor; private protected override Color ClearColor => Color.black; - internal override bool RunsInHeadless => true; private protected override ComputeShader SimulationShader => WaterResources.Instance.Compute._UpdateDynamicWaves; private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch { @@ -88,7 +87,7 @@ namespace WaveHarmonic.Crest target.SetFloat(ShaderIDs.s_DisplaceClamp, Settings._DisplaceClamp); } - private protected override void SetAdditionalSimulationParameters(T simMaterial) + private protected override void SetAdditionalSimulationParameters(PropertyWrapperCompute simMaterial) { base.SetAdditionalSimulationParameters(simMaterial); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FlowLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FlowLod.cs index 40b501fde..cff9f4824 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FlowLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FlowLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -21,7 +21,6 @@ namespace WaveHarmonic.Crest internal override Color GizmoColor => s_GizmoColor; private protected override Color ClearColor => Color.black; private protected override bool NeedToReadWriteTextureData => true; - internal override bool RunsInHeadless => true; private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FoamLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FoamLod.cs index 1c71cbd06..653a820d4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FoamLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/FoamLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -52,7 +52,7 @@ namespace WaveHarmonic.Crest _ => throw new System.NotImplementedException(), }; - private protected override void SetAdditionalSimulationParameters(T properties) + private protected override void SetAdditionalSimulationParameters(PropertyWrapperCompute properties) { base.SetAdditionalSimulationParameters(properties); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Generated/Lod.Generated.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Generated/Lod.Generated.cs index 8470f269c..15aca1ef6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Generated/Lod.Generated.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Generated/Lod.Generated.cs @@ -8,6 +8,32 @@ using WaveHarmonic.Crest.Utility; namespace WaveHarmonic.Crest { + [System.Serializable] + partial class AbsorptionLod + { + } + + [System.Serializable] + partial class AlbedoLod + { + } + + [System.Serializable] + partial class AnimatedWavesLod + { + } + + [System.Serializable] + partial class ClipLod + { + } + + [System.Serializable] + partial class DepthLod + { + } + + [System.Serializable] partial class DynamicWavesLod { DynamicWavesLodSettings _DefaultSettings; @@ -36,6 +62,12 @@ namespace WaveHarmonic.Crest } } + [System.Serializable] + partial class FlowLod + { + } + + [System.Serializable] partial class FoamLod { FoamLodSettings _DefaultSettings; @@ -63,4 +95,19 @@ namespace WaveHarmonic.Crest Helpers.Destroy(_DefaultSettings); } } + + [System.Serializable] + partial class LevelLod + { + } + + [System.Serializable] + partial class ScatteringLod + { + } + + [System.Serializable] + partial class ShadowLod + { + } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AbsorptionLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AbsorptionLodInput.cs index f5947af48..5a1cb4fc4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AbsorptionLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AbsorptionLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AlbedoLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AlbedoLodInput.cs index 85484d7a0..7b81eb2a8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AlbedoLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AlbedoLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AnimatedWavesLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AnimatedWavesLodInput.cs index 2e161871d..da2b9a89e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AnimatedWavesLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/AnimatedWavesLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthLodInput.cs index 340c0a3af..2371e1d2c 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -32,7 +32,7 @@ namespace WaveHarmonic.Crest [Tooltip("Whether the data is relative to the input height.\n\nUseful for procedural placement.")] [@GenerateAPI] [@DecoratedField, SerializeField] - internal bool _Relative; + internal bool _Relative = true; [@Label("Copy Signed Distance Field")] [Tooltip("Whether to copy the signed distance field.")] diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthProbe.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthProbe.cs index a5b6a5b16..c541ec527 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthProbe.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DepthProbe.cs @@ -1,11 +1,8 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. -using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; -using UnityEngine.Rendering.HighDefinition; -using UnityEngine.Rendering.Universal; using WaveHarmonic.Crest.Internal; using WaveHarmonic.Crest.Utility; @@ -14,55 +11,51 @@ namespace WaveHarmonic.Crest /// /// 's update mode. /// + [@GenerateDoc] public enum DepthProbeMode { - /// - /// is updating in real-time, in accordance to . - /// + /// + [Tooltip("Update in real-time in accordance to refresh mode.")] RealTime, - /// - /// is baked in the Editor. - /// + /// + [Tooltip("Baked in the editor.")] Baked, } /// /// How the refreshes when using . /// + [@GenerateDoc] public enum DepthProbeRefreshMode { - /// - /// Populates the in Start. - /// + /// + [Tooltip("Populates the DepthProbe in Start.")] OnStart = 0, // EveryFrame = 1, - /// - /// Requires manual updating via . - /// + /// + [Tooltip("Requires manual updating via DepthProbe.Populate.")] ViaScripting = 2, } /// /// How a component is placed in the world. /// + [@GenerateDoc] public enum Placement { - /// - /// The component is in a fixed position. - /// + /// + [Tooltip("The component is in a fixed position.")] Fixed, - /// - /// The component follows the transform. - /// + /// + [Tooltip("The component follows the transform.")] Transform, - /// - /// The component follows the viewpoint. - /// + /// + [Tooltip("The component follows the viewpoint.")] Viewpoint, } @@ -317,17 +310,6 @@ namespace WaveHarmonic.Crest public static readonly int s_VoronoiPingPong1 = Shader.PropertyToID("_Crest_VoronoiPingPong1"); } -#if d_UnityHDRP - static readonly List s_FrameSettingsFields = new() - { - FrameSettingsField.OpaqueObjects, - FrameSettingsField.TransparentObjects, - FrameSettingsField.TransparentPrepass, - FrameSettingsField.TransparentPostpass, - FrameSettingsField.AsyncCompute, - }; -#endif - internal void Bind(T wrapper) where T : IPropertyWrapper { wrapper.SetTexture(ShaderIDs.s_DepthProbe, Texture); @@ -446,39 +428,13 @@ namespace WaveHarmonic.Crest if (RenderPipelineHelper.IsUniversal) { #if d_UnityURP - var additionalCameraData = _Camera.GetUniversalAdditionalCameraData(); - additionalCameraData.renderShadows = false; - additionalCameraData.requiresColorTexture = false; - additionalCameraData.requiresDepthTexture = false; - additionalCameraData.renderPostProcessing = false; - additionalCameraData.allowXRRendering = false; + SetUpCameraURP(); #endif } else if (RenderPipelineHelper.IsHighDefinition) { #if d_UnityHDRP - var additionalCameraData = _Camera.gameObject.AddComponent(); - - additionalCameraData.clearColorMode = HDAdditionalCameraData.ClearColorMode.Color; - additionalCameraData.volumeLayerMask = 0; - additionalCameraData.probeLayerMask = 0; - additionalCameraData.xrRendering = false; - - // Override camera frame settings to disable most of the expensive rendering for this camera. - // Most importantly, disable custom passes and post-processing as third-party stuff might throw - // errors because of this camera. Even with excluding a lot of HDRP features, it still does a - // lit pass which is not cheap. - additionalCameraData.customRenderingSettings = true; - - foreach (FrameSettingsField frameSetting in System.Enum.GetValues(typeof(FrameSettingsField))) - { - if (!s_FrameSettingsFields.Contains(frameSetting)) - { - // Enable override and then disable the feature. - additionalCameraData.renderingPathCustomFrameSettingsOverrideMask.mask[(uint)frameSetting] = true; - additionalCameraData.renderingPathCustomFrameSettings.SetEnabled(frameSetting, false); - } - } + SetUpCameraHD(); #endif } } @@ -557,6 +513,10 @@ namespace WaveHarmonic.Crest OnBeforeRender?.Invoke(this); + _CommandBuffer ??= new(); + _CommandBuffer.Clear(); + _CommandBuffer.name = "Crest.DepthProbe"; + #if UNITY_EDITOR try #endif @@ -566,6 +526,9 @@ namespace WaveHarmonic.Crest if (_FillHolesCaptureHeight > 0f) { + Graphics.ExecuteCommandBuffer(_CommandBuffer); + _CommandBuffer.Clear(); + // Fill holes pass. RenderDepthIntoProbe(k_FillKernel, _CaptureRange.y + _FillHolesCaptureHeight); } @@ -588,10 +551,14 @@ namespace WaveHarmonic.Crest if (_GenerateSignedDistanceField) { + _CommandBuffer.BeginSample("SDF"); RenderSignedDistanceField(inverted: false); RenderSignedDistanceField(inverted: true); + _CommandBuffer.EndSample("SDF"); } + Graphics.ExecuteCommandBuffer(_CommandBuffer); + HashState(ref _RenderedStateHash); } @@ -621,9 +588,17 @@ namespace WaveHarmonic.Crest backFaces = RenderTexture.GetTemporary(target.descriptor); _Camera.targetTexture = backFaces; + // Does not work for HDRP (handled elsewhere). var oldInvertCulling = GL.invertCulling; GL.invertCulling = true; +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + _HDAdditionalCameraData.invertFaceCulling = true; + } +#endif + // Render scene, saving depths in depth buffer. #if d_UnityURP if (RenderPipelineHelper.IsUniversal) @@ -637,6 +612,14 @@ namespace WaveHarmonic.Crest } _Camera.targetTexture = target; + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + _HDAdditionalCameraData.invertFaceCulling = false; + } +#endif + GL.invertCulling = oldInvertCulling; } @@ -652,7 +635,7 @@ namespace WaveHarmonic.Crest _Camera.Render(); } - var wrapper = new PropertyWrapperComputeStandalone(WaterResources.Instance.Compute._RenderDepthProbe, kernel); + var wrapper = new PropertyWrapperCompute(_CommandBuffer, WaterResources.Instance.Compute._RenderDepthProbe, kernel); wrapper.SetFloat(ShaderIDs.s_HeightOffset, transform.position.y); @@ -699,13 +682,12 @@ namespace WaveHarmonic.Crest return; } + var buffer = _CommandBuffer; + var cameraToWorldMatrix = _Camera.cameraToWorldMatrix; var projectionMatrix = _Camera.projectionMatrix; var projectionToWorldMatrix = cameraToWorldMatrix * projectionMatrix.inverse; - var buffer = _CommandBuffer ??= new(); - buffer.Clear(); - buffer.name = "Jump Flood"; // Common uniforms. buffer.SetComputeFloatParam(shader, DepthLodInput.ShaderIDs.s_HeightOffset, transform.position.y); buffer.SetComputeIntParam(shader, Crest.ShaderIDs.s_TextureSize, _Resolution); @@ -802,7 +784,6 @@ namespace WaveHarmonic.Crest ); } - Graphics.ExecuteCommandBuffer(buffer); buffer.ReleaseTemporaryRT(voronoiPingPong0); buffer.ReleaseTemporaryRT(voronoiPingPong1); } @@ -929,6 +910,7 @@ namespace WaveHarmonic.Crest wrapper.SetVector(Crest.ShaderIDs.s_TextureSize, _Probe.Scale); wrapper.SetVector(Crest.ShaderIDs.s_TexturePosition, position.XZ()); wrapper.SetVector(Crest.ShaderIDs.s_TextureRotation, new Vector2(matrix.m20, matrix.m00).normalized); + wrapper.SetVector(Crest.ShaderIDs.s_Multiplier, Vector4.one); wrapper.SetInteger(Crest.ShaderIDs.s_Blend, (int)LodInputBlend.Maximum); wrapper.SetTexture(Crest.ShaderIDs.s_Texture, _Probe.Texture); wrapper.SetTexture(Crest.ShaderIDs.s_Target, target); @@ -962,9 +944,9 @@ namespace WaveHarmonic.Crest Hash.AddBool(_EnableBackFaceInclusion, ref hash); Hash.AddInt(_AdditionalJumpFloodRounds, ref hash); Hash.AddBool(_GenerateSignedDistanceField, ref hash); - Hash.AddObject(Position, ref hash); - Hash.AddObject(Rotation, ref hash); - Hash.AddObject(Scale, ref hash); + Hash.AddObject(Managed ? Vector3.zero : Position, ref hash); + Hash.AddObject(Managed ? Quaternion.identity : Rotation, ref hash); + Hash.AddObject(Managed ? Vector2.zero : Scale, ref hash); } #if UNITY_EDITOR @@ -992,7 +974,7 @@ namespace WaveHarmonic.Crest void Update() { - if (_Debug._ForceAlwaysUpdateDebug) + if (_Debug._ForceAlwaysUpdateDebug && _Type != DepthProbeMode.Baked) { Populate(); } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DynamicWavesLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DynamicWavesLodInput.cs index f29751aaf..943a043bc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DynamicWavesLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/DynamicWavesLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FlowLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FlowLodInput.cs index d04063ddf..3a112dce8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FlowLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FlowLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FoamLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FoamLodInput.cs index 351af4db4..91b2de6fb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FoamLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/FoamLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/GeometryLodInputData.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/GeometryLodInputData.cs index 67f3bf311..23beb86a0 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/GeometryLodInputData.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/GeometryLodInputData.cs @@ -97,6 +97,7 @@ namespace WaveHarmonic.Crest /// [ForLodInput(typeof(LevelLodInput), LodInputMode.Geometry)] + [System.Serializable] public sealed class LevelGeometryLodInputData : GeometryLodInputData { private protected override Shader GeometryShader => WaterResources.Instance.Shaders._LevelGeometry; @@ -104,6 +105,7 @@ namespace WaveHarmonic.Crest /// [ForLodInput(typeof(DepthLodInput), LodInputMode.Geometry)] + [System.Serializable] public sealed class DepthGeometryLodInputData : GeometryLodInputData { private protected override Shader GeometryShader => WaterResources.Instance.Shaders._DepthGeometry; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LevelLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LevelLodInput.cs index 488f21916..68995c1b5 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LevelLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LevelLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInput.cs index 09267b46a..621ecf8d3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System; @@ -17,7 +17,7 @@ namespace WaveHarmonic.Crest /// /// Draw the input (the render target will be bound) /// - public void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1); + void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1); float Filter(WaterRenderer water, int slice); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInputData.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInputData.cs index d7395d4fc..7965fd430 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInputData.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/LodInputData.cs @@ -23,6 +23,7 @@ namespace WaveHarmonic.Crest /// /// Data storage for an input, pertinent to the associated input mode. /// + [Serializable] public abstract class LodInputData { [SerializeField, HideInInspector] @@ -109,82 +110,70 @@ namespace WaveHarmonic.Crest /// /// Modes that inputs can use. Not all inputs support all modes. Refer to the UI. /// + [@GenerateDoc] public enum LodInputMode { - /// - /// Unset is the serialization default. - /// - /// - /// This will be replaced with the default mode automatically. Unset can also be - /// used if something is invalid. - /// + /// + [Tooltip("Unset is the serialization default.\n\nThis will be replaced with the default mode automatically. Unset can also be used if something is invalid.")] Unset = 0, - /// - /// Hand-painted data by the user. Currently unused. - /// + + /// + [Tooltip("Hand-painted data by the user.")] Paint, - /// - /// Driven by a user created spline. - /// + + /// + [Tooltip("Driven by a user created spline.")] Spline, - /// - /// Attached 'Renderer' (mesh, particle or other) used to drive data. - /// + + /// + [Tooltip("Attached 'Renderer' (mesh, particle or other) used to drive data.")] Renderer, - /// - /// Driven by a mathematical primitive such as a cube or sphere. - /// + + /// + [Tooltip("Driven by a mathematical primitive such as a cube or sphere.")] Primitive, - /// - /// Covers the entire water area. - /// + + /// + [Tooltip("Covers the entire water area.")] Global, - /// - /// Data driven by a user provided texture. - /// + + /// + [Tooltip("Data driven by a user provided texture.")] Texture, - /// - /// Renders geometry using a default material. - /// + + /// + [Tooltip("Renders geometry using a default material.")] Geometry, } /// /// Blend presets for inputs. /// + [@GenerateDoc] public enum LodInputBlend { - /// - /// No blending. Overwrites. - /// + /// + [Tooltip("No blending. Overwrites.")] Off, - /// - /// Additive blending. - /// + /// + [Tooltip("Additive blending.")] Additive, - /// - /// Takes the minimum value. - /// + /// + [Tooltip("Takes the minimum value.")] Minimum, - /// - /// Takes the maximum value. - /// + /// + [Tooltip("Takes the maximum value.")] Maximum, - /// - /// Applies the inverse weight to the target. - /// - /// - /// Basically overwrites what is already in the simulation. - /// + /// + [Tooltip("Applies the inverse weight to the target.\n\nBasically overwrites what is already in the simulation.")] Alpha, - /// - /// Same as alpha except anything above zero will overwrite rather than blend. - /// + /// + [Tooltip("Same as alpha except anything above zero will overwrite rather than blend.")] AlphaClip, } @@ -192,21 +181,19 @@ namespace WaveHarmonic.Crest /// Primitive shapes. /// // Have this match UnityEngine.PrimitiveType. + [@GenerateDoc] public enum LodInputPrimitive { - /// - /// Spheroid. - /// + /// + [Tooltip("Spheroid.")] Sphere = 0, - /// - /// Cuboid. - /// + /// + [Tooltip("Cuboid.")] Cube = 3, - /// - /// Quad. - /// + /// + [Tooltip("Quad.")] Quad = 5, } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe.meta new file mode 100644 index 000000000..6c0904843 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef4f3d3c2ad88274294da9c9be0143e7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs new file mode 100644 index 000000000..b4878e530 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs @@ -0,0 +1,54 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using System.Collections.Generic; +using UnityEngine.Rendering.HighDefinition; + +namespace WaveHarmonic.Crest +{ + partial class DepthProbe + { + static readonly List s_FrameSettingsFields = new() + { + FrameSettingsField.OpaqueObjects, + FrameSettingsField.TransparentObjects, + FrameSettingsField.TransparentPrepass, + FrameSettingsField.TransparentPostpass, + FrameSettingsField.AsyncCompute, + }; + + HDAdditionalCameraData _HDAdditionalCameraData; + + void SetUpCameraHD() + { + var additionalCameraData = _Camera.gameObject.AddComponent(); + + additionalCameraData.clearColorMode = HDAdditionalCameraData.ClearColorMode.Color; + additionalCameraData.volumeLayerMask = 0; + additionalCameraData.probeLayerMask = 0; + additionalCameraData.xrRendering = false; + + // Override camera frame settings to disable most of the expensive rendering for this camera. + // Most importantly, disable custom passes and post-processing as third-party stuff might throw + // errors because of this camera. Even with excluding a lot of HDRP features, it still does a + // lit pass which is not cheap. + additionalCameraData.customRenderingSettings = true; + + foreach (FrameSettingsField frameSetting in System.Enum.GetValues(typeof(FrameSettingsField))) + { + if (!s_FrameSettingsFields.Contains(frameSetting)) + { + // Enable override and then disable the feature. + additionalCameraData.renderingPathCustomFrameSettingsOverrideMask.mask[(uint)frameSetting] = true; + additionalCameraData.renderingPathCustomFrameSettings.SetEnabled(frameSetting, false); + } + } + + _HDAdditionalCameraData = additionalCameraData; + } + } +} + +#endif // d_UnityHDRP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs.meta new file mode 100644 index 000000000..188a39cc2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93b38270a78f94e43bfbbe01ef2e351b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 300 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs new file mode 100644 index 000000000..e0db58ed9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs @@ -0,0 +1,24 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityURP + +using UnityEngine.Rendering.Universal; + +namespace WaveHarmonic.Crest +{ + partial class DepthProbe + { + void SetUpCameraURP() + { + var additionalCameraData = _Camera.GetUniversalAdditionalCameraData(); + additionalCameraData.renderShadows = false; + additionalCameraData.requiresColorTexture = false; + additionalCameraData.requiresDepthTexture = false; + additionalCameraData.renderPostProcessing = false; + additionalCameraData.allowXRRendering = false; + } + } +} + +#endif // d_UnityURP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs.meta new file mode 100644 index 000000000..3aa4c07c6 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Probe/DepthProbe.Universal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3d572236539a490aaddc647129ad141 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 300 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/RendererLodInputData.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/RendererLodInputData.cs index 921ee1cfd..3789db0a4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/RendererLodInputData.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/RendererLodInputData.cs @@ -11,6 +11,7 @@ namespace WaveHarmonic.Crest /// /// Data storage for for the Renderer input mode. /// + [System.Serializable] public abstract partial class RendererLodInputData : LodInputData { [Tooltip("The renderer to use for this input.\n\nCan be anything that inherits from Renderer like MeshRenderer, TrailRenderer etc.")] @@ -47,12 +48,6 @@ namespace WaveHarmonic.Crest #pragma warning restore 414 - static class ShaderIDs - { - public static readonly int s_Time = Shader.PropertyToID("_Time"); - } - - // Some renderers require multiple materials like particles with trails. // We pass this to GetSharedMaterials to avoid allocations. internal List _Materials = new(); @@ -169,35 +164,31 @@ namespace WaveHarmonic.Crest } #endif - var pass = _ShaderPassIndex; + // BIRP/URP SG first pass is the right one. + // HDRP SG does not support matrix override, but users can just use BIRP instead. + var pass = 0; + if (ShapeWaves.s_RenderPassOverride > -1) { // Needs to use a second pass to disable blending. pass = ShapeWaves.s_RenderPassOverride; } - else if (!_OverrideShaderPass) + else if (_OverrideShaderPass) { - // BIRP/URP SG first pass is the right one. - pass = 0; - - // Support HDRP SG. It will always have more than one pass. - if (RenderPipelineHelper.IsHighDefinition && material.shader.passCount > 1) - { - var sgPass = material.FindPass("ForwardOnly"); - if (sgPass > -1) pass = sgPass; - } + pass = _ShaderPassIndex; } - else if (_ShaderPassIndex > material.shader.passCount - 1) + + if (pass > material.shader.passCount - 1) { return; } // Time is not set for us for some reason… Use Time.timeSinceLevelLoad as per: // https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html - if (RenderPipelineHelper.IsLegacy) + if (RenderPipelineHelper.IsLegacy || RenderPipelineHelper.IsHighDefinition) { _Renderer.GetPropertyBlock(_MaterialPropertyBlock); - _MaterialPropertyBlock.SetVector(ShaderIDs.s_Time, new + _MaterialPropertyBlock.SetVector(ShaderIDs.Unity.s_Time, new ( Time.timeSinceLevelLoad / 20, Time.timeSinceLevelLoad, diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ScatteringLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ScatteringLodInput.cs index 9c2718f7f..ab37d95fc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ScatteringLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ScatteringLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ShadowLodInput.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ShadowLodInput.cs index 55e5026d9..8d989a2ef 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ShadowLodInput.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/ShadowLodInput.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeFFT.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeFFT.cs index b3cf7abb0..1cbed8353 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeFFT.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeFFT.cs @@ -14,14 +14,21 @@ namespace WaveHarmonic.Crest { // Waves - [Tooltip("How turbulent/chaotic the waves are.")] - [@Range(0, 1, order = -3)] + [Tooltip("Whether to use the wind turbulence on this component rather than the global wind turbulence.\n\nGlobal wind turbulence comes from the Water Renderer component.")] [@GenerateAPI] + [@InlineToggle(order = -3), SerializeField] + bool _OverrideGlobalWindTurbulence; + + [Tooltip("How turbulent/chaotic the waves are.")] + [@Predicated(nameof(_OverrideGlobalWindTurbulence), hide: true)] + [@ShowComputedProperty(nameof(WindTurbulence))] + [@Range(0, 1, order = -4)] + [@GenerateAPI(Getter.Custom)] [SerializeField] float _WindTurbulence = 0.145f; [Tooltip("How aligned the waves are with wind.")] - [@Range(0, 1, order = -4)] + [@Range(0, 1, order = -5)] [@GenerateAPI] [SerializeField] float _WindAlignment; @@ -51,23 +58,39 @@ namespace WaveHarmonic.Crest [@Heading("Collision Data Baking")] +#if !d_WaveHarmonic_Crest_CPUQueries + [HideInInspector] +#endif + [Tooltip("Enable running this FFT with baked data.\n\nThis makes the FFT periodic (repeating in time).")] [@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)] [@DecoratedField, SerializeField] internal bool _EnableBakedCollision = false; +#if !d_WaveHarmonic_Crest_CPUQueries + [HideInInspector] +#endif + [Tooltip("Frames per second of baked data.\n\nLarger values may help the collision track the surface closely at the cost of more frames and increase baked data size.")] [@Predicated(nameof(_EnableBakedCollision))] [@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)] [@DecoratedField, SerializeField] internal int _TimeResolution = 4; +#if !d_WaveHarmonic_Crest_CPUQueries + [HideInInspector] +#endif + [Tooltip("Smallest wavelength required in collision.\n\nTo preview the effect of this, disable power sliders in spectrum for smaller values than this number. Smaller values require more resolution and increase baked data size.")] [@Predicated(nameof(_EnableBakedCollision))] [@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)] [@DecoratedField, SerializeField] internal float _SmallestWavelengthRequired = 2f; +#if !d_WaveHarmonic_Crest_CPUQueries + [HideInInspector] +#endif + [Tooltip("FFT waves will loop with a period of this many seconds.\n\nSmaller values decrease data size but can make waves visibly repetitive.")] [@Predicated(nameof(_EnableBakedCollision))] [@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)] @@ -75,21 +98,28 @@ namespace WaveHarmonic.Crest [SerializeField] internal float _BakedTimeLoopLength = 32f; - internal float LoopPeriod => _EnableBakedCollision ? _BakedTimeLoopLength : _TimeLoopLength; + internal float LoopPeriod => +#if d_WaveHarmonic_Crest_CPUQueries + _EnableBakedCollision ? _BakedTimeLoopLength : +#endif + _TimeLoopLength; private protected override int MinimumResolution => 16; private protected override int MaximumResolution => int.MaxValue; + FFTCompute _FFTCompute; + FFTCompute.Parameters _OldFFTParameters; - internal FFTCompute.Parameters FFTParameters => new + internal FFTCompute.Parameters GetFFTParameters(float gravity) => new ( _ActiveSpectrum, Resolution, _TimeLoopLength, WindSpeedMPS, WindDirRadForFFT, - _WindTurbulence, - _WindAlignment + WindTurbulence, + _WindAlignment, + gravity ); private protected override void OnUpdate(WaterRenderer water) @@ -103,7 +133,7 @@ namespace WaveHarmonic.Crest ReportMaxDisplacement(water); // If geometry is being used, the water input shader will rotate the waves to align to geo - var parameters = FFTParameters; + var parameters = GetFFTParameters(water.Gravity); // Don't create tons of generators when values are varying. Notify so that existing generators may be adapted. if (parameters.GetHashCode() != _OldFFTParameters.GetHashCode()) @@ -111,6 +141,10 @@ namespace WaveHarmonic.Crest FFTCompute.OnGenerationDataUpdated(_OldFFTParameters, parameters); } +#if UNITY_EDITOR + _FFTCompute = FFTCompute.GetInstance(parameters); +#endif + _OldFFTParameters = parameters; } @@ -118,14 +152,22 @@ namespace WaveHarmonic.Crest { if (_LastGenerateFrameCount != Time.frameCount) { + // Parameters will unlikely change as our Update is called in LateUpdate with Draw + // not too far after. + var parameters = GetFFTParameters(lod.Water.Gravity); + _WaveBuffers = FFTCompute.GenerateDisplacements ( buffer, lod.Water.CurrentTime, - FFTParameters, + parameters, UpdateDataEachFrame ); +#if UNITY_EDITOR + _FFTCompute = FFTCompute.GetInstance(parameters); +#endif + _LastGenerateFrameCount = Time.frameCount; } @@ -157,11 +199,6 @@ namespace WaveHarmonic.Crest } } - private protected override void DestroySharedResources() - { - FFTCompute.CleanUpAll(); - } - float WindDirRadForFFT { get @@ -172,36 +209,64 @@ namespace WaveHarmonic.Crest return 0f; } - return _WaveDirectionHeadingAngle * Mathf.Deg2Rad; + return WaveDirectionHeadingAngle * Mathf.Deg2Rad; } } + float GetWindTurbulence() + { + return _OverrideGlobalWindTurbulence || WaterRenderer.Instance == null ? _WindTurbulence : WaterRenderer.Instance.WindTurbulence; + } + #if UNITY_EDITOR void OnGUI() { if (_DrawSlicesInEditor) { - FFTCompute.GetInstance(FFTParameters)?.OnGUI(); + _FFTCompute?.OnGUI(); } } - - internal FFTCompute GetFFTComputeInstance() - { - return FFTCompute.GetInstance(FFTParameters); - } #endif } + partial class ShapeFFT + { + static int s_InstanceCount; + + private protected override void Awake() + { + base.Awake(); + s_InstanceCount++; + } + + private protected override void OnDestroy() + { + base.OnDestroy(); + + if (--s_InstanceCount <= 0) + { + FFTCompute.CleanUpAll(); + } + } + } + partial class ShapeFFT : ISerializationCallbackReceiver { [SerializeField, HideInInspector] #pragma warning disable 414 - int _Version = 1; + int _Version = 2; #pragma warning restore 414 void ISerializationCallbackReceiver.OnAfterDeserialize() { _Version = MigrateV1(_Version); + + if (_Version < 2) + { + _OverrideGlobalWindTurbulence = true; + } + + _Version = MigrateV2(_Version); } void ISerializationCallbackReceiver.OnBeforeSerialize() @@ -209,4 +274,19 @@ namespace WaveHarmonic.Crest // Empty. } } + +#if UNITY_EDITOR + partial class ShapeFFT + { + private protected override void Reset() + { + base.Reset(); + + if (_Mode != LodInputMode.Global) + { + _OverrideGlobalWindTurbulence = true; + } + } + } +#endif } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeGerstner.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeGerstner.cs index 10e0783a1..de3179a85 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeGerstner.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeGerstner.cs @@ -17,9 +17,17 @@ namespace WaveHarmonic.Crest { // Waves - [Tooltip("The weight of the opposing, second pair of Gerstner waves.\n\nEach Gerstner wave is actually a pair of waves travelling in opposite directions (similar to FFT). This weight is applied to the wave travelling in against-wind direction. Set to zero to obtain simple single waves which are useful for shorelines waves.")] - [@Range(0f, 1f, order = -3)] + [@Space(10)] + + [Tooltip("Use a swell spectrum as the default.\n\nUses a swell spectrum as default (when none is assigned), and disabled reverse waves.")] [@GenerateAPI] + [@DecoratedField(order = -3), SerializeField] + bool _Swell = true; + + [Tooltip("The weight of the opposing, second pair of Gerstner waves.\n\nEach Gerstner wave is actually a pair of waves travelling in opposite directions (similar to FFT). This weight is applied to the wave travelling in against-wind direction. Set to zero to obtain simple single waves which are useful for shorelines waves.")] + [Predicated(nameof(_Swell), inverted: true)] + [@Range(0f, 1f, order = -4)] + [@GenerateAPI(Getter.Custom)] [SerializeField] float _ReverseWaveWeight = 0.5f; @@ -37,6 +45,11 @@ namespace WaveHarmonic.Crest [SerializeField] int _RandomSeed = 0; + [Tooltip("Prevent data arrays from being written to so one can provide their own.")] + [@GenerateAPI] + [SerializeField] + bool _ManualGeneration; + private protected override int MinimumResolution => 8; private protected override int MaximumResolution => 64; @@ -45,12 +58,39 @@ namespace WaveHarmonic.Crest const int k_MaximumWaveComponents = 1024; // Data for all components - float[] _Wavelengths; - float[] _Amplitudes; + + /// + /// Wavelengths. Requires Manual Generation to be enabled. + /// + [System.NonSerialized] + public float[] _Wavelengths; + + /// + /// Amplitudes. Requires Manual Generation to be enabled. + /// + [System.NonSerialized] + public float[] _Amplitudes; + + /// + /// Powers. Requires Manual Generation to be enabled. + /// + [System.NonSerialized] + public float[] _Powers; + + /// + /// Angles. Requires Manual Generation to be enabled. + /// + [System.NonSerialized] + public float[] _AngleDegrees; + + /// + /// Phases. Requires Manual Generation to be enabled. + /// + [System.NonSerialized] + public float[] _Phases; + + // Reverse. float[] _Amplitudes2; - float[] _Powers; - float[] _AngleDegrees; - float[] _Phases; float[] _Phases2; struct GerstnerCascadeParams @@ -82,6 +122,33 @@ namespace WaveHarmonic.Crest ComputeShader _ShaderGerstner; int _KernelGerstner = -1; + private protected override WaveSpectrum DefaultSpectrum => _Swell ? SwellSpectrum : WindSpectrum; + static WaveSpectrum s_SwellSpectrum; + static WaveSpectrum SwellSpectrum + { + get + { + if (s_SwellSpectrum == null) + { + s_SwellSpectrum = ScriptableObject.CreateInstance(); + s_SwellSpectrum.name = "Swell Waves (auto)"; + s_SwellSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable; + s_SwellSpectrum._PowerDisabled[0] = true; + s_SwellSpectrum._PowerDisabled[1] = true; + s_SwellSpectrum._PowerDisabled[2] = true; + s_SwellSpectrum._PowerDisabled[3] = true; + s_SwellSpectrum._PowerDisabled[4] = true; + s_SwellSpectrum._PowerDisabled[5] = true; + s_SwellSpectrum._PowerDisabled[6] = true; + s_SwellSpectrum._PowerDisabled[7] = true; + s_SwellSpectrum._WaveDirectionVariance = 15f; + s_SwellSpectrum._Chop = 1.3f; + } + + return s_SwellSpectrum; + } + } + static new class ShaderIDs { @@ -103,6 +170,11 @@ namespace WaveHarmonic.Crest s_Instances.Clear(); } + float GetReverseWaveWeight() + { + return _Swell ? 0f : _ReverseWaveWeight; + } + void InitData() { if (_WaveBuffers == null) @@ -167,7 +239,7 @@ namespace WaveHarmonic.Crest { UpdateGenerateWaves(buffer); // Above changes the render target. Change it back if necessary. - if (!IsCompute) buffer.SetRenderTarget(target, 0, CubemapFace.Unknown, slice); + if (!IsCompute) CoreUtils.SetRenderTarget(buffer, target, depthSlice: slice); } _LastGenerateFrameCount = Time.frameCount; @@ -196,6 +268,16 @@ namespace WaveHarmonic.Crest var outputIdx = 0; _CascadeParameters[0]._StartIndex = 0; + if (_ManualGeneration) + { + for (var i = 0; i < _WaveData.Length; i++) + { + _WaveData[i]._Phase2 = Vector4.zero; + _WaveData[i]._Amplitude2 = Vector4.zero; + _WaveData[i]._ChopAmplitude2 = Vector4.zero; + } + } + // Seek forward to first wavelength that is big enough to render into current cascades var minWl = MinWavelength(cascadeIdx); while (componentIdx < _Wavelengths.Length && _Wavelengths[componentIdx] < minWl) @@ -230,10 +312,13 @@ namespace WaveHarmonic.Crest _WaveData[vi]._WaveDirectionZ[ei] = 0f; _WaveData[vi]._Omega[ei] = 0f; _WaveData[vi]._Phase[ei] = 0f; - _WaveData[vi]._Phase2[ei] = 0f; _WaveData[vi]._ChopAmplitude[ei] = 0f; - _WaveData[vi]._Amplitude2[ei] = 0f; - _WaveData[vi]._ChopAmplitude2[ei] = 0f; + if (!_ManualGeneration) + { + _WaveData[vi]._Phase2[ei] = 0f; + _WaveData[vi]._Amplitude2[ei] = 0f; + _WaveData[vi]._ChopAmplitude2[ei] = 0f; + } ei = (ei + 1) % 4; outputIdx++; } @@ -254,11 +339,15 @@ namespace WaveHarmonic.Crest var ei = outputIdx - vi * 4; _WaveData[vi]._Amplitude[ei] = _Amplitudes[componentIdx]; - _WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx]; var chopScale = _ActiveSpectrum._ChopScales[componentIdx / _ComponentsPerOctave]; _WaveData[vi]._ChopAmplitude[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes[componentIdx]; - _WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx]; + + if (!_ManualGeneration) + { + _WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx]; + _WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx]; + } var angle = Mathf.Deg2Rad * _AngleDegrees[componentIdx]; var dx = Mathf.Cos(angle); @@ -295,7 +384,11 @@ namespace WaveHarmonic.Crest // Repeat every 2pi to keep angle bounded - helps precision on 16bit platforms _WaveData[vi]._Omega[ei] = k * c; _WaveData[vi]._Phase[ei] = Mathf.Repeat(_Phases[componentIdx], Mathf.PI * 2f); - _WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f); + + if (!_ManualGeneration) + { + _WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f); + } outputIdx++; } @@ -316,10 +409,13 @@ namespace WaveHarmonic.Crest _WaveData[vi]._WaveDirectionZ[ei] = 0f; _WaveData[vi]._Omega[ei] = 0f; _WaveData[vi]._Phase[ei] = 0f; - _WaveData[vi]._Phase2[ei] = 0f; _WaveData[vi]._ChopAmplitude[ei] = 0f; - _WaveData[vi]._Amplitude2[ei] = 0f; - _WaveData[vi]._ChopAmplitude2[ei] = 0f; + if (!_ManualGeneration) + { + _WaveData[vi]._Phase2[ei] = 0f; + _WaveData[vi]._Amplitude2[ei] = 0f; + _WaveData[vi]._ChopAmplitude2[ei] = 0f; + } ei = (ei + 1) % 4; outputIdx++; } @@ -340,8 +436,7 @@ namespace WaveHarmonic.Crest void UpdateGenerateWaves(CommandBuffer buf) { // Clear existing waves or they could get copied. - buf.SetRenderTarget(_WaveBuffers, 0, CubemapFace.Unknown, -1); - buf.ClearRenderTarget(RTClearFlags.Color, Color.black, 0, 0); + CoreUtils.SetRenderTarget(buf, _WaveBuffers, ClearFlag.Color); buf.SetComputeFloatParam(_ShaderGerstner, ShaderIDs.s_TextureRes, _WaveBuffers.width); buf.SetComputeIntParam(_ShaderGerstner, ShaderIDs.s_FirstCascadeIndex, _FirstCascade); buf.SetComputeBufferParam(_ShaderGerstner, _KernelGerstner, ShaderIDs.s_CascadeParams, _BufferCascadeParameters); @@ -358,13 +453,23 @@ namespace WaveHarmonic.Crest /// Wind speed in m/s void UpdateWaveData(WaterRenderer water, float windSpeed) { + if (_ManualGeneration) + { + if (_Wavelengths != null) + { + SliceUpWaves(water, windSpeed); + } + + return; + } + // Set random seed to get repeatable results var randomStateBkp = Random.state; Random.InitState(_RandomSeed); _ActiveSpectrum.GenerateWaveData(_ComponentsPerOctave, ref _Wavelengths, ref _AngleDegrees); - UpdateAmplitudes(); + UpdateAmplitudes(water); // Won't run every time so put last in the random sequence if (_Phases == null || _Phases.Length != _Wavelengths.Length || _Phases2 == null || _Phases2.Length != _Wavelengths.Length) @@ -377,7 +482,7 @@ namespace WaveHarmonic.Crest SliceUpWaves(water, windSpeed); } - void UpdateAmplitudes() + void UpdateAmplitudes(WaterRenderer water) { if (_Amplitudes == null || _Amplitudes.Length != _Wavelengths.Length) { @@ -396,9 +501,9 @@ namespace WaveHarmonic.Crest for (var i = 0; i < _Wavelengths.Length; i++) { - var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, out _Powers[i]); + var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, water.Gravity, out _Powers[i]); _Amplitudes[i] = Random.value * amp; - _Amplitudes2[i] = Random.value * amp * _ReverseWaveWeight; + _Amplitudes2[i] = Random.value * amp * ReverseWaveWeight; } } @@ -490,8 +595,6 @@ namespace WaveHarmonic.Crest } } - private protected override void DestroySharedResources() { } - #if UNITY_EDITOR void OnGUI() { @@ -503,16 +606,44 @@ namespace WaveHarmonic.Crest #endif } + partial class ShapeGerstner + { + static int s_InstanceCount; + + private protected override void Awake() + { + base.Awake(); + s_InstanceCount++; + } + + private protected override void OnDestroy() + { + base.OnDestroy(); + + if (s_SwellSpectrum != null) + { + Helpers.Destroy(s_SwellSpectrum); + } + } + } + partial class ShapeGerstner : ISerializationCallbackReceiver { [SerializeField, HideInInspector] #pragma warning disable 414 - int _Version = 1; + int _Version = 2; #pragma warning restore 414 void ISerializationCallbackReceiver.OnAfterDeserialize() { _Version = MigrateV1(_Version); + + if (_Version < 2) + { + _Swell = false; + } + + _Version = MigrateV2(_Version); } void ISerializationCallbackReceiver.OnBeforeSerialize() diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeWaves.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeWaves.cs index 14a131d02..38a952124 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeWaves.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/Shape/ShapeWaves.cs @@ -18,7 +18,7 @@ namespace WaveHarmonic.Crest [@Heading("Waves")] [Tooltip("The spectrum that defines the water surface shape.")] - [@Embedded] + [@Embedded(defaultPropertyName: nameof(_ActiveSpectrum))] [@GenerateAPI] [SerializeField] internal WaveSpectrum _Spectrum; @@ -35,17 +35,25 @@ namespace WaveHarmonic.Crest [SerializeField] float _RespectShallowWaterAttenuation = 1f; + [Tooltip("Whether to use the wind direction on this component rather than the global wind direction.\n\nGlobal wind direction comes from the Water Renderer component.")] + [@GenerateAPI] + [@InlineToggle, SerializeField] + bool _OverrideGlobalWindDirection; + + [@Label("Wind Direction")] [Tooltip("Primary wave direction heading (degrees).\n\nThis is the angle from x axis in degrees that the waves are oriented towards. If a spline is being used to place the waves, this angle is relative to the spline.")] [@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Paint))] + [@Predicated(nameof(_OverrideGlobalWindDirection), hide: true)] + [@ShowComputedProperty(nameof(WaveDirectionHeadingAngle))] [@Range(-180, 180)] - [@GenerateAPI] + [@GenerateAPI(Getter.Custom)] [SerializeField] private protected float _WaveDirectionHeadingAngle = 0f; [Tooltip("Whether to use the wind speed on this component rather than the global wind speed.\n\nGlobal wind speed comes from the Water Renderer component.")] [@GenerateAPI] - [SerializeField] - bool _OverrideGlobalWindSpeed = false; + [@InlineToggle, SerializeField] + bool _OverrideGlobalWindSpeed; [Tooltip("Wind speed in km/h. Controls wave conditions.")] [@ShowComputedProperty(nameof(WindSpeedKPH))] @@ -86,19 +94,21 @@ namespace WaveHarmonic.Crest public static readonly int s_AxisX = Shader.PropertyToID("_Crest_AxisX"); } - static WaveSpectrum s_DefaultSpectrum; - private protected static WaveSpectrum DefaultSpectrum + private protected virtual WaveSpectrum DefaultSpectrum => WindSpectrum; + + static WaveSpectrum s_WindSpectrum; + private protected static WaveSpectrum WindSpectrum { get { - if (s_DefaultSpectrum == null) + if (s_WindSpectrum == null) { - s_DefaultSpectrum = ScriptableObject.CreateInstance(); - s_DefaultSpectrum.name = "Default Waves (instance)"; - s_DefaultSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable; + s_WindSpectrum = ScriptableObject.CreateInstance(); + s_WindSpectrum.name = "Wind Waves (instance)"; + s_WindSpectrum.hideFlags = HideFlags.DontSave | HideFlags.NotEditable; } - return s_DefaultSpectrum; + return s_WindSpectrum; } } @@ -113,7 +123,7 @@ namespace WaveHarmonic.Crest internal static int s_RenderPassOverride = -1; private protected WaveSpectrum _ActiveSpectrum = null; - private protected Vector2 PrimaryWaveDirection => new(Mathf.Cos(Mathf.PI * _WaveDirectionHeadingAngle / 180f), Mathf.Sin(Mathf.PI * _WaveDirectionHeadingAngle / 180f)); + private protected Vector2 PrimaryWaveDirection => new(Mathf.Cos(Mathf.PI * WaveDirectionHeadingAngle / 180f), Mathf.Sin(Mathf.PI * WaveDirectionHeadingAngle / 180f)); /// /// The wind speed in kilometers per hour (KPH). @@ -121,7 +131,7 @@ namespace WaveHarmonic.Crest /// /// Wind speed can come from this component or the . /// - public float WindSpeedKPH => _OverrideGlobalWindSpeed || WaterRenderer.Instance == null ? _WindSpeed : WaterRenderer.Instance.WindSpeedKPH; + public float WindSpeedKPH => _OverrideGlobalWindSpeed || WaterRenderer.Instance == null ? _WindSpeed : WaterRenderer.Instance.WindSpeed; /// /// The wind speed in meters per second (MPS). @@ -301,7 +311,7 @@ namespace WaveHarmonic.Crest // Wave generation done in Draw. Keeps track to limit to once per frame. private protected int _LastGenerateFrameCount = -1; - internal override bool Enabled => _FirstCascade > -1 && WaterRenderer.Instance.Gravity != 0f && Mode switch + internal override bool Enabled => _FirstCascade > -1 && (WaterRenderer.Instance == null || WaterRenderer.Instance.Gravity != 0f) && Mode switch { LodInputMode.Global => enabled && s_TransferWavesComputeShader != null, _ => base.Enabled, @@ -324,7 +334,6 @@ namespace WaveHarmonic.Crest private protected float MaximumReportedVerticalDisplacement { get; set; } private protected float MaximumReportedWavesDisplacement { get; set; } - static int s_InstanceCount = 0; private protected bool UpdateDataEachFrame { @@ -349,7 +358,6 @@ namespace WaveHarmonic.Crest } private protected abstract void ReportMaxDisplacement(WaterRenderer water); - private protected abstract void DestroySharedResources(); private protected override void OnUpdate(WaterRenderer water) { @@ -367,26 +375,6 @@ namespace WaveHarmonic.Crest wrapper.SetFloat(ShaderIDs.s_MaximumAttenuationDepth, water._AnimatedWavesLod.ShallowsMaximumDepth); } - private protected override void Awake() - { - base.Awake(); - s_InstanceCount++; - } - - private protected void OnDestroy() - { - // Since FFTCompute resources are shared we will clear after last ShapeFFT is destroyed. - if (--s_InstanceCount <= 0) - { - DestroySharedResources(); - - if (s_DefaultSpectrum != null) - { - Helpers.Destroy(s_DefaultSpectrum); - } - } - } - private protected override void Initialize() { base.Initialize(); @@ -441,6 +429,11 @@ namespace WaveHarmonic.Crest return false; } + + float GetWaveDirectionHeadingAngle() + { + return _OverrideGlobalWindDirection || WaterRenderer.Instance == null ? _WaveDirectionHeadingAngle : WaterRenderer.Instance.WindDirection; + } } partial class ShapeWaves @@ -455,6 +448,28 @@ namespace WaveHarmonic.Crest } } + partial class ShapeWaves + { + static int s_InstanceCount = 0; + + private protected override void Awake() + { + base.Awake(); + s_InstanceCount++; + } + + private protected virtual void OnDestroy() + { + if (--s_InstanceCount <= 0) + { + if (s_WindSpectrum != null) + { + Helpers.Destroy(s_WindSpectrum); + } + } + } + } + partial class ShapeWaves { [HideInInspector, SerializeField] @@ -486,5 +501,34 @@ namespace WaveHarmonic.Crest return version; } + + private protected int MigrateV2(int version) + { + // Version 2 + // - Global wind direction + if (version < 2) + { + _OverrideGlobalWindDirection = true; + version = 2; + } + + return version; + } } + +#if UNITY_EDITOR + partial class ShapeWaves + { + private protected override void Reset() + { + base.Reset(); + + if (_Mode != LodInputMode.Global) + { + _OverrideGlobalWindSpeed = true; + _OverrideGlobalWindDirection = true; + } + } + } +#endif } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/SphereWaterInteraction.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/SphereWaterInteraction.cs index 290608d36..f12b4f83f 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/SphereWaterInteraction.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/SphereWaterInteraction.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/TextureLodInputData.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/TextureLodInputData.cs index e7238b257..e225608a4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/TextureLodInputData.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/TextureLodInputData.cs @@ -18,6 +18,11 @@ namespace WaveHarmonic.Crest [@DecoratedField, SerializeField] internal Texture _Texture; + [Tooltip("Multiplies the texture sample.\n\nThis is useful for normalized textures. The four components map to the four color/alpha components of the texture (if they exist).\n\nIf you just want to fade out the input, consider using weight instead.")] + [@GenerateAPI] + [@DecoratedField, SerializeField] + Vector4 _Multiplier = Vector4.one; + private protected abstract ComputeShader TextureShader { get; } internal override bool IsEnabled => _Texture != null; internal override bool HasHeightRange => false; @@ -41,6 +46,7 @@ namespace WaveHarmonic.Crest wrapper.SetVector(ShaderIDs.s_TexturePosition, transform.position.XZ()); wrapper.SetVector(ShaderIDs.s_TextureRotation, rotation); wrapper.SetVector(ShaderIDs.s_Resolution, new(_Texture.width, _Texture.height)); + wrapper.SetVector(ShaderIDs.s_Multiplier, _Multiplier); wrapper.SetFloat(ShaderIDs.s_FeatherWidth, _Input.FeatherWidth); wrapper.SetTexture(ShaderIDs.s_Texture, _Texture); wrapper.SetInteger(ShaderIDs.s_Blend, (int)_Input.Blend); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/WatertightHull.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/WatertightHull.cs index 350568d83..422103176 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/WatertightHull.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Input/WatertightHull.cs @@ -13,17 +13,14 @@ namespace WaveHarmonic.Crest /// /// Each mode has its strengths and weaknesses. /// + [@GenerateDoc] public enum WatertightHullMode { - /// - /// Uses to remove water. - /// + /// [Tooltip("Use displacement to remove water.\n\nUsing displacement will also affect the underwater and can nest bouyant objects. Requires the displacement layer to be enabled.")] Displacement, - /// - /// Uses to remove water. - /// + /// [Tooltip("Clips the surface to remove water.\n\nThis option is more precise and can be submerged.")] Clip, } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/LevelLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/LevelLod.cs index f90e4967d..80ef07eb6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/LevelLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/LevelLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // We do not add height to displacement directly for better precision and layering. @@ -21,7 +21,6 @@ namespace WaveHarmonic.Crest internal override Color GizmoColor => s_GizmoColor; private protected override Color ClearColor => Color.black; private protected override bool NeedToReadWriteTextureData => true; - internal override bool RunsInHeadless => true; private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Lod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Lod.cs index 323028631..6608109ec 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Lod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Lod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -18,32 +18,23 @@ namespace WaveHarmonic.Crest /// /// Texture format preset. /// + [@GenerateDoc] public enum LodTextureFormatMode { - /// - /// Uses . - /// + /// + [Tooltip("Uses the Texture Format property.")] Manual, - /// - /// Chooses a texture format for performance. - /// + /// + [Tooltip("Chooses a texture format for performance.")] Performance = 100, - /// - /// Chooses a texture format for precision. - /// - /// - /// This format can reduce artifacts. - /// + /// + [Tooltip("Chooses a texture format for precision.\n\nThis format can reduce artifacts.")] Precision = 200, - /// - /// Chooses a texture format based on another. - /// - /// - /// For example, Dynamic Waves will match precision of Animated Waves. - /// + /// + [Tooltip("Chooses a texture format based on another.\n\nFor example, Dynamic Waves will match precision of Animated Waves.")] Automatic = 300, } @@ -61,11 +52,13 @@ namespace WaveHarmonic.Crest [Tooltip("Whether to override the resolution.\n\nIf not enabled, then the simulation will use the resolution defined on the Water Renderer.")] [@Predicated(typeof(AnimatedWavesLod), inverted: true, hide: true)] [@GenerateAPI(Setter.Dirty)] - [@DecoratedField, SerializeField] + [@InlineToggle(fix: true), SerializeField] internal bool _OverrideResolution = true; [Tooltip("The resolution of the simulation data.\n\nSet higher for sharper results at the cost of higher memory usage.")] [@Predicated(typeof(AnimatedWavesLod), inverted: true, hide: true)] + [@Predicated(nameof(_OverrideResolution), hide: true)] + [@ShowComputedProperty(nameof(Resolution))] [@Delayed] [@GenerateAPI(Getter.Custom, Setter.Dirty)] [SerializeField] @@ -151,8 +144,6 @@ namespace WaveHarmonic.Crest // Always use linear filtering. GraphicsFormatUsage.Linear; - internal virtual bool RunsInHeadless => false; - private protected BufferedData _Targets; internal RenderTexture DataTexture => _Targets.Current; internal RenderTexture GetDataTexture(int frameDelta) => _Targets.Previous(frameDelta); @@ -218,8 +209,14 @@ namespace WaveHarmonic.Crest ReAllocate(); } - _Targets.Flip(); - _SamplingParameters.Flip(); +#if UNITY_EDITOR + // Fixes flickering in frame debugger when navigating draw calls. + if (!UnityEditor.EditorApplication.isPaused || Time.deltaTime > 0) +#endif + { + _Targets.Flip(); + _SamplingParameters.Flip(); + } UpdateSamplingParameters(); } @@ -245,12 +242,11 @@ namespace WaveHarmonic.Crest { FlipBuffers(); - buffer.BeginSample(Name); + buffer.BeginSample(ID); if (_TargetsToClear > 0 || AlwaysClear) { - buffer.SetRenderTarget(DataTexture, 0, CubemapFace.Unknown, -1); - buffer.ClearRenderTarget(RTClearFlags.Color, ClearColor, 0, 0); + CoreUtils.SetRenderTarget(buffer, DataTexture, ClearFlag.Color, ClearColor); _TargetsToClear--; } @@ -270,7 +266,7 @@ namespace WaveHarmonic.Crest Queryable?.UpdateQueries(_Water); - buffer.EndSample(Name); + buffer.EndSample(ID); } private protected bool SubmitDraws(CommandBuffer buffer, Inputs draws, RenderTargetIdentifier target, int pass = -1, bool filter = false) @@ -323,8 +319,8 @@ namespace WaveHarmonic.Crest // Parameters override RTI values: // https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.SetRenderTarget.html - buffer.SetRenderTarget(target, 0, CubemapFace.Unknown, slice); - buffer.SetGlobalInt(ShaderIDs.s_LodIndex, slice); + CoreUtils.SetRenderTarget(buffer, target, depthSlice: slice); + buffer.SetGlobalInteger(ShaderIDs.s_LodIndex, slice); // This will work for CG but not for HDRP hlsl files. buffer.SetViewProjectionMatrices(_ViewMatrices[slice], _Water.GetProjectionMatrix(slice)); @@ -373,24 +369,35 @@ namespace WaveHarmonic.Crest wrapper.Dispatch(1, size, 1); } - void UpdateSamplingParameters() + void UpdateSamplingParameters(bool initialize = false) { - for (var slice = 0; slice < Slices; slice++) + var position = _Water.Position; + var resolution = _Enabled ? Resolution : TextureArrayHelpers.k_SmallTextureSize; + + var parameters = _SamplingParameters.Current; + var levels = Slices; + + for (var slice = 0; slice < levels; slice++) { // Find snap period. - var texel = 2f * 2f * _Water.CalcLodScale(slice) / Resolution; + var texel = 2f * 2f * _Water._CascadeData.Current[slice].x / resolution; // Snap so that shape texels are stationary. - var snapped = _Water.Root.position - new Vector3(Mathf.Repeat(_Water.Root.position.x, texel), 0, Mathf.Repeat(_Water.Root.position.z, texel)); + var snapped = position - new Vector3(Mathf.Repeat(position.x, texel), 0, Mathf.Repeat(position.z, texel)); - var cascade = new Cascade(snapped.XZ(), texel, Resolution); + var cascade = new Cascade(snapped.XZ(), texel, resolution); _Cascades[slice] = cascade; - _SamplingParameters.Current[slice] = cascade.Packed; + parameters[slice] = cascade.Packed; + if (initialize && BufferCount > 1) _SamplingParameters.Previous(1)[slice] = cascade.Packed; _ViewMatrices[slice] = WaterRenderer.CalculateViewMatrixFromSnappedPositionRHS(snapped); } - Shader.SetGlobalVector(_SamplingParametersShaderID, new(_Water.LodLevels, Resolution, 1f / Resolution, 0)); - Shader.SetGlobalVectorArray(_SamplingParametersCascadeShaderID, _SamplingParameters.Current); + if (initialize) + { + Shader.SetGlobalVector(_SamplingParametersShaderID, new(levels, resolution, 1f / resolution, 0)); + } + + Shader.SetGlobalVectorArray(_SamplingParametersCascadeShaderID, parameters); if (BufferCount > 1) { @@ -490,13 +497,6 @@ namespace WaveHarmonic.Crest return; } - // Some simulations are pointless in non-interactive mode. - if (_Water.IsRunningHeadless && !RunsInHeadless) - { - _Valid = false; - return; - } - // Validate textures. { // Find a compatible texture format. @@ -522,6 +522,21 @@ namespace WaveHarmonic.Crest if (_Water.IsRunningWithoutGraphics) return; // Bind/unbind data texture for all shaders. Shader.SetGlobalTexture(_TextureShaderID, enable && Enabled ? DataTexture : NullTexture); + + if (BufferCount > 1) + { + Shader.SetGlobalTexture(_TextureSourceShaderID, enable && Enabled ? GetDataTexture(1) : NullTexture); + } + + if (_SamplingParameters == null || _SamplingParameters.Size != BufferCount) + { + _SamplingParameters = new(BufferCount, () => new Vector4[k_MaximumSlices]); + } + + // For safety. Disable to see if we are sampling outside of LOD chain. + _SamplingParameters.RunLambda(x => System.Array.Fill(x, Vector4.zero)); + + UpdateSamplingParameters(initialize: true); } internal virtual void Enable() @@ -545,13 +560,16 @@ namespace WaveHarmonic.Crest }); } + internal virtual void AfterExecute() + { + + } + private protected virtual void Allocate() { _Targets = new(BufferCount, CreateLodDataTextures); _Targets.RunLambda(Clear); - _SamplingParameters = new(BufferCount, () => new Vector4[k_MaximumSlices]); - // Bind globally once here on init, which will bind to all graphics shaders (not compute) Shader.SetGlobalTexture(_TextureShaderID, DataTexture); @@ -580,7 +598,7 @@ namespace WaveHarmonic.Crest SetGlobals(current); } - int GetResolution() => _OverrideResolution ? _Resolution : Water.LodResolution; + int GetResolution() => _OverrideResolution || Water == null ? _Resolution : Water.LodResolution; private protected void ReAllocate() { @@ -597,6 +615,8 @@ namespace WaveHarmonic.Crest }); _ReAllocateTexture = false; + + UpdateSamplingParameters(initialize: true); } #if UNITY_EDITOR @@ -641,6 +661,7 @@ namespace WaveHarmonic.Crest /// Base type for simulations with a provider. /// /// The query provider. + [System.Serializable] public abstract class Lod : Lod where T : IQueryProvider { /// @@ -662,5 +683,10 @@ namespace WaveHarmonic.Crest // None providers are not IQueryable. Queryable = Provider as IQueryable; } + + internal override void AfterExecute() + { + Queryable?.SendReadBack(_Water); + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/PersistentLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/PersistentLod.cs index a9765c356..74b1083fc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/PersistentLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/PersistentLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -9,6 +9,7 @@ namespace WaveHarmonic.Crest /// /// A persistent simulation that moves around with a displacement LOD. /// + [System.Serializable] public abstract partial class PersistentLod : Lod { [Tooltip("Frequency to run the simulation, in updates per second.\n\nLower frequencies are more efficient but may lead to visible jitter or slowness.")] @@ -37,6 +38,8 @@ namespace WaveHarmonic.Crest internal int LastUpdateSubstepCount { get; private set; } + private protected virtual int Kernel => 0; + private protected virtual bool SkipFlipBuffers => false; private protected abstract ComputeShader SimulationShader { get; } private protected abstract void GetSubstepData(float timeToSimulate, out int substeps, out float delta); @@ -61,9 +64,12 @@ namespace WaveHarmonic.Crest internal override void BuildCommandBuffer(WaterRenderer water, CommandBuffer buffer) { - buffer.BeginSample(Name); + buffer.BeginSample(ID); - FlipBuffers(); + if (!SkipFlipBuffers) + { + FlipBuffers(); + } var slices = water.LodLevels; @@ -91,19 +97,19 @@ namespace WaveHarmonic.Crest // artifacts if not and there is a renderer input. Happens for foam and dynamic // waves. Confusing/concerning. buffer.GetTemporaryRT(ShaderIDs.s_TemporaryPersistentTarget, DataTexture.descriptor); - buffer.SetRenderTarget(ShaderIDs.s_TemporaryPersistentTarget, 0, CubemapFace.Unknown, -1); - buffer.ClearRenderTarget(RTClearFlags.Color, ClearColor, 0, 0); + CoreUtils.SetRenderTarget(buffer, ShaderIDs.s_TemporaryPersistentTarget, ClearFlag.Color, ClearColor); } var target = new RenderTargetIdentifier(DataTexture); var source = new RenderTargetIdentifier(ShaderIDs.s_TemporaryPersistentTarget); var current = target; + var wrapper = new PropertyWrapperCompute(buffer, SimulationShader, Kernel); + for (var substep = 0; substep < substeps; substep++) { var isFirstStep = substep == 0; var frame = isFirstStep ? 1 : 0; - var wrapper = new PropertyWrapperCompute(buffer, SimulationShader, 0); // Record how much we caught up _TimeToSimulate -= delta; @@ -168,14 +174,15 @@ namespace WaveHarmonic.Crest // Set the target texture as to make sure we catch the 'pong' each frame. Shader.SetGlobalTexture(_TextureShaderID, DataTexture); - buffer.EndSample(Name); + buffer.EndSample(ID); } /// /// Set any simulation specific shader parameters. /// - private protected virtual void SetAdditionalSimulationParameters(T properties) where T : IPropertyWrapper + private protected virtual void SetAdditionalSimulationParameters(PropertyWrapperCompute properties) { + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionAreaVisualizer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionAreaVisualizer.cs index dfd3b922c..227542e12 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionAreaVisualizer.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionAreaVisualizer.cs @@ -1,8 +1,9 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; using WaveHarmonic.Crest.Internal; +using WaveHarmonic.Crest.Utility; namespace WaveHarmonic.Crest { @@ -84,60 +85,46 @@ namespace WaveHarmonic.Crest } } - if (_UseDisplacements) + var success = _UseDisplacements + ? collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _ObjectWidth, _SamplePositions, _ResultDisplacements, _UseNormals ? _ResultNormals : null, null, _Layer)) + : collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _ObjectWidth, _SamplePositions, _ResultHeights, _UseNormals ? _ResultNormals : null, null, _Layer)); + +#if !UNITY_EDITOR + // Gizmos handle this in editor. + if (success) { - if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _ObjectWidth, _SamplePositions, _ResultDisplacements, _UseNormals ? _ResultNormals : null, null, _Layer))) - { - for (var i = 0; i < _Steps; i++) - { - for (var j = 0; j < _Steps; j++) - { - var result = _SamplePositions[j * _Steps + i]; - result.y = water.SeaLevel; - result += _ResultDisplacements[j * _Steps + i]; - - var norm = _UseNormals ? _ResultNormals[j * _Steps + i] : Vector3.up; - - DebugDrawCross(result, norm, Mathf.Min(_StepSize / 4f, 1f), Color.green); - } - } - } - } - else - { - if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _ObjectWidth, _SamplePositions, _ResultHeights, _UseNormals ? _ResultNormals : null, null, _Layer))) - { - for (var i = 0; i < _Steps; i++) - { - for (var j = 0; j < _Steps; j++) - { - var result = _SamplePositions[j * _Steps + i]; - result.y = _ResultHeights[j * _Steps + i]; - - var norm = _UseNormals ? _ResultNormals[j * _Steps + i] : Vector3.up; - - DebugDrawCross(result, norm, Mathf.Min(_StepSize / 4f, 1f), Color.green); - } - } - } + Render(water, Debug.DrawLine); } +#endif } - public static void DebugDrawCross(Vector3 pos, float r, Color col, float duration = 0f) + internal void Render(WaterRenderer water, DebugUtility.DrawLine draw) { - Debug.DrawLine(pos - Vector3.up * r, pos + Vector3.up * r, col, duration); - Debug.DrawLine(pos - Vector3.right * r, pos + Vector3.right * r, col, duration); - Debug.DrawLine(pos - Vector3.forward * r, pos + Vector3.forward * r, col, duration); - } + if (_SamplePositions == null) + { + return; + } - public static void DebugDrawCross(Vector3 pos, Vector3 up, float r, Color col, float duration = 0f) - { - up.Normalize(); - var right = Vector3.Normalize(Vector3.Cross(up, Vector3.forward)); - var forward = Vector3.Cross(up, right); - Debug.DrawLine(pos - up * r, pos + up * r, col, duration); - Debug.DrawLine(pos - right * r, pos + right * r, col, duration); - Debug.DrawLine(pos - forward * r, pos + forward * r, col, duration); + for (var i = 0; i < _Steps; i++) + { + for (var j = 0; j < _Steps; j++) + { + var result = _SamplePositions[j * _Steps + i]; + + if (_UseDisplacements) + { + result.y = water.SeaLevel; + result += _ResultDisplacements[j * _Steps + i]; + } + else + { + result.y = _ResultHeights[j * _Steps + i]; + } + + var normal = _UseNormals ? _ResultNormals[j * _Steps + i] : Vector3.up; + DebugUtility.DrawCross(draw, result, normal, Mathf.Min(_StepSize / 4f, 1f), Color.green); + } + } } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionProvider.cs index 2bc43cc94..e5ba95825 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // NOTE: DWP2 depends on this file. Any API changes need to be communicated to the DWP2 authors in advance. @@ -13,23 +13,18 @@ namespace WaveHarmonic.Crest /// /// A layer/event where queries are executed. /// + [@GenerateDoc] public enum CollisionLayer { - /// - /// Include all displacement. - /// + /// [Tooltip("Include all displacement.")] Everything, - /// - /// Only include Animated Waves. - /// + /// [Tooltip("Only include Animated Waves.")] AfterAnimatedWaves, - /// - /// Include Animated Waves and Dynamic Waves. - /// + /// [Tooltip("Include Animated Waves and Dynamic Waves.")] AfterDynamicWaves, } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionQuery.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionQuery.cs index 5bddbf916..d8f4dfa6d 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionQuery.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/CollisionQuery.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -82,27 +82,28 @@ namespace WaveHarmonic.Crest { var layers = _Water.AnimatedWavesLod._CollisionLayers; + // Displacement is the fallback if there are no layers (ie single layer). if (layers == CollisionLayers.Nothing) { return _Displacement; } - if (layer == CollisionLayer.Everything) + var everything = layer == CollisionLayer.Everything; + + // Displacement is the final layer, if present. + if (everything && layers.HasFlag(CollisionLayers.Displacement)) { - if (layers.HasFlag(CollisionLayers.Displacement)) - { - return _Displacement; - } + return _Displacement; } - if (layer >= CollisionLayer.AfterDynamicWaves) + // Chosen/fallback to Dynamic Waves. + if ((everything || layer >= CollisionLayer.AfterDynamicWaves) && + layers.HasFlag(CollisionLayers.DynamicWaves) && _Water.DynamicWavesLod.Enabled) { - if (layers.HasFlag(CollisionLayers.DynamicWaves) && _Water.DynamicWavesLod.Enabled) - { - return _DynamicWaves; - } + return _DynamicWaves; } + // If not single layer, this is always present. return _AnimatedWaves; } @@ -131,6 +132,19 @@ namespace WaveHarmonic.Crest _Displacement.UpdateQueries(water); } + public void SendReadBack(WaterRenderer water, CollisionLayers layers) + { + // Will only submit readback if there are queries. + _AnimatedWaves.SendReadBack(water); + _DynamicWaves.SendReadBack(water); + _Displacement.SendReadBack(water); + } + + public void SendReadBack(WaterRenderer water) + { + _Displacement.SendReadBack(water); + } + public void CleanUp() { _AnimatedWaves.CleanUp(); @@ -143,6 +157,7 @@ namespace WaveHarmonic.Crest { public static void UpdateQueries(this ICollisionProvider self, WaterRenderer water, CollisionLayer layer) => (self as CollisionQueryWithPasses)?.UpdateQueries(water, layer); public static void UpdateQueries(this ICollisionProvider self, WaterRenderer water) => (self as IQueryable)?.UpdateQueries(water); + public static void SendReadBack(this ICollisionProvider self, WaterRenderer water, CollisionLayers layer) => (self as CollisionQueryWithPasses)?.SendReadBack(water, layer); public static void CleanUp(this ICollisionProvider self) => (self as IQueryable)?.CleanUp(); } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceHelper.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceHelper.cs index db8ace44f..28b23f318 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceHelper.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceHelper.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceVisualizer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceVisualizer.cs index 629bc1023..aacb94177 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceVisualizer.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Collision/RayTraceVisualizer.cs @@ -1,8 +1,9 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; using WaveHarmonic.Crest.Internal; +using WaveHarmonic.Crest.Utility; namespace WaveHarmonic.Crest { @@ -33,7 +34,7 @@ namespace WaveHarmonic.Crest { var endPos = transform.position + transform.forward * dist; Debug.DrawLine(transform.position, endPos, Color.green); - CollisionAreaVisualizer.DebugDrawCross(endPos, 2f, Color.green, 0f); + DebugUtility.DrawCross(Debug.DrawLine, endPos, 2f, Color.green, 0f); } else { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthProvider.cs index 9df5c3458..acaa35535 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthQuery.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthQuery.cs index 7f62dbae1..aaf71d6c1 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthQuery.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Depth/DepthQuery.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowProvider.cs index 7a23be980..ac3e4df91 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowQuery.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowQuery.cs index 67a95b7bf..36ffacebd 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowQuery.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Flow/FlowQuery.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. namespace WaveHarmonic.Crest diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Query.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Query.cs index 618abda01..f2f85bead 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Query.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/Query.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Potential improvements @@ -43,6 +43,7 @@ namespace WaveHarmonic.Crest int RequestCount { get; } int QueryCount { get; } void UpdateQueries(WaterRenderer water); + void SendReadBack(WaterRenderer water); void CleanUp(); } @@ -512,7 +513,20 @@ namespace WaveHarmonic.Crest if (_SegmentRegistrarRingBuffer.Current._QueryCount > 0) { ExecuteQueries(); + } + } + public void SendReadBack(WaterRenderer water) + { +#if UNITY_EDITOR + // Seems to be a terrible memory leak coming from creating async GPU readbacks. + // This was marked as resolved by Unity and confirmed fixed by forum posts. + // May be worth keeping. See issue #630 for more details. + if (!water._HeightQueries && !Application.isPlaying) return; +#endif + + if (_SegmentRegistrarRingBuffer.Current._QueryCount > 0) + { // Remove oldest requests if we have hit the limit while (_Requests.Count >= k_MaximumRequests) { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/QueryEvents.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/QueryEvents.cs index b05134751..504b3e154 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/QueryEvents.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/QueryEvents.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -10,19 +10,15 @@ namespace WaveHarmonic.Crest /// /// What transform to use for queries. /// + [@GenerateDoc] public enum QuerySource { - /// - /// This game object's transform. - /// + /// + [Tooltip("This game object's transform.")] Transform, - /// - /// The viewer's transform. - /// - /// - /// The viewer is the main camera the system uses. - /// + /// + [Tooltip("The viewer's transform.\n\nThe viewer is the main camera the system uses.")] Viewer } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/SamplingHelpers.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/SamplingHelpers.cs index bc1930725..efff75dd7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/SamplingHelpers.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Query/SamplingHelpers.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -226,7 +226,7 @@ namespace WaveHarmonic.Crest public bool Sample(Vector3 position, out Vector2 flow, float minimumLength = 0f) { var water = WaterRenderer.Instance; - var flowProvider = WaterRenderer.Instance == null ? null : water.FlowLod.Provider; + var flowProvider = water == null ? null : water.FlowLod.Provider; if (flowProvider == null) { @@ -262,7 +262,7 @@ namespace WaveHarmonic.Crest bool Sample(Vector3 position, out Vector2 result) { var water = WaterRenderer.Instance; - var depthProvider = WaterRenderer.Instance == null ? null : water.DepthLod.Provider; + var depthProvider = water == null ? null : water.DepthLod.Provider; if (depthProvider == null) { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsHDRP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsHDRP.cs index 361e5e395..ca0e427d3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsHDRP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsHDRP.cs @@ -1,10 +1,8 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityHDRP -using UnityEditor; -using UnityEngine; using UnityEngine.Rendering.HighDefinition; namespace WaveHarmonic.Crest @@ -14,36 +12,20 @@ namespace WaveHarmonic.Crest static SampleShadowsHDRP s_Instance; static readonly string s_Name = "Sample Shadows"; - // These values come from unity_MatrxVP value in the frame debugger. unity_MatrxVP is marked as legacy and - // breaks XR SPI. It is defined in: - // "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/EditorShaderVariables.hlsl" - static readonly Matrix4x4 s_Matrix = new - ( - new(2f, 0f, 0f, 0f), - new(0f, -2f, 0f, 0f), - new(0f, 0f, 0.00990099f, 0f), - new(-1f, 1f, 0.990099f, 1f) - ); - - static class ShaderIDs - { - public static readonly int s_ViewProjectionMatrix = Shader.PropertyToID("_Crest_ViewProjectionMatrix"); - } - - GameObject _GameObject; + WaterRenderer _Water; int _XrTargetEyeIndex = -1; protected override void Execute(CustomPassContext context) { - var water = WaterRenderer.Instance; + var water = _Water; - if (water == null || !water._ShadowLod.Enabled) + if (!water._ShadowLod.Enabled) { return; } #if UNITY_EDITOR - if (!WaterRenderer.IsWithinEditorUpdate || EditorApplication.isPaused) + if (!WaterRenderer.IsWithinEditorUpdate) { return; } @@ -58,36 +40,19 @@ namespace WaveHarmonic.Crest camera.TryGetComponent(out var cameraData); - if (cameraData != null && cameraData.xrRendering) + // Skip the right eye for multi-pass as data is not stereo. + if (Rendering.HDRP.SkipPassXR(ref _XrTargetEyeIndex, cameraData)) { - XRHelpers.UpdatePassIndex(ref _XrTargetEyeIndex); - - // Skip the right eye as data is not stereo. - if (_XrTargetEyeIndex == 1) - { - return; - } + return; } // Disable for XR SPI otherwise input will not have correct world position. - if (cameraData != null && cameraData.xrRendering && XRHelpers.IsSinglePass) - { - context.cmd.DisableShaderKeyword("STEREO_INSTANCING_ON"); - } + Rendering.HDRP.DisableXR(context.cmd, cameraData); - // We cannot seem to override this matrix so a reference manually. - context.cmd.SetGlobalMatrix(ShaderIDs.s_ViewProjectionMatrix, s_Matrix); water._ShadowLod.BuildCommandBuffer(water, context.cmd); - // Restore matrices otherwise remaining render will have incorrect matrices. Each pass is responsible for - // restoring matrices if required. - context.cmd.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix); - // Restore XR SPI as we cannot rely on remaining pipeline to do it for us. - if (cameraData != null && cameraData.xrRendering && XRHelpers.IsSinglePass) - { - context.cmd.EnableShaderKeyword("STEREO_INSTANCING_ON"); - } + Rendering.HDRP.EnableXR(context.cmd, cameraData); } internal static void Enable(WaterRenderer water) @@ -103,11 +68,12 @@ namespace WaveHarmonic.Crest ( gameObject, ref s_Instance, - s_Name, - CustomPassInjectionPoint.BeforeTransparent + WaterRenderer.k_DrawLodData, + // Earliest point after shadow maps have populated. + CustomPassInjectionPoint.AfterOpaqueAndSky ); - s_Instance._GameObject = gameObject; + s_Instance._Water = water; } internal static void Disable() diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.RenderGraph.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.RenderGraph.cs index b3cfeb8db..de8c6757e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.RenderGraph.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.RenderGraph.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityURP @@ -32,7 +32,7 @@ namespace WaveHarmonic.Crest public override void RecordRenderGraph(RenderGraph graph, ContextContainer frame) { - using (var builder = graph.AddUnsafePass(k_Name, out var data)) + using (var builder = graph.AddUnsafePass(WaterRenderer.k_DrawLodData, out var data)) { data.Init(frame, builder); builder.AllowPassCulling(false); @@ -49,7 +49,7 @@ namespace WaveHarmonic.Crest public override void Execute(ScriptableRenderContext context, ref RenderingData data) { _PassData.Init(data.GetFrameData()); - var buffer = CommandBufferPool.Get(k_Name); + var buffer = CommandBufferPool.Get(WaterRenderer.k_DrawLodData); Execute(context, buffer, _PassData); context.ExecuteCommandBuffer(buffer); CommandBufferPool.Release(buffer); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.cs index aaa8a0f33..7bae8db40 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/SampleShadowsURP.cs @@ -1,9 +1,8 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityURP -using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; @@ -12,55 +11,38 @@ namespace WaveHarmonic.Crest { sealed partial class SampleShadowsURP : ScriptableRenderPass { - const string k_Name = "Crest Shadow Data"; - static SampleShadowsURP s_Instance; internal static bool Created => s_Instance != null; + WaterRenderer _Water; + SampleShadowsURP(RenderPassEvent renderPassEvent) { this.renderPassEvent = renderPassEvent; } - internal static void Enable() + internal static void Enable(WaterRenderer water) { - s_Instance ??= new(RenderPassEvent.AfterRenderingSkybox); - - RenderPipelineManager.beginCameraRendering -= EnqueuePass; - RenderPipelineManager.beginCameraRendering += EnqueuePass; - - RenderPipelineManager.activeRenderPipelineTypeChanged -= s_Instance.OnActiveRenderPipelineTypeChanged; - RenderPipelineManager.activeRenderPipelineTypeChanged += s_Instance.OnActiveRenderPipelineTypeChanged; + s_Instance ??= new(RenderPassEvent.AfterRenderingShadows); + s_Instance._Water = water; } - internal static void Disable() + internal static void EnqueuePass(ScriptableRenderContext context, Camera camera) { - // TODO: Currently on RP change this method can be called with Enable ever being called leading to null - // exceptions. It can be removed once those problems are sorted. - if (s_Instance != null) + if (s_Instance == null) { - RenderPipelineManager.activeRenderPipelineTypeChanged -= s_Instance.OnActiveRenderPipelineTypeChanged; + return; } - RenderPipelineManager.beginCameraRendering -= EnqueuePass; - } + var water = s_Instance._Water; - void OnActiveRenderPipelineTypeChanged() - { - Disable(); - } - - static void EnqueuePass(ScriptableRenderContext context, Camera camera) - { - var water = WaterRenderer.Instance; - - if (water == null || !water._ShadowLod.Enabled) + if (!water._ShadowLod.Enabled) { return; } #if UNITY_EDITOR - if (!WaterRenderer.IsWithinEditorUpdate || EditorApplication.isPaused) + if (!WaterRenderer.IsWithinEditorUpdate) { return; } @@ -84,7 +66,7 @@ namespace WaveHarmonic.Crest public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) #endif { - var water = WaterRenderer.Instance; + var water = _Water; if (water == null || !water._ShadowLod.Enabled) { @@ -103,30 +85,16 @@ namespace WaveHarmonic.Crest var camera = renderingData.cameraData.camera; #if !UNITY_6000_0_OR_NEWER - var buffer = CommandBufferPool.Get(k_Name); + var buffer = CommandBufferPool.Get(WaterRenderer.k_DrawLodData); #endif - // We need to check the mask or it will cause entire pipeline to output black. Appears to only affect URP. - var isStereoRendering = renderingData.cameraData.xrRendering && XRHelpers.IsSinglePass && - camera.stereoTargetEye == StereoTargetEyeMask.Both; - // Disable for XR SPI otherwise input will not have correct world position. - if (isStereoRendering) - { - buffer.DisableShaderKeyword("STEREO_INSTANCING_ON"); - } + Rendering.URP.DisableXR(buffer, renderingData.cameraData); water._ShadowLod.BuildCommandBuffer(water, buffer); - // Restore matrices otherwise remaining render will have incorrect matrices. Each pass is responsible for - // restoring matrices if required. - buffer.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix); - // Restore XR SPI as we cannot rely on remaining pipeline to do it for us. - if (isStereoRendering) - { - buffer.EnableShaderKeyword("STEREO_INSTANCING_ON"); - } + Rendering.URP.EnableXR(buffer, renderingData.cameraData); #if !UNITY_6000_0_OR_NEWER context.ExecuteCommandBuffer(buffer); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ScatteringLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ScatteringLod.cs index 264e15d68..8a30e9bc7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ScatteringLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ScatteringLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -32,10 +32,11 @@ namespace WaveHarmonic.Crest get { var color = Color.clear; + var surface = _Water.Surface; - if (_Water.Material != null) + if (surface.Material != null && surface.Material.HasColor(WaterRenderer.ShaderIDs.s_Scattering)) { - color = _Water.Material.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear(); + color = surface.Material.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear(); color.a = 0f; } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/DynamicWavesLodSettings.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/DynamicWavesLodSettings.cs index 3232c99d5..b070873cc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/DynamicWavesLodSettings.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/DynamicWavesLodSettings.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/FoamLodSettings.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/FoamLodSettings.cs index a16908872..28a86537c 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/FoamLodSettings.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/FoamLodSettings.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/LodSettings.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/LodSettings.cs index c1b9bbed7..1087bf9fd 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/LodSettings.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/Settings/LodSettings.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs new file mode 100644 index 000000000..ecab8beec --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs @@ -0,0 +1,119 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + partial class ShadowLod + { + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + // TODO: refactor this similar to MaskRenderer. + if (!RenderPipelineHelper.IsLegacy) + { +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + SampleShadowsURP.EnqueuePass(context, camera); + } +#endif + + return; + } + +#if UNITY_EDITOR + // Do not execute when editor is not active to conserve power and prevent possible leaks. + if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) + { + CopyShadowMapBuffer?.Clear(); + return; + } + + if (!WaterRenderer.IsWithinEditorUpdate) + { + CopyShadowMapBuffer?.Clear(); + return; + } +#endif + + var water = _Water; + + if (water == null) + { + return; + } + + if (!WaterRenderer.ShouldRender(camera, water.Surface.Layer)) + { + return; + } + + if (camera == water.Viewer && CopyShadowMapBuffer != null) + { + if (_Light != null) + { + // Calling this in OnPreRender was too late to be executed in the same frame. + _Light.RemoveCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); + _Light.AddCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); + } + + // Disable for XR SPI otherwise input will not have correct world position. + Rendering.BIRP.DisableXR(CopyShadowMapBuffer, camera); + + BuildCommandBuffer(water, CopyShadowMapBuffer); + + // Restore XR SPI as we cannot rely on remaining pipeline to do it for us. + Rendering.BIRP.EnableXR(CopyShadowMapBuffer, camera); + } + } + + internal void OnEndCameraRendering(Camera camera) + { + if (!RenderPipelineHelper.IsLegacy) + { + return; + } + +#if UNITY_EDITOR + // Do not execute when editor is not active to conserve power and prevent possible leaks. + if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) + { + CopyShadowMapBuffer?.Clear(); + return; + } + + if (!WaterRenderer.IsWithinEditorUpdate) + { + CopyShadowMapBuffer?.Clear(); + return; + } +#endif + + var water = _Water; + + if (water == null) + { + return; + } + + if (!WaterRenderer.ShouldRender(camera, water.Surface.Layer)) + { + return; + } + + if (camera == water.Viewer) + { + // CBs added to a light are executed for every camera, but the LOD data is only + // supports a single camera. Removing the CB after the camera renders restricts the + // CB to one camera. Careful of recursive rendering for planar reflections, as it + // executes a camera within this camera's frame. + if (_Light != null && CopyShadowMapBuffer != null) + { + _Light.RemoveCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); + } + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs.meta new file mode 100644 index 000000000..51cbf5262 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.Legacy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a4edb90370784ae2be24a7f430ee23e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.cs index 10e1b528d..71e0a1ffb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Data/ShadowLod.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // BIRP fallback not really tested yet - shaders need fixing up. @@ -20,7 +20,7 @@ namespace WaveHarmonic.Crest /// sampling for (very) soft shadows. Soft shadows is red, hard shadows is green. /// [FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)] - public sealed partial class ShadowLod : Lod + public sealed partial class ShadowLod : PersistentLod { [@Space(10)] @@ -77,13 +77,14 @@ namespace WaveHarmonic.Crest public static readonly int s_Scale = Shader.PropertyToID("_Crest_Scale"); public static readonly int s_JitterDiameters_CurrentFrameWeights = Shader.PropertyToID("_Crest_JitterDiameters_CurrentFrameWeights"); public static readonly int s_MainCameraProjectionMatrix = Shader.PropertyToID("_Crest_MainCameraProjectionMatrix"); - public static readonly int s_SimDeltaTime = Shader.PropertyToID("_Crest_SimDeltaTime"); // BIRP only. - public static readonly int s_ShadowCastersPresent = Shader.PropertyToID("_Crest_ShadowCastersPresent"); + public static readonly int s_ShadowPassExecuteLastFrame = Shader.PropertyToID("_Crest_ShadowPassExecuteLastFrame"); public static readonly int s_ClearShadows = Shader.PropertyToID("_Crest_ClearShadows"); } + const string k_DrawLodSample = "Sample"; + const float k_MaximumJitter = 32f; internal static readonly Color s_GizmoColor = new(0f, 0f, 0f, 0.5f); @@ -120,6 +121,13 @@ namespace WaveHarmonic.Crest Error _Error; + private protected override int Kernel => (int)RenderPipelineHelper.RenderPipeline; + private protected override bool SkipFlipBuffers => true; + private protected override ComputeShader SimulationShader => WaterResources.Instance.Compute._UpdateShadow; + + bool _IsSimulationBuffer; + + internal override void Initialize() { if (WaterResources.Instance.Shaders._UpdateShadow == null) @@ -178,7 +186,7 @@ namespace WaveHarmonic.Crest if (RenderPipelineHelper.IsLegacy) { - Helpers.SetGlobalBoolean(ShaderIDs.s_ShadowCastersPresent, true); + Helpers.SetGlobalBoolean(ShaderIDs.s_ShadowPassExecuteLastFrame, true); } } @@ -186,14 +194,6 @@ namespace WaveHarmonic.Crest { base.Enable(); - if (RenderPipelineHelper.IsLegacy) - { - Camera.onPreCull -= OnPreCullCamera; - Camera.onPreCull += OnPreCullCamera; - Camera.onPostRender -= OnPostRenderCamera; - Camera.onPostRender += OnPostRenderCamera; - } - CleanUpShadowCommandBuffers(); if (RenderPipelineHelper.IsHighDefinition) @@ -205,7 +205,7 @@ namespace WaveHarmonic.Crest else if (RenderPipelineHelper.IsUniversal) { #if d_UnityURP - SampleShadowsURP.Enable(); + SampleShadowsURP.Enable(_Water); #endif } } @@ -217,16 +217,9 @@ namespace WaveHarmonic.Crest CleanUpShadowCommandBuffers(); Shader.SetGlobalFloat(ShaderIDs.s_DynamicSoftShadowsFactor, 1f); - Camera.onPreCull -= OnPreCullCamera; - Camera.onPostRender -= OnPostRenderCamera; - #if d_UnityHDRP SampleShadowsHDRP.Disable(); #endif - -#if d_UnityURP - SampleShadowsURP.Disable(); -#endif } internal override void Destroy() @@ -265,7 +258,7 @@ namespace WaveHarmonic.Crest else if (RenderPipelineHelper.IsUniversal) { #if d_UnityURP - SampleShadowsURP.Enable(); + SampleShadowsURP.Enable(_Water); #endif } } @@ -276,106 +269,6 @@ namespace WaveHarmonic.Crest _Targets.RunLambda(buffer => Clear(buffer)); } - void OnPreCullCamera(Camera camera) - { -#if UNITY_EDITOR - // Do not execute when editor is not active to conserve power and prevent possible leaks. - if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) - { - CopyShadowMapBuffer?.Clear(); - return; - } - - if (!WaterRenderer.IsWithinEditorUpdate) - { - CopyShadowMapBuffer?.Clear(); - return; - } -#endif - - var water = _Water; - - if (water == null) - { - return; - } - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, water.Layer)) - { - return; - } - - if (camera == water.Viewer && CopyShadowMapBuffer != null) - { - // Calling this in OnPreRender was too late to be executed in the same frame. - AddCommandBufferToPrimaryLight(); - - // Disable for XR SPI otherwise input will not have correct world position. - if (camera.stereoEnabled && XRHelpers.IsSinglePass) - { - CopyShadowMapBuffer.DisableShaderKeyword("STEREO_INSTANCING_ON"); - } - - BuildCommandBuffer(water, CopyShadowMapBuffer); - - // Restore XR SPI as we cannot rely on remaining pipeline to do it for us. - if (camera.stereoEnabled && XRHelpers.IsSinglePass) - { - CopyShadowMapBuffer.EnableShaderKeyword("STEREO_INSTANCING_ON"); - } - } - } - - void OnPostRenderCamera(Camera camera) - { -#if UNITY_EDITOR - // Do not execute when editor is not active to conserve power and prevent possible leaks. - if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) - { - CopyShadowMapBuffer?.Clear(); - return; - } - - if (!WaterRenderer.IsWithinEditorUpdate) - { - CopyShadowMapBuffer?.Clear(); - return; - } -#endif - - var water = _Water; - - if (water == null) - { - return; - } - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, water.Layer)) - { - return; - } - - if (camera == water.Viewer) - { - // CBs added to a light are executed for every camera, but the LOD data is only supports a single - // camera. Removing the CB after the camera renders restricts the CB to one camera. - RemoveCommandBufferFromPrimaryLight(); - } - } - - internal void AddCommandBufferToPrimaryLight() - { - if (_Light == null || CopyShadowMapBuffer == null) return; - _Light.RemoveCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); - _Light.AddCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); - } - - internal void RemoveCommandBufferFromPrimaryLight() - { - if (_Light == null || CopyShadowMapBuffer == null) return; - _Light.RemoveCommandBuffer(LightEvent.BeforeScreenspaceMask, CopyShadowMapBuffer); - } - /// /// Validates the primary light. /// @@ -476,7 +369,7 @@ namespace WaveHarmonic.Crest CopyShadowMapBuffer = null; } - void Update() + void Update(CommandBuffer buffer) { // If disabled then we hit a failure state. Try and recover in edit mode by proceeding. if (!_Valid && Application.isPlaying) @@ -502,7 +395,7 @@ namespace WaveHarmonic.Crest return; } - CopyShadowMapBuffer ??= new() { name = "Crest Shadow Data" }; + CopyShadowMapBuffer ??= new() { name = WaterRenderer.k_DrawLodData }; CopyShadowMapBuffer.Clear(); FlipBuffers(); @@ -514,7 +407,9 @@ namespace WaveHarmonic.Crest if (Application.isPlaying) #endif { - Clear(DataTexture); + buffer.BeginSample(ID); + CoreUtils.SetRenderTarget(buffer, DataTexture, ClearFlag.Color, ClearColor); + buffer.EndSample(ID); } } @@ -522,6 +417,8 @@ namespace WaveHarmonic.Crest { var isSimulationBuffer = buffer == _Water.SimulationBuffer; + _IsSimulationBuffer = isSimulationBuffer; + if (isSimulationBuffer) { var skip = true; @@ -529,101 +426,94 @@ namespace WaveHarmonic.Crest { // If no shadow casters are present, BIRP will not execute the command buffer // leaving outdated shadows in data. We set a flag to determine if the command - // buffer was executed. - skip = Helpers.GetGlobalBoolean(ShaderIDs.s_ShadowCastersPresent); - Helpers.SetGlobalBoolean(ShaderIDs.s_ShadowCastersPresent, false); + // buffer was executed. There will a 1-frame delay. + skip = Helpers.GetGlobalBoolean(ShaderIDs.s_ShadowPassExecuteLastFrame); + Helpers.SetGlobalBoolean(ShaderIDs.s_ShadowPassExecuteLastFrame, false); } - Update(); + Update(buffer); // Only do a partial update when called by WaterRenderer as we want to execute // with the camera's command buffer (in frame). - if (skip) return; + if (skip) + { + return; + } } - // NOTE: FlipBuffers called elsewhere. - // Cache the camera for further down. var camera = water.Viewer; -#pragma warning disable 618 - using (new ProfilingSample(buffer, isSimulationBuffer ? "Shadows" : "Crest.Shadows")) -#pragma warning restore 618 + if (camera == null) { - var jitter = new Vector4 - ( - _JitterDiameterSoft, - _JitterDiameterHard, - _CurrentFrameWeightSoft, - _CurrentFrameWeightHard - ); + return; + } - var waterMaterial = _Water.Material; - var hasColor = waterMaterial.HasVector(WaterRenderer.ShaderIDs.s_Absorption) && waterMaterial.HasProperty(WaterRenderer.ShaderIDs.s_Scattering); - var absorption = hasColor ? waterMaterial.GetVector(WaterRenderer.ShaderIDs.s_Absorption).XYZ() : Vector3.zero; - var scattering = hasColor ? ((Vector4)waterMaterial.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear()).XYZ() : Vector3.zero; - var sampleAbsorption = _Water.AbsorptionLod.Enabled; - var sampleScattering = _Water.ScatteringLod.Enabled; - var sampleColor = sampleAbsorption || sampleScattering; + base.BuildCommandBuffer(water, buffer); - if (_DynamicSoftShadows && hasColor && !sampleColor) - { - // This approximates varying of soft shadowing by volume scattering/absorption density. - var extinction = absorption + scattering; - var factor = Mathf.Clamp01(Mathf.Min(Mathf.Min(extinction.x, extinction.y), extinction.z) * _SoftJitterExtinctionFactor); - jitter.x = (1f - factor) * k_MaximumJitter; - } + if (RenderPipelineHelper.IsLegacy && !isSimulationBuffer) + { + buffer.SetGlobalBoolean(ShaderIDs.s_ShadowPassExecuteLastFrame, true); + } + } - Shader.SetGlobalFloat(ShaderIDs.s_DynamicSoftShadowsFactor, _DynamicSoftShadows ? _SoftJitterExtinctionFactor : 1f); + private protected override void GetSubstepData(float timeToSimulate, out int substeps, out float delta) + { + substeps = Mathf.FloorToInt(timeToSimulate * _SimulationFrequency); + delta = substeps > 0 ? (1f / _SimulationFrequency) : 0f; + } - buffer.BeginSample("Sample"); + private protected override void SetAdditionalSimulationParameters(PropertyWrapperCompute properties) + { + base.SetAdditionalSimulationParameters(properties); - for (var slice = Slices - 1; slice >= 0; slice--) - { - _RenderMaterial[slice].SetVector(ShaderIDs.s_CenterPos, _Cascades[slice]._SnappedPosition.XNZ(_Water.SeaLevel)); - var scale = water.CalcLodScale(slice); - _RenderMaterial[slice].SetVector(ShaderIDs.s_Scale, new(scale, 1f, scale)); - _RenderMaterial[slice].SetVector(ShaderIDs.s_JitterDiameters_CurrentFrameWeights, jitter); - _RenderMaterial[slice].SetMatrix(ShaderIDs.s_MainCameraProjectionMatrix, GL.GetGPUProjectionMatrix(camera.projectionMatrix, renderIntoTexture: true) * camera.worldToCameraMatrix); - _RenderMaterial[slice].SetFloat(ShaderIDs.s_SimDeltaTime, Time.deltaTime); + var jitter = new Vector4 + ( + _JitterDiameterSoft, + _JitterDiameterHard, + _CurrentFrameWeightSoft, + _CurrentFrameWeightHard + ); - // Dynamic Soft Shadows. - _RenderMaterial[slice].SetBoolean(ShaderIDs.s_SampleColorMap, _DynamicSoftShadows && sampleColor); - if (_DynamicSoftShadows && sampleColor) - { - _RenderMaterial[slice].SetVector(WaterRenderer.ShaderIDs.s_Absorption, absorption); - _RenderMaterial[slice].SetVector(WaterRenderer.ShaderIDs.s_Scattering, scattering); - } + var waterMaterial = _Water.Surface.Material; + var hasColor = waterMaterial != null && waterMaterial.HasVector(WaterRenderer.ShaderIDs.s_Absorption) && waterMaterial.HasProperty(WaterRenderer.ShaderIDs.s_Scattering); + var absorption = hasColor ? waterMaterial.GetVector(WaterRenderer.ShaderIDs.s_Absorption).XYZ() : Vector3.zero; + var scattering = hasColor ? ((Vector4)waterMaterial.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear()).XYZ() : Vector3.zero; + var sampleAbsorption = _Water.AbsorptionLod.Enabled; + var sampleScattering = _Water.ScatteringLod.Enabled; + var sampleColor = sampleAbsorption || sampleScattering; - _RenderMaterial[slice].SetTexture(_TextureSourceShaderID, _Targets.Previous(1)); + if (_DynamicSoftShadows && hasColor && !sampleColor) + { + // This approximates varying of soft shadowing by volume scattering/absorption density. + var extinction = absorption + scattering; + var factor = Mathf.Clamp01(Mathf.Min(Mathf.Min(extinction.x, extinction.y), extinction.z) * _SoftJitterExtinctionFactor); + jitter.x = (1f - factor) * k_MaximumJitter; + } -#if UNITY_EDITOR - // On recompiles this becomes unset even though we run over the code path to set it again... - _RenderMaterial[slice].SetInteger(Lod.ShaderIDs.s_LodIndex, slice); -#endif + Shader.SetGlobalFloat(ShaderIDs.s_DynamicSoftShadowsFactor, _DynamicSoftShadows ? _SoftJitterExtinctionFactor : 1f); - if (RenderPipelineHelper.IsLegacy) - { - // If we are executing the simulation buffer, then we are clearing. - _RenderMaterial[slice].SetBoolean(ShaderIDs.s_ClearShadows, isSimulationBuffer); - } + var camera = _Water.Viewer; - Helpers.Blit(buffer, DataTexture, _RenderMaterial[slice].Material, depthSlice: slice); - } + properties.SetVector(ShaderIDs.s_JitterDiameters_CurrentFrameWeights, jitter); + properties.SetMatrix(ShaderIDs.s_MainCameraProjectionMatrix, GL.GetGPUProjectionMatrix(camera.projectionMatrix, renderIntoTexture: true) * camera.worldToCameraMatrix); - buffer.EndSample("Sample"); + // Dynamic Soft Shadows. + properties.SetBoolean(ShaderIDs.s_SampleColorMap, _DynamicSoftShadows && sampleColor); - // BUG: These draw calls will "leak" and be duplicated before the above blit. They are executed at - // the beginning of this CB before any commands are applied. - SubmitDraws(buffer, s_Inputs, DataTexture); + if (_DynamicSoftShadows && sampleColor) + { + properties.SetVector(WaterRenderer.ShaderIDs.s_Absorption, absorption); + properties.SetVector(WaterRenderer.ShaderIDs.s_Scattering, scattering); + } - // Set the target texture as to make sure we catch the 'pong' each frame - Shader.SetGlobalTexture(_TextureShaderID, DataTexture); + if (RenderPipelineHelper.IsLegacy) + { + // If we are executing the simulation buffer, then we are clearing. + properties.SetBoolean(ShaderIDs.s_ClearShadows, _IsSimulationBuffer); - if (RenderPipelineHelper.IsLegacy && !isSimulationBuffer) - { - buffer.SetGlobalBoolean(ShaderIDs.s_ShadowCastersPresent, true); - } + properties.SetKeyword(new LocalKeyword(SimulationShader, "SHADOWS_SINGLE_CASCADE"), QualitySettings.shadowCascades == 1); + properties.SetKeyword(new LocalKeyword(SimulationShader, "SHADOWS_SPLIT_SPHERES"), QualitySettings.shadowProjection == ShadowProjection.StableFit); } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Debug/DebugGUI.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Debug/DebugGUI.cs index fe18658a4..38c19d3e5 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Debug/DebugGUI.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Debug/DebugGUI.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityInputSystem && ENABLE_INPUT_SYSTEM @@ -249,7 +249,7 @@ namespace WaveHarmonic.Crest #if UNITY_EDITOR if (GUI.Button(new(x, y, w, h), "Select Water Material")) { - var path = UnityEditor.AssetDatabase.GetAssetPath(_Water.Material); + var path = UnityEditor.AssetDatabase.GetAssetPath(_Water.Surface.Material); var asset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(path); UnityEditor.Selection.activeObject = asset; } @@ -415,7 +415,7 @@ namespace WaveHarmonic.Crest GUI.color = Color.white; // Only use Graphics.DrawTexture in EventType.Repaint events if called in OnGUI - if (Event.current.type.Equals(EventType.Repaint)) + if (Event.current.type == EventType.Repaint) { for (var idx = 0; idx < lodData.DataTexture.volumeDepth; idx++) { @@ -453,7 +453,7 @@ namespace WaveHarmonic.Crest GUI.color = Color.white; // Only use Graphics.DrawTexture in EventType.Repaint events if called in OnGUI - if (Event.current.type.Equals(EventType.Repaint)) + if (Event.current.type == EventType.Repaint) { for (var idx = 0; idx < data.volumeDepth; idx++) { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs new file mode 100644 index 000000000..912ff29cb --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs @@ -0,0 +1,154 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System; +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + partial class WaterRenderer + { + const string k_SurfaceRendererObsoleteMessage = "This property can now be found on WaterRenderer.Surface"; + + // + // Fields + // + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("The water chunk renderers will have this layer.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + int _Layer = 4; // Water + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Material to use for the water surface.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + internal Material _Material = null; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Underwater will copy from this material if set.\n\nUseful for overriding properties for the underwater effect. To see what properties can be overriden, see the disabled properties on the underwater material. This does not affect the surface.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + internal Material _VolumeMaterial = null; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Template for water chunks as a prefab.\n\nThe only requirements are that the prefab must contain a MeshRenderer at the root and not a MeshFilter or WaterChunkRenderer. MR values will be overwritten where necessary and the prefabs are linked in edit mode.")] + [SerializeField] + internal GameObject _ChunkTemplate; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Have the water surface cast shadows for albedo (both foam and custom).")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + internal bool _CastShadows; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Whether 'Water Body' components will cull the water tiles.\n\nDisable if you want to use the 'Material Override' feature and still have an ocean.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + bool _WaterBodyCulling = true; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("How many frames to distribute the chunk bounds calculation.\n\nThe chunk bounds are calculated per frame to ensure culling is correct when using inputs that affect displacement. Some performance can be saved by distributing the load over several frames. The higher the frames, the longer it will take - lowest being instant.")] + [@Range(1, 30, Range.Clamp.Minimum)] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + int _TimeSliceBoundsUpdateFrameCount = 1; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("How to handle self-intersections of the water surface.\n\nThey can be caused by choppy waves which can cause a flipped underwater effect. When not using the portals/volumes, this fix is only applied when within 2 metres of the water surface. Automatic will disable the fix if portals/volumes are used which is the recommend setting.")] + [SerializeField] + internal SurfaceRenderer.SurfaceSelfIntersectionFixMode _SurfaceSelfIntersectionFixMode = SurfaceRenderer.SurfaceSelfIntersectionFixMode.Automatic; + + [Obsolete(k_SurfaceRendererObsoleteMessage)] + [HideInInspector] + [Tooltip("Whether to allow sorting using the render queue.\n\nIf you need to change the minor part of the render queue (eg +100), then enable this option. As a side effect, it will also disable the front-to-back rendering optimization for Crest. This option does not affect changing the major part of the render queue (eg AlphaTest, Transparent), as that is always allowed.\n\nRender queue sorting is required for some third-party integrations.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [SerializeField] + bool _AllowRenderQueueSorting; + + + // + // API + // + + int GetLayer() + { + return Surface.Layer; + } + + void SetLayer(int previous, int current) + { + Surface.Layer = current; + } + + Material GetMaterial() + { + return Surface.Material; + } + + void SetMaterial(Material previous, Material current) + { + Surface.Material = current; + } + + Material GetVolumeMaterial() + { + return Surface.VolumeMaterial; + } + + void SetVolumeMaterial(Material previous, Material current) + { + Surface.VolumeMaterial = current; + } + + bool GetCastShadows() + { + return Surface.CastShadows; + } + + void SetCastShadows(bool previous, bool current) + { + Surface.CastShadows = current; + } + + bool GetWaterBodyCulling() + { + return Surface.WaterBodyCulling; + } + + void SetWaterBodyCulling(bool previous, bool current) + { + Surface.WaterBodyCulling = current; + } + + int GetTimeSliceBoundsUpdateFrameCount() + { + return Surface.TimeSliceBoundsUpdateFrameCount; + } + + void SetTimeSliceBoundsUpdateFrameCount(int previous, int current) + { + Surface.TimeSliceBoundsUpdateFrameCount = current; + } + + bool GetAllowRenderQueueSorting() + { + return Surface.AllowRenderQueueSorting; + } + + void SetAllowRenderQueueSorting(bool previous, bool current) + { + Surface.AllowRenderQueueSorting = current; + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs.meta new file mode 100644 index 000000000..8d2f70a8a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Deprecated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40c7e9cba055f4ed9a6dfb8dc5de0051 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/API.Generated.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/API.Generated.cs index 3a10b657c..01b907897 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/API.Generated.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/API.Generated.cs @@ -245,6 +245,14 @@ namespace WaveHarmonic.Crest /// Requires a two component texture format. /// public bool EnableSignedDistanceFields { get => _EnableSignedDistanceFields; set => SetEnableSignedDistanceFields(_EnableSignedDistanceFields, _EnableSignedDistanceFields = value); } + + /// + /// Whether to include the terrain height automatically. + /// + /// + /// This will not include terrain details, nor will it produce a signed-distance field. There may also be a slight deviation due to differences in height data and terrain mesh. In these cases, please use the DepthProbe. + /// + public bool IncludeTerrainHeight { get => _IncludeTerrainHeight; set => _IncludeTerrainHeight = value; } } } @@ -740,6 +748,27 @@ namespace WaveHarmonic.Crest } } +namespace WaveHarmonic.Crest +{ + partial class Meniscus + { + /// + /// Whether the meniscus is enabled. + /// + public bool Enabled { get => GetEnabled(); set => SetEnabled(_Enabled, _Enabled = value); } + + /// + /// Any camera with this layer in its culling mask will render the meniscus. + /// + public int Layer { get => _Layer; set => _Layer = value; } + + /// + /// The meniscus material. + /// + public UnityEngine.Material Material { get => _Material; set => SetMaterial(_Material, _Material = value); } + } +} + namespace WaveHarmonic.Crest { partial class PersistentLod @@ -1013,6 +1042,14 @@ namespace WaveHarmonic.Crest /// public float MaximumVerticalDisplacement { get => _MaximumVerticalDisplacement; set => _MaximumVerticalDisplacement = value; } + /// + /// Whether to use the wind turbulence on this component rather than the global wind turbulence. + /// + /// + /// Global wind turbulence comes from the Water Renderer component. + /// + public bool OverrideGlobalWindTurbulence { get => _OverrideGlobalWindTurbulence; set => _OverrideGlobalWindTurbulence = value; } + /// /// FFT waves will loop with a period of this many seconds. /// @@ -1026,7 +1063,7 @@ namespace WaveHarmonic.Crest /// /// How turbulent/chaotic the waves are. /// - public float WindTurbulence { get => _WindTurbulence; set => _WindTurbulence = value; } + public float WindTurbulence { get => GetWindTurbulence(); set => _WindTurbulence = value; } } } @@ -1039,6 +1076,11 @@ namespace WaveHarmonic.Crest /// public int ComponentsPerOctave { get => _ComponentsPerOctave; set => _ComponentsPerOctave = value; } + /// + /// Prevent data arrays from being written to so one can provide their own. + /// + public bool ManualGeneration { get => _ManualGeneration; set => _ManualGeneration = value; } + /// /// Change to get a different set of waves. /// @@ -1050,7 +1092,15 @@ namespace WaveHarmonic.Crest /// /// Each Gerstner wave is actually a pair of waves travelling in opposite directions (similar to FFT). This weight is applied to the wave travelling in against-wind direction. Set to zero to obtain simple single waves which are useful for shorelines waves. /// - public float ReverseWaveWeight { get => _ReverseWaveWeight; set => _ReverseWaveWeight = value; } + public float ReverseWaveWeight { get => GetReverseWaveWeight(); set => _ReverseWaveWeight = value; } + + /// + /// Use a swell spectrum as the default. + /// + /// + /// Uses a swell spectrum as default (when none is assigned), and disabled reverse waves. + /// + public bool Swell { get => _Swell; set => _Swell = value; } } } @@ -1066,6 +1116,14 @@ namespace WaveHarmonic.Crest /// public bool EvaluateSpectrumAtRunTimeEveryFrame { get => _EvaluateSpectrumAtRunTimeEveryFrame; set => _EvaluateSpectrumAtRunTimeEveryFrame = value; } + /// + /// Whether to use the wind direction on this component rather than the global wind direction. + /// + /// + /// Global wind direction comes from the Water Renderer component. + /// + public bool OverrideGlobalWindDirection { get => _OverrideGlobalWindDirection; set => _OverrideGlobalWindDirection = value; } + /// /// Whether to use the wind speed on this component rather than the global wind speed. /// @@ -1101,7 +1159,7 @@ namespace WaveHarmonic.Crest /// /// This is the angle from x axis in degrees that the waves are oriented towards. If a spline is being used to place the waves, this angle is relative to the spline. /// - public float WaveDirectionHeadingAngle { get => _WaveDirectionHeadingAngle; set => _WaveDirectionHeadingAngle = value; } + public float WaveDirectionHeadingAngle { get => GetWaveDirectionHeadingAngle(); set => _WaveDirectionHeadingAngle = value; } /// /// Wind speed in km/h. Controls wave conditions. @@ -1203,10 +1261,79 @@ namespace WaveHarmonic.Crest } } +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + /// + /// Whether to allow sorting using the render queue. + /// + /// + /// If you need to change the minor part of the render queue (eg +100), then enable this option. As a side effect, it will also disable the front-to-back rendering optimization for Crest. This option does not affect changing the major part of the render queue (eg AlphaTest, Transparent), as that is always allowed. + /// + public bool AllowRenderQueueSorting { get => _AllowRenderQueueSorting; set => _AllowRenderQueueSorting = value; } + + /// + /// Have the water surface cast shadows for albedo (both foam and custom). + /// + public bool CastShadows { get => GetCastShadows(); set => _CastShadows = value; } + + /// + /// Whether the underwater effect is enabled. + /// + /// + /// Allocates/releases resources if state has changed. + /// + public bool Enabled { get => GetEnabled(); set => SetEnabled(_Enabled, _Enabled = value); } + + /// + /// The water chunk renderers will have this layer. + /// + public int Layer { get => _Layer; set => _Layer = value; } + + /// + /// Material to use for the water surface. + /// + public UnityEngine.Material Material { get => _Material; set => _Material = value; } + + /// + /// How many frames to distribute the chunk bounds calculation. + /// + /// + /// The chunk bounds are calculated per frame to ensure culling is correct when using inputs that affect displacement. Some performance can be saved by distributing the load over several frames. The higher the frames, the longer it will take - lowest being instant. + /// + public int TimeSliceBoundsUpdateFrameCount { get => _TimeSliceBoundsUpdateFrameCount; set => _TimeSliceBoundsUpdateFrameCount = value; } + + /// + /// Underwater will copy from this material if set. + /// + /// + /// Useful for overriding properties for the underwater effect. To see what properties can be overriden, see the disabled properties on the underwater material. This does not affect the surface. + /// + public UnityEngine.Material VolumeMaterial { get => _VolumeMaterial; set => _VolumeMaterial = value; } + + /// + /// Whether 'Water Body' components will cull the water tiles. + /// + /// + /// Disable if you want to use the 'Material Override' feature and still have an ocean. + /// + public bool WaterBodyCulling { get => _WaterBodyCulling; set => _WaterBodyCulling = value; } + } +} + namespace WaveHarmonic.Crest { partial class TextureLodInputData { + /// + /// Multiplies the texture sample. + /// + /// + /// This is useful for normalized textures. The four components map to the four color/alpha components of the texture (if they exist). + /// + public UnityEngine.Vector4 Multiplier { get => _Multiplier; set => _Multiplier = value; } + /// /// Texture to render into the simulation. /// @@ -1506,7 +1633,8 @@ namespace WaveHarmonic.Crest /// /// If you need to change the minor part of the render queue (eg +100), then enable this option. As a side effect, it will also disable the front-to-back rendering optimization for Crest. This option does not affect changing the major part of the render queue (eg AlphaTest, Transparent), as that is always allowed. /// - public bool AllowRenderQueueSorting { get => _AllowRenderQueueSorting; set => _AllowRenderQueueSorting = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public bool AllowRenderQueueSorting { get => GetAllowRenderQueueSorting(); set => SetAllowRenderQueueSorting(_AllowRenderQueueSorting, _AllowRenderQueueSorting = value); } /// /// All waves (including Dynamic Waves) are written to this simulation. @@ -1524,7 +1652,16 @@ namespace WaveHarmonic.Crest /// /// Have the water surface cast shadows for albedo (both foam and custom). /// - public bool CastShadows { get => GetCastShadows(); set => _CastShadows = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public bool CastShadows { get => GetCastShadows(); set => SetCastShadows(_CastShadows, _CastShadows = value); } + + /// + /// Keep the center of detail from drifting from the viewpoint. + /// + /// + /// Large horizontal displacement can displace the center of detail. This uses queries to keep the center of detail aligned. + /// + public bool CenterOfDetailDisplacementCorrection { get => _CenterOfDetailDisplacementCorrection; set => _CenterOfDetailDisplacementCorrection = value; } /// /// Clip surface information for clipping the water surface. @@ -1593,10 +1730,19 @@ namespace WaveHarmonic.Crest /// public float GravityOverride { get => _GravityOverride; set => _GravityOverride = value; } + /// + /// When in the render pipeline the water is rendered. + /// + /// + /// Default is the old behaviour which is controlled by Unity. + /// + public WaterInjectionPoint InjectionPoint { get => _InjectionPoint; set => _InjectionPoint = value; } + /// /// The water chunk renderers will have this layer. /// - public int Layer { get => _Layer; set => _Layer = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public int Layer { get => GetLayer(); set => SetLayer(_Layer, _Layer = value); } /// /// Varying water level to support water bodies at different heights and rivers to run down slopes. @@ -1606,7 +1752,13 @@ namespace WaveHarmonic.Crest /// /// Material to use for the water surface. /// - public UnityEngine.Material Material { get => _Material; set => _Material = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public UnityEngine.Material Material { get => GetMaterial(); set => SetMaterial(_Material, _Material = value); } + + /// + /// The meniscus module. + /// + public Meniscus Meniscus => _Meniscus; /// /// Provide your own gravity value instead of Physics.gravity. @@ -1689,6 +1841,11 @@ namespace WaveHarmonic.Crest /// public int LodLevels { get => _Slices; set => _Slices = value; } + /// + /// The water surface renderer. + /// + public SurfaceRenderer Surface => _Surface; + /// /// The distance threshold for when the viewer has considered to have teleported. /// @@ -1703,7 +1860,8 @@ namespace WaveHarmonic.Crest /// /// The chunk bounds are calculated per frame to ensure culling is correct when using inputs that affect displacement. Some performance can be saved by distributing the load over several frames. The higher the frames, the longer it will take - lowest being instant. /// - public int TimeSliceBoundsUpdateFrameCount { get => _TimeSliceBoundsUpdateFrameCount; set => _TimeSliceBoundsUpdateFrameCount = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public int TimeSliceBoundsUpdateFrameCount { get => GetTimeSliceBoundsUpdateFrameCount(); set => SetTimeSliceBoundsUpdateFrameCount(_TimeSliceBoundsUpdateFrameCount, _TimeSliceBoundsUpdateFrameCount = value); } /// /// The underwater renderer. @@ -1724,7 +1882,8 @@ namespace WaveHarmonic.Crest /// /// Useful for overriding properties for the underwater effect. To see what properties can be overriden, see the disabled properties on the underwater material. This does not affect the surface. /// - public UnityEngine.Material VolumeMaterial { get => _VolumeMaterial; set => _VolumeMaterial = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public UnityEngine.Material VolumeMaterial { get => GetVolumeMaterial(); set => SetVolumeMaterial(_VolumeMaterial, _VolumeMaterial = value); } /// /// Whether 'Water Body' components will cull the water tiles. @@ -1732,7 +1891,16 @@ namespace WaveHarmonic.Crest /// /// Disable if you want to use the 'Material Override' feature and still have an ocean. /// - public bool WaterBodyCulling { get => _WaterBodyCulling; set => _WaterBodyCulling = value; } + [System.Obsolete("This property can now be found on WaterRenderer.Surface")] + public bool WaterBodyCulling { get => GetWaterBodyCulling(); set => SetWaterBodyCulling(_WaterBodyCulling, _WaterBodyCulling = value); } + + /// + /// Base wind direction in degrees. + /// + /// + /// Controls wave conditions. Can be overridden on Shape* components. + /// + public float WindDirection { get => GetWindDirection(); set => _WindDirection = value; } /// /// Base wind speed in km/h. @@ -1740,7 +1908,23 @@ namespace WaveHarmonic.Crest /// /// Controls wave conditions. Can be overridden on Shape* components. /// - public float WindSpeed { get => _WindSpeed; set => _WindSpeed = value; } + public float WindSpeed { get => GetWindSpeed(); set => _WindSpeed = value; } + + /// + /// Base wind turbulence. + /// + /// + /// Controls wave conditions. Can be overridden on ShapeFFT components. + /// + public float WindTurbulence { get => GetWindTurbulence(); set => _WindTurbulence = value; } + + /// + /// Uses a provided WindZone as the source of global wind. + /// + /// + /// It must be directional. Wind speed units are presumed to be in m/s. + /// + public UnityEngine.WindZone WindZone { get => _WindZone; set => _WindZone = value; } /// /// Whether to enable motion vector support. @@ -1748,12 +1932,20 @@ namespace WaveHarmonic.Crest public bool WriteMotionVectors { get => GetWriteMotionVectors(); set => _WriteMotionVectors = value; } /// - /// Whether to write the water surface depth to the depth texture (URP only). + /// Whether to write the water surface color to the color/opaque texture. /// /// - /// The water surface writes to the depth buffer, but Unity does not copy it to the depth texture for post-processing effects like Depth of Field. This will copy the depth buffer to the depth texture. + /// This is likely only beneficial if the water injection point is before transparency, and there are shaders which need it (like refraction). /// - public bool WriteToDepthTexture { get => _WriteToDepthTexture; set => _WriteToDepthTexture = value; } + public bool WriteToColorTexture { get => GetWriteToColorTexture(); set => _WriteToColorTexture = value; } + + /// + /// Whether to write the water surface depth to the depth texture. + /// + /// + /// The water surface writes to the depth buffer, but Unity does not copy it to the depth texture for post-processing effects like Depth of Field (or refraction). This will copy the depth buffer to the depth texture. + /// + public bool WriteToDepthTexture { get => GetWriteToDepthTexture(); set => _WriteToDepthTexture = value; } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs new file mode 100644 index 000000000..cb31f4f00 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs @@ -0,0 +1,453 @@ +// + +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +namespace WaveHarmonic.Crest.Generated +{ + enum CollisionLayer + { + /// + /// Include all displacement. + /// + Everything, + + /// + /// Only include Animated Waves. + /// + AfterAnimatedWaves, + + /// + /// Include Animated Waves and Dynamic Waves. + /// + AfterDynamicWaves, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum CollisionLayers + { + /// + /// All layers. + /// + Everything, + + /// + /// No extra layers (ie single layer). + /// + Nothing, + + /// + /// Separate layer for dynamic waves. + /// + /// + /// Dynamic waves are normally combined together for efficiency. By enabling this layer, dynamic waves are combined and added in a separate pass. + /// + DynamicWaves, + + /// + /// Extra displacement layer for visual displacement. + /// + Displacement, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum CollisionSource + { + /// + /// No collision source. Flat water. + /// + None, + + /// + /// Uses AsyncGPUReadback to retrieve data from GPU to CPU. + /// + /// + /// This is the most optimal approach. + /// + GPU, + + /// + /// Computes data entirely on the CPU. + /// + CPU, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum DefaultClippingState + { + /// + /// By default, nothing is clipped. Use clip inputs to remove water. + /// + NothingClipped, + + /// + /// By default, everything is clipped. Use clip inputs to add water. + /// + EverythingClipped, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum DepthProbeMode + { + /// + /// Update in real-time in accordance to refresh mode. + /// + RealTime, + + /// + /// Baked in the editor. + /// + Baked, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum DepthProbeRefreshMode + { + /// + /// Populates the DepthProbe in Start. + /// + OnStart, + + /// + /// Requires manual updating via DepthProbe.Populate. + /// + ViaScripting, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum DisplacementPass + { + /// + /// Displacement that is dependent on an LOD (eg waves). + /// + /// + /// Uses filtering to determine which LOD to write to. + /// + LodDependent, + + /// + /// Renders to all LODs. + /// + LodIndependent, + + /// + /// Renders to all LODs, but as a separate pass. + /// + /// + /// Typically used to render visual displacement which does not affect collisions. + /// + LodIndependentLast, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum FloatingObjectModel + { + /// + /// A simple model which aligns the object with the wave normal. + /// + AlignNormal, + + /// + /// A more advanced model which samples water at the probes positions. + /// + Probes, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum LodInputBlend + { + /// + /// No blending. Overwrites. + /// + Off, + + /// + /// Additive blending. + /// + Additive, + + /// + /// Takes the minimum value. + /// + Minimum, + + /// + /// Takes the maximum value. + /// + Maximum, + + /// + /// Applies the inverse weight to the target. + /// + /// + /// Basically overwrites what is already in the simulation. + /// + Alpha, + + /// + /// Same as alpha except anything above zero will overwrite rather than blend. + /// + AlphaClip, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum LodInputMode + { + /// + /// Unset is the serialization default. + /// + /// + /// This will be replaced with the default mode automatically. Unset can also be used if something is invalid. + /// + Unset, + + /// + /// Hand-painted data by the user. + /// + Paint, + + /// + /// Driven by a user created spline. + /// + Spline, + + /// + /// Attached 'Renderer' (mesh, particle or other) used to drive data. + /// + Renderer, + + /// + /// Driven by a mathematical primitive such as a cube or sphere. + /// + Primitive, + + /// + /// Covers the entire water area. + /// + Global, + + /// + /// Data driven by a user provided texture. + /// + Texture, + + /// + /// Renders geometry using a default material. + /// + Geometry, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum LodInputPrimitive + { + /// + /// Spheroid. + /// + Sphere, + + /// + /// Cuboid. + /// + Cube, + + /// + /// Quad. + /// + Quad, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum LodTextureFormatMode + { + /// + /// Uses the Texture Format property. + /// + Manual, + + /// + /// Chooses a texture format for performance. + /// + Performance, + + /// + /// Chooses a texture format for precision. + /// + /// + /// This format can reduce artifacts. + /// + Precision, + + /// + /// Chooses a texture format based on another. + /// + /// + /// For example, Dynamic Waves will match precision of Animated Waves. + /// + Automatic, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum Placement + { + /// + /// The component is in a fixed position. + /// + Fixed, + + /// + /// The component follows the transform. + /// + Transform, + + /// + /// The component follows the viewpoint. + /// + Viewpoint, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum QuerySource + { + /// + /// This game object's transform. + /// + Transform, + + /// + /// The viewer's transform. + /// + /// + /// The viewer is the main camera the system uses. + /// + Viewer, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum ShorelineVolumeColorSource + { + /// + /// No depth color. + /// + None, + + /// + /// Depth color based on water depth. + /// + Depth, + + /// + /// Depth color based on shoreline distance. + /// + Distance, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum WaterInjectionPoint + { + /// + /// Renders in the default pass. + /// + /// + /// For the water surface, this will be determined by the material (opaque or transparent). This pass is controlled by Unity, and is not compatible with certain features like soft particles. + /// + Default, + + /// + /// Renders before the transparent pass. + /// + /// + /// This has advantages like being compatible with soft particles, refractive shaders, and possibly third-party fog. + /// + BeforeTransparent, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum WaterReflectionSide + { + /// + /// Both sides. Most expensive. + /// + Both, + + /// + /// Above only. Typical for planar reflections. + /// + Above, + + /// + /// Below only. For total internal reflections. + /// + Below, + } +} + + +namespace WaveHarmonic.Crest.Generated +{ + enum WatertightHullMode + { + /// + /// Use displacement to remove water. + /// + /// + /// Using displacement will also affect the underwater and can nest bouyant objects. Requires the displacement layer to be enabled. + /// + Displacement, + + /// + /// Clips the surface to remove water. + /// + /// + /// This option is more precise and can be submerged. + /// + Clip, + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs.meta new file mode 100644 index 000000000..54053f317 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Generated/Documentation.Generated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b32089d5327840948a90ac2add66a1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Interaction/FloatingObject.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Interaction/FloatingObject.cs index c611f63e4..87cbaffa1 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Interaction/FloatingObject.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Interaction/FloatingObject.cs @@ -3,22 +3,22 @@ using UnityEngine; using WaveHarmonic.Crest.Internal; +using WaveHarmonic.Crest.Utility; namespace WaveHarmonic.Crest { /// /// Different physics models for /// + [@GenerateDoc] public enum FloatingObjectModel { - /// - /// A simple model which aligns the object with the wave normal. - /// + /// + [Tooltip("A simple model which aligns the object with the wave normal.")] AlignNormal, - /// - /// A more advanced model which samples water at the probes positions. - /// + /// + [Tooltip("A more advanced model which samples water at the probes positions.")] Probes, } @@ -165,6 +165,10 @@ namespace WaveHarmonic.Crest internal bool _DrawQueries = false; } + internal const string k_FixedUpdateMarker = "Crest.FloatingObject.FixedUpdate"; + + static readonly Unity.Profiling.ProfilerMarker s_FixedUpdateMarker = new(k_FixedUpdateMarker); + /// /// Is any part of this object in water. /// @@ -204,7 +208,7 @@ namespace WaveHarmonic.Crest private protected override System.Action OnFixedUpdateMethod => OnFixedUpdate; void OnFixedUpdate(WaterRenderer water) { - UnityEngine.Profiling.Profiler.BeginSample("Buoyancy.FixedUpdate"); + s_FixedUpdateMarker.Begin(this); var points = Advanced ? _Probes : _Probe; @@ -232,7 +236,7 @@ namespace WaveHarmonic.Crest { var query = _QueryPoints[i]; query.y = water.SeaLevel + _QueryResultDisplacements[i].y; - CollisionAreaVisualizer.DebugDrawCross(query, 1f, Color.magenta); + DebugUtility.DrawCross(Debug.DrawLine, query, 1f, Color.magenta); } } } @@ -276,7 +280,7 @@ namespace WaveHarmonic.Crest if (!InWater) { - UnityEngine.Profiling.Profiler.EndSample(); + s_FixedUpdateMarker.End(); return; } } @@ -290,13 +294,13 @@ namespace WaveHarmonic.Crest { var surfPos = transform.position; surfPos.y = height; - CollisionAreaVisualizer.DebugDrawCross(surfPos, normal, 1f, Color.red); + DebugUtility.DrawCross(Debug.DrawLine, surfPos, normal, 1f, Color.red); } InWater = bottomDepth > 0f; if (!InWater) { - UnityEngine.Profiling.Profiler.EndSample(); + s_FixedUpdateMarker.End(); return; } @@ -366,7 +370,7 @@ namespace WaveHarmonic.Crest _RigidBody.AddForceAtPosition(_Drag.z * Vector3.Dot(transform.forward, -velocityRelativeToWater) * transform.forward, forcePosition, ForceMode.Acceleration); } - UnityEngine.Profiling.Profiler.EndSample(); + s_FixedUpdateMarker.End(); } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask.meta new file mode 100644 index 000000000..a26b19ca3 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2b0d4d3edfa685248878df8f18fd1756 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs new file mode 100644 index 000000000..3e7035014 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs @@ -0,0 +1,97 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; + +namespace WaveHarmonic.Crest +{ + sealed class MaskRendererHDRP : MaskRenderer + { + const string k_Name = "Water Mask"; + MaskCustomPass _MaskCustomPass; + GameObject _GameObject; + + public MaskRendererHDRP(WaterRenderer water) : base(water) { } + + public override void Enable() + { + base.Enable(); + + _GameObject = CustomPassHelpers.CreateOrUpdate + ( + parent: _Water.Container.transform, + k_Name, + hide: !_Water._Debug._ShowHiddenObjects + ); + + CustomPassHelpers.CreateOrUpdate + ( + _GameObject, + ref _MaskCustomPass, + UnderwaterRenderer.k_DrawMask, + CustomPassInjectionPoint.BeforeRendering + ); + + _MaskCustomPass._MaskPass = this; + } + + public override void Disable() + { + base.Disable(); + + if (_GameObject != null) + { + // Will also trigger Cleanup below. + _GameObject.SetActive(false); + } + } + + public override void OnBeginCameraRendering(Camera camera) + { + + } + + public override void OnEndCameraRendering(Camera camera) + { + + } + + sealed class MaskCustomPass : CustomPass + { + internal MaskRenderer _MaskPass; + + // Called when the custom pass object is enabled making it somewhat useless. + protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) + { + _MaskPass.Allocate(); + } + + protected override void Cleanup() + { + _MaskPass.Release(); + } + + protected override void Execute(CustomPassContext context) + { + var camera = context.hdCamera.camera; + + if (!_MaskPass.ShouldExecute(camera)) + { + return; + } + + // HDRP does not need ReAllocate. But it is easier to also call Allocate here. + // Allocating RTHandles outside the render loop raises an error. Seriously, do not + // attempt to optmize this away. + _MaskPass.Allocate(); + _MaskPass.Execute(camera, context.cmd); + } + } + } +} + +#endif // d_UnityHDRP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs.meta new file mode 100644 index 000000000..842e1c173 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c293f6238a2e7418f9348c7c99b8aacf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs new file mode 100644 index 000000000..1bd46eaf6 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs @@ -0,0 +1,63 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + sealed class MaskRendererBIRP : MaskRenderer + { + CommandBuffer _Commands; + + public MaskRendererBIRP(WaterRenderer water) : base(water) { } + + public override void Enable() + { + base.Enable(); + Allocate(); + } + + + public override void OnBeginCameraRendering(Camera camera) + { + if (!ShouldExecute(camera)) + { + return; + } + + + _Commands ??= new() + { + name = UnderwaterRenderer.k_DrawMask, + }; + + _Water.UpdateMatrices(camera); + + var descriptor = Rendering.BIRP.GetCameraTargetDescriptor(camera); + descriptor.useDynamicScale = camera.allowDynamicResolution; + + Allocate(); + + ReAllocate(descriptor); + Execute(camera, _Commands); + + // Handles both forward and deferred. + camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, _Commands); + camera.AddCommandBuffer(CameraEvent.BeforeDepthTexture, _Commands); + } + + public override void OnEndCameraRendering(Camera camera) + { + if (_Commands == null) + { + return; + } + + camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, _Commands); + camera.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, _Commands); + + _Commands.Clear(); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs.meta new file mode 100644 index 000000000..c4bc204ae --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Legacy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8abc65ea1dd9433c972aa074694f5b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs new file mode 100644 index 000000000..8d5fcf4f0 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs @@ -0,0 +1,103 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityURP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace WaveHarmonic.Crest +{ + sealed class MaskRendererURP : MaskRenderer + { + readonly MaskRenderPass _MaskRenderPass = new(); + + public MaskRendererURP(WaterRenderer water) : base(water) { } + + public override void OnBeginCameraRendering(Camera camera) + { + if (!ShouldExecute(camera)) + { + return; + } + + _MaskRenderPass._Renderer = this; + _MaskRenderPass.EnqueuePass(camera); + } + + public override void OnEndCameraRendering(Camera camera) + { + + } + + sealed partial class MaskRenderPass : ScriptableRenderPass + { + const string k_Name = "Crest.DrawMask"; + + internal MaskRenderer _Renderer; + + public MaskRenderPass() + { + // Will always execute and matrices will be ready. + renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses; + } + + internal void EnqueuePass(Camera camera) + { + // TODO: check if we need to even enqueue a pass + var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer; + +#if UNITY_EDITOR + if (renderer == null) + { + return; + } +#endif + + _Renderer.Allocate(); + + // Enqueue the pass. This happens every frame. + renderer.EnqueuePass(this); + } + +#if UNITY_6000_0_OR_NEWER + class PassData + { + public UniversalCameraData _CameraData; + public MaskRenderer _Renderer; + } + + public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) + { + using (var builder = graph.AddUnsafePass(k_Name, out var data)) + { + builder.AllowPassCulling(false); + + data._CameraData = frame.Get(); + data._Renderer = _Renderer; + + builder.SetRenderFunc((data, context) => + { + var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); + data._Renderer.ReAllocate(data._CameraData.cameraTargetDescriptor); + data._Renderer.Execute(data._CameraData.camera, buffer); + }); + } + } + + [System.Obsolete] +#endif + public override void Execute(ScriptableRenderContext context, ref RenderingData data) + { + var buffer = CommandBufferPool.Get(k_Name); + _Renderer.ReAllocate(data.cameraData.cameraTargetDescriptor); + _Renderer.Execute(data.cameraData.camera, buffer); + context.ExecuteCommandBuffer(buffer); + CommandBufferPool.Release(buffer); + } + } + } +} + +#endif // d_UnityURP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs.meta new file mode 100644 index 000000000..e9ec7dc74 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.Universal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b884ed0c0033342c78bdc398e0060299 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs new file mode 100644 index 000000000..4f6c36ec7 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs @@ -0,0 +1,314 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + abstract partial class MaskRenderer + { + protected const string k_MaskColor = "_Crest_MaskColor"; + protected const string k_MaskDepth = "_Crest_MaskDepth"; + + public static class ShaderIDs + { + public static readonly int s_WaterMaskTexture = Shader.PropertyToID("_Crest_WaterMaskTexture"); + public static readonly int s_WaterMaskDepthTexture = Shader.PropertyToID("_Crest_WaterMaskDepthTexture"); + } + + public static MaskRenderer Instantiate(WaterRenderer water) + { +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + return new MaskRendererHDRP(water); + } + else +#endif + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + return new MaskRendererURP(water); + } + else +#endif + + { + return new MaskRendererBIRP(water); + } + } + + // For PortalRenderer. + public static System.Action s_OnAllocate; + public static System.Action s_OnRelease; + public static System.Action s_OnReAllocate; + + public MaskRenderer(WaterRenderer water) + { + _Water = water; + } + + public bool Enabled => true; //_Water.Underwater.Enabled; + + internal RenderTargetIdentifier _ColorRTI; + internal RenderTargetIdentifier _DepthRTI; + + public RenderTextureDescriptor ColorDescriptor => ColorRT.descriptor; + public RenderTextureDescriptor DepthDescriptor => DepthRT.descriptor; + + public abstract void OnBeginCameraRendering(Camera camera); + public abstract void OnEndCameraRendering(Camera camera); + + + public virtual void Enable() + { + + } + + public virtual void Disable() + { + + } + + public virtual void Destroy() + { + Release(); + } + + protected void UpdateColor(Texture color) + { + _ColorRTI = new(color, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); + Shader.SetGlobalTexture(ShaderIDs.s_WaterMaskTexture, color); + } + + protected void UpdateDepth(Texture depth) + { + _DepthRTI = new(depth, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); + Shader.SetGlobalTexture(ShaderIDs.s_WaterMaskDepthTexture, depth); + } + + + // + // Pub/Sub + // + + [System.Flags] + public enum MaskInput + { + None, + Zero = 1 << 0, + Color = 1 << 1, + Depth = 1 << 2, + Both = Color | Depth, + } + + protected MaskInput _Inputs; + + protected readonly WaterRenderer _Water; + + internal readonly Utility.SortedList _Providers = new(Helpers.DuplicateComparison); + internal readonly List _Receivers = new(); + + public interface IMaskProvider + { + MaskInput Allocate(); + MaskInput Write(Camera camera); + void OnMaskPass(CommandBuffer commands, Camera camera, MaskRenderer mask); + } + + public interface IMaskReceiver + { + MaskInput Allocate(); + } + + void Initialize() + { + _Inputs = MaskInput.None; + + foreach (var receiver in _Receivers) + { + _Inputs |= receiver.Allocate(); + } + } + + internal void Add(IMaskReceiver receiver) + { + if (_Receivers.Contains(receiver)) + { + return; + } + + _Receivers.Add(receiver); + + Initialize(); + } + + internal void Remove(IMaskReceiver receiver) + { + if (!_Receivers.Remove(receiver)) + { + return; + } + + Initialize(); + } + + internal void Add(int queue, IMaskProvider provider) + { + if (_Providers.Contains(provider)) + { + return; + } + + _Providers.Add(queue, provider); + + Initialize(); + } + + internal void Remove(IMaskProvider provider) + { + if (!_Providers.Remove(provider)) + { + return; + } + + Initialize(); + } + + public void Execute(Camera camera, CommandBuffer commands) + { + foreach (var provider in _Providers) + { + if (provider.Value.Write(camera) == MaskInput.None) + { + continue; + } + + provider.Value.OnMaskPass(commands, camera, this); + } + } + + internal bool ShouldExecute(Camera camera) + { + var input = MaskInput.None; + + foreach (var providers in _Providers) + { + input |= providers.Value.Write(camera); + } + + return input != MaskInput.None; + } + } + + // Holds common stuff for SRPs + abstract partial class MaskRenderer + { + internal RTHandle _ColorRTH; + internal RTHandle _DepthRTH; + + + // Null check due to U6 not being able to cast if null (Unity bug?). + public Texture ColorT => _ColorRTH?.rt; + public Texture DepthT => _DepthRTH?.rt; + public RTHandle ColorRTH => _ColorRTH; + public RTHandle DepthRTH => _DepthRTH; + public RenderTexture ColorRT => _ColorRTH; + public RenderTexture DepthRT => _DepthRTH; + + public void ResetRenderTarget(CommandBuffer commands) + { + CoreUtils.SetRenderTarget(commands, ColorRTH, DepthRTH); + } + + public void Allocate() + { + if (_Inputs.HasFlag(MaskInput.Color) && _ColorRTH == null) + { + _ColorRTH = RTHandles.Alloc + ( + scaleFactor: Vector2.one, + slices: TextureXR.slices, + dimension: TextureXR.dimension, + depthBufferBits: DepthBits.None, + colorFormat: GraphicsFormat.R16_SFloat, + enableRandomWrite: true, + useDynamicScale: true, + name: k_MaskColor + ); + + UpdateColor(_ColorRTH); + } + + if (_Inputs.HasFlag(MaskInput.Depth) && _DepthRTH == null) + { + _DepthRTH = RTHandles.Alloc + ( + scaleFactor: Vector2.one, + slices: TextureXR.slices, + dimension: TextureXR.dimension, + depthBufferBits: Helpers.k_DepthBits, + colorFormat: GraphicsFormat.None, + enableRandomWrite: false, + useDynamicScale: true, + name: k_MaskDepth + ); + + UpdateDepth(_DepthRTH); + } + + s_OnAllocate?.Invoke(); + } + + public void ReAllocate(RenderTextureDescriptor descriptor) + { + // Shared settings. Enabling MSAA might be a good idea except cannot enable random + // writes. Having a raster shader to remove artifacts is a workaround. + // This looks safe to do as Unity's CopyDepthPass does the same. + descriptor.bindMS = false; + descriptor.msaaSamples = 1; + + s_OnReAllocate?.Invoke(descriptor); + + if (_Inputs.HasFlag(MaskInput.Depth)) + { + descriptor.graphicsFormat = GraphicsFormat.None; + descriptor.depthBufferBits = Helpers.k_DepthBufferBits; + + if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _DepthRTH, descriptor, name: k_MaskDepth)) + { + UpdateDepth(_DepthRTH); + } + } + + if (_Inputs.HasFlag(MaskInput.Color)) + { + // NOTE: Intel iGPU for Metal and DirectX both had issues with R16 (2021.11.18). + descriptor.graphicsFormat = GraphicsFormat.R16_SFloat; + descriptor.depthBufferBits = 0; + descriptor.enableRandomWrite = true; + + if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _ColorRTH, descriptor, name: k_MaskColor)) + { + UpdateColor(_ColorRTH); + } + } + } + + public void Release() + { + _ColorRTH?.Release(); + _DepthRTH?.Release(); + + // Set to null possibly due to Initialize/Destroy overlap. + _ColorRTH = null; + _DepthRTH = null; + + s_OnRelease?.Invoke(); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs.meta new file mode 100644 index 000000000..5a7df4f21 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Mask/MaskRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 797f30610ca4c477fbbaaf38f758dc95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus.meta new file mode 100644 index 000000000..fe768b495 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a77538aae73c514bb42831e04b8041e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs new file mode 100644 index 000000000..f1f85f3ef --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs @@ -0,0 +1,32 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if UNITY_EDITOR + +using UnityEditor; +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + partial class Meniscus + { + internal const string k_MaterialPath = "Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat"; + + internal void Reset() + { + _Material = AssetDatabase.LoadAssetAtPath(k_MaterialPath); + } + + [@OnChange] + void OnChange(string path, object previous) + { + switch (path) + { + case nameof(_Enabled): SetEnabled((bool)previous, _Enabled); break; + case nameof(_Material): SetMaterial((Material)previous, _Material); break; + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs.meta new file mode 100644 index 000000000..17d924af9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Editor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 20f5eb7691544460796ae81ca7816cbb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs new file mode 100644 index 000000000..0daab558a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs @@ -0,0 +1,88 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using UnityEngine; +using UnityEngine.Rendering.HighDefinition; + +namespace WaveHarmonic.Crest +{ + partial class Meniscus + { + internal sealed class MeniscusRendererHDRP : MeniscusRenderer + { + const string k_Name = "Meniscus"; + MeniscusCustomPass _CustomPass; + GameObject _GameObject; + + public MeniscusRendererHDRP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus) + { + + } + + public override void Enable() + { + base.Enable(); + + _GameObject = CustomPassHelpers.CreateOrUpdate + ( + parent: _Water.Container.transform, + k_Name, + hide: !_Water._Debug._ShowHiddenObjects + ); + + CustomPassHelpers.CreateOrUpdate + ( + _GameObject, + ref _CustomPass, + k_Draw, + CustomPassInjectionPoint.BeforePostProcess, + priority: -1 + ); + + _CustomPass._Renderer = this; + } + + public override void Disable() + { + base.Disable(); + + if (_GameObject != null) + { + // Will also trigger Cleanup below. + _GameObject.SetActive(false); + } + } + + public override void OnBeginCameraRendering(Camera camera) + { + + } + + public override void OnEndCameraRendering(Camera camera) + { + + } + + sealed class MeniscusCustomPass : CustomPass + { + internal MeniscusRenderer _Renderer; + + protected override void Execute(CustomPassContext context) + { + var camera = context.hdCamera.camera; + + if (!_Renderer.ShouldExecute(camera)) + { + return; + } + + _Renderer.Execute(camera, new CommandWrapper(context.cmd)); + } + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs.meta new file mode 100644 index 000000000..7e9f4a598 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec8f31a3e4e434fa0a8e771834d9dc16 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs new file mode 100644 index 000000000..ddedc07b1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs @@ -0,0 +1,57 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + partial class Meniscus + { + internal sealed class MeniscusRendererBIRP : MeniscusRenderer + { + CommandBuffer _Commands; + + // NOTE: This will not work for recursive rendering. + bool _CommandsRegistered; + + public MeniscusRendererBIRP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus) + { + + } + + public override void OnBeginCameraRendering(Camera camera) + { + if (!ShouldExecute(camera)) + { + return; + } + + _Commands ??= new() + { + name = k_Draw, + }; + + _Commands.Clear(); + + Execute(camera, new CommandWrapper(_Commands)); + + camera.AddCommandBuffer(CameraEvent.AfterForwardAlpha, _Commands); + + _CommandsRegistered = true; + } + + public override void OnEndCameraRendering(Camera camera) + { + if (!_CommandsRegistered) + { + return; + } + + camera.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, _Commands); + + _CommandsRegistered = false; + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs.meta new file mode 100644 index 000000000..fd4fac4e2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Legacy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a79d71a3e88424f27877abd4102b5af9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs new file mode 100644 index 000000000..152b56b9a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs @@ -0,0 +1,118 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityURP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace WaveHarmonic.Crest +{ + partial class Meniscus + { + internal sealed class MeniscusRendererURP : MeniscusRenderer + { + readonly MeniscusRenderPass _MaskRenderPass = new(); + + public MeniscusRendererURP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus) + { + + } + + public override void OnBeginCameraRendering(Camera camera) + { + if (!ShouldExecute(camera)) + { + return; + } + + _MaskRenderPass._Renderer = this; + _MaskRenderPass.EnqueuePass(camera); + } + + public override void OnEndCameraRendering(Camera camera) + { + + } + + sealed partial class MeniscusRenderPass : ScriptableRenderPass + { + const string k_Name = k_Draw; + + internal MeniscusRenderer _Renderer; + + bool _RequiresOpaqueTexture; + + public MeniscusRenderPass() + { + renderPassEvent = RenderPassEvent.AfterRenderingTransparents; + } + + internal void EnqueuePass(Camera camera) + { + // TODO: check if we need to even enqueue a pass + var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer; + +#if UNITY_EDITOR + if (renderer == null) + { + return; + } +#endif + + _RequiresOpaqueTexture = _Renderer._Meniscus.RequiresOpaqueTexture; + + ConfigureInput(_RequiresOpaqueTexture ? ScriptableRenderPassInput.Color : ScriptableRenderPassInput.None); + + // Enqueue the pass. This happens every frame. + renderer.EnqueuePass(this); + } + +#if UNITY_6000_0_OR_NEWER + class PassData + { + public UniversalCameraData _CameraData; + public MeniscusRenderer _Renderer; + } + + public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) + { + using (var builder = graph.AddRasterRenderPass(k_Name, out var data)) + { + builder.AllowPassCulling(false); + + var resources = frame.Get(); + + if (_RequiresOpaqueTexture) + { + builder.UseTexture(resources.cameraOpaqueTexture); + } + + data._CameraData = frame.Get(); + data._Renderer = _Renderer; + + builder.SetRenderAttachment(resources.activeColorTexture, index: 0); + + builder.SetRenderFunc((data, context) => + { + data._Renderer.Execute(data._CameraData.camera, new RasterCommandWrapper(context.cmd)); + }); + } + } + + [System.Obsolete] +#endif + public override void Execute(ScriptableRenderContext context, ref RenderingData data) + { + var buffer = CommandBufferPool.Get(k_Name); + _Renderer.Execute(data.cameraData.camera, new CommandWrapper(buffer)); + context.ExecuteCommandBuffer(buffer); + CommandBufferPool.Release(buffer); + } + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs.meta new file mode 100644 index 000000000..0654d0692 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.Universal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6888087ee71bb4b378cf0e4f30479f93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs new file mode 100644 index 000000000..eb5d94713 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs @@ -0,0 +1,250 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + /// + /// Renders the meniscus (waterline). + /// + [System.Serializable] + public sealed partial class Meniscus + { + [@Space(10)] + + [Tooltip("Whether the meniscus is enabled.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [@DecoratedField] + [SerializeField] + internal bool _Enabled = true; + + [Tooltip("Any camera with this layer in its culling mask will render the meniscus.")] + [@Layer] + [@GenerateAPI] + [SerializeField] + int _Layer = 4; // Water + + [Tooltip("The meniscus material.")] + [@AttachMaterialEditor(order: 2)] + [@MaterialField("Crest/Meniscus", name: "Meniscus", title: "Create Meniscus Material")] + [@GenerateAPI(Setter.Custom)] + [SerializeField] + internal Material _Material; + + + WaterRenderer _Water; + + internal MeniscusRenderer Renderer { get; private set; } + + internal bool RequiresOpaqueTexture => Enabled && Material != null && Material.IsKeywordEnabled("d_Crest_Refraction"); + + /// + /// Disables rendering without de-allocating. + /// + public bool ForceRenderingOff { get; set; } + + internal void Enable() + { + Initialize(_Water); + Renderer?.Enable(); + } + + internal void Disable() + { + Renderer?.Disable(); + } + + internal void Destroy() + { + Renderer?.Destroy(); + Renderer = null; + } + + internal void OnActiveRenderPipelineTypeChanged() + { + Destroy(); + Initialize(_Water); + } + + internal void Initialize(WaterRenderer water) + { + _Water = water; + + if (!Enabled) + { + return; + } + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + Renderer ??= new MeniscusRendererHDRP(water, this); + } + else +#endif + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + Renderer ??= new MeniscusRendererURP(water, this); + } + else +#endif + + // Legacy + { + Renderer ??= new MeniscusRendererBIRP(water, this); + } + } + } + + // Getters/Setters + partial class Meniscus + { + bool GetEnabled() + { + return _Enabled && _Material != null; + } + + void SetEnabled(bool previous, bool current) + { + if (previous == current) return; + if (_Water == null || !_Water.isActiveAndEnabled) return; + if (_Enabled) Enable(); else Disable(); + } + + void SetMaterial(Material previous, Material current) + { + if (previous == current) return; + if (_Water == null || !_Water.isActiveAndEnabled) return; + if (previous == null) Enable(); else if (current == null) Disable(); + } + } + + partial class Meniscus + { + internal abstract partial class MeniscusRenderer + { + private protected const string k_Draw = "Crest.DrawWater/Meniscus"; + + private protected readonly WaterRenderer _Water; + internal readonly Meniscus _Meniscus; + + static partial class ShaderIDs + { + public static readonly int s_HorizonNormal = Shader.PropertyToID("_Crest_HorizonNormal"); + } + + public abstract void OnBeginCameraRendering(Camera camera); + public abstract void OnEndCameraRendering(Camera camera); + + public MeniscusRenderer(WaterRenderer water, Meniscus meniscus) + { + _Water = water; + _Meniscus = meniscus; + } + + public virtual void Enable() + { + + } + + public virtual void Disable() + { + + } + + public virtual void Destroy() + { + + } + + internal bool ShouldExecute(Camera camera) + { +#if UNITY_EDITOR + if (GL.wireframe) + { + return false; + } +#endif + + if (_Meniscus.ForceRenderingOff) + { + return false; + } + + // Meniscus is a product of the water surface. + if (!_Water.Surface.Enabled) + { + return false; + } + + if (camera.cameraType is not CameraType.Game and not CameraType.SceneView) + { + return false; + } + + if (!WaterRenderer.ShouldRender(camera, _Meniscus.Layer)) + { + return false; + } + +#if d_CrestPortals + if (_Water.Portals.Active) + { + // Near surface check not compatible with portals. + return true; + } +#endif + + _Water.UpdatePerCameraHeight(camera); + + // Only execute if near the surface. + if (_Water._ViewerHeightAboveWaterPerCamera is > 2f or < -8f) + { + return false; + } + + return true; + } + + internal void Execute(Camera camera, T commands) where T : ICommandWrapper + { + // Project water normal onto camera plane. + _Meniscus.Material.SetVector(ShaderIDs.s_HorizonNormal, new Vector2 + ( + Vector3.Dot(Vector3.up, camera.transform.right), + Vector3.Dot(Vector3.up, camera.transform.up) + )); + + var isFullScreenRequired = true; + var isMasked = false; + var passOffset = 1; + +#if d_CrestPortals + passOffset = (int)Portals.PortalRenderer.MeniscusPass.Length; + + if (_Water.Portals.Active) + { + isMasked = isFullScreenRequired = _Water._Portals.RenderMeniscus(commands, _Meniscus.Material); + } +#endif + + if (isFullScreenRequired) + { + var pass = isMasked ? 1 : 0; + var mpb = _Water.Surface._SurfaceDataMPB; + + if (_Water._Underwater.UseLegacyMask) + { + pass += passOffset; + mpb = null; + } + + commands.DrawFullScreenTriangle(_Meniscus.Material, pass, mpb); + } + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs.meta new file mode 100644 index 000000000..0a08bb790 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Meniscus/Meniscus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df109675493a845f7ad07008e1c1aaaa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Scripting/Extensions.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Scripting/Extensions.cs index 6913cab19..2fe00d128 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Scripting/Extensions.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Scripting/Extensions.cs @@ -23,7 +23,7 @@ namespace WaveHarmonic.Crest var input = gameObject.AddComponent(); input._Mode = mode; // Not all modes have associated data. - if (mode is not LodInputMode.Global or LodInputMode.Primitive or LodInputMode.Unset) AddData(input, mode); + if (mode is not (LodInputMode.Global or LodInputMode.Primitive or LodInputMode.Unset)) AddData(input, mode); input.InferBlend(); return input; } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs new file mode 100644 index 000000000..e04bdd91c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs @@ -0,0 +1,215 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; +using WaveHarmonic.Crest.Internal; + +// Possible improvements: +// - Add quality property +// - Add water level separately (seems fine) +// - Loop over all chunks for larger near clip planes + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + internal const int k_SurfaceDataShaderPass = 2; + + internal static partial class ShaderIDs + { + public static int s_WaterLine = Shader.PropertyToID("_Crest_WaterLine"); + public static int s_WaterLineSnappedPosition = Shader.PropertyToID("_Crest_WaterLineSnappedPosition"); + public static int s_WaterLineResolution = Shader.PropertyToID("_Crest_WaterLineResolution"); + public static int s_WaterLineTexel = Shader.PropertyToID("_Crest_WaterLineTexel"); + } + + RenderTexture _HeightRT; + internal RenderTexture HeightRT { get => _HeightRT; } + + CommandBuffer _BeforeRenderingCommands; + Material _DisplacedMaterial; + + internal struct SurfaceDataParameters + { + public Vector2 _SnappedPosition; + public Vector2 _Resolution; + public float _Texel; + } + + internal SurfaceDataParameters _SurfaceDataParameters; + internal MaterialPropertyBlock _SurfaceDataMPB; + + internal void BindDisplacedSurfaceData(T properties) where T : IPropertyWrapper + { + properties.SetTexture(ShaderIDs.s_WaterLine, HeightRT); + properties.SetVector(ShaderIDs.s_WaterLineSnappedPosition, _SurfaceDataParameters._SnappedPosition); + properties.SetVector(ShaderIDs.s_WaterLineResolution, _SurfaceDataParameters._Resolution); + properties.SetFloat(ShaderIDs.s_WaterLineTexel, _SurfaceDataParameters._Texel); + } + + internal void UpdateDisplacedSurfaceData(Camera camera) + { + // World size of the texture. Formula should effectively cover the camera. + var size = 1f + (camera.nearClipPlane * 2f); + + // Do not use the water position. It will cause a mismatch when using displacement + // correction. + var bounds = new Bounds(camera.transform.position, Vector3.one * size); + + if (_DisplacedMaterial == null) + { + _DisplacedMaterial = new(WaterResources.Instance.Shaders._UnderwaterMask); + } + + _BeforeRenderingCommands ??= new(); + var commands = _BeforeRenderingCommands; + commands.name = "Crest.DrawMask"; + commands.Clear(); + + // TODO: add control so users can set this. + // Diminishing returns beyond 0.0125. + UpdateDisplacedSurfaceData + ( + commands, + bounds, + "_Crest_WaterLine", + ref _HeightRT, + texel: 0.0125f, + out _SurfaceDataParameters + ); + + _SurfaceDataMPB ??= new(); + var wrapper = new PropertyWrapperMPB(_SurfaceDataMPB); + BindDisplacedSurfaceData(wrapper); + + var lod = (int)Builder.PatchType.Interior; + var mpb = _PerCascadeMPB.Current[lod]; + + if (_Water.Viewpoint != camera.transform && Vector3.Distance(_Water.Viewpoint.position, camera.transform.position) > 0.01f) + { + foreach (var chunk in _Water.Surface.Chunks) + { + if (!bounds.IntersectsXZ(chunk.Rend.bounds)) + { + continue; + } + + commands.DrawMesh + ( + chunk._Mesh, + chunk.transform.localToWorldMatrix, + _DisplacedMaterial, + submeshIndex: 0, + shaderPass: k_SurfaceDataShaderPass, + chunk._MaterialPropertyBlock + ); + } + } + else + { + for (var i = 0; i < 4; i++) + { + commands.DrawMesh + ( + _Meshes[lod], + Root.localToWorldMatrix * Matrix4x4.TRS(Builder.s_OffsetsFirstLod[i].XNZ(), Quaternion.identity, Vector3.one), + _DisplacedMaterial, + submeshIndex: 0, + k_SurfaceDataShaderPass, + mpb + ); + } + } + + Graphics.ExecuteCommandBuffer(commands); + } + + internal void UpdateDisplacedSurfaceData(CommandBuffer commands, Bounds bounds, string name, ref RenderTexture target, float texel, out SurfaceDataParameters parameters) + { + var size = bounds.size.XZ(); + var position = bounds.center.XZ(); + + var scale = size; + + // TODO: texel needs to be calculates is clamped + // TODO: aspect ratio + var resolution = new Vector2Int + ( + // TODO: Floor, Ceil or Round? + Mathf.CeilToInt(size.x / texel), + Mathf.CeilToInt(size.y / texel) + ); + + // Snapping for spatial stability. Different results, but could not tell which is + // more accurate. At higher resolution, appears negligable anyway. + var snapped = position - new Vector2(Mathf.Repeat(position.x, texel), Mathf.Repeat(position.y, texel)); + + // Store for binding later. + parameters = new() + { + _SnappedPosition = snapped, + _Resolution = resolution, + _Texel = texel, + }; + + if (resolution.x > 2048 || resolution.y > 2048) + { + return; + } + + // FIXME: LOD scale less than two has cut off and fall off at edges. + var view = WaterRenderer.CalculateViewMatrixFromSnappedPositionRHS(snapped.XNZ()); + var projection = Matrix4x4.Ortho(size.x * -0.5f, size.x * 0.5f, size.y * -0.5f, size.y * 0.5f, 1f, 10000f + 10000f); + + if (target == null) + { + target = new(resolution.x, resolution.y, 0) + { + name = name, + // Needs this precision. + graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat + }; + } + else if (target.width != resolution.x || target.height != resolution.y) + { + target.Release(); + target.width = resolution.x; + target.height = resolution.y; + } + + if (!target.IsCreated()) + { + target.Create(); + } + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + var buffer = new UnityEngine.Rendering.HighDefinition.ShaderVariablesGlobal(); + + projection = GL.GetGPUProjectionMatrix(projection, true); + + // If we want to use camera relative rendering, then we should not set the matrix + // position. Instead set _WorldSpaceCameraPos_Internal. + buffer._ViewProjMatrix = projection * view; + + ConstantBuffer.PushGlobal(commands, buffer, Crest.ShaderIDs.Unity.s_ShaderVariablesGlobal); + } + else +#endif + { + commands.SetViewProjectionMatrices(view, projection); + } + + commands.SetRenderTarget(target); + commands.ClearRenderTarget(true, true, Color.clear); + + // For mask compute, meniscus etc. + commands.SetGlobalTexture(ShaderIDs.s_WaterLine, target); + commands.SetGlobalVector(ShaderIDs.s_WaterLineSnappedPosition, snapped); + commands.SetGlobalVector(ShaderIDs.s_WaterLineResolution, (Vector2)resolution); + commands.SetGlobalFloat(ShaderIDs.s_WaterLineTexel, texel); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs.meta new file mode 100644 index 000000000..fb3b1f9ae --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Displaced.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d53923414758449c896818d2fa45191 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs new file mode 100644 index 000000000..eee19dcd4 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs @@ -0,0 +1,50 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if UNITY_EDITOR + +using UnityEditor; +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + internal void Reset() + { + _Material = AssetDatabase.LoadAssetAtPath("Packages/com.waveharmonic.crest/Runtime/Materials/Water.mat"); + _ChunkTemplate = AssetDatabase.LoadAssetAtPath("Packages/com.waveharmonic.crest/Runtime/Prefabs/Chunk.prefab"); + } + + [@OnChange] + void OnChange(string path, object previous) + { + switch (path) + { + case nameof(_Enabled): + SetEnabled((bool)previous, _Enabled); + break; + case nameof(_Layer): + SetLayer((int)previous, _Layer); + break; + case nameof(_ChunkTemplate): + // We have to rebuild, as we instantiate entire GO. If we restricted it to just a + // MeshRenderer, then we could just replace those. + Rebuild(); + break; + case nameof(_CastShadows): + SetCastShadows((bool)previous, _CastShadows); + break; + case nameof(_AllowRenderQueueSorting): + SetAllowRenderQueueSorting((bool)previous, _AllowRenderQueueSorting); + break; + case nameof(_Debug) + "." + nameof(DebugFields._DisableSkirt): + case nameof(_Debug) + "." + nameof(DebugFields._UniformTiles): + Rebuild(); + break; + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs.meta new file mode 100644 index 000000000..02fa22da7 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Editor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 909d252964c5e41a8893e54eda8d7199 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs new file mode 100644 index 000000000..34cad4e02 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs @@ -0,0 +1,133 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; +using UnityEngine.Rendering.RendererUtils; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + internal sealed class WaterSurfaceCustomPass : CustomPass + { + const string k_Name = "Water Surface"; + + static WaterSurfaceCustomPass s_Instance; + + WaterRenderer _Water; + + // We disable the pass we want, so target another. + ShaderTagId _ShaderTagID = new("DepthOnly"); + + static readonly RenderTargetIdentifier[] s_RenderTargets = new RenderTargetIdentifier[2]; + + public static void Enable(WaterRenderer renderer) + { + var gameObject = CustomPassHelpers.CreateOrUpdate + ( + parent: renderer.Container.transform, + k_Name, + hide: !renderer._Debug._ShowHiddenObjects + ); + + CustomPassHelpers.CreateOrUpdate + ( + gameObject, + ref s_Instance, + WaterRenderer.k_DrawWater, + CustomPassInjectionPoint.BeforeTransparent + ); + + s_Instance._Water = renderer; + + s_Instance.targetColorBuffer = TargetBuffer.Camera; + s_Instance.targetDepthBuffer = TargetBuffer.Camera; + } + + public static void Disable() + { + // It should be safe to rely on this reference for this reference to fail. + if (s_Instance != null && s_Instance._GameObject != null) + { + // Will also trigger Cleanup below. + s_Instance._GameObject.SetActive(false); + } + } + + protected override void Execute(CustomPassContext context) + { + var hdCamera = context.hdCamera; + var camera = hdCamera.camera; + + if (!WaterRenderer.ShouldRender(camera, _Water.Surface.Layer)) + { + return; + } + + // Our reflections do not need them. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + if (_Water.Surface.Material == null) + { + return; + } + + if (hdCamera.msaaEnabled) + { + WaterRenderer.s_CameraMSAA = true; + return; + } + + var buffer = context.cmd; + + buffer.BeginSample(k_DrawWaterSurface); + + s_RenderTargets[0] = context.cameraColorBuffer; + s_RenderTargets[1] = context.cameraMotionVectorsBuffer; + + CoreUtils.SetRenderTarget(buffer, s_RenderTargets, context.cameraDepthBuffer); + + var apv = FrameSettingsField. +#if UNITY_6000_0_OR_NEWER + AdaptiveProbeVolume; +#else + ProbeVolume; +#endif + + var rendererConfiguration = HDUtils.GetRendererConfiguration + ( + context.hdCamera.frameSettings.IsEnabled(apv), + context.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask) + ); + + if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.MotionVectors)) + { + rendererConfiguration |= PerObjectData.MotionVectors; + } + + var rld = new RendererListDesc(_ShaderTagID, context.cullingResults, camera) + { + layerMask = 1 << _Water.Surface.Layer, + overrideShader = _Water.Surface.Material.shader, + overrideShaderPassIndex = _Water.Surface.Material.FindPass("Forward"), + renderQueueRange = RenderQueueRange.transparent, + sortingCriteria = SortingCriteria.CommonOpaque, + excludeObjectMotionVectors = false, + rendererConfiguration = rendererConfiguration, + }; + + buffer.DrawRendererList(context.renderContext.CreateRendererList(rld)); + + buffer.EndSample(k_DrawWaterSurface); + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs.meta new file mode 100644 index 000000000..28893bc54 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 144e7e4c014db437fbf04fcce4ae4aac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs new file mode 100644 index 000000000..80ecbd838 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs @@ -0,0 +1,243 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; +using WaveHarmonic.Crest.Internal; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + partial class ShaderIDs + { + public static readonly int s_DummyTarget = Shader.PropertyToID("_Crest_DummyTarget"); + public static readonly int s_WorldToShadow = Shader.PropertyToID("_Crest_WorldToShadow"); + + public static class Unity + { + public static readonly int s_BuiltInSurface = Shader.PropertyToID("_BUILTIN_Surface"); + public static readonly int s_BuiltInTransparentReceiveShadows = Shader.PropertyToID("_BUILTIN_TransparentReceiveShadows"); + } + } + + CommandBuffer _DrawWaterSurfaceBuffer; + + void OnBeginCameraRenderingLegacy(Camera camera) + { + _Water.UpdateMatrices(camera); + +#if UNITY_EDITOR + if (!Application.isPlaying) + { + OnPreRenderWaterLevelDepthTexture(camera); + } +#endif + + // Everything from here depends on the material being transparent. + if (!IsTransparent(Material)) + { + return; + } + + camera.depthTextureMode |= DepthTextureMode.Depth; + + _DrawWaterSurfaceBuffer ??= new() { name = WaterRenderer.k_DrawWater }; + _DrawWaterSurfaceBuffer.Clear(); + + // Create or update RT. + _Water.OnBeginCameraOpaqueTexture(camera); + + SetUpShadows(camera); + + + if (_Water.RenderBeforeTransparency) + { + Draw(_DrawWaterSurfaceBuffer, camera); + } + + camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _DrawWaterSurfaceBuffer); + } + + void OnEndCameraRenderingLegacy(Camera camera) + { +#if UNITY_EDITOR + if (!Application.isPlaying) + { + OnPostRenderWaterLevelDepthTexture(camera); + } +#endif + + _Water.OnEndCameraOpaqueTexture(camera); + + if (_DrawWaterSurfaceBuffer != null) + { + camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _DrawWaterSurfaceBuffer); + } + + if (QualitySettings.shadows != ShadowQuality.Disable && _Water.PrimaryLight != null) + { + if (_ScreenSpaceShadowMapBuffer != null) + { + _Water.PrimaryLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer); + } + + if (_DeferredShadowMapBuffer != null) + { + _Water.PrimaryLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer); + } + } + + Shader.SetGlobalTexture(Crest.ShaderIDs.Unity.s_ShadowMapTexture, Texture2D.whiteTexture); + } + + // Draws the water surface including lighting. + internal void Draw(CommandBuffer commands, Camera camera) + { + commands.BeginSample(k_DrawWaterSurface); + + CoreUtils.SetRenderTarget(commands, BuiltinRenderTextureType.CameraTarget); + + var sun = RenderSettings.sun; + if (sun != null) + { + // Unity does not set up lighting for us so we will get the last value which could incorrect. + // SetGlobalColor is just an alias for SetGlobalVector (no color space conversion like Material.SetColor): + // https://docs.unity3d.com/2017.4/Documentation/ScriptReference/Shader.SetGlobalColor.html + commands.SetGlobalVector(Crest.ShaderIDs.Unity.s_LightColor0, sun.FinalColor()); + commands.SetGlobalVector(Crest.ShaderIDs.Unity.s_WorldSpaceLightPos0, -sun.transform.forward); + } + + // Always enabled. + commands.SetShaderKeyword("LIGHTPROBE_SH", true); + + UpdateChunkVisibility(camera); + + foreach (var chunk in Chunks) + { + var renderer = chunk.Rend; + + if (chunk.Rend == null) + { + continue; + } + + if (!chunk._Visible) + { + continue; + } + + if (chunk._Culled) + { + continue; + } + + if (!chunk._WaterDataHasBeenBound) + { + chunk.Bind(); + } + + var mpb = new PropertyWrapperMPB(chunk._MaterialPropertyBlock); + mpb.SetSHCoefficients(chunk.transform.position); + commands.DrawMesh(chunk._Mesh, chunk.transform.localToWorldMatrix, renderer.sharedMaterial, 0, 0, chunk._MaterialPropertyBlock); + } + + commands.EndSample(k_DrawWaterSurface); + } + } + + partial class SurfaceRenderer + { + Material _ForceShadowsMaterial; + ComputeBuffer _ShadowMatrixBuffer; + readonly Matrix4x4[] _ShadowMatrixDefaults = { Matrix4x4.zero, Matrix4x4.zero, Matrix4x4.zero, Matrix4x4.zero }; + Material _CaptureShadowMatrices; + + CommandBuffer _DeferredShadowMapBuffer; + CommandBuffer _ScreenSpaceShadowMapBuffer; + + void LegacyOnEnable() + { + _ShadowMatrixBuffer ??= new(4, sizeof(float) * 16, ComputeBufferType.Structured); + _ShadowMatrixBuffer.SetData(_ShadowMatrixDefaults); + } + + void LegacyOnDisable() + { + _ShadowMatrixBuffer?.Dispose(); + _ShadowMatrixBuffer = null; + } + + void SetUpShadows(Camera camera) + { + if (QualitySettings.shadows == ShadowQuality.Disable || _Water.PrimaryLight == null) + { + return; + } + + var transform = camera.transform; + + if (_ForceShadowsMaterial == null) + { + _ForceShadowsMaterial = new Material(WaterResources.Instance.Shaders._ForceShadows); + } + + // Force shadows, as Unity ignores transparent shadow receivers, otherwise shadow + // passes will skip if caster or receiver out of view. ShadowLod also depends on this. + Graphics.RenderMesh + ( + new(_ForceShadowsMaterial) + { + receiveShadows = true, + shadowCastingMode = ShadowCastingMode.Off, + }, + mesh: Helpers.QuadMesh, + submeshIndex: 0, + objectToWorld: QualitySettings.shadowProjection == ShadowProjection.StableFit + ? Matrix4x4.TRS(transform.position + transform.forward, Quaternion.LookRotation(transform.forward), Vector3.one * 0.01f) + // TODO: render water level inputs to support shadows for varying water level. + // Sort of works for close fit. But will decrease shadow quality. + : Matrix4x4.TRS(Vector3.up * _Water.SeaLevel, Quaternion.LookRotation(-Vector3.up), Vector3.one * 100f) + ); + + if (!Material.IsKeywordEnabled("_BUILTIN_TRANSPARENT_RECEIVES_SHADOWS")) + { + return; + } + + if (_CaptureShadowMatrices == null) + { + _CaptureShadowMatrices = new Material(WaterResources.Instance.Shaders._CaptureShadowMatrices); + } + + // Used ComputeBuffer must always be bound! + Shader.SetGlobalBuffer(ShaderIDs.s_WorldToShadow, _ShadowMatrixBuffer); + // Capture shadow matrices, as Unity clears all but the first cascade. + _ScreenSpaceShadowMapBuffer ??= new() { name = WaterRenderer.k_DrawWater }; + _ScreenSpaceShadowMapBuffer.Clear(); + // Cannot set target to None, as it will make some UI black (Unity bug?). + _ScreenSpaceShadowMapBuffer.GetTemporaryRT(ShaderIDs.s_DummyTarget, new RenderTextureDescriptor(4, 4)); + CoreUtils.SetRenderTarget(_ScreenSpaceShadowMapBuffer, ShaderIDs.s_DummyTarget); + // Setting the buffer (SetGlobalBuffer) and writing to it only worked with Metal. + // For other graphics APIs, had to use SetRandomWriteTarget. + _ScreenSpaceShadowMapBuffer.ClearRandomWriteTargets(); + _ScreenSpaceShadowMapBuffer.SetRandomWriteTarget(1, _ShadowMatrixBuffer); + _ScreenSpaceShadowMapBuffer.DrawProcedural(Matrix4x4.identity, _CaptureShadowMatrices, 0, MeshTopology.Triangles, 3); + _ScreenSpaceShadowMapBuffer.ClearRandomWriteTargets(); + _ScreenSpaceShadowMapBuffer.ReleaseTemporaryRT(ShaderIDs.s_DummyTarget); + _Water.PrimaryLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer); + + // Make shadow map available to transparents. + // Call this regardless of rendering path as it has no negative consequences for forward. + _DeferredShadowMapBuffer ??= new() { name = WaterRenderer.k_DrawWater }; + _DeferredShadowMapBuffer.Clear(); + _DeferredShadowMapBuffer.SetGlobalTexture(Crest.ShaderIDs.Unity.s_ShadowMapTexture, BuiltinRenderTextureType.CurrentActive); + _Water.PrimaryLight.AddCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer); + + // Set up shadow keywords. + _DrawWaterSurfaceBuffer.SetKeyword(new("SHADOWS_SINGLE_CASCADE"), QualitySettings.shadowCascades == 1); + _DrawWaterSurfaceBuffer.SetKeyword(new("SHADOWS_SPLIT_SPHERES"), QualitySettings.shadowProjection == ShadowProjection.StableFit); + _DrawWaterSurfaceBuffer.SetKeyword(new("SHADOWS_SOFT"), QualitySettings.shadows == ShadowQuality.All); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs.meta new file mode 100644 index 000000000..613f13307 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Legacy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 729ce6767111740d78a05608c8fb03c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs new file mode 100644 index 000000000..0fd2f3848 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs @@ -0,0 +1,70 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using UnityEngine; +using UnityEngine.Rendering.HighDefinition; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + sealed class WaterLevelDepthTextureHDRP : CustomPass + { + static WaterLevelDepthTextureHDRP s_Instance; + WaterRenderer _Water; + SurfaceRenderer _Surface; + + internal static void Enable(WaterRenderer water, SurfaceRenderer surface) + { + var gameObject = CustomPassHelpers.CreateOrUpdate + ( + parent: water.Container.transform, + k_WaterLevelDepthTextureName, + hide: !water._Debug._ShowHiddenObjects + ); + + CustomPassHelpers.CreateOrUpdate + ( + gameObject, + ref s_Instance, + k_WaterLevelDepthTextureName, + CustomPassInjectionPoint.BeforeRendering + ); + + s_Instance._Water = water; + s_Instance._Surface = surface; + } + + public static void Disable() + { + // It should be safe to rely on this reference for this reference to fail. + if (s_Instance != null && s_Instance._GameObject != null) + { + // Will also trigger Cleanup below. + s_Instance._GameObject.SetActive(false); + } + } + + protected override void Execute(CustomPassContext context) + { + var camera = context.hdCamera.camera; + + if (Application.isPlaying) + { + return; + } + + if (camera.cameraType != CameraType.SceneView || camera != _Water.Viewer) + { + return; + } + + _Surface.ExecuteWaterLevelDepthTexture(camera, context.cmd); + } + } + } +} + +#endif // d_UnityHDRP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs.meta new file mode 100644 index 000000000..c507b4579 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bc32c22349e84f57b3571b886bc8b63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs new file mode 100644 index 000000000..0b4529075 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs @@ -0,0 +1,40 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + CommandBuffer _WaterLevelDepthBuffer; + + void OnPreRenderWaterLevelDepthTexture(Camera camera) + { + if (camera.cameraType != CameraType.SceneView || camera != _Water.Viewer) + { + return; + } + + _WaterLevelDepthBuffer ??= new() { name = k_WaterLevelDepthTextureName }; + _WaterLevelDepthBuffer.Clear(); + + ExecuteWaterLevelDepthTexture(camera, _WaterLevelDepthBuffer); + + // Both forward and deferred. + camera.AddCommandBuffer(CameraEvent.BeforeDepthTexture, _WaterLevelDepthBuffer); + camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, _WaterLevelDepthBuffer); + } + + void OnPostRenderWaterLevelDepthTexture(Camera camera) + { + if (_WaterLevelDepthBuffer != null) + { + // Both forward and deferred. + camera.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, _WaterLevelDepthBuffer); + camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, _WaterLevelDepthBuffer); + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs.meta new file mode 100644 index 000000000..5a10c5f6a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Legacy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb2445377c8974383bd1b3b4afa85646 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs new file mode 100644 index 000000000..d48fcd3de --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs @@ -0,0 +1,86 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityURP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + sealed class WaterLevelDepthTextureURP : ScriptableRenderPass + { + internal static WaterLevelDepthTextureURP s_Instance; + WaterRenderer _Water; + SurfaceRenderer _Surface; + + internal WaterLevelDepthTextureURP() + { + // Will always execute and matrices will be ready. + renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses; + } + + internal static void Enable(WaterRenderer water, SurfaceRenderer surface) + { + s_Instance ??= new(); + s_Instance._Water = water; + s_Instance._Surface = surface; + } + + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + if (Application.isPlaying) + { + return; + } + + if (camera.cameraType != CameraType.SceneView || camera != _Water.Viewer) + { + return; + } + + // Enqueue the pass. This happens every frame. + camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(this); + } + +#if UNITY_6000_0_OR_NEWER + class PassData + { + public UniversalCameraData _CameraData; + public SurfaceRenderer _Surface; + } + + public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) + { + using (var builder = graph.AddUnsafePass(k_WaterLevelDepthTextureName, out var data)) + { + builder.AllowPassCulling(false); + + data._CameraData = frame.Get(); + data._Surface = _Surface; + + builder.SetRenderFunc((data, context) => + { + var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); + _Surface.ExecuteWaterLevelDepthTexture(data._CameraData.camera, buffer); + }); + } + } + + [System.Obsolete] +#endif + public override void Execute(ScriptableRenderContext context, ref RenderingData data) + { + var buffer = CommandBufferPool.Get(k_WaterLevelDepthTextureName); + _Surface.ExecuteWaterLevelDepthTexture(data.cameraData.camera, buffer); + context.ExecuteCommandBuffer(buffer); + CommandBufferPool.Release(buffer); + } + } + } +} + +#endif // d_UnityURP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs.meta new file mode 100644 index 000000000..f50b68d75 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.Universal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8926d03a42e31434eb70caddd59f0466 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs new file mode 100644 index 000000000..e2db06a3b --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs @@ -0,0 +1,84 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// FIXME: Broken for BIRP on MacOS. Either platform specific problem or bug in Unity. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + RenderTexture _WaterLevelDepthTexture; + internal RenderTexture WaterLevelDepthTexture => _WaterLevelDepthTexture; + RenderTargetIdentifier _WaterLevelDepthTarget; + Material _WaterLevelDepthMaterial; + + const string k_WaterLevelDepthTextureName = "Crest Water Level Depth Texture"; + + void ExecuteWaterLevelDepthTexture(Camera camera, CommandBuffer buffer) + { + Helpers.CreateRenderTargetTextureReference(ref _WaterLevelDepthTexture, ref _WaterLevelDepthTarget); + _WaterLevelDepthTexture.name = k_WaterLevelDepthTextureName; + + if (_WaterLevelDepthMaterial == null) + { + _WaterLevelDepthMaterial = new(Shader.Find("Hidden/Crest/Editor/Water Level (Depth)")); + } + + var descriptor = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight) + { + graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.None, + depthBufferBits = 32, + }; + + // Depth buffer. + buffer.GetTemporaryRT(Helpers.ShaderIDs.s_MainTexture, descriptor); + CoreUtils.SetRenderTarget(buffer, Helpers.ShaderIDs.s_MainTexture, ClearFlag.Depth); + + Render(camera, buffer, _WaterLevelDepthMaterial); + + // Depth texture. + // Always release to handle screen size changes. + _WaterLevelDepthTexture.Release(); + descriptor.graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat; + descriptor.depthBufferBits = 0; + Helpers.SafeCreateRenderTexture(ref _WaterLevelDepthTexture, descriptor); + _WaterLevelDepthTexture.Create(); + + // Convert. + Helpers.Blit(buffer, _WaterLevelDepthTarget, Rendering.BIRP.UtilityMaterial, (int)Rendering.BIRP.UtilityPass.Copy); + + buffer.ReleaseTemporaryRT(Helpers.ShaderIDs.s_MainTexture); + } + + void EnableWaterLevelDepthTexture() + { + if (Application.isPlaying) return; + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + WaterLevelDepthTextureURP.Enable(_Water, this); + } +#endif + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + WaterLevelDepthTextureHDRP.Enable(_Water, this); + } +#endif + } + + void DisableWaterLevelDepthTexture() + { + if (Application.isPlaying) return; + +#if d_UnityHDRP + WaterLevelDepthTextureHDRP.Disable(); +#endif + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs.meta new file mode 100644 index 000000000..a50c728f7 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.LevelDepthTexture.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b48c0a50256ea4177ba95870d7a211b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs new file mode 100644 index 000000000..023398fbd --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs @@ -0,0 +1,163 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityURP + +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.RendererUtils; +using UnityEngine.Rendering.Universal; + +namespace WaveHarmonic.Crest +{ + partial class SurfaceRenderer + { + internal sealed class WaterSurfaceRenderPass : ScriptableRenderPass + { + readonly WaterRenderer _Water; + public static WaterSurfaceRenderPass Instance { get; set; } + + // We disable the pass we want, so target another. + ShaderTagId _ShaderTagID = new("DepthOnly"); + + public WaterSurfaceRenderPass(WaterRenderer water) + { + _Water = water; + renderPassEvent = RenderPassEvent.BeforeRenderingTransparents; + + // Copy color happens between "after skybox" and "before transparency". + ConfigureInput(ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth); + } + + public static void Enable(WaterRenderer water) + { +#if UNITY_EDITOR + var data = water.Viewer != null ? water.Viewer.GetUniversalAdditionalCameraData() : null; + + // Type is internal. + if (data != null && data.scriptableRenderer.GetType().Name == "Renderer2D") + { + UnityEditor.EditorUtility.DisplayDialog + ( + "Crest Error!", + "The project has been detected as a URP 2D project. Crest only supports 3D projects. " + + "You may see errors from Crest in the console, and other issues.", + "Ok" + ); + } +#endif + + Instance = new WaterSurfaceRenderPass(water); + } + + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + if (!WaterRenderer.ShouldRender(camera, Instance._Water.Surface.Layer)) + { + return; + } + + // Our reflections do not need them. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + if (Instance._Water.Surface.Material == null) + { + return; + } + + if (!IsTransparent(Instance._Water.Surface.Material)) + { + return; + } + + camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(Instance); + } + +#if UNITY_6000_0_OR_NEWER + class PassData + { + public UnityEngine.Rendering.RenderGraphModule.RendererListHandle _RendererList; + } + + readonly RenderGraphHelper.PassData _PassData = new(); + + public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) + { + if (!_Water.RenderBeforeTransparency) + { + return; + } + + using (var builder = graph.AddRasterRenderPass("Crest.DrawWater/Surface", out var data)) + { + + var resourceData = frame.Get(); + var cameraData = frame.Get(); + var renderingData = frame.Get(); + + // Make inputs show in RG viewer. We configure them already which makes them + // available, but that might change when Unity removes compatibility mode. If that + // happens, we also have to reconsider pass culling to ensure inputs are available + // when rendering to transparent pass. + builder.UseTexture(resourceData.cameraDepthTexture, UnityEngine.Rendering.RenderGraphModule.AccessFlags.Read); + builder.UseTexture(resourceData.cameraOpaqueTexture, UnityEngine.Rendering.RenderGraphModule.AccessFlags.Read); + + // We do not want to use the back buffers, as it will prevent merging? + // This is recommended. Back buffers are used at end of frame typically. + builder.SetRenderAttachment(resourceData.activeColorTexture, 0); + builder.SetRenderAttachmentDepth(resourceData.activeDepthTexture); + + var rld = new RendererListDesc(_ShaderTagID, renderingData.cullResults, cameraData.camera) + { + layerMask = 1 << _Water.Surface.Layer, + overrideShader = _Water.Surface.Material.shader, + overrideShaderPassIndex = 0, // UniversalForward + renderQueueRange = RenderQueueRange.transparent, + sortingCriteria = SortingCriteria.CommonOpaque, + rendererConfiguration = renderingData.perObjectData, + }; + + data._RendererList = graph.CreateRendererList(rld); + builder.UseRendererList(data._RendererList); + + builder.SetRenderFunc((data, context) => + { + context.cmd.DrawRendererList(data._RendererList); + }); + } + } + + [System.Obsolete] +#endif + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + if (!_Water.RenderBeforeTransparency) + { + return; + } + + var buffer = CommandBufferPool.Get("Crest.DrawWater/Surface"); + + var rld = new RendererListDesc(_ShaderTagID, renderingData.cullResults, renderingData.cameraData.camera) + { + layerMask = 1 << _Water.Surface.Layer, + overrideShader = _Water.Surface.Material.shader, + overrideShaderPassIndex = 0, // UniversalForward + renderQueueRange = RenderQueueRange.transparent, + sortingCriteria = SortingCriteria.CommonOpaque, + rendererConfiguration = renderingData.perObjectData, + }; + + buffer.DrawRendererList(context.CreateRendererList(rld)); + + context.ExecuteCommandBuffer(buffer); + CommandBufferPool.Release(buffer); + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs.meta new file mode 100644 index 000000000..32ddb73e4 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.Universal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ea612be74ded47e5a970d7e4e8d540a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs new file mode 100644 index 000000000..26f446692 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs @@ -0,0 +1,858 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System.Buffers; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; +using WaveHarmonic.Crest.Utility; + +namespace WaveHarmonic.Crest +{ + /// + /// Renders the water surface. + /// + [System.Serializable] + public sealed partial class SurfaceRenderer + { + [SerializeField, HideInInspector] +#pragma warning disable 414 + int _Version = 0; +#pragma warning restore 414 + + [@Space(10)] + + [Tooltip("Whether the underwater effect is enabled.\n\nAllocates/releases resources if state has changed.")] + [@GenerateAPI(Getter.Custom, Setter.Custom)] + [@DecoratedField, SerializeField] + internal bool _Enabled = true; + + [Tooltip("The water chunk renderers will have this layer.")] + [@Layer] + [@GenerateAPI] + [SerializeField] + internal int _Layer = 4; // Water + + [Tooltip("Material to use for the water surface.")] + [@AttachMaterialEditor(order: 0)] + [@MaterialField("Crest/Water", name: "Water", title: "Create Water Material")] + [@GenerateAPI] + [SerializeField] + internal Material _Material = null; + + [Tooltip("Underwater will copy from this material if set.\n\nUseful for overriding properties for the underwater effect. To see what properties can be overriden, see the disabled properties on the underwater material. This does not affect the surface.")] + [@AttachMaterialEditor(order: 1)] + [@MaterialField("Crest/Water", name: "Water (Below)", title: "Create Water Material", parent: "_Material")] + [@GenerateAPI] + [SerializeField] + internal Material _VolumeMaterial = null; + + [Tooltip("Template for water chunks as a prefab.\n\nThe only requirements are that the prefab must contain a MeshRenderer at the root and not a MeshFilter or WaterChunkRenderer. MR values will be overwritten where necessary and the prefabs are linked in edit mode.")] + [@PrefabField(title: "Create Chunk Prefab", name: "Water Chunk")] + [SerializeField] + internal GameObject _ChunkTemplate; + + [@Space(10)] + + [Tooltip("Have the water surface cast shadows for albedo (both foam and custom).")] + [@GenerateAPI(Getter.Custom)] + [@DecoratedField, SerializeField] + internal bool _CastShadows; + + [@Heading("Culling")] + + [Tooltip("Whether 'Water Body' components will cull the water tiles.\n\nDisable if you want to use the 'Material Override' feature and still have an ocean.")] + [@GenerateAPI] + [@DecoratedField, SerializeField] + internal bool _WaterBodyCulling = true; + + [Tooltip("How many frames to distribute the chunk bounds calculation.\n\nThe chunk bounds are calculated per frame to ensure culling is correct when using inputs that affect displacement. Some performance can be saved by distributing the load over several frames. The higher the frames, the longer it will take - lowest being instant.")] + [@Range(1, 30, Range.Clamp.Minimum)] + [@GenerateAPI] + [SerializeField] + internal int _TimeSliceBoundsUpdateFrameCount = 1; + + [@Heading("Advanced")] + + [Tooltip("How to handle self-intersections of the water surface.\n\nThey can be caused by choppy waves which can cause a flipped underwater effect. When not using the portals/volumes, this fix is only applied when within 2 metres of the water surface. Automatic will disable the fix if portals/volumes are used which is the recommend setting.")] + [@DecoratedField, SerializeField] + internal SurfaceSelfIntersectionFixMode _SurfaceSelfIntersectionFixMode = SurfaceSelfIntersectionFixMode.Automatic; + + [Tooltip("Whether to allow sorting using the render queue.\n\nIf you need to change the minor part of the render queue (eg +100), then enable this option. As a side effect, it will also disable the front-to-back rendering optimization for Crest. This option does not affect changing the major part of the render queue (eg AlphaTest, Transparent), as that is always allowed.\n\nRender queue sorting is required for some third-party integrations.")] + [@Predicated(RenderPipeline.HighDefinition, inverted: true, hide: true)] + [@GenerateAPI] + [@DecoratedField, SerializeField] + internal bool _AllowRenderQueueSorting; + + [@Space(10)] + +#if !CREST_DEBUG + [HideInInspector] +#endif + [@DecoratedField, SerializeField] + internal DebugFields _Debug = new(); + + [System.Serializable] + internal sealed class DebugFields + { +#if !CREST_DEBUG + [HideInInspector] +#endif + [Tooltip("Whether to generate water geometry tiles uniformly (with overlaps).")] + [@DecoratedField, SerializeField] + public bool _UniformTiles; + +#if !CREST_DEBUG + [HideInInspector] +#endif + [Tooltip("Disable generating a wide strip of triangles at the outer edge to extend water to edge of view frustum.")] + [@DecoratedField, SerializeField] + public bool _DisableSkirt; + } + + const string k_DrawWaterSurface = "Surface"; + + internal WaterRenderer _Water; + internal Transform Root { get; private set; } + internal List Chunks { get; } = new(); + internal bool _Rebuild; + + + // + // Level of Detail + // + + // Extra frame is for motion vectors. + internal BufferedData _PerCascadeMPB = new(2, () => new MaterialPropertyBlock[Lod.k_MaximumSlices]); + + // We are computing these values to be optimal based on the base mesh vertex density. + float _LodAlphaBlackPointFade; + float _LodAlphaBlackPointWhitePointFade; + + + // + // Culling + // + + internal readonly Plane[] _CameraFrustumPlanes = new Plane[6]; + bool _CanSkipCulling; + internal bool _DoneChunkVisibility; + + + // + // Events + // + + /// + /// Invoked after water chunk modification. + /// + /// + /// Gives an opportunity to modify the renderer. + /// + public static System.Action OnCreateChunkRenderer { get; set; } + + + internal Material _MotionVectorMaterial; + + internal Material AboveOrBelowSurfaceMaterial => _VolumeMaterial == null ? _Material : _VolumeMaterial; + + + // + // Facing + // + + internal enum SurfaceSelfIntersectionFixMode + { + [Tooltip("Uses VFACE/IsFrontFace.")] + Off, + + [Tooltip("Force entire water surface to render as below water.")] + ForceBelowWater, + + [Tooltip("Force entire water surface to render as above water.")] + ForceAboveWater, + + [Tooltip("Force entire water surface to render as above or below water if beyond a distance from surface, otherwise use mask/facing.")] + On, + + [Tooltip("Force entire water surface to render as above or below water if beyond a distance from surface (except in special circumstances like Portals).")] + Automatic, + } + + enum ForceFacing + { + None, + BelowWater, + AboveWater, + Facing, + } + + + static partial class ShaderIDs + { + public static readonly int s_ForceUnderwater = Shader.PropertyToID("g_Crest_ForceUnderwater"); + public static readonly int s_LodAlphaBlackPointFade = Shader.PropertyToID("g_Crest_LodAlphaBlackPointFade"); + public static readonly int s_LodAlphaBlackPointWhitePointFade = Shader.PropertyToID("g_Crest_LodAlphaBlackPointWhitePointFade"); + + public static readonly int s_BuiltShadowCasterZTest = Shader.PropertyToID("_Crest_BUILTIN_ShadowCasterZTest"); + + public static readonly int s_ChunkMeshScaleAlpha = Shader.PropertyToID("_Crest_ChunkMeshScaleAlpha"); + public static readonly int s_ChunkGeometryGridWidth = Shader.PropertyToID("_Crest_ChunkGeometryGridWidth"); + public static readonly int s_ChunkFarNormalsWeight = Shader.PropertyToID("_Crest_ChunkFarNormalsWeight"); + public static readonly int s_ChunkNormalScrollSpeed = Shader.PropertyToID("_Crest_ChunkNormalScrollSpeed"); + public static readonly int s_ChunkMeshScaleAlphaSource = Shader.PropertyToID("_Crest_ChunkMeshScaleAlphaSource"); + public static readonly int s_ChunkGeometryGridWidthSource = Shader.PropertyToID("_Crest_ChunkGeometryGridWidthSource"); + } + + internal void Initialize() + { + Root = Builder.GenerateMesh(_Water, this, Chunks, _Water.LodResolution, _Water._GeometryDownSampleFactor, _Water.LodLevels); + + Root.position = _Water.Position; + Root.localScale = new(_Water.Scale, 1f, _Water.Scale); + + // Populate MPBs with defaults. + for (var index = 0; index < _Water.LodLevels; index++) + { + for (var frame = 0; frame < 2; frame++) + { + var mpb = new MaterialPropertyBlock(); + mpb.SetInteger(Lod.ShaderIDs.s_LodIndex, index); + mpb.SetFloat(ShaderIDs.s_ChunkFarNormalsWeight, 1f); + mpb.SetFloat(ShaderIDs.s_ChunkMeshScaleAlpha, 0f); + mpb.SetFloat(ShaderIDs.s_ChunkMeshScaleAlphaSource, 0f); + _PerCascadeMPB.Previous(frame)[index] = mpb; + } + } + + // Resolution is 4 tiles across. + var baseMeshDensity = _Water.LodResolution * 0.25f / _Water._GeometryDownSampleFactor; + // 0.4f is the "best" value when base mesh density is 8. Scaling down from there produces results similar to + // hand crafted values which looked good when the water is flat. + _LodAlphaBlackPointFade = 0.4f / (baseMeshDensity / 8f); + _LodAlphaBlackPointWhitePointFade = 1f - _LodAlphaBlackPointFade - _LodAlphaBlackPointFade; + + Shader.SetGlobalFloat(ShaderIDs.s_LodAlphaBlackPointFade, _LodAlphaBlackPointFade); + Shader.SetGlobalFloat(ShaderIDs.s_LodAlphaBlackPointWhitePointFade, _LodAlphaBlackPointWhitePointFade); + + UpdateMaterial(_Material, ref _MotionVectorMaterial); + + _CanSkipCulling = false; + + if (RenderPipelineHelper.IsLegacy) + { + LegacyOnEnable(); + } + +#if UNITY_EDITOR + EnableWaterLevelDepthTexture(); +#endif + } + + internal void OnDestroy() + { +#if UNITY_EDITOR + DisableWaterLevelDepthTexture(); +#endif + + // Clean up everything created through the Water Builder. + // Not every mesh is assigned to a chunk thus we should destroy all of them here. + for (var i = 0; i < _Meshes?.Length; i++) + { + Helpers.Destroy(_Meshes[i]); + } + + Chunks.Clear(); + CoreUtils.Destroy(_MotionVectorMaterial); + CoreUtils.Destroy(_DisplacedMaterial); + + if (Root != null) + { + CoreUtils.Destroy(Root.gameObject); + Root = null; + } + + if (RenderPipelineHelper.IsLegacy) + { + LegacyOnDisable(); + } + } + + void ShowHiddenObjects(bool show) + { + foreach (var chunk in Chunks) + { + chunk.gameObject.hideFlags = show ? HideFlags.DontSave : HideFlags.HideAndDontSave; + } + } + + // Chunk Visibility. + // check if needed here + // complicated. cos we would have to either check everything that may need it + // or have a loop going over an abstraction + internal void UpdateChunkVisibility(Camera camera) + { + if (_DoneChunkVisibility) + { + return; + } + + GeometryUtility.CalculateFrustumPlanes(camera, _CameraFrustumPlanes); + + foreach (var chunk in Chunks) + { + var renderer = chunk.Rend; + // Can happen in edit mode. + if (renderer == null) continue; + chunk._Visible = GeometryUtility.TestPlanesAABB(_CameraFrustumPlanes, renderer.bounds); + } + + _DoneChunkVisibility = true; + } + + internal void UpdateMaterial(Material material, ref Material motion) + { + if (material == null) + { + return; + } + + var enable = !_Water.RenderBeforeTransparency; + material.SetShaderPassEnabled("Forward", enable); + material.SetShaderPassEnabled("ForwardAdd", enable); + material.SetShaderPassEnabled("ForwardBase", enable); + material.SetShaderPassEnabled("UniversalForward", enable); + + // HDRP will automatically disable this pass for unknown reasons. It might be that + // we are sampling from the depth texture which does not work with shadow casting. + if (RenderPipelineHelper.IsHighDefinition) + { + material.SetShaderPassEnabled("ShadowCaster", _CastShadows); + } + + UpdateMotionVectorsMaterial(material, ref motion); + } + + internal static bool IsTransparent(Material material) + { + return RenderPipelineHelper.IsLegacy + ? material.IsKeywordEnabled("_BUILTIN_SURFACE_TYPE_TRANSPARENT") + : material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT"); + } + + void Rebuild() + { + OnDestroy(); + Initialize(); + _Rebuild = false; + } + + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + if (!WaterRenderer.ShouldRender(camera, Layer)) + { + return; + } + + // Our planar reflection camera must never render the surface. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + if (Material == null) + { + return; + } + + WritePerCameraMaterialParameters(camera); + + // Motion Vectors. + if (ShouldRenderMotionVectors(camera) && _QueueMotionVectors) + { + UpdateChunkVisibility(camera); + + foreach (var chunk in Chunks) + { + chunk.RenderMotionVectors(this, camera); + } + } + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { +#if UNITY_EDITOR + WaterLevelDepthTextureURP.s_Instance?.OnBeginCameraRendering(context, camera); +#endif + WaterSurfaceRenderPass.Instance?.OnBeginCameraRendering(context, camera); + } + else +#endif + + if (RenderPipelineHelper.IsLegacy) + { + OnBeginCameraRenderingLegacy(camera); + } + } + + internal void OnEndCameraRendering(Camera camera) + { + _DoneChunkVisibility = false; + + if (!WaterRenderer.ShouldRender(camera, Layer)) + { + return; + } + + // Our planar reflection camera must never render the surface. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + if (RenderPipelineHelper.IsLegacy) + { + OnEndCameraRenderingLegacy(camera); + } + } + + void WritePerCameraMaterialParameters(Camera camera) + { + if (Material == null) + { + return; + } + + // If no underwater, then no need for underwater surface. + if (!_Water.Underwater.Enabled) + { + Shader.SetGlobalInteger(ShaderIDs.s_ForceUnderwater, (int)ForceFacing.AboveWater); + return; + } + + _Water.UpdatePerCameraHeight(camera); + + // Override isFrontFace when camera is far enough from the water surface to fix self-intersecting waves. + // Hack - due to SV_IsFrontFace occasionally coming through as true for back faces, + // add a param here that forces water to be in underwater state. I think the root + // cause here might be imprecision or numerical issues at water tile boundaries, although + // i'm not sure why cracks are not visible in this case. + var height = _Water._ViewerHeightAboveWaterPerCamera; + + var value = _SurfaceSelfIntersectionFixMode switch + { + SurfaceSelfIntersectionFixMode.On => + height < -2f + ? ForceFacing.BelowWater + : height > 2f + ? ForceFacing.AboveWater + : ForceFacing.None, + // Skip for portals as it is possible to see both sides of the surface at any position. + SurfaceSelfIntersectionFixMode.Automatic => + _Water.Portaled + ? ForceFacing.None + : height < -2f + ? ForceFacing.BelowWater + : height > 2f + ? ForceFacing.AboveWater + : ForceFacing.None, + // Always use facing (VFACE). + SurfaceSelfIntersectionFixMode.Off => ForceFacing.Facing, + _ => (ForceFacing)_SurfaceSelfIntersectionFixMode, + }; + + Shader.SetGlobalInteger(ShaderIDs.s_ForceUnderwater, (int)value); + } + + internal void LateUpdate() + { + if (_Rebuild) + { + Rebuild(); + } + + Root.position = _Water.Position; + Root.localScale = new(_Water.Scale, 1f, _Water.Scale); + + _PerCascadeMPB.Flip(); + WritePerCascadeInstanceData(); + + foreach (var chunk in Chunks) + { + chunk.UpdateMeshBounds(_Water, this); + } + + ApplyWaterBodyCulling(); + + LateUpdateMotionVectors(); + + UpdateMaterial(_Material, ref _MotionVectorMaterial); + + foreach (var body in WaterBody.WaterBodies) + { + if (body._Material != null) + { + UpdateMaterial(body._Material, ref body._MotionVectorMaterial); + } + } + + foreach (var chunk in Chunks) + { + chunk.OnLateUpdate(); + } + } + + void WritePerCascadeInstanceData() + { + var levels = _Water.LodLevels; + var texel = _Water.LodResolution * 0.25f / _Water._GeometryDownSampleFactor; + var mpbsCurrent = _PerCascadeMPB.Current; + var mpbsPrevious = _PerCascadeMPB.Previous(1); + + // LOD 0 + { + var mpb = mpbsCurrent[0]; + + if (_Water.WriteMotionVectors) + { + // NOTE: it may be more optimal to store in an array than fetching from MPB. + mpb.SetFloat(ShaderIDs.s_ChunkMeshScaleAlphaSource, mpbsPrevious[0].GetFloat(ShaderIDs.s_ChunkMeshScaleAlpha)); + } + + // Blend LOD 0 shape in/out to avoid pop, if scale could increase. + mpb.SetFloat(ShaderIDs.s_ChunkMeshScaleAlpha, _Water.ScaleCouldIncrease ? _Water.ViewerAltitudeLevelAlpha : 0f); + } + + // LOD N + { + var mpb = mpbsCurrent[levels - 1]; + + // Blend furthest normals scale in/out to avoid pop, if scale could reduce. + mpb.SetFloat(ShaderIDs.s_ChunkFarNormalsWeight, _Water.ScaleCouldDecrease ? _Water.ViewerAltitudeLevelAlpha : 1f); + } + + for (var index = 0; index < levels; index++) + { + var mpbCurrent = mpbsCurrent[index]; + var mpbPrevious = mpbsPrevious[index]; + + // geometry data + // compute grid size of geometry. take the long way to get there - make sure we land exactly on a power of two + // and not inherit any of the lossy-ness from lossyScale. + var scale = _Water._CascadeData.Current[index].x; + var width = scale / texel; + + if (_Water.WriteMotionVectors) + { + // NOTE: it may be more optimal to store in an array than fetching from MPB. + mpbPrevious.SetFloat(ShaderIDs.s_ChunkGeometryGridWidthSource, mpbCurrent.GetFloat(ShaderIDs.s_ChunkGeometryGridWidth)); + } + + mpbCurrent.SetFloat(ShaderIDs.s_ChunkGeometryGridWidth, width); + + var mul = 1.875f; // fudge 1 + var pow = 1.4f; // fudge 2 + var texelWidth = width / _Water._GeometryDownSampleFactor; + mpbCurrent.SetVector(ShaderIDs.s_ChunkNormalScrollSpeed, new + ( + Mathf.Pow(Mathf.Log(1f + 2f * texelWidth) * mul, pow), + Mathf.Pow(Mathf.Log(1f + 4f * texelWidth) * mul, pow), + 0, + 0 + )); + } + } + + void ApplyWaterBodyCulling() + { + var canSkipCulling = WaterBody.WaterBodies.Count == 0 && _CanSkipCulling; + + // Chunk bounds needs to be up-to-date at this point. + foreach (var tile in Chunks) + { + if (tile.Rend == null) + { + continue; + } + + tile._Culled = false; + tile.MaterialOverridden = false; + + // If there are local bodies of water, this will do overlap tests between the water tiles + // and the water bodies and turn off any that don't overlap. + if (!canSkipCulling) + { + var chunkBounds = tile.Rend.bounds; + var chunkUndisplacedBoundsXZ = tile.UnexpandedBoundsXZ; + + var largestOverlap = 0f; + var overlappingOne = false; + foreach (var body in WaterBody.WaterBodies) + { + // If tile has already been excluded from culling, then skip this iteration. But finish this + // iteration if the water body has a material override to work out most influential water body. + if (overlappingOne && body.AboveSurfaceMaterial == null) + { + continue; + } + + var bounds = body.AABB; + + var overlapping = + bounds.max.x > chunkBounds.min.x && bounds.min.x < chunkBounds.max.x && + bounds.max.z > chunkBounds.min.z && bounds.min.z < chunkBounds.max.z; + if (overlapping) + { + overlappingOne = true; + + if (body.AboveSurfaceMaterial != null) + { + var overlap = 0f; + { + // Use the unexpanded bounds to prevent leaking as generally this feature will be + // for an inland body of water where hopefully there is attenuation between it and + // the water to handle the water's displacement. The inland water body will unlikely + // have large displacement but can be mitigated with a decent buffer zone. + var xMin = Mathf.Max(bounds.min.x, chunkUndisplacedBoundsXZ.min.x); + var xMax = Mathf.Min(bounds.max.x, chunkUndisplacedBoundsXZ.max.x); + var zMin = Mathf.Max(bounds.min.z, chunkUndisplacedBoundsXZ.min.y); + var zMax = Mathf.Min(bounds.max.z, chunkUndisplacedBoundsXZ.max.y); + if (xMin < xMax && zMin < zMax) + { + overlap = (xMax - xMin) * (zMax - zMin); + } + } + + // If this water body has the most overlap, then the chunk will get its material. + if (overlap > largestOverlap) + { + tile.MaterialOverridden = true; + tile.Rend.sharedMaterial = body.AboveSurfaceMaterial; + tile._MotionVectorMaterial = body._MotionVectorMaterial; + largestOverlap = overlap; + } + } + else + { + tile.MaterialOverridden = false; + } + } + } + + tile._Culled = _WaterBodyCulling && !overlappingOne && WaterBody.WaterBodies.Count > 0; + } + + tile.Rend.enabled = !tile._Culled; + } + + // Can skip culling next time around if water body count stays at 0 + _CanSkipCulling = WaterBody.WaterBodies.Count == 0; + } + + internal void Render(Camera camera, CommandBuffer buffer, Material material = null, int pass = 0, bool culled = false) + { + var noMaterial = material == null; + + if (noMaterial && Material == null) + { + return; + } + + UpdateChunkVisibility(camera); + + // Spends approx 0.2-0.3ms here on 2018 Dell XPS 15. + foreach (var chunk in Chunks) + { + var renderer = chunk.Rend; + + // Can happen in edit mode. + if (renderer == null) + { + continue; + } + + if (!chunk._Visible) + { + continue; + } + + if (culled && chunk._Culled) + { + continue; + } + + // Make sure properties are bound for this frame. + if (!chunk._WaterDataHasBeenBound) + { + chunk.Bind(); + } + + if (noMaterial) + { + material = renderer.sharedMaterial; + } + + buffer.DrawRenderer(renderer, material, submeshIndex: 0, pass); + } + } + } + + // API + partial class SurfaceRenderer + { + bool GetEnabled() + { + return _Enabled && !_Water.IsRunningWithoutGraphics; + } + + void SetEnabled(bool previous, bool current) + { + if (previous == current) return; + if (_Water == null || !_Water.isActiveAndEnabled) return; + if (_Enabled) Initialize(); else OnDestroy(); + } + + void SetLayer(int previous, int current) + { + if (previous == current) return; + + foreach (var chunk in Chunks) + { + chunk.gameObject.layer = current; + } + } + + bool GetCastShadows() + { + return _CastShadows; + } + + void SetCastShadows(bool previous, bool current) + { + if (previous == current) return; + + foreach (var chunk in Chunks) + { + chunk.Rend.shadowCastingMode = current ? ShadowCastingMode.On : ShadowCastingMode.Off; + } + } + + void SetAllowRenderQueueSorting(bool previous, bool current) + { + if (previous == current) return; + + foreach (var chunk in Chunks) + { + chunk.Rend.sortingOrder = current ? chunk._SortingOrder : 0; + } + } + } + + // Motion Vectors + partial class SurfaceRenderer + { + bool _QueueMotionVectors; + + bool ShouldRenderMotionVectors(Camera camera) + { + // Unity enables this when motion vectors are used - even for SRPs. + if (!camera.depthTextureMode.HasFlag(DepthTextureMode.MotionVectors)) + { + return false; + } + + return true; + } + + void LateUpdateMotionVectors() + { + _QueueMotionVectors = false; + + // Handled by Unity. + if (RenderPipelineHelper.IsHighDefinition) + { + return; + } + + if (!Application.isPlaying) + { + return; + } + + if (!_Water.WriteMotionVectors) + { + return; + } + + // This will not support WBs with material overrides, but mixing opaque and + // transparent would be odd. + if (!IsTransparent(Material)) + { + return; + } + + var pool = ArrayPool.Shared; + var cameras = pool.Rent(Camera.allCamerasCount); + Camera.GetAllCameras(cameras); + + for (var i = 0; i < Camera.allCamerasCount; i++) + { + var camera = cameras[i]; + + if (!WaterRenderer.ShouldRender(camera, _Layer)) + { + continue; + } + + if (!ShouldRenderMotionVectors(camera)) + { + continue; + } + + _QueueMotionVectors = true; + } + + pool.Return(cameras); + } + + void UpdateMotionVectorsMaterial(Material surface, ref Material motion) + { + if (!_QueueMotionVectors) + { + return; + } + + if (motion == null || motion.shader != surface.shader) + { + CoreUtils.Destroy(motion); + motion = CoreUtils.CreateEngineMaterial(surface.shader); + + // BIRP + motion.SetShaderPassEnabled("ForwardBase", false); + motion.SetShaderPassEnabled("ForwardAdd", false); + motion.SetShaderPassEnabled("Deferred", false); + + // URP + motion.SetShaderPassEnabled("UniversalForward", false); + motion.SetShaderPassEnabled("UniversalGBuffer", false); + motion.SetShaderPassEnabled("Universal2D", false); + + motion.SetShaderPassEnabled("ShadowCaster", false); + motion.SetShaderPassEnabled("DepthOnly", false); + motion.SetShaderPassEnabled("DepthNormals", false); + motion.SetShaderPassEnabled("Meta", false); + motion.SetShaderPassEnabled("SceneSelectionPass", false); + motion.SetShaderPassEnabled("Picking", false); + motion.SetShaderPassEnabled("MotionVectors", true); + } + + motion.CopyMatchingPropertiesFromMaterial(surface); + motion.renderQueue = (int)RenderQueue.Geometry; + motion.SetOverrideTag("RenderType", "Opaque"); + motion.SetFloat(Crest.ShaderIDs.Unity.s_Surface, 0); // SurfaceType.Opaque + motion.SetFloat(Crest.ShaderIDs.Unity.s_SrcBlend, 1); + motion.SetFloat(Crest.ShaderIDs.Unity.s_DstBlend, 0); + motion.SetFloat(ShaderIDs.s_BuiltShadowCasterZTest, 1); // ZTest Never + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs.meta new file mode 100644 index 000000000..f4074044c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/SurfaceRenderer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 212222792a1a241d889bed1dc799ba37 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBody.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBody.cs index a3c9e665c..efc9884dc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBody.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBody.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System.Collections.Generic; @@ -42,7 +42,7 @@ namespace WaveHarmonic.Crest internal Material _BelowSurfaceMaterial; [Tooltip("Overrides the Water Renderer's volume material when the camera is inside the bounds.")] - [@MaterialField("Crest/Underwater", name: "Underwater", title: "Create Underwater Material")] + [@MaterialField(UnderwaterRenderer.k_ShaderNameEffect, name: "Underwater", title: "Create Underwater Material")] [@AttachMaterialEditor] [@GenerateAPI] [SerializeField] @@ -52,13 +52,14 @@ namespace WaveHarmonic.Crest bool _RecalculateRect = true; bool _RecalculateBounds = true; + internal Material _MotionVectorMaterial; sealed class ClipInput : ILodInput { readonly WaterBody _Owner; readonly Transform _Transform; - public bool Enabled => WaterRenderer.Instance._ClipLod._DefaultClippingState == DefaultClippingState.EverythingClipped; + public bool Enabled => WaterRenderer.Instance != null && WaterRenderer.Instance._ClipLod._DefaultClippingState == DefaultClippingState.EverythingClipped; public bool IsCompute => true; public int Pass => -1; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBuilder.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBuilder.cs index af6c598b5..0e7a708bc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBuilder.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterBuilder.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. //#define PROFILE_CONSTRUCTION @@ -9,529 +9,529 @@ using UnityEngine.Rendering; namespace WaveHarmonic.Crest { - /// - /// Instantiates all the water geometry, as a set of tiles. - /// - static class WaterBuilder + partial class SurfaceRenderer { - // The comments below illustrate case when BASE_VERT_DENSITY = 2. The water mesh is built up from these patches. Rotational symmetry - // is used where possible to eliminate combinations. The slim variants are used to eliminate overlap between patches. - enum PatchType - { - /// - /// Adds no skirt. Used in interior of highest detail LOD (0) - /// - /// 1 ------- - /// | | | - /// z ------- - /// | | | - /// 0 ------- - /// 0 1 - /// x - /// - /// - Interior, - - /// - /// Adds a full skirt all of the way around a patch - /// - /// ------------- - /// | | | | | - /// 1 ------------- - /// | | | | | - /// z ------------- - /// | | | | | - /// 0 ------------- - /// | | | | | - /// ------------- - /// 0 1 - /// x - /// - /// - Fat, - - /// - /// Adds a skirt on the right hand side of the patch - /// - /// 1 ---------- - /// | | | | - /// z ---------- - /// | | | | - /// 0 ---------- - /// 0 1 - /// x - /// - /// - FatX, - - /// - /// Adds a skirt on the right hand side of the patch, removes skirt from top - /// - FatXSlimZ, - - /// - /// Outer most side - this adds an extra skirt on the left hand side of the patch, - /// which will point outwards and be extended to Zfar - /// - /// 1 -------------------------------------------------------------------------------------- - /// | | | | - /// z -------------------------------------------------------------------------------------- - /// | | | | - /// 0 -------------------------------------------------------------------------------------- - /// 0 1 - /// x - /// - /// - FatXOuter, - - /// - /// Adds skirts at the top and right sides of the patch - /// - FatXZ, - - /// - /// Adds skirts at the top and right sides of the patch and pushes them to horizon - /// - FatXZOuter, - - /// - /// One less set of verts in x direction - /// - SlimX, - - /// - /// One less set of verts in both x and z directions - /// - SlimXZ, - - /// - /// One less set of verts in x direction, extra verts at start of z direction - /// - /// ---- - /// | | - /// 1 ---- - /// | | - /// z ---- - /// | | - /// 0 ---- - /// 0 1 - /// x - /// - /// - SlimXFatZ, - - /// - /// Number of patch types - /// - Count, - } - // Keep references to meshes so they can be cleaned up later. - static Mesh[] s_Meshes; + readonly Mesh[] _Meshes = new Mesh[(int)Builder.PatchType.Count]; /// - /// Destroy tiles and any resources. + /// Instantiates all the water geometry, as a set of tiles. /// - public static void CleanUp(WaterRenderer water) + static class Builder { - // Not every mesh is assigned to a chunk thus we should destroy all of them here. - for (var i = 0; i < s_Meshes?.Length; i++) + // The comments below illustrate case when BASE_VERT_DENSITY = 2. The water mesh is built up from these patches. Rotational symmetry + // is used where possible to eliminate combinations. The slim variants are used to eliminate overlap between patches. + internal enum PatchType { - Helpers.Destroy(s_Meshes[i]); + /// + /// Adds no skirt. Used in interior of highest detail LOD (0) + /// + /// 1 ------- + /// | | | + /// z ------- + /// | | | + /// 0 ------- + /// 0 1 + /// x + /// + /// + Interior, + + /// + /// Adds a full skirt all of the way around a patch + /// + /// ------------- + /// | | | | | + /// 1 ------------- + /// | | | | | + /// z ------------- + /// | | | | | + /// 0 ------------- + /// | | | | | + /// ------------- + /// 0 1 + /// x + /// + /// + Fat, + + /// + /// Adds a skirt on the right hand side of the patch + /// + /// 1 ---------- + /// | | | | + /// z ---------- + /// | | | | + /// 0 ---------- + /// 0 1 + /// x + /// + /// + FatX, + + /// + /// Adds a skirt on the right hand side of the patch, removes skirt from top + /// + FatXSlimZ, + + /// + /// Outer most side - this adds an extra skirt on the left hand side of the patch, + /// which will point outwards and be extended to Zfar + /// + /// 1 -------------------------------------------------------------------------------------- + /// | | | | + /// z -------------------------------------------------------------------------------------- + /// | | | | + /// 0 -------------------------------------------------------------------------------------- + /// 0 1 + /// x + /// + /// + FatXOuter, + + /// + /// Adds skirts at the top and right sides of the patch + /// + FatXZ, + + /// + /// Adds skirts at the top and right sides of the patch and pushes them to horizon + /// + FatXZOuter, + + /// + /// One less set of verts in x direction + /// + SlimX, + + /// + /// One less set of verts in both x and z directions + /// + SlimXZ, + + /// + /// One less set of verts in x direction, extra verts at start of z direction + /// + /// ---- + /// | | + /// 1 ---- + /// | | + /// z ---- + /// | | + /// 0 ---- + /// 0 1 + /// x + /// + /// + SlimXFatZ, + + /// + /// Number of patch types + /// + Count, } - water.Chunks.Clear(); - - // May not be present when entering play mode. - if (water.Root) + // Instance Indices: + // 00 01 02 03 + // 04 05 + // 06 07 + // 08 09 10 11 + static readonly Vector2[] s_Offsets = { - Helpers.Destroy(water.Root.gameObject); - } - } + new(-1.5f, +1.5f), new(-0.5f, +1.5f), new(+0.5f, +1.5f), new(+1.5f, +1.5f), + new(-1.5f, +0.5f), new(+1.5f, +0.5f), + new(-1.5f, -0.5f), new(+1.5f, -0.5f), + new(-1.5f, -1.5f), new(-0.5f, -1.5f), new(+0.5f, -1.5f), new(+1.5f, -1.5f), + }; - public static Transform GenerateMesh(WaterRenderer water, List tiles, int lodDataResolution, int geoDownSampleFactor, int lodCount) - { - if (lodCount < 1) + // First LOD has inside bit as well: + // 00 01 02 03 + // 04 05 06 07 + // 08 09 10 11 + // 12 13 14 15 + internal static readonly Vector2[] s_OffsetsFirstLod = { - Debug.LogError("Crest: Invalid LOD count: " + lodCount.ToString(), water); - return null; - } + // Interior first for sorted rendering. + new(-0.5f, +0.5f), new(+0.5f, +0.5f), new(-0.5f, -0.5f), new(+0.5f, -0.5f), + + // Exterior. + new(-1.5f, +1.5f), new(-0.5f, +1.5f), new(+0.5f, +1.5f), new(+1.5f, +1.5f), + new(-1.5f, +0.5f), new(+1.5f, +0.5f), + new(-1.5f, -0.5f), new(+1.5f, -0.5f), + new(-1.5f, -1.5f), new(-0.5f, -1.5f), new(+0.5f, -1.5f), new(+1.5f, -1.5f), + }; + + // Usually rings have an extra side of vertices that point inwards. The outermost + // ring has both the inward vertices and also an additional outwards set of + // vertices that go to the horizon. + static readonly PatchType[] s_PatchTypes = + { + PatchType.SlimXFatZ, PatchType.SlimX, PatchType.SlimX, PatchType.SlimXZ, + PatchType.FatX, PatchType.SlimX, + PatchType.FatX, PatchType.SlimX, + PatchType.FatXZ, PatchType.FatX, PatchType.FatX, PatchType.FatXSlimZ, + }; + + // All interior - the "side" types have an extra skirt that points inwards - this + // means that this inner most section does not need any skirting. This is good, as + // this is the highest density part of the mesh. + static readonly PatchType[] s_PatchTypesFirstLod = + { + PatchType.Interior, PatchType.Interior, PatchType.Interior, PatchType.Interior, + PatchType.SlimXFatZ, PatchType.SlimX, PatchType.SlimX, PatchType.SlimXZ, + PatchType.FatX, PatchType.SlimX, + PatchType.FatX, PatchType.SlimX, + PatchType.FatXZ, PatchType.FatX, PatchType.FatX, PatchType.FatXSlimZ, + }; + + static readonly PatchType[] s_PatchTypesLastLod = + { + PatchType.FatXZOuter, PatchType.FatXOuter, PatchType.FatXOuter, PatchType.FatXZOuter, + PatchType.FatXOuter, PatchType.FatXOuter, + PatchType.FatXOuter, PatchType.FatXOuter, + PatchType.FatXZOuter, PatchType.FatXOuter, PatchType.FatXOuter, PatchType.FatXZOuter, + }; + + static int s_SiblingIndex; + + public static Transform GenerateMesh(WaterRenderer water, SurfaceRenderer surface, List tiles, int lodDataResolution, int geoDownSampleFactor, int lodCount) + { + if (lodCount < 1) + { + Debug.LogError("Crest: Invalid LOD count: " + lodCount.ToString(), water); + return null; + } #if PROFILE_CONSTRUCTION - var sw = new System.Diagnostics.Stopwatch(); - sw.Start(); + var sw = new System.Diagnostics.Stopwatch(); + sw.Start(); #endif - var root = new GameObject("Root"); - Debug.Assert(root != null, "Crest: The water Root transform could not be immediately constructed. Please report this issue to the Crest developers via our support email or GitHub at https://github.com/wave-harmonic/crest/issues ."); + s_SiblingIndex = 0; - root.hideFlags = water._Debug._ShowHiddenObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; - root.transform.parent = water.transform; - root.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); - root.transform.localScale = Vector3.one; + var root = new GameObject("Root"); + Debug.Assert(root != null, "Crest: The water Root transform could not be immediately constructed. Please report this issue to the Crest developers via our support email or GitHub at https://github.com/wave-harmonic/crest/issues ."); + + root.hideFlags = water._Debug._ShowHiddenObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; + root.transform.parent = water.Container.transform; + root.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); + root.transform.localScale = Vector3.one; - if (!water.IsRunningHeadless && !water.IsRunningWithoutGraphics) - { // create mesh data - s_Meshes = new Mesh[(int)PatchType.Count]; - var meshBounds = new Bounds[(int)PatchType.Count]; // 4 tiles across a LOD, and support lowering density by a factor var tileResolution = Mathf.Round(0.25f * lodDataResolution / geoDownSampleFactor); for (var i = 0; i < (int)PatchType.Count; i++) { - s_Meshes[i] = BuildPatch(water, (PatchType)i, tileResolution, out meshBounds[i]); + surface._Meshes[i] = BuildPatch(water, (PatchType)i, tileResolution); } for (var i = 0; i < lodCount; i++) { - CreateLOD(water, tiles, root.transform, i, lodCount, s_Meshes, meshBounds, lodDataResolution, geoDownSampleFactor, water.Layer); + CreateLOD(water, surface, tiles, root.transform, i, lodCount, surface._Meshes, lodDataResolution, geoDownSampleFactor, surface.Layer); } - } #if PROFILE_CONSTRUCTION - sw.Stop(); - Debug.Log( "Crest: Finished generating " + lodCount.ToString() + " LODs, time: " + (1000.0*sw.Elapsed.TotalSeconds).ToString(".000") + "ms" ); + sw.Stop(); + Debug.Log( "Crest: Finished generating " + lodCount.ToString() + " LODs, time: " + (1000.0*sw.Elapsed.TotalSeconds).ToString(".000") + "ms" ); #endif - return root.transform; - } + return root.transform; + } - static Mesh BuildPatch(WaterRenderer water, PatchType pt, float vertDensity, out Bounds bounds) - { - var verts = new List(); - var indices = new List(); - - // stick a bunch of verts into a 1m x 1m patch (scaling happens later) - var dx = 1f / vertDensity; - - - ////////////////////////////////////////////////////////////////////////////////// - // verts - - // see comments within PatchType for diagrams of each patch mesh - - // skirt widths on left, right, bottom and top (in order) - float skirtXminus = 0f, skirtXplus = 0f; - float skirtZminus = 0f, skirtZplus = 0f; - // set the patch size - if (pt == PatchType.Fat) { skirtXminus = skirtXplus = skirtZminus = skirtZplus = 1f; } - else if (pt is PatchType.FatX or PatchType.FatXOuter) { skirtXplus = 1f; } - else if (pt is PatchType.FatXZ or PatchType.FatXZOuter) { skirtXplus = skirtZplus = 1f; } - else if (pt == PatchType.FatXSlimZ) { skirtXplus = 1f; skirtZplus = -1f; } - else if (pt == PatchType.SlimX) { skirtXplus = -1f; } - else if (pt == PatchType.SlimXZ) { skirtXplus = skirtZplus = -1f; } - else if (pt == PatchType.SlimXFatZ) { skirtXplus = -1f; skirtZplus = 1f; } - - var sideLength_verts_x = 1f + vertDensity + skirtXminus + skirtXplus; - var sideLength_verts_z = 1f + vertDensity + skirtZminus + skirtZplus; - - var start_x = -0.5f - skirtXminus * dx; - var start_z = -0.5f - skirtZminus * dx; - var end_x = 0.5f + skirtXplus * dx; - var end_z = 0.5f + skirtZplus * dx; - - // With a default value of 100, this will reach the horizon at all levels at - // a far plane of 200k. - var extentsMultiplier = water._ExtentsSizeMultiplier * (Lod.k_MaximumSlices + 1 - water.LodLevels); - - for (float j = 0; j < sideLength_verts_z; j++) + static Mesh BuildPatch(WaterRenderer water, PatchType pt, float vertDensity) { - // interpolate z across patch - var z = Mathf.Lerp(start_z, end_z, j / (sideLength_verts_z - 1f)); + var verts = new List(); + var indices = new List(); - // push outermost edge out to horizon - if (pt == PatchType.FatXZOuter && j == sideLength_verts_z - 1f) - z *= extentsMultiplier; + // stick a bunch of verts into a 1m x 1m patch (scaling happens later) + var dx = 1f / vertDensity; - for (float i = 0; i < sideLength_verts_x; i++) + + ////////////////////////////////////////////////////////////////////////////////// + // verts + + // see comments within PatchType for diagrams of each patch mesh + + // skirt widths on left, right, bottom and top (in order) + float skirtXminus = 0f, skirtXplus = 0f; + float skirtZminus = 0f, skirtZplus = 0f; + // set the patch size + if (pt == PatchType.Fat) { skirtXminus = skirtXplus = skirtZminus = skirtZplus = 1f; } + else if (pt is PatchType.FatX or PatchType.FatXOuter) { skirtXplus = 1f; } + else if (pt is PatchType.FatXZ or PatchType.FatXZOuter) { skirtXplus = skirtZplus = 1f; } + else if (pt == PatchType.FatXSlimZ) { skirtXplus = 1f; skirtZplus = -1f; } + else if (pt == PatchType.SlimX) { skirtXplus = -1f; } + else if (pt == PatchType.SlimXZ) { skirtXplus = skirtZplus = -1f; } + else if (pt == PatchType.SlimXFatZ) { skirtXplus = -1f; skirtZplus = 1f; } + + var sideLength_verts_x = 1f + vertDensity + skirtXminus + skirtXplus; + var sideLength_verts_z = 1f + vertDensity + skirtZminus + skirtZplus; + + var start_x = -0.5f - skirtXminus * dx; + var start_z = -0.5f - skirtZminus * dx; + var end_x = 0.5f + skirtXplus * dx; + var end_z = 0.5f + skirtZplus * dx; + + // With a default value of 100, this will reach the horizon at all levels at + // a far plane of 200k. + var extentsMultiplier = water._ExtentsSizeMultiplier * (Lod.k_MaximumSlices + 1 - water.LodLevels); + + for (float j = 0; j < sideLength_verts_z; j++) { - // interpolate x across patch - var x = Mathf.Lerp(start_x, end_x, i / (sideLength_verts_x - 1f)); + // interpolate z across patch + var z = Mathf.Lerp(start_z, end_z, j / (sideLength_verts_z - 1f)); // push outermost edge out to horizon - if (i == sideLength_verts_x - 1f && (pt == PatchType.FatXOuter || pt == PatchType.FatXZOuter)) - x *= extentsMultiplier; + if (pt == PatchType.FatXZOuter && j == sideLength_verts_z - 1f) + z *= extentsMultiplier; - // could store something in y, although keep in mind this is a shared mesh that is shared across multiple lods - verts.Add(new(x, 0f, z)); + for (float i = 0; i < sideLength_verts_x; i++) + { + // interpolate x across patch + var x = Mathf.Lerp(start_x, end_x, i / (sideLength_verts_x - 1f)); + + // push outermost edge out to horizon + if (i == sideLength_verts_x - 1f && (pt == PatchType.FatXOuter || pt == PatchType.FatXZOuter)) + x *= extentsMultiplier; + + // could store something in y, although keep in mind this is a shared mesh that is shared across multiple lods + verts.Add(new(x, 0f, z)); + } } - } - ////////////////////////////////////////////////////////////////////////////////// - // indices + ////////////////////////////////////////////////////////////////////////////////// + // indices - var sideLength_squares_x = (int)sideLength_verts_x - 1; - var sideLength_squares_z = (int)sideLength_verts_z - 1; + var sideLength_squares_x = (int)sideLength_verts_x - 1; + var sideLength_squares_z = (int)sideLength_verts_z - 1; - for (var j = 0; j < sideLength_squares_z; j++) - { - for (var i = 0; i < sideLength_squares_x; i++) + for (var j = 0; j < sideLength_squares_z; j++) { - var flipEdge = false; - - if (i % 2 == 1) flipEdge = !flipEdge; - if (j % 2 == 1) flipEdge = !flipEdge; - - var i0 = i + j * (sideLength_squares_x + 1); - var i1 = i0 + 1; - var i2 = i0 + (sideLength_squares_x + 1); - var i3 = i2 + 1; - - if (!flipEdge) + for (var i = 0; i < sideLength_squares_x; i++) { - // tri 1 - indices.Add(i3); - indices.Add(i1); - indices.Add(i0); + var flipEdge = false; - // tri 2 - indices.Add(i0); - indices.Add(i2); - indices.Add(i3); - } - else - { - // tri 1 - indices.Add(i3); - indices.Add(i1); - indices.Add(i2); + if (i % 2 == 1) flipEdge = !flipEdge; + if (j % 2 == 1) flipEdge = !flipEdge; - // tri 2 - indices.Add(i0); - indices.Add(i2); - indices.Add(i1); + var i0 = i + j * (sideLength_squares_x + 1); + var i1 = i0 + 1; + var i2 = i0 + (sideLength_squares_x + 1); + var i3 = i2 + 1; + + if (!flipEdge) + { + // tri 1 + indices.Add(i3); + indices.Add(i1); + indices.Add(i0); + + // tri 2 + indices.Add(i0); + indices.Add(i2); + indices.Add(i3); + } + else + { + // tri 1 + indices.Add(i3); + indices.Add(i1); + indices.Add(i2); + + // tri 2 + indices.Add(i0); + indices.Add(i2); + indices.Add(i1); + } } } - } - ////////////////////////////////////////////////////////////////////////////////// - // create mesh + ////////////////////////////////////////////////////////////////////////////////// + // create mesh - var mesh = new Mesh(); - if (verts != null && verts.Count > 0) - { - var arrV = new Vector3[verts.Count]; - verts.CopyTo(arrV); + var mesh = new Mesh(); + if (verts != null && verts.Count > 0) + { + var arrV = new Vector3[verts.Count]; + verts.CopyTo(arrV); - var arrI = new int[indices.Count]; - indices.CopyTo(arrI); + var arrI = new int[indices.Count]; + indices.CopyTo(arrI); - mesh.SetIndices(null, MeshTopology.Triangles, 0); - mesh.vertices = arrV; + mesh.SetIndices(null, MeshTopology.Triangles, 0); + mesh.vertices = arrV; - // HDRP needs full data. Do this on a define to keep door open to runtime changing of RP. + // HDRP needs full data. Do this on a define to keep door open to runtime changing of RP. #if d_UnityHDRP - var norms = new Vector3[verts.Count]; - for (var i = 0; i < norms.Length; i++) norms[i] = Vector3.up; - var tans = new Vector4[verts.Count]; - for (var i = 0; i < tans.Length; i++) tans[i] = new(1, 0, 0, 1); + var norms = new Vector3[verts.Count]; + for (var i = 0; i < norms.Length; i++) norms[i] = Vector3.up; + var tans = new Vector4[verts.Count]; + for (var i = 0; i < tans.Length; i++) tans[i] = new(1, 0, 0, 1); - mesh.normals = norms; - mesh.tangents = tans; + mesh.normals = norms; + mesh.tangents = tans; #else - mesh.normals = null; + mesh.normals = null; #endif - mesh.SetIndices(arrI, MeshTopology.Triangles, 0); + mesh.SetIndices(arrI, MeshTopology.Triangles, 0); - // recalculate bounds. add a little allowance for snapping. in the chunk renderer script, the bounds will be expanded further - // to allow for horizontal displacement - mesh.RecalculateBounds(); - bounds = mesh.bounds; - // Increase snapping allowance (see #1148). Value was chosen by observation with a - // custom debug mode to show pixels that were out of bounds. - dx *= 3f; - bounds.extents = new(bounds.extents.x + dx, bounds.extents.y, bounds.extents.z + dx); - mesh.bounds = bounds; - mesh.name = pt.ToString(); + // recalculate bounds. add a little allowance for snapping. in the chunk renderer script, the bounds will be expanded further + // to allow for horizontal displacement + mesh.RecalculateBounds(); + var bounds = mesh.bounds; + // Increase snapping allowance (see #1148). Value was chosen by observation with a + // custom debug mode to show pixels that were out of bounds. + dx *= 3f; + bounds.extents = new(bounds.extents.x + dx, bounds.extents.y, bounds.extents.z + dx); + mesh.bounds = bounds; + mesh.name = pt.ToString(); + } + + return mesh; } - else + + static void CreateLOD(WaterRenderer water, SurfaceRenderer surface, List tiles, Transform parent, int lodIndex, int lodCount, Mesh[] meshData, int lodDataResolution, int geoDownSampleFactor, int layer) { - bounds = new(); - } + var horizScale = Mathf.Pow(2f, lodIndex); - return mesh; - } - - static void CreateLOD(WaterRenderer water, List tiles, Transform parent, int lodIndex, int lodCount, Mesh[] meshData, Bounds[] meshBounds, int lodDataResolution, int geoDownSampleFactor, int layer) - { - var horizScale = Mathf.Pow(2f, lodIndex); - - var isBiggestLOD = lodIndex == lodCount - 1; - var generateSkirt = isBiggestLOD; + var isBiggestLOD = lodIndex == lodCount - 1; + var generateSkirt = isBiggestLOD; #if CREST_DEBUG - generateSkirt = generateSkirt && !water._Debug._DisableSkirt; + generateSkirt = generateSkirt && !surface._Debug._DisableSkirt; #endif - Vector2[] offsets; - PatchType[] patchTypes; + Vector2[] offsets; + PatchType[] patchTypes; - var leadSideType = generateSkirt ? PatchType.FatXOuter : PatchType.SlimX; - var trailSideType = generateSkirt ? PatchType.FatXOuter : PatchType.FatX; - var leadCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.SlimXZ; - var trailCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.FatXZ; - var tlCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.SlimXFatZ; - var brCornerType = generateSkirt ? PatchType.FatXZOuter : PatchType.FatXSlimZ; - - if (lodIndex != 0) - { - // instance indices: - // 0 1 2 3 - // 4 5 - // 6 7 - // 8 9 10 11 - offsets = new Vector2[] { - new(-1.5f,1.5f), new(-0.5f,1.5f), new(0.5f,1.5f), new(1.5f,1.5f), - new(-1.5f,0.5f), new(1.5f,0.5f), - new(-1.5f,-0.5f), new(1.5f,-0.5f), - new(-1.5f,-1.5f), new(-0.5f,-1.5f), new(0.5f,-1.5f), new(1.5f,-1.5f), - }; - - // usually rings have an extra side of verts that point inwards. the outermost ring has both the inward - // verts and also and additional outwards set of verts that go to the horizon - patchTypes = new PatchType[] { - tlCornerType, leadSideType, leadSideType, leadCornerType, - trailSideType, leadSideType, - trailSideType, leadSideType, - trailCornerType, trailSideType, trailSideType, brCornerType, - }; - } - else - { - // first LOD has inside bit as well: - // 0 1 2 3 - // 4 5 6 7 - // 8 9 10 11 - // 12 13 14 15 - offsets = new Vector2[] { - new(-1.5f,1.5f), new(-0.5f,1.5f), new(0.5f,1.5f), new(1.5f,1.5f), - new(-1.5f,0.5f), new(-0.5f,0.5f), new(0.5f,0.5f), new(1.5f,0.5f), - new(-1.5f,-0.5f), new(-0.5f,-0.5f), new(0.5f,-0.5f), new(1.5f,-0.5f), - new(-1.5f,-1.5f), new(-0.5f,-1.5f), new(0.5f,-1.5f), new(1.5f,-1.5f), - }; - - - // all interior - the "side" types have an extra skirt that points inwards - this means that this inner most - // section doesn't need any skirting. this is good - this is the highest density part of the mesh. - patchTypes = new PatchType[] { - tlCornerType, leadSideType, leadSideType, leadCornerType, - trailSideType, PatchType.Interior, PatchType.Interior, leadSideType, - trailSideType, PatchType.Interior, PatchType.Interior, leadSideType, - trailCornerType, trailSideType, trailSideType, brCornerType, - }; - } + if (lodIndex != 0) + { + offsets = s_Offsets; + patchTypes = generateSkirt ? s_PatchTypesLastLod : s_PatchTypes; + } + else + { + offsets = s_OffsetsFirstLod; + patchTypes = s_PatchTypesFirstLod; + } #if CREST_DEBUG - // debug toggle to force all patches to be the same. they'll be made with a surrounding skirt to make sure patches - // overlap - if (water._Debug._UniformTiles) - { - for (var i = 0; i < patchTypes.Length; i++) + // debug toggle to force all patches to be the same. they'll be made with a surrounding skirt to make sure patches + // overlap + if (surface._Debug._UniformTiles) { - patchTypes[i] = PatchType.Fat; + patchTypes = new PatchType[patchTypes.Length]; + System.Array.Fill(patchTypes, PatchType.Fat); } - } #endif - // create the water patches - for (var i = 0; i < offsets.Length; i++) - { - // instantiate and place patch - var patch = water._ChunkTemplate - ? Helpers.InstantiatePrefab(water._ChunkTemplate) - : new(); - // Also applying the hide flags to the chunk will prevent it from being pickable in the editor. - patch.hideFlags = water._Debug._ShowHiddenObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; - patch.name = $"Tile_L{lodIndex}_{patchTypes[i]}"; - patch.layer = layer; - patch.transform.parent = parent; - var pos = offsets[i]; - patch.transform.localPosition = horizScale * new Vector3(pos.x, 0f, pos.y); - // scale only horizontally, otherwise culling bounding box will be scaled up in y - patch.transform.localScale = new(horizScale, 1f, horizScale); - - if (!patch.TryGetComponent(out var mr)) + // create the water patches + for (var i = 0; i < offsets.Length; i++) { - mr = patch.AddComponent(); - // I don't think one would use light probes for a purely specular water surface? (although diffuse - // foam shading would benefit). - mr.lightProbeUsage = LightProbeUsage.Off; - } + // instantiate and place patch + var patch = surface._ChunkTemplate + ? Helpers.InstantiatePrefab(surface._ChunkTemplate) + : new(); + // Also applying the hide flags to the chunk will prevent it from being pickable in the editor. + patch.hideFlags = water._Debug._ShowHiddenObjects ? HideFlags.DontSave : HideFlags.HideAndDontSave; + patch.name = $"Tile_L{lodIndex}_{patchTypes[i]}"; + patch.layer = layer; + patch.transform.parent = parent; + var pos = offsets[i]; + patch.transform.localPosition = horizScale * new Vector3(pos.x, 0f, pos.y); + // scale only horizontally, otherwise culling bounding box will be scaled up in y + patch.transform.localScale = new(horizScale, 1f, horizScale); - { - var mesh = Object.Instantiate(meshData[(int)patchTypes[i]]); - mesh.name = meshData[(int)patchTypes[i]].name; - patch.AddComponent().sharedMesh = mesh; - - var chunk = patch.AddComponent(); - chunk._Water = water; - chunk._BoundsLocal = meshBounds[(int)patchTypes[i]]; - - chunk.SetInstanceData(lodIndex); - tiles.Add(chunk); - } - - // Sorting order to stop unity drawing it back to front. Make the innermost four tiles draw first, - // followed by the rest of the tiles by LOD index. - if (RenderPipelineHelper.IsHighDefinition) - { - // HDRP has a different rendering priority system: - // https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@10.10/manual/Renderer-And-Material-Priority.html#sorting-by-renderer - mr.rendererPriority = -lodCount + (patchTypes[i] == PatchType.Interior ? -1 : lodIndex); - } - else if (!water.AllowRenderQueueSorting) - { - // Sorting order to stop unity drawing it back to front. make the innermost 4 tiles draw first, followed by - // the rest of the tiles by LOD index. all this happens before layer 0 - the sorting layer takes priority over the - // render queue it seems! ( https://cdry.wordpress.com/2017/04/28/unity-render-queues-vs-sorting-layers/ ). This pushes - // water rendering way early, so transparent objects will by default render afterwards, which is typical for water rendering. - mr.sortingOrder = -lodCount + (patchTypes[i] == PatchType.Interior ? -1 : lodIndex); - } - - mr.shadowCastingMode = water.CastShadows ? ShadowCastingMode.On : ShadowCastingMode.Off; - - // This setting is ignored by Unity for the transparent water shader. - mr.receiveShadows = false; - - // BIRP needs further investigation. - mr.motionVectorGenerationMode = !water.WriteMotionVectors - ? MotionVectorGenerationMode.ForceNoMotion - : MotionVectorGenerationMode.Object; - - mr.material = water.Material; - - // rotate side patches to point the +x side outwards - var rotateXOutwards = patchTypes[i] is PatchType.FatX or PatchType.FatXOuter or PatchType.SlimX or PatchType.SlimXFatZ; - if (rotateXOutwards) - { - if (Mathf.Abs(pos.y) >= Mathf.Abs(pos.x)) - patch.transform.localEulerAngles = 90f * Mathf.Sign(pos.y) * -Vector3.up; - else - patch.transform.localEulerAngles = pos.x < 0f ? Vector3.up * 180f : Vector3.zero; - } - - // rotate the corner patches so the +x and +z sides point outwards - var rotateXZOutwards = patchTypes[i] is PatchType.FatXZ or PatchType.SlimXZ or PatchType.FatXSlimZ or PatchType.FatXZOuter; - if (rotateXZOutwards) - { - // xz direction before rotation - var from = new Vector3(1f, 0f, 1f).normalized; - // target xz direction is outwards vector given by local patch position - assumes this patch is a corner (checked below) - var to = patch.transform.localPosition.normalized; - if (Mathf.Abs(patch.transform.localPosition.x) < 0.0001f || Mathf.Abs(Mathf.Abs(patch.transform.localPosition.x) - Mathf.Abs(patch.transform.localPosition.z)) > 0.001f) + if (!patch.TryGetComponent(out var mr)) { - Debug.LogWarning("Crest: Skipped rotating a patch because it isn't a corner, click here to highlight.", patch); - continue; + mr = patch.AddComponent(); + // I don't think one would use light probes for a purely specular water surface? (although diffuse + // foam shading would benefit). + mr.lightProbeUsage = LightProbeUsage.Off; } - // Detect 180 degree rotations as it doesn't always rotate around Y - if (Vector3.Dot(from, to) < -0.99f) - patch.transform.localEulerAngles = Vector3.up * 180f; - else - patch.transform.localRotation = Quaternion.FromToRotation(from, to); + var order = -lodCount + (patchTypes[i] == PatchType.Interior ? -1 : lodIndex); + + { + var mesh = meshData[(int)patchTypes[i]]; + patch.AddComponent().sharedMesh = mesh; + + var chunk = patch.AddComponent(); + chunk._Water = water; + chunk._SortingOrder = order; + chunk._SiblingIndex = s_SiblingIndex++; + + chunk.Initialize(lodIndex, mr, mesh); + + // When custom rendering, we loop over chunks to render, which means these need to + // be optimally sorted. We statically sort by LOD. Sub-sort is only done for LOD0, + // where interior tiles are placed first. Further sorting must be done dynamically. + tiles.Add(chunk); + } + + // Sorting order to stop unity drawing it back to front. Make the innermost four tiles draw first, + // followed by the rest of the tiles by LOD index. + if (RenderPipelineHelper.IsHighDefinition) + { + // HDRP has a different rendering priority system: + // https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@10.10/manual/Renderer-And-Material-Priority.html#sorting-by-renderer + mr.rendererPriority = order; + } + else if (!water.Surface.AllowRenderQueueSorting) + { + // Sorting order to stop unity drawing it back to front. make the innermost 4 tiles draw first, followed by + // the rest of the tiles by LOD index. all this happens before layer 0 - the sorting layer takes priority over the + // render queue it seems! ( https://cdry.wordpress.com/2017/04/28/unity-render-queues-vs-sorting-layers/ ). This pushes + // water rendering way early, so transparent objects will by default render afterwards, which is typical for water rendering. + mr.sortingOrder = order; + } + + mr.shadowCastingMode = water.Surface.CastShadows ? ShadowCastingMode.On : ShadowCastingMode.Off; + + // This setting is ignored by Unity for the transparent water shader. + mr.receiveShadows = false; + + mr.motionVectorGenerationMode = !water.WriteMotionVectors + ? MotionVectorGenerationMode.ForceNoMotion + : MotionVectorGenerationMode.Object; + + mr.material = water.Surface.Material; + + OnCreateChunkRenderer?.Invoke(mr); + + // rotate side patches to point the +x side outwards + var rotateXOutwards = patchTypes[i] is PatchType.FatX or PatchType.FatXOuter or PatchType.SlimX or PatchType.SlimXFatZ; + if (rotateXOutwards) + { + if (Mathf.Abs(pos.y) >= Mathf.Abs(pos.x)) + patch.transform.localEulerAngles = 90f * Mathf.Sign(pos.y) * -Vector3.up; + else + patch.transform.localEulerAngles = pos.x < 0f ? Vector3.up * 180f : Vector3.zero; + } + + // rotate the corner patches so the +x and +z sides point outwards + var rotateXZOutwards = patchTypes[i] is PatchType.FatXZ or PatchType.SlimXZ or PatchType.FatXSlimZ or PatchType.FatXZOuter; + if (rotateXZOutwards) + { + // xz direction before rotation + var from = new Vector3(1f, 0f, 1f).normalized; + // target xz direction is outwards vector given by local patch position - assumes this patch is a corner (checked below) + var to = patch.transform.localPosition.normalized; + if (Mathf.Abs(patch.transform.localPosition.x) < 0.0001f || Mathf.Abs(Mathf.Abs(patch.transform.localPosition.x) - Mathf.Abs(patch.transform.localPosition.z)) > 0.001f) + { + Debug.LogWarning("Crest: Skipped rotating a patch because it isn't a corner, click here to highlight.", patch); + continue; + } + + // Detect 180 degree rotations as it doesn't always rotate around Y + if (Vector3.Dot(from, to) < -0.99f) + patch.transform.localEulerAngles = Vector3.up * 180f; + else + patch.transform.localRotation = Quaternion.FromToRotation(from, to); + } } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterChunkRenderer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterChunkRenderer.cs index b251b814d..3162ffeed 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterChunkRenderer.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterChunkRenderer.cs @@ -1,9 +1,8 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System.Collections.Generic; using UnityEngine; -using UnityEngine.Rendering; using WaveHarmonic.Crest.Internal; namespace WaveHarmonic.Crest @@ -27,29 +26,22 @@ namespace WaveHarmonic.Crest [@ExecuteDuringEditMode] sealed class WaterChunkRenderer : ManagedBehaviour { - [SerializeField, HideInInspector] -#pragma warning disable 414 - int _Version = 0; -#pragma warning restore 414 - [SerializeField] internal bool _DrawRenderBounds = false; - static class ShaderIDs - { - public static readonly int s_ChunkMeshScaleAlpha = Shader.PropertyToID("_Crest_ChunkMeshScaleAlpha"); - public static readonly int s_ChunkGeometryGridWidth = Shader.PropertyToID("_Crest_ChunkGeometryGridWidth"); - public static readonly int s_ChunkFarNormalsWeight = Shader.PropertyToID("_Crest_ChunkFarNormalsWeight"); - public static readonly int s_ChunkNormalScrollSpeed = Shader.PropertyToID("_Crest_ChunkNormalScrollSpeed"); - public static readonly int s_ChunkMeshScaleAlphaSource = Shader.PropertyToID("_Crest_ChunkMeshScaleAlphaSource"); - public static readonly int s_ChunkGeometryGridWidthSource = Shader.PropertyToID("_Crest_ChunkGeometryGridWidthSource"); - } + internal const string k_UpdateMeshBoundsMarker = "Crest.WaterChunkRenderer.UpdateMeshBounds"; - internal Bounds _BoundsLocal; - Mesh _Mesh; + static readonly Unity.Profiling.ProfilerMarker s_UpdateMeshBoundsMarker = new(k_UpdateMeshBoundsMarker); + + internal Transform _Transform; + internal Mesh _Mesh; public Renderer Rend { get; private set; } internal MaterialPropertyBlock _MaterialPropertyBlock; + Matrix4x4 _CurrentObjectToWorld; Matrix4x4 _PreviousObjectToWorld; + internal Material _MotionVectorMaterial; + internal int _SortingOrder; + internal int _SiblingIndex; internal Rect _UnexpandedBoundsXZ = new(); public Rect UnexpandedBoundsXZ => _UnexpandedBoundsXZ; @@ -72,24 +64,17 @@ namespace WaveHarmonic.Crest public static List HeightReporters { get; } = new(); public static List DisplacementReporters { get; } = new(); - private protected override System.Action OnLateUpdateMethod => OnLateUpdate; - - private protected override void Initialize() + // There is a 1-frame delay with Initialized in edit mode due to setting + // enableInEditMode in EditorApplication.update. This only really affect this + // component as it is instantiate via script, and is partial driven externally. + // So instead, call this after instantiation. + internal void Initialize(int index, Renderer renderer, Mesh mesh) { - base.Initialize(); - - _MaterialPropertyBlock ??= new(); - - if (Rend == null) - { - Rend = GetComponent(); - } - - if (_Mesh == null) - { - // Meshes are cloned so it is safe to use sharedMesh in play mode. We need clones to modify the render bounds. - _Mesh = GetComponent().sharedMesh; - } + _LodIndex = index; + Rend = renderer; + _Mesh = mesh; + _PreviousObjectToWorld = _CurrentObjectToWorld = transform.localToWorldMatrix; + _Transform = transform; } private protected override void OnStart() @@ -99,97 +84,95 @@ namespace WaveHarmonic.Crest UpdateMeshBounds(); } - void OnLateUpdate(WaterRenderer water) + internal void UpdateMeshBounds(WaterRenderer water, SurfaceRenderer surface) { + _WaterDataHasBeenBound = false; + + var count = surface.TimeSliceBoundsUpdateFrameCount; + // Time slice update to distribute the load. - if (!(transform.GetSiblingIndex() % water.TimeSliceBoundsUpdateFrameCount != Time.frameCount % water.Chunks.Count % water.TimeSliceBoundsUpdateFrameCount)) + if (count <= 1 || !(_SiblingIndex % count != Time.frameCount % surface.Chunks.Count % count)) { // This needs to be called on Update because the bounds depend on transform scale which can change. Also OnWillRenderObject depends on // the bounds being correct. This could however be called on scale change events, but would add slightly more complexity. UpdateMeshBounds(); } + } - // Update chunk shader data. - _MaterialPropertyBlock ??= new(); - - // FIXME: Sometimes thrown. - // NullReferenceException: Object reference not set to an instance of an object - // WaveHarmonic.Crest.WaterChunkRenderer.OnLateUpdate(WaveHarmonic.Crest.WaterRenderer water)(at Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterChunkRenderer.cs:119) - // WaveHarmonic.Crest.WaterRenderer.LateUpdate()(at Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.cs:733) - if (Rend == null) + bool ShouldRender(bool culled) + { + // Is visible to camera. + if (!_Visible) { - Rend = GetComponent(); + return false; } - Rend.GetPropertyBlock(_MaterialPropertyBlock); - _MaterialPropertyBlock.SetInteger(Lod.ShaderIDs.s_LodIndex, _LodIndex); - var data = water._PerCascadeInstanceData.Current[_LodIndex]; - _MaterialPropertyBlock.SetFloat(ShaderIDs.s_ChunkMeshScaleAlpha, data._MeshScaleLerp); - _MaterialPropertyBlock.SetFloat(ShaderIDs.s_ChunkGeometryGridWidth, data._GeometryGridWidth); - _MaterialPropertyBlock.SetFloat(ShaderIDs.s_ChunkFarNormalsWeight, data._FarNormalsWeight); - _MaterialPropertyBlock.SetVector(ShaderIDs.s_ChunkNormalScrollSpeed, data._NormalScrollSpeeds); - data = water._PerCascadeInstanceData.Previous(1)[_LodIndex]; - _MaterialPropertyBlock.SetFloat(ShaderIDs.s_ChunkMeshScaleAlphaSource, data._MeshScaleLerp); - _MaterialPropertyBlock.SetFloat(ShaderIDs.s_ChunkGeometryGridWidthSource, data._GeometryGridWidth); - Rend.SetPropertyBlock(_MaterialPropertyBlock); - -#if UNITY_6000_0_OR_NEWER - if (Application.isPlaying && RenderPipelineHelper.IsUniversal && water.WriteMotionVectors) + // If including culling, is it culled. + if (culled && _Culled) { - var material = water._MotionVectorsMaterial; - - var parameters = new RenderParams(material) - { - motionVectorMode = MotionVectorGenerationMode.Object, - material = material, - matProps = _MaterialPropertyBlock, - worldBounds = Rend.bounds, - layer = water.Layer, - receiveShadows = false, - shadowCastingMode = ShadowCastingMode.Off, - lightProbeUsage = LightProbeUsage.Off, - reflectionProbeUsage = ReflectionProbeUsage.Off, - }; - - if (_Mesh == null) - { - _Mesh = GetComponent().sharedMesh; - } - - Graphics.RenderMesh(parameters, _Mesh, 0, transform.localToWorldMatrix, _PreviousObjectToWorld); - _PreviousObjectToWorld = transform.localToWorldMatrix; + return false; } -#endif + + return true; + } + + internal void OnLateUpdate() + { + _PreviousObjectToWorld = _CurrentObjectToWorld; + _CurrentObjectToWorld = _Transform.localToWorldMatrix; + } + + internal void RenderMotionVectors(SurfaceRenderer surface, Camera camera) + { + if (!ShouldRender(culled: true)) + { + return; + } + + // RenderMesh will copy properties immediately, thus we need them bound. + if (!_WaterDataHasBeenBound) + { + Bind(); + } + + var material = MaterialOverridden ? _MotionVectorMaterial : surface._MotionVectorMaterial; + + var parameters = new RenderParams(material) + { + motionVectorMode = MotionVectorGenerationMode.Object, + material = material, + matProps = _MaterialPropertyBlock, + worldBounds = Rend.bounds, + layer = surface.Layer, + receiveShadows = false, + shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off, + lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off, + reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off, + camera = camera, + }; + + Graphics.RenderMesh(parameters, _Mesh, 0, _CurrentObjectToWorld, _PreviousObjectToWorld); } void UpdateMeshBounds() { - UnityEngine.Profiling.Profiler.BeginSample("Crest.WaterChunkRenderer.UpdateMeshBounds"); + s_UpdateMeshBoundsMarker.Begin(this); + + var bounds = _Mesh.bounds; if (WaterBody.WaterBodies.Count > 0) { - _UnexpandedBoundsXZ = ComputeBoundsXZ(transform, ref _BoundsLocal); + _UnexpandedBoundsXZ = ComputeBoundsXZ(_Transform, bounds); } - var newBounds = _BoundsLocal; - ExpandBoundsForDisplacements(transform, ref newBounds); + bounds = ExpandBoundsForDisplacements(_Transform, bounds); - // FIXME: Fixes a crash which was reported twice. Could not reproduce. - // NullReferenceException: Object reference not set to an instance of an object. - // at WaveHarmonic.Crest.WaterChunkRenderer.UpdateMeshBounds()[0x00000] in < 00000000000000000000000000000000 >:0 - // at WaveHarmonic.Crest.WaterChunkRenderer.OnUpdate(WaveHarmonic.Crest.WaterRenderer water)[0x00000] in < 00000000000000000000000000000000 >:0 - // at WaveHarmonic.Crest.WaterRenderer.Update()[0x00000] in < 00000000000000000000000000000000 >:0 - if (_Mesh == null) - { - _Mesh = GetComponent().sharedMesh; - } + Rend.localBounds = bounds; - _Mesh.bounds = newBounds; - - UnityEngine.Profiling.Profiler.EndSample(); + s_UpdateMeshBoundsMarker.End(); } - public static Rect ComputeBoundsXZ(Transform transform, ref Bounds bounds) + public static Rect ComputeBoundsXZ(Transform transform, Bounds bounds) { // Since chunks are axis-aligned it is safe to rotate the bounds. var center = transform.rotation * bounds.center * transform.lossyScale.x + transform.position; @@ -201,31 +184,14 @@ namespace WaveHarmonic.Crest }; } - static Camera s_CurrentCamera = null; - - static void BeginCameraRendering(ScriptableRenderContext context, Camera camera) - { - // Camera.current is only supported in the built-in pipeline. This provides the current camera for - // OnWillRenderObject for SRPs. BeginCameraRendering is called for each active camera in every frame. - // OnWillRenderObject is called after BeginCameraRendering for the current camera so this works. - s_CurrentCamera = camera; - } - // Used by the water mask system if we need to render the water mask in situations // where the water itself doesn't need to be rendered or has otherwise been disabled - internal void Bind(Camera camera) + internal void Bind() { + _MaterialPropertyBlock = _Water.Surface._PerCascadeMPB.Current[_LodIndex]; + Rend.SetPropertyBlock(_MaterialPropertyBlock); + _WaterDataHasBeenBound = true; - - if (Rend == null) - { - return; - } - - if (!MaterialOverridden && Rend.sharedMaterial != _Water.Material) - { - Rend.sharedMaterial = _Water.Material; - } } void OnDestroy() @@ -236,22 +202,21 @@ namespace WaveHarmonic.Crest // Called when visible to a camera void OnWillRenderObject() { - // Camera.current is only supported in built-in pipeline. - if (RenderPipelineHelper.IsLegacy && Camera.current != null) - { - s_CurrentCamera = Camera.current; - } - - // If only the game view is visible, this reference will be dropped for SRP on recompile. - if (s_CurrentCamera == null) + if (Rend == null) { return; } - // Depth texture is used by water shader for transparency/depth fog, and for fading out foam at shoreline. - s_CurrentCamera.depthTextureMode |= DepthTextureMode.Depth; + if (!MaterialOverridden && Rend.sharedMaterial != _Water.Surface.Material) + { + Rend.sharedMaterial = _Water.Surface.Material; + _MotionVectorMaterial = _Water.Surface._MotionVectorMaterial; + } - Bind(s_CurrentCamera); + if (!_WaterDataHasBeenBound) + { + Bind(); + } if (_DrawRenderBounds) { @@ -261,8 +226,11 @@ namespace WaveHarmonic.Crest // this is called every frame because the bounds are given in world space and depend on the transform scale, which // can change depending on view altitude - public void ExpandBoundsForDisplacements(Transform transform, ref Bounds bounds) + public Bounds ExpandBoundsForDisplacements(Transform transform, Bounds bounds) { + var extents = bounds.extents; + var center = bounds.center; + var scale = transform.lossyScale; var rotation = transform.rotation; @@ -276,14 +244,10 @@ namespace WaveHarmonic.Crest boundsY += 5f; } - var extents = bounds.extents; - // Extend bounds by global waves. - bounds.extents = new(extents.x + expandXZ, boundsY, extents.z + expandXZ); - - extents = bounds.extents; - var center = bounds.center; - var size = bounds.size; + extents.x += expandXZ; + extents.y += boundsY; + extents.z += expandXZ; // Get XZ bounds. Doing this manually bypasses updating render bounds call. Rect rect; @@ -291,7 +255,7 @@ namespace WaveHarmonic.Crest var p1 = transform.position; var p2 = rotation * new Vector3(center.x, 0f, center.z); var s1 = scale; - var s2 = rotation * new Vector3(size.x, 0f, size.z); + var s2 = rotation * (extents.XNZ(0f) * 2f); rect = new(0, 0, Mathf.Abs(s1.x * s2.x), Mathf.Abs(s1.z * s2.z)) { @@ -319,7 +283,9 @@ namespace WaveHarmonic.Crest expandXZ = boundsPadding / scale.x; boundsY = totalVertical; - bounds.extents = new(extents.x + expandXZ, extents.y + boundsY, extents.z + expandXZ); + extents.x += expandXZ; + extents.y += boundsY; + extents.z += expandXZ; } // Expand and offset bounds by height. @@ -342,35 +308,23 @@ namespace WaveHarmonic.Crest maximumWaterLevelBounds *= 0.5f; boundsY = minimumWaterLevelBounds + maximumWaterLevelBounds; - extents = bounds.extents; - bounds.extents = new(extents.x, extents.y + boundsY, extents.z); + extents.y += boundsY; + bounds.extents = extents; var offset = maximumWaterLevelBounds - minimumWaterLevelBounds; - center = bounds.center; - bounds.center = new(center.x, center.y + offset, center.z); + center.y += offset; + bounds.center = center; } - } - public void SetInstanceData(int lodIndex) - { - _LodIndex = lodIndex; + return bounds; } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void InitStatics() { - // Init here from 2019.3 onwards - s_CurrentCamera = null; HeightReporters.Clear(); DisplacementReporters.Clear(); } - - [RuntimeInitializeOnLoadMethod] - static void RunOnStart() - { - RenderPipelineManager.beginCameraRendering -= BeginCameraRendering; - RenderPipelineManager.beginCameraRendering += BeginCameraRendering; - } } static class BoundsHelper diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterReflections.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterReflections.cs index 51785dcd8..e0cc8bdbf 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterReflections.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Surface/WaterReflections.cs @@ -16,21 +16,19 @@ namespace WaveHarmonic.Crest /// /// What side of the water surface to render planar reflections for. /// + [@GenerateDoc] public enum WaterReflectionSide { - /// - /// Both sides. Most expensive. - /// + /// + [Tooltip("Both sides. Most expensive.")] Both, - /// - /// Above only. Typical for planar reflections. - /// + /// + [Tooltip("Above only. Typical for planar reflections.")] Above, - /// - /// Below only. For total internal reflections. - /// + /// + [Tooltip("Below only. For total internal reflections.")] Below, } @@ -269,27 +267,48 @@ namespace WaveHarmonic.Crest } } - internal void OnPreRenderCamera(Camera camera) + bool ShouldRender(Camera camera) { + // If no surface, then do not execute the reflection camera. + if (!WaterRenderer.ShouldRender(camera, _Water.Surface.Layer)) + { + return false; + } + + // This method could be executed twice: once by the camera rendering the surface, + // and once again by the planar reflection camera. For the latter, we do not want + // to proceed or infinite recursion. For safety. + if (camera == CurrentCamera) + { + return false; + } + + // Avoid these types for now. + if (camera.cameraType == CameraType.Reflection) + { + return false; + } + + return true; + } + + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + if (!ShouldRender(camera)) + { + return; + } + if (SupportsRecursiveRendering) { - if (camera.cameraType is CameraType.Preview or CameraType.Reflection) - { - return; - } - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, _Water.Layer)) - { - return; - } - + // This option only valid for recursive, otherwise, it is always single camera. if (_RenderOnlySingleCamera && camera != _Water.Viewer) { return; } _CameraViewpoint = camera; - LateUpdate(); + LateUpdate(context); } if (camera == _CameraViewpoint) @@ -299,13 +318,17 @@ namespace WaveHarmonic.Crest } } - internal void OnAfterCameraRender(Camera camera) + internal void OnEndCameraRendering(Camera camera) { - if (SupportsRecursiveRendering && !_RenderOnlySingleCamera) return; + if (!ShouldRender(camera)) + { + return; + } + Shader.SetGlobalTexture(ShaderIDs.s_ReflectionTexture, Texture2D.blackTexture); } - internal void LateUpdate() + internal void LateUpdate(ScriptableRenderContext context) { // Frame rate limiter. if (_LastRefreshOnFrame > 0 && RefreshPerFrames > 1) @@ -362,7 +385,7 @@ namespace WaveHarmonic.Crest } // We do not want the water plane when rendering planar reflections. - _Water.Root.gameObject.SetActive(false); + _Water.Surface.Root.gameObject.SetActive(false); CurrentCamera = _CameraReflections; @@ -390,7 +413,7 @@ namespace WaveHarmonic.Crest try #endif { - Render(); + Render(context); } #if UNITY_EDITOR // Ensure that any global settings are restored. @@ -414,15 +437,18 @@ namespace WaveHarmonic.Crest _QualitySettingsOverride.Restore(); CurrentCamera = null; - _Water.Root.gameObject.SetActive(true); + _Water.Surface.Root.gameObject.SetActive(true); // Remember this frame as last refreshed. _LastRefreshOnFrame = Time.renderedFrameCount; } } - void Render() + void Render(ScriptableRenderContext context) { +#if UNITY_6000_0_OR_NEWER && d_UnityURP + _CameraReflections.targetTexture = _ReflectionTexture; +#else var descriptor = _ReflectionTexture.descriptor; descriptor.dimension = TextureDimension.Tex2D; descriptor.volumeDepth = 1; @@ -430,6 +456,7 @@ namespace WaveHarmonic.Crest // No need to clear, as camera clears using the skybox. var target = RenderTexture.GetTemporary(descriptor); _CameraReflections.targetTexture = target; +#endif if (_Mode != WaterReflectionSide.Below) { @@ -441,8 +468,11 @@ namespace WaveHarmonic.Crest _CameraReflections.cullingMask = _Layers & ~(1 << _UnderWater.Layer); } - RenderCamera(_CameraReflections, Vector3.up, false); + RenderCamera(context, _CameraReflections, Vector3.up, false, 0); + +#if !(UNITY_6000_0_OR_NEWER && d_UnityURP) Graphics.CopyTexture(target, 0, 0, _ReflectionTexture, 0, 0); +#endif _CameraReflections.ResetProjectionMatrix(); } @@ -459,29 +489,33 @@ namespace WaveHarmonic.Crest _CameraReflections.depthTextureMode = DepthTextureMode.Depth; } - RenderCamera(_CameraReflections, Vector3.down, _NonObliqueNearSurface); + RenderCamera(context, _CameraReflections, Vector3.down, _NonObliqueNearSurface, 1); + +#if !(UNITY_6000_0_OR_NEWER && d_UnityURP) Graphics.CopyTexture(target, 0, 0, _ReflectionTexture, 1, 0); +#endif _CameraReflections.ResetProjectionMatrix(); } - +#if !(UNITY_6000_0_OR_NEWER && d_UnityURP) RenderTexture.ReleaseTemporary(target); +#endif _ReflectionTexture.GenerateMips(); Shader.SetGlobalVectorArray(ShaderIDs.s_ReflectionPositionNormal, _ReflectionPositionNormal); } - void RenderCamera(Camera camera, Vector3 planeNormal, bool nonObliqueNearSurface) + void RenderCamera(ScriptableRenderContext context, Camera camera, Vector3 planeNormal, bool nonObliqueNearSurface, int slice) { // Find out the reflection plane: position and normal in world space - var planePosition = _Water.Root.position; + var planePosition = _Water.Position; var offset = _ClipPlaneOffset; { var viewpoint = _CameraViewpoint.transform; - if (offset == 0f && viewpoint.position.y == 0f && viewpoint.rotation.eulerAngles.y == 0f) + if (offset == 0f && viewpoint.position.y == planePosition.y) { // Minor offset to prevent "Screen position out of view frustum". Smallest number // to work with both above and below. Smallest number to work with both above and @@ -518,7 +552,7 @@ namespace WaveHarmonic.Crest if (SupportsRecursiveRendering) { - Helpers.RenderCamera(camera, _Water._Context); + Helpers.RenderCamera(camera, context, slice); } else { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CustomTimeProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CustomTimeProvider.cs index 088bc487b..9173879d3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CustomTimeProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CustomTimeProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -47,20 +47,34 @@ namespace WaveHarmonic.Crest readonly DefaultTimeProvider _DefaultTimeProvider = new(); float _TimeInternal = 0f; + bool _FirstUpdate = true; - private protected override void OnEnable() + private protected override void Initialize() { - base.OnEnable(); - - // May as well start on the same time value as unity - _TimeInternal = UnityEngine.Time.time; + base.Initialize(); + _FirstUpdate = true; } - void Update() + private protected override System.Action OnUpdateMethod => OnUpdate; + + void OnUpdate(WaterRenderer water) { // Use default TP delta time to update our time, because this dt works // well in edit mode - if (!_Paused) + if (_FirstUpdate) + { + _TimeInternal = _DefaultTimeProvider.Time; + +#if UNITY_EDITOR + if (!Application.isPlaying) + { + _TimeInternal += _DefaultTimeProvider.Delta; + } +#endif + + _FirstUpdate = false; + } + else if (!_Paused) { _TimeInternal += _DefaultTimeProvider.Delta; } @@ -71,20 +85,17 @@ namespace WaveHarmonic.Crest { get { + if (!isActiveAndEnabled) + { + return _DefaultTimeProvider.Time; + } + // Override means override if (_OverrideTime) { return _Time; } - // In edit mode, update is seldom called, so rely on the default TP -#if UNITY_EDITOR - if (!Application.isPlaying && !_Paused) - { - return _DefaultTimeProvider.Time; - } -#endif - // Otherwise use our accumulated time return _TimeInternal; } @@ -92,6 +103,27 @@ namespace WaveHarmonic.Crest // Either use override, or the default TP which works in edit mode /// - public override float Delta => _OverrideDeltaTime ? _DeltaTime : _DefaultTimeProvider.Delta; + public override float Delta + { + get + { + if (!isActiveAndEnabled) + { + return _DefaultTimeProvider.Delta; + } + + if (_Paused) + { + return 0f; + } + + if (_OverrideDeltaTime) + { + return _DeltaTime; + } + + return _DefaultTimeProvider.Delta; + } + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CutsceneTimeProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CutsceneTimeProvider.cs index c3c2983b7..f0b28b78b 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CutsceneTimeProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/CutsceneTimeProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/DefaultTimeProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/DefaultTimeProvider.cs index b5d546026..cac6bf3a6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/DefaultTimeProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/DefaultTimeProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. namespace WaveHarmonic.Crest @@ -19,7 +19,7 @@ namespace WaveHarmonic.Crest } else { - return WaterRenderer.LastUpdateEditorTime; + return WaterRenderer.EditorTime; } #else return UnityEngine.Time.time; @@ -38,7 +38,7 @@ namespace WaveHarmonic.Crest } else { - return 1f / 20f; + return WaterRenderer.EditorDeltaTime; } #else return UnityEngine.Time.deltaTime; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/NetworkedTimeProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/NetworkedTimeProvider.cs index 407c613d5..33a5b00d7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/NetworkedTimeProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/NetworkedTimeProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/TimeProvider.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/TimeProvider.cs index 6a852a3fa..7f773ff66 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/TimeProvider.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Time/TimeProvider.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using WaveHarmonic.Crest.Internal; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Uniforms.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Uniforms.cs index f0b6198a6..710bb7fef 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Uniforms.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Uniforms.cs @@ -21,9 +21,38 @@ namespace WaveHarmonic.Crest public static readonly int s_TextureSize = Shader.PropertyToID("_Crest_TextureSize"); public static readonly int s_TexturePosition = Shader.PropertyToID("_Crest_TexturePosition"); public static readonly int s_TextureRotation = Shader.PropertyToID("_Crest_TextureRotation"); + public static readonly int s_Multiplier = Shader.PropertyToID("_Crest_Multiplier"); public static readonly int s_FeatherWidth = Shader.PropertyToID("_Crest_FeatherWidth"); public static readonly int s_NegativeValues = Shader.PropertyToID("_Crest_NegativeValues"); public static readonly int s_BoundaryXZ = Shader.PropertyToID("_Crest_BoundaryXZ"); public static readonly int s_DrawBoundaryXZ = Shader.PropertyToID("_Crest_DrawBoundaryXZ"); + + public static class Unity + { + public static readonly int s_CameraDepthTexture = Shader.PropertyToID("_CameraDepthTexture"); + public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture"); + public static readonly int s_MatrixPreviousM = Shader.PropertyToID("unity_MatrixPreviousM"); + public static readonly int s_SpecCube0 = Shader.PropertyToID("unity_SpecCube0"); + public static readonly int s_Time = Shader.PropertyToID("_Time"); + public static readonly int s_CameraToWorld = Shader.PropertyToID("_CameraToWorld"); + + + // Shader Graph + public static readonly int s_Surface = Shader.PropertyToID("_Surface"); + public static readonly int s_SrcBlend = Shader.PropertyToID("_SrcBlend"); + public static readonly int s_DstBlend = Shader.PropertyToID("_DstBlend"); + + + // Built-In Renderer + public static readonly int s_LightColor0 = Shader.PropertyToID("_LightColor0"); + public static readonly int s_ShadowMapTexture = Shader.PropertyToID("_ShadowMapTexture"); + public static readonly int s_WorldSpaceLightPos0 = Shader.PropertyToID("_WorldSpaceLightPos0"); + + // High Definition Renderer + public static readonly int s_ShaderVariablesGlobal = Shader.PropertyToID("ShaderVariablesGlobal"); + + // Universal Renderer + public static readonly int s_GlossyEnvironmentCubeMap = Shader.PropertyToID("_GlossyEnvironmentCubeMap"); + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core.meta new file mode 100644 index 000000000..bae4c8c6f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f03dd318ef494ed4793cac667ef2858f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime.meta new file mode 100644 index 000000000..aeed52fdd --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c9d8168ffc7eeda4fad34275d57c585d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs new file mode 100644 index 000000000..c9debe042 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs @@ -0,0 +1,7 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("WaveHarmonic.Crest")] +[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Shared")] diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs.meta new file mode 100644 index 000000000..e4c8039e1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/Assembly.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9d248516e9d84702a7da49167649f40 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref new file mode 100644 index 000000000..0319582cf --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref @@ -0,0 +1,3 @@ +{ + "reference": "GUID:df380645f10b7bc4b97d4f5eb6303d95" +} \ No newline at end of file diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref.meta new file mode 100644 index 000000000..630e0fc02 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Core/Runtime/WaveHarmonic.Crest.Bridge.asmref.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9a761b4f3cc5b4e468121ec3c51dda5a +AssemblyDefinitionReferenceImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Universal/Runtime/Assembly.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Universal/Runtime/Assembly.cs index 62ec8004b..c9debe042 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Universal/Runtime/Assembly.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Bridges/Unity.RenderPipelines.Universal/Runtime/Assembly.cs @@ -4,3 +4,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("WaveHarmonic.Crest")] +[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Shared")] diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Collections/SortedList.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Collections/SortedList.cs index d58ae306b..0bbd08337 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Collections/SortedList.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Collections/SortedList.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System.Collections; @@ -42,6 +42,16 @@ namespace WaveHarmonic.Crest.Utility _NeedsSorting = true; } + public bool Contains(TValue value) + { + foreach (var item in _BackingList) + { + if (item.Value.Equals(value)) return true; + } + + return false; + } + public bool Remove(TValue value) { // This remove function has a fairly high complexity, as we need to search diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/Attributes.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/Attributes.cs index 65245785d..ca555c14d 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/Attributes.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/Attributes.cs @@ -84,6 +84,16 @@ namespace WaveHarmonic.Crest } } + [Conditional(Symbols.k_UnityEditor)] + [AttributeUsage(AttributeTargets.Enum, AllowMultiple = false, Inherited = false)] + sealed class GenerateDoc : Attribute + { + public GenerateDoc() + { + + } + } + #if !UNITY_EDITOR [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] @@ -102,12 +112,21 @@ namespace WaveHarmonic.Crest sealed class Disabled : Decorator { } [Conditional(Symbols.k_UnityEditor)] - sealed class AttachMaterialEditor : Decorator { } + sealed class AttachMaterialEditor : Attribute + { + public AttachMaterialEditor(int order = 0) { } + } + + [Conditional(Symbols.k_UnityEditor)] + sealed class InlineToggle : Decorator + { + public InlineToggle(bool fix = false) { } + } [Conditional(Symbols.k_UnityEditor)] sealed class Embedded : Decorator { - public Embedded(int margin = 0) { } + public Embedded(int margin = 0, string defaultPropertyName = null) { } } [Conditional(Symbols.k_UnityEditor)] diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/EditorBehaviour.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/EditorBehaviour.cs index 8006d5ca2..af1def4fa 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/EditorBehaviour.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Component/EditorBehaviour.cs @@ -21,8 +21,13 @@ namespace WaveHarmonic.Crest.Internal bool _IsFirstOnValidate = true; internal bool _IsPrefabStageInstance; + private protected virtual bool CanRunInEditMode => true; + private protected virtual void Awake() { + // Prevents allocations. + useGUILayout = false; + // When copy and pasting from one scene to another, destroy instance objects as // they will have bad state. foreach (var generated in transform.GetComponentsInChildren(includeInactive: true)) @@ -37,7 +42,7 @@ namespace WaveHarmonic.Crest.Internal /// /// Start method. Must be called if overriden. /// - protected virtual void Start() + private protected virtual void Start() { if (Application.isPlaying && !(bool)s_ExecuteValidators.Invoke(null, new object[] { this })) { @@ -63,6 +68,11 @@ namespace WaveHarmonic.Crest.Internal return; } + if (!CanRunInEditMode) + { + return; + } + if (_IsFirstOnValidate) { var attribute = Helpers.GetCustomAttribute(GetType()); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug.meta new file mode 100644 index 000000000..b34049290 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65e84a69730de24458beac07cc1bde92 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs new file mode 100644 index 000000000..eb310c67e --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs @@ -0,0 +1,29 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; + +namespace WaveHarmonic.Crest.Utility +{ + static class DebugUtility + { + public delegate void DrawLine(Vector3 position, Vector3 up, Color color, float duration); + + public static void DrawCross(DrawLine draw, Vector3 position, float r, Color color, float duration = 0f) + { + draw(position - Vector3.up * r, position + Vector3.up * r, color, duration); + draw(position - Vector3.right * r, position + Vector3.right * r, color, duration); + draw(position - Vector3.forward * r, position + Vector3.forward * r, color, duration); + } + + public static void DrawCross(DrawLine draw, Vector3 position, Vector3 up, float r, Color color, float duration = 0f) + { + up.Normalize(); + var right = Vector3.Normalize(Vector3.Cross(up, Vector3.forward)); + var forward = Vector3.Cross(up, right); + draw(position - up * r, position + up * r, color, duration); + draw(position - right * r, position + right * r, color, duration); + draw(position - forward * r, position + forward * r, color, duration); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs.meta new file mode 100644 index 000000000..d09e58170 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Debug/Debug.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afcafd3203e384a54aa71d2c40f2025c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Helpers.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Helpers.cs index 8500c7d33..e6037e6bf 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Helpers.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Helpers.cs @@ -21,6 +21,18 @@ namespace WaveHarmonic.Crest /// static partial class Helpers { + // Adapted from: + // Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs +#if UNITY_SWITCH || UNITY_ANDROID || UNITY_EMBEDDED_LINUX || UNITY_QNX + internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D24_UNorm_S8_UInt; + internal const int k_DepthBufferBits = 24; + internal const DepthBits k_DepthBits = DepthBits.Depth24; +#else + internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D32_SFloat_S8_UInt; + internal const int k_DepthBufferBits = 32; + internal const DepthBits k_DepthBits = DepthBits.Depth32; +#endif + public static class ShaderIDs { public static readonly int s_MainTexture = Shader.PropertyToID("_Utility_MainTexture"); @@ -128,31 +140,6 @@ namespace WaveHarmonic.Crest public static WaitForEndOfFrame WaitForEndOfFrame { get; } = new(); - static Material s_UtilityMaterial; - public static Material UtilityMaterial - { - get - { - if (s_UtilityMaterial == null) - { - s_UtilityMaterial = new(Shader.Find("Hidden/Crest/Utility/Blit")); - } - - return s_UtilityMaterial; - } - } - - // Need to cast to int but no conversion cost. - // https://stackoverflow.com/a/69148528 - internal enum UtilityPass - { - CopyColor, - CopyDepth, - ClearDepth, - ClearStencil, - Copy, - } - // Taken from: // https://github.com/Unity-Technologies/Graphics/blob/871df5563d88e1ba778c82a43f39c9afc95368e6/Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl#L1149-L1152 // Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane). @@ -220,15 +207,22 @@ namespace WaveHarmonic.Crest } /// - /// Uses PrefabUtility.InstantiatePrefab in editor and GameObject.Instantiate in standalone. + /// Uses PrefabUtility.InstantiatePrefab in edit mode, otherwise uses GameObject.Instantiate. /// public static GameObject InstantiatePrefab(GameObject prefab) { #if UNITY_EDITOR - return (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefab); -#else - return GameObject.Instantiate(prefab); + if (!Application.isPlaying) + { + // Previously we always used this in the editor, including play mode. But it was + // reported to have failed (null return) when Asset Bundles were used in play mode. + return (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefab); + } + else #endif + { + return Object.Instantiate(prefab); + } } // Taken from Unity @@ -343,7 +337,7 @@ namespace WaveHarmonic.Crest if (RenderPipelineHelper.IsUniversal) { // MSAA will be the same for every camera if XR rendering. - isMSAA = isMSAA || XRHelpers.IsRunning; + isMSAA = isMSAA || Rendering.EnabledXR; } #endif @@ -588,7 +582,7 @@ namespace WaveHarmonic.Crest /// /// Uses Destroy in play mode or DestroyImmediate in edit mode. /// - public static void Destroy(Object @object) + public static void Destroy(Object @object, bool undo = false) { #if UNITY_EDITOR // We must use DestroyImmediate in edit mode. As it apparently has an overhead, use recommended Destroy in @@ -596,7 +590,14 @@ namespace WaveHarmonic.Crest // https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html if (!Application.isPlaying) { - Object.DestroyImmediate(@object); + if (undo) + { + UnityEditor.Undo.DestroyObjectImmediate(@object); + } + else + { + Object.DestroyImmediate(@object); + } } else #endif @@ -605,11 +606,13 @@ namespace WaveHarmonic.Crest } } + static readonly Matrix4x4 s_ScaleMatrix = Matrix4x4.Scale(new(1f, 1f, -1f)); + // Borrowed from SRP code: // https://github.com/Unity-Technologies/Graphics/blob/7d292932bec3b4257a4defaf698fc7d77e2027f5/com.unity.render-pipelines.high-definition/Runtime/Core/Utilities/GeometryUtils.cs#L181-L184 public static Matrix4x4 CalculateWorldToCameraMatrixRHS(Vector3 position, Quaternion rotation) { - return Matrix4x4.Scale(new(1, 1, -1)) * Matrix4x4.TRS(position, rotation, Vector3.one).inverse; + return s_ScaleMatrix * Matrix4x4.TRS(position, rotation, Vector3.one).inverse; } /// @@ -618,14 +621,7 @@ namespace WaveHarmonic.Crest /// public static void Blit(CommandBuffer buffer, RenderTargetIdentifier target, Material material, int pass = -1, MaterialPropertyBlock properties = null) { - if (!RenderPipelineHelper.IsLegacy) - { - CoreUtils.SetRenderTarget(buffer, target); - } - else - { - buffer.SetRenderTarget(target); - } + CoreUtils.SetRenderTarget(buffer, target); buffer.DrawProcedural ( @@ -795,7 +791,7 @@ namespace WaveHarmonic.Crest static readonly UnityEngine.Rendering.RenderPipeline.StandardRequest s_RenderStandardRequest = new(); - public static void RenderCamera(Camera camera, ScriptableRenderContext context) + public static void RenderCamera(Camera camera, ScriptableRenderContext context, int slice) { #if d_UnityURP if (RenderPipelineHelper.IsUniversal) @@ -804,7 +800,9 @@ namespace WaveHarmonic.Crest // SingleCameraRequest does not render the full camera stack, thus should exclude // overlays which is likely desirable. Alternative approach worth investigating: // https://docs.unity3d.com/6000.0/Documentation/Manual/urp/User-Render-Requests.html - // TODO: pass destination texture and slice instead of copying later. + // Setting destination silences a warning if Opaque Texture enabled. + s_RenderSingleCameraRequest.destination = camera.targetTexture; + s_RenderSingleCameraRequest.slice = slice; UnityEngine.Rendering.RenderPipeline.SubmitRenderRequest(camera, s_RenderSingleCameraRequest); #else #pragma warning disable CS0618 // Type or member is obsolete @@ -828,7 +826,44 @@ namespace WaveHarmonic.Crest } + // Undo + static partial class Helpers + { + public static class Undo + { + static class Symbols + { + public const string k_UnityEditor = "UNITY_EDITOR"; + } + + [System.Diagnostics.Conditional(Symbols.k_UnityEditor)] + public static void RecordObject(Object @object, string label) + { +#if UNITY_EDITOR + UnityEditor.Undo.RecordObject(@object, label); +#endif + } + + [System.Diagnostics.Conditional(Symbols.k_UnityEditor)] + public static void SetSiblingIndex(Transform transform, int index, string label) + { +#if UNITY_EDITOR + UnityEditor.Undo.SetSiblingIndex(transform, index, label); +#endif + } + + [System.Diagnostics.Conditional(Symbols.k_UnityEditor)] + public static void RegisterCreatedObjectUndo(Object @object, string label) + { +#if UNITY_EDITOR + UnityEditor.Undo.RegisterCreatedObjectUndo(@object, label); +#endif + } + } + } + // Terrain +#if d_Unity_Terrain static partial class Helpers { static readonly List s_Terrains = new(); @@ -838,6 +873,11 @@ namespace WaveHarmonic.Crest foreach (var terrain in s_Terrains) { + if (terrain.terrainData == null) + { + continue; + } + var rect = new Rect(terrain.transform.position.XZ(), terrain.terrainData.size.XZ()); // Return the first one. @@ -850,6 +890,7 @@ namespace WaveHarmonic.Crest return null; } } +#endif // d_Unity_Terrain namespace Internal { @@ -869,6 +910,7 @@ namespace WaveHarmonic.Crest public static Vector4 XYNN(this Vector2 v, float n = 0f) => new(v.x, v.y, n, n); public static Vector4 XYNN(this Vector2 v, Vector2 n) => new(v.x, v.y, n.x, n.y); public static Vector4 NNZW(this Vector2 v, float n = 0f) => new(n, n, v.x, v.y); + public static Vector4 XNZW(this Vector4 v, float n) => new(v.x, n, v.z, v.w); public static float Maximum(this Vector3 v) => Mathf.Max(Mathf.Max(v.x, v.y), v.z); public static Vector2 Absolute(this Vector2 v) => new @@ -961,6 +1003,12 @@ namespace WaveHarmonic.Crest return GeometryUtility.CalculateBounds(s_BoundsPoints, transform.localToWorldMatrix); } + public static bool IntersectsXZ(this Bounds a, Bounds b) + { + return a.min.x <= b.max.x && a.max.x >= b.min.x && + a.min.z <= b.max.z && a.max.z >= b.min.z; + } + public static Rect RectXZ(this Bounds bounds) { return Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs new file mode 100644 index 000000000..e1bbdbee2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs @@ -0,0 +1,111 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; +using UnityEngine.Rendering; + +namespace WaveHarmonic.Crest +{ + interface ICommandWrapper : IPropertyWrapper + { + void SetInvertCulling(bool invert); + void DrawFullScreenTriangle(Material material, int pass, MaterialPropertyBlock block = null); + void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null); + } + + + readonly struct CommandWrapper : ICommandWrapper + { + public CommandBuffer Commands { get; } + public CommandWrapper(CommandBuffer commands) => Commands = commands; + public void SetFloat(int param, float value) => Commands.SetGlobalFloat(param, value); + public void SetFloatArray(int param, float[] value) => Commands.SetGlobalFloatArray(param, value); + public void SetTexture(int param, Texture value) => Commands.SetGlobalTexture(param, value); + public void SetVector(int param, Vector4 value) => Commands.SetGlobalVector(param, value); + public void SetVectorArray(int param, Vector4[] value) => Commands.SetGlobalVectorArray(param, value); + public void SetMatrix(int param, Matrix4x4 value) => Commands.SetGlobalMatrix(param, value); + public void SetInteger(int param, int value) => Commands.SetGlobalInteger(param, value); + public void SetBoolean(int param, bool value) => Commands.SetGlobalInteger(param, value ? 1 : 0); + + public void GetBlock() { } + public void SetBlock() { } + + public void SetInvertCulling(bool invert) => Commands.SetInvertCulling(invert); + + public void DrawFullScreenTriangle(Material material, int pass = -1, MaterialPropertyBlock block = null) + { + Commands.DrawProcedural + ( + Matrix4x4.identity, + material, + pass, + MeshTopology.Triangles, + vertexCount: 3, + instanceCount: 1, + block + ); + } + + public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null) + { + Commands.DrawMesh + ( + mesh, + matrix, + material, + submeshIndex: 0, + pass, + block + ); + } + } + +#if UNITY_6000_0_OR_NEWER + readonly struct RasterCommandWrapper : ICommandWrapper + { + public RasterCommandBuffer Commands { get; } + public RasterCommandWrapper(RasterCommandBuffer commands) => Commands = commands; + public void SetFloat(int param, float value) => Commands.SetGlobalFloat(param, value); + public void SetFloatArray(int param, float[] value) => Commands.SetGlobalFloatArray(param, value); + // WARNING: bypasses RG checks. Only use for textures external to RG. + public void SetTexture(int param, Texture value) => Commands.m_WrappedCommandBuffer.SetGlobalTexture(param, value); + public void SetVector(int param, Vector4 value) => Commands.SetGlobalVector(param, value); + public void SetVectorArray(int param, Vector4[] value) => Commands.SetGlobalVectorArray(param, value); + public void SetMatrix(int param, Matrix4x4 value) => Commands.SetGlobalMatrix(param, value); + public void SetInteger(int param, int value) => Commands.SetGlobalInteger(param, value); + public void SetBoolean(int param, bool value) => Commands.SetGlobalInteger(param, value ? 1 : 0); + + public void GetBlock() { } + public void SetBlock() { } + + public void SetInvertCulling(bool invert) => Commands.SetInvertCulling(invert); + + public void DrawFullScreenTriangle(Material material, int pass, MaterialPropertyBlock block = null) + { + Commands.DrawProcedural + ( + Matrix4x4.identity, + material, + pass, + MeshTopology.Triangles, + vertexCount: 3, + instanceCount: 1, + block + ); + } + + public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null) + { + Commands.DrawMesh + ( + mesh, + matrix, + material, + submeshIndex: 0, + pass, + block + ); + } + } +#endif // UNITY_6000_0_OR_NEWER +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs.meta new file mode 100644 index 000000000..7ffa291dc --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CommandWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a5766c3523cc4af586139878192e12d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CustomPassHelpers.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CustomPassHelpers.cs index 663c0693a..1eed39ae5 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CustomPassHelpers.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/CustomPassHelpers.cs @@ -9,6 +9,12 @@ using UnityEngine.Rendering.HighDefinition; namespace WaveHarmonic.Crest { + class CustomPass : UnityEngine.Rendering.HighDefinition.CustomPass + { + internal GameObject _GameObject; + internal CustomPassVolume _Volume; + } + static class CustomPassHelpers { internal static List s_Volumes = new(); @@ -62,7 +68,8 @@ namespace WaveHarmonic.Crest GameObject gameObject, ref T pass, string name, - CustomPassInjectionPoint injectionPoint + CustomPassInjectionPoint injectionPoint, + int priority = 0 ) where T : CustomPass, new() { @@ -85,14 +92,15 @@ namespace WaveHarmonic.Crest volume = gameObject.AddComponent(); volume.injectionPoint = injectionPoint; volume.isGlobal = true; + volume.priority = priority; } // Create custom pass. pass ??= new() { - name = $"Crest {name}", - targetColorBuffer = CustomPass.TargetBuffer.None, - targetDepthBuffer = CustomPass.TargetBuffer.None, + name = name, + targetColorBuffer = UnityEngine.Rendering.HighDefinition.CustomPass.TargetBuffer.None, + targetDepthBuffer = UnityEngine.Rendering.HighDefinition.CustomPass.TargetBuffer.None, }; // Add custom pass. @@ -100,6 +108,27 @@ namespace WaveHarmonic.Crest { volume.customPasses.Add(pass); } + + pass._GameObject = gameObject; + pass._Volume = volume; + } + + public static void Update(GameObject go, T pass, CustomPassInjectionPoint point, int priority = 0) where T : CustomPass + { + CustomPassVolume volume = null; + go.GetComponents(s_Volumes); + + foreach (var v in s_Volumes) + { + if (v.customPasses.Contains(pass)) + { + volume = v; + break; + } + } + + volume.injectionPoint = point; + volume.priority = priority; } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs new file mode 100644 index 000000000..610eda74e --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs @@ -0,0 +1,52 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// Adapted from: +// https://github.com/keijiro/LightProbeUtility/blob/85c93577338e10a52dd53f263056de08d883337a/Assets/LightProbeUtility.cs + +// With fixes from: +// https://github.com/keijiro/LightProbeUtility/pull/2 + +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + static class LightProbeUtility + { + static readonly int[] s_SHA = + { + Shader.PropertyToID("unity_SHAr"), + Shader.PropertyToID("unity_SHAg"), + Shader.PropertyToID("unity_SHAb") + }; + + static readonly int[] s_SHB = + { + Shader.PropertyToID("unity_SHBr"), + Shader.PropertyToID("unity_SHBg"), + Shader.PropertyToID("unity_SHBb") + }; + + static readonly int s_SHC = Shader.PropertyToID("unity_SHC"); + + public static void SetSHCoefficients(this T properties, Vector3 position) where T : IPropertyWrapper + { + LightProbes.GetInterpolatedProbe(position, null, out var sh); + + // Constant + Linear. + for (var i = 0; i < 3; i++) + { + properties.SetVector(s_SHA[i], new(sh[i, 3], sh[i, 1], sh[i, 2], sh[i, 0] - sh[i, 6])); + } + + // Quadratic polynomials. + for (var i = 0; i < 3; i++) + { + properties.SetVector(s_SHB[i], new(sh[i, 4], sh[i, 5], sh[i, 6] * 3, sh[i, 7])); + } + + // Final quadratic polynomial. + properties.SetVector(s_SHC, new(sh[0, 8], sh[1, 8], sh[2, 8], 1)); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs.meta new file mode 100644 index 000000000..ab1d6c21f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/LightProbeUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf4aa5298ac5b4562a8c1f0466045eff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/PropertyWrapper.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/PropertyWrapper.cs index f4fbfc9de..6d6a83c50 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/PropertyWrapper.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/PropertyWrapper.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs new file mode 100644 index 000000000..30eed4aef --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs @@ -0,0 +1,37 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// RTHandles for Built-In Render Pipeline. +// We cannot call dispose ourselves, but it does not seem to be a problem. + +using UnityEngine; + +namespace WaveHarmonic.Crest.Utility +{ + static class RTHandles + { + public static void Initialize() + { + if (!RenderPipelineHelper.IsLegacy) + { + return; + } + + // Check whether already initialized. + if (UnityEngine.Rendering.RTHandles.maxWidth > 1) + { + return; + } + + UnityEngine.Rendering.RTHandles.Initialize(Screen.width, Screen.height); + UnityEngine.Rendering.RTHandles.SetHardwareDynamicResolutionState(false); + } + + public static void OnBeginCameraRendering(Camera camera) + { + // Forget Dynamic Scaling, as is broken for Shader Graph and Post-Processing anyway. + // The only foreseeable problem is if a third party calls this with a different size. + UnityEngine.Rendering.RTHandles.SetReferenceSize(camera.pixelWidth, camera.pixelHeight); + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs.meta new file mode 100644 index 000000000..9096bd404 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RTHandles.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fed5f2fe3fcaa450f9c621080f7989ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RenderGraphUtility.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RenderGraphUtility.cs index f7760fa44..7c9309bd8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RenderGraphUtility.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/RenderGraphUtility.cs @@ -34,18 +34,48 @@ namespace WaveHarmonic.Crest public static implicit operator TextureHandle(Handle texture) => texture._TextureHandle; } - static readonly FieldInfo s_RenderContext = typeof(InternalRenderGraphContext).GetField("renderContext", BindingFlags.NonPublic | BindingFlags.Instance); static readonly FieldInfo s_WrappedContext = typeof(UnsafeGraphContext).GetField("wrappedContext", BindingFlags.NonPublic | BindingFlags.Instance); - static readonly FieldInfo s_FrameData = typeof(RenderingData).GetField("frameData", BindingFlags.NonPublic | BindingFlags.Instance); public static ScriptableRenderContext GetRenderContext(this UnsafeGraphContext unsafeContext) { - return (ScriptableRenderContext)s_RenderContext.GetValue((InternalRenderGraphContext)s_WrappedContext.GetValue(unsafeContext)); + return ((InternalRenderGraphContext)s_WrappedContext.GetValue(unsafeContext)).renderContext; } public static ContextContainer GetFrameData(this ref RenderingData renderingData) { - return (ContextContainer)s_FrameData.GetValue(renderingData); + return renderingData.frameData; + } + + internal class PassData + { +#pragma warning disable IDE1006 // Naming Styles + public UniversalCameraData cameraData; + public UniversalRenderingData renderingData; + public Handle colorTargetHandle; + public Handle depthTargetHandle; +#pragma warning restore IDE1006 // Naming Styles + + public void Init(ContextContainer frameData, IUnsafeRenderGraphBuilder builder = null) + { + var resources = frameData.Get(); + cameraData = frameData.Get(); + renderingData = frameData.Get(); + + if (builder == null) + { +#pragma warning disable CS0618 // Type or member is obsolete + colorTargetHandle = cameraData.renderer.cameraColorTargetHandle; + depthTargetHandle = cameraData.renderer.cameraDepthTargetHandle; +#pragma warning restore CS0618 // Type or member is obsolete + } + else + { + colorTargetHandle = resources.activeColorTexture; + depthTargetHandle = resources.activeDepthTexture; + builder.UseTexture(colorTargetHandle, AccessFlags.ReadWrite); + builder.UseTexture(depthTargetHandle, AccessFlags.ReadWrite); + } + } } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs new file mode 100644 index 000000000..d0f01b9fd --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs @@ -0,0 +1,260 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// ENABLE_VR is defined if the platform supports XR. +// d_UnityModuleVR is defined if the VR module is installed. +// VR module depends on XR module (which does nothing by itself) so we only need to check the VR module. +#if ENABLE_VR && d_UnityModuleVR +#define _XR_ENABLED +#endif + +using System.Collections.Generic; +using System.Diagnostics; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; +using UnityEngine.Rendering.Universal; +using UnityEngine.XR; + +namespace WaveHarmonic.Crest +{ + static partial class Rendering + { + // Adaptor layer for XR module similar to Unity's XRGraphics/XRSRPSettings. + // We cannot use theirs as they keep on renaming it… + + static readonly GlobalKeyword s_SinglePassInstancedKeyword = new("STEREO_INSTANCING_ON"); + static readonly GlobalKeyword s_SinglePassMultiViewKeyword = new("STEREO_MULTIVIEW_ON"); + +#if _XR_ENABLED + internal static GlobalKeyword SinglePassKeyword => XRSettings.stereoRenderingMode switch + { + XRSettings.StereoRenderingMode.SinglePassInstanced => s_SinglePassInstancedKeyword, + XRSettings.StereoRenderingMode.SinglePassMultiview => s_SinglePassMultiViewKeyword, + _ => throw new System.NotImplementedException(), + }; +#endif + + public static bool EnabledXR + { + get + { +#if _XR_ENABLED + return XRSettings.enabled; +#else + return false; +#endif + } + } + + static bool SinglePassXR + { + get + { +#if _XR_ENABLED + return XRSettings.enabled && (XRSettings.stereoRenderingMode is XRSettings.StereoRenderingMode.SinglePassInstanced or XRSettings.StereoRenderingMode.SinglePassMultiview); +#else + return false; +#endif + } + } + + static bool MultiPassXR + { + get + { +#if _XR_ENABLED + return XRSettings.enabled && XRSettings.stereoRenderingMode is XRSettings.StereoRenderingMode.MultiPass; +#else + return false; +#endif + } + } + + public static partial class BIRP + { + [Conditional("_XR_ENABLED")] + public static void EnableXR(CommandBuffer commands, Camera camera) + { +#if _XR_ENABLED + if (!SinglePassXR || !camera.stereoEnabled) + { + return; + } + + commands.EnableKeyword(SinglePassKeyword); +#endif + } + + [Conditional("_XR_ENABLED")] + public static void DisableXR(CommandBuffer commands, Camera camera) + { +#if _XR_ENABLED + if (!SinglePassXR || !camera.stereoEnabled) + { + return; + } + + commands.DisableKeyword(SinglePassKeyword); +#endif + } + } + + + // + // Stereo Rendering + // + +#if _XR_ENABLED + public static partial class BIRP + { + // NOTE: This is the same value as Unity, but in the future it could be higher. + const int k_MaximumViewsXR = 2; + + static partial class ShaderIDs + { + public static readonly int s_StereoInverseViewProjection = Shader.PropertyToID("_Crest_StereoInverseViewProjection"); + } + + static readonly List s_DisplayListXR = new(); + + // Unity only supports one display right now. + static XRDisplaySubsystem DisplayXR => XRSettings.enabled ? s_DisplayListXR[0] : null; + + static Matrix4x4[] InverseViewProjectionMatrixXR { get; set; } = new Matrix4x4[2]; + + static Texture2DArray s_WhiteTextureXR = null; + public static Texture2DArray WhiteTextureXR + { + get + { + if (s_WhiteTextureXR == null) + { + s_WhiteTextureXR = TextureArrayHelpers.CreateTexture2DArray(Texture2D.whiteTexture, k_MaximumViewsXR); + s_WhiteTextureXR.name = "_Crest_WhiteTextureXR"; + } + + return s_WhiteTextureXR; + } + } + + public static void SetMatricesXR(Camera camera) + { + if (!camera.stereoEnabled || !SinglePassXR) + { + return; + } + + SubsystemManager.GetSubsystems(s_DisplayListXR); + // XR SPI only has one pass by definition. + DisplayXR.GetRenderPass(renderPassIndex: 0, out var xrPass); + xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrLeftEye); + xrPass.GetRenderParameter(camera, renderParameterIndex: 1, out var xrRightEye); + // We must opt for renderIntoTexture for Unity to handle Y flip. + InverseViewProjectionMatrixXR[0] = (GL.GetGPUProjectionMatrix(xrLeftEye.projection, true) * xrLeftEye.view).inverse; + InverseViewProjectionMatrixXR[1] = (GL.GetGPUProjectionMatrix(xrRightEye.projection, true) * xrRightEye.view).inverse; + Shader.SetGlobalMatrixArray(ShaderIDs.s_StereoInverseViewProjection, InverseViewProjectionMatrixXR); + } + } +#endif // _XR_ENABLED + } +} + +#if d_UnityURP +namespace WaveHarmonic.Crest +{ +#if !UNITY_6000_0_OR_NEWER + using UniversalCameraData = CameraData; +#endif + + static partial class Rendering + { + public static class URP + { + [Conditional("_XR_ENABLED")] + public static void EnableXR(CommandBuffer commands, UniversalCameraData camera) + { +#if _XR_ENABLED + // We need to check the mask or it will cause entire pipeline to output black. Appears to only affect URP. + if (!SinglePassXR || !camera.xrRendering || camera.camera.stereoTargetEye != StereoTargetEyeMask.Both) + { + return; + } + + commands.EnableKeyword(SinglePassKeyword); +#endif + } + + [Conditional("_XR_ENABLED")] + public static void DisableXR(CommandBuffer commands, UniversalCameraData camera) + { +#if _XR_ENABLED + if (!SinglePassXR || !camera.xrRendering || camera.camera.stereoTargetEye != StereoTargetEyeMask.Both) + { + return; + } + + commands.DisableKeyword(SinglePassKeyword); +#endif + } + } + } +} +#endif // d_UnityURP + +#if d_UnityHDRP +namespace WaveHarmonic.Crest +{ + static partial class Rendering + { + public static class HDRP + { + [Conditional("_XR_ENABLED")] + public static void EnableXR(CommandBuffer commands, HDAdditionalCameraData camera) + { +#if _XR_ENABLED + if (!SinglePassXR || camera == null || !camera.xrRendering) + { + return; + } + + commands.EnableKeyword(SinglePassKeyword); +#endif + } + + [Conditional("_XR_ENABLED")] + public static void DisableXR(CommandBuffer commands, HDAdditionalCameraData camera) + { +#if _XR_ENABLED + if (!SinglePassXR || camera == null || !camera.xrRendering) + { + return; + } + + commands.DisableKeyword(SinglePassKeyword); +#endif + } + + public static bool SkipPassXR(ref int index, HDAdditionalCameraData data) + { +#if _XR_ENABLED + if (MultiPassXR && data != null && data.xrRendering) + { + // Alternate between left and right eye. + index += 1; + index %= 2; + } + else +#endif + + { + index = -1; + } + + // Skip if rendering the right eye. + return index == 1; + } + } + } +} +#endif // d_UnityHDRP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs.meta new file mode 100644 index 000000000..b2da90142 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.XR.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: beeb15d60da12461bb224ab1b3a6a12a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs new file mode 100644 index 000000000..2ace7ffc7 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs @@ -0,0 +1,124 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if ENABLE_VR && d_UnityModuleVR +#define _XR_ENABLED +#endif + +using UnityEngine; +using UnityEngine.Experimental.Rendering; +using UnityEngine.XR; + +namespace WaveHarmonic.Crest +{ + static partial class Rendering + { + public static partial class BIRP + { + static partial class ShaderIDs + { + public static readonly int s_InverseViewProjection = Shader.PropertyToID("_Crest_InverseViewProjection"); + } + + public static Texture GetWhiteTexture(Camera camera) + { +#if _XR_ENABLED + if (camera.stereoEnabled && SinglePassXR) + { + return WhiteTextureXR; + } +#endif + + return Texture2D.whiteTexture; + } + + public static void SetMatrices(Camera camera) + { + Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, (GL.GetGPUProjectionMatrix(camera.projectionMatrix, true) * camera.worldToCameraMatrix).inverse); + +#if _XR_ENABLED + SetMatricesXR(camera); +#endif + } + + public enum FrameBufferFormatOverride + { + None, + LDR, + HDR, + } + + public static RenderTextureDescriptor GetCameraTargetDescriptor(Camera camera, FrameBufferFormatOverride hdrOverride = FrameBufferFormatOverride.None) + { + RenderTextureDescriptor descriptor; + +#if _XR_ENABLED + if (camera.stereoEnabled) + { + // Will not set the following correctly: + // - HDR format + descriptor = XRSettings.eyeTextureDesc; + } + else +#endif + { + // As recommended by Unity, in 2021.2 using SystemInfo.GetGraphicsFormat with DefaultFormat.LDR is + // necessary or gamma color space texture is returned: + // https://docs.unity3d.com/ScriptReference/Experimental.Rendering.DefaultFormat.html + descriptor = new(camera.pixelWidth, camera.pixelHeight, SystemInfo.GetGraphicsFormat(DefaultFormat.LDR), 0); + } + + // Set HDR format. + if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear) + { + var format = DefaultFormat.HDR; + + if (hdrOverride is not FrameBufferFormatOverride.None) + { + format = hdrOverride is FrameBufferFormatOverride.HDR ? DefaultFormat.HDR : DefaultFormat.LDR; + } +#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS + else + { + format = DefaultFormat.LDR; + } +#endif + + descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(format); + } + + return descriptor; + } + } + } + + static partial class Rendering + { + // Blit + public static partial class BIRP + { + // Need to cast to int but no conversion cost. + // https://stackoverflow.com/a/69148528 + internal enum UtilityPass + { + CopyDepth, + Copy, + MergeDepth, + } + + static Material s_UtilityMaterial; + public static Material UtilityMaterial + { + get + { + if (s_UtilityMaterial == null) + { + s_UtilityMaterial = new(Shader.Find("Hidden/Crest/Legacy/Blit")); + } + + return s_UtilityMaterial; + } + } + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs.meta new file mode 100644 index 000000000..291243d2e --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/Rendering.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 33d8472e9ea11461b8bf02d7c4a72ec4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/TextureArrayHelpers.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/TextureArrayHelpers.cs index 50908399c..352cb7b92 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/TextureArrayHelpers.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/Rendering/TextureArrayHelpers.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -7,7 +7,7 @@ namespace WaveHarmonic.Crest { static class TextureArrayHelpers { - const int k_SmallTextureSize = 4; + internal const int k_SmallTextureSize = 4; public static Texture2D CreateTexture2D(Color color, TextureFormat format) { diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/WaveHarmonic.Crest.Shared.asmdef b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/WaveHarmonic.Crest.Shared.asmdef index 69ab61993..25d16ebf4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/WaveHarmonic.Crest.Shared.asmdef +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/WaveHarmonic.Crest.Shared.asmdef @@ -16,6 +16,11 @@ "UNITY_2022_3_OR_NEWER" ], "versionDefines": [ + { + "name": "com.unity.modules.terrain", + "expression": "", + "define": "d_Unity_Terrain" + }, { "name": "com.unity.modules.xr", "expression": "", diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/XR/XRHelpers.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/XR/XRHelpers.cs index f556492d7..0fc2a485a 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/XR/XRHelpers.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Utility/Shared/XR/XRHelpers.cs @@ -1,183 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. -// Adaptor layer for XR module. Could be replaced with the following one day: -// com.unity.render-pipelines.core/Runtime/Common/XRGraphics.cs - -// Currently, only the horizon line uses it. - -// ENABLE_VR is defined if platform support XR. -// d_UnityModuleVR is defined if VR module is installed. -// VR module depends on XR module so we only need to check the VR module. -#if ENABLE_VR && d_UnityModuleVR -#define _XR_ENABLED -#endif - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.XR; - -namespace WaveHarmonic.Crest -{ - static class XRHelpers - { - // NOTE: This is the same value as Unity, but in the future it could be higher. - const int k_MaximumViews = 2; - -#if _XR_ENABLED - static readonly List s_DisplayList = new(); - - // Unity only supports one display right now. - static XRDisplaySubsystem Display => IsRunning ? s_DisplayList[0] : null; -#endif - - static Matrix4x4 LeftEyeProjectionMatrix { get; set; } - static Matrix4x4 RightEyeProjectionMatrix { get; set; } - static Matrix4x4 LeftEyeViewMatrix { get; set; } - static Matrix4x4 RightEyeViewMatrix { get; set; } - static Matrix4x4 LeftInverseViewProjectionMatrixGPU { get; set; } - static Matrix4x4 RightInverseViewProjectionMatrixGPU { get; set; } - - static class ShaderIDs - { - public static readonly int s_InverseViewProjection = Shader.PropertyToID("_Crest_InverseViewProjection"); - public static readonly int s_InverseViewProjectionRight = Shader.PropertyToID("_Crest_InverseViewProjectionRight"); - } - - internal static bool IsRunning - { - get - { -#if _XR_ENABLED - return XRSettings.enabled; -#else - return false; -#endif - } - } - - public static bool IsSinglePass - { - get - { -#if _XR_ENABLED - return IsRunning && (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced || - XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview); -#else - return false; -#endif - } - } - - static Texture2DArray s_WhiteTexture = null; - public static Texture2DArray WhiteTexture - { - get - { - if (s_WhiteTexture == null) - { - s_WhiteTexture = TextureArrayHelpers.CreateTexture2DArray(Texture2D.whiteTexture, k_MaximumViews); - s_WhiteTexture.name = "Crest White Texture XR"; - } - return s_WhiteTexture; - } - } - - public static RenderTextureDescriptor GetRenderTextureDescriptor(Camera camera) - { -#if _XR_ENABLED - if (camera.stereoEnabled) - { - return XRSettings.eyeTextureDesc; - } - else -#endif - { - // As recommended by Unity, in 2021.2 using SystemInfo.GetGraphicsFormat with DefaultFormat.LDR is - // necessary or gamma color space texture is returned: - // https://docs.unity3d.com/ScriptReference/Experimental.Rendering.DefaultFormat.html - return new(camera.pixelWidth, camera.pixelHeight, SystemInfo.GetGraphicsFormat(UnityEngine.Experimental.Rendering.DefaultFormat.LDR), 0); - } - } - - static void SetViewProjectionMatrices(Camera camera, int passIndex) - { -#if _XR_ENABLED - if (!XRSettings.enabled || IsSinglePass) - { - return; - } - // Not going to use cached values here just in case. - Display.GetRenderPass(passIndex, out var xrPass); - xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrEye); - camera.projectionMatrix = xrEye.projection; -#endif - } - - public static void UpdatePassIndex(ref int passIndex) - { - if (IsRunning) - { -#if _XR_ENABLED - if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.MultiPass) - { - // Alternate between left and right eye. - passIndex += 1; - passIndex %= 2; - } - else - { - passIndex = 0; - } -#endif - } - else - { - passIndex = -1; - } - } - - public static void SetInverseViewProjectionMatrix(Camera camera) - { - // Have to set these explicitly as the built-in transforms aren't in world-space for the blit function. - if (camera.stereoEnabled && IsSinglePass) - { - Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU); - Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjectionRight, RightInverseViewProjectionMatrixGPU); - } - else - { - Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU); - } - } - - public static void Update(Camera camera) - { -#if _XR_ENABLED - SubsystemManager.GetSubsystems(s_DisplayList); -#endif - - if (!camera.stereoEnabled || !IsSinglePass) - { - // Built-in renderer does not provide these matrices. - LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(camera.projectionMatrix, false) * camera.worldToCameraMatrix).inverse; - return; - } - -#if _XR_ENABLED - // XR SPI only has one pass by definition. - Display.GetRenderPass(renderPassIndex: 0, out var xrPass); - // Grab left and right eye. - xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrLeftEye); - xrPass.GetRenderParameter(camera, renderParameterIndex: 1, out var xrRightEye); - // Store all the matrices. - LeftEyeViewMatrix = xrLeftEye.view; - RightEyeViewMatrix = xrRightEye.view; - LeftEyeProjectionMatrix = xrLeftEye.projection; - RightEyeProjectionMatrix = xrRightEye.projection; - LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(LeftEyeProjectionMatrix, false) * LeftEyeViewMatrix).inverse; - RightInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(RightEyeProjectionMatrix, false) * RightEyeViewMatrix).inverse; -#endif - } - } -} +// Empty. diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPass.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPass.cs index beac85437..89f157fd3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPass.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPass.cs @@ -16,14 +16,15 @@ namespace WaveHarmonic.Crest RTHandle _ColorTarget; RTHandle _DepthTarget; - bool _FirstRender = true; readonly System.Action _CopyColorTexture; + readonly System.Action _SetRenderTargetToBackBuffers; public UnderwaterEffectPass(UnderwaterRenderer renderer) { _Renderer = renderer; _CopyColorTexture = new(CopyColorTexture); + _SetRenderTargetToBackBuffers = new(SetRenderTargetToBackBuffers); } void CopyColorTexture(CommandBuffer buffer) @@ -32,10 +33,20 @@ namespace WaveHarmonic.Crest CoreUtils.SetRenderTarget(buffer, _ColorTarget, _DepthTarget, ClearFlag.None); } + void SetRenderTargetToBackBuffers(CommandBuffer commands) + { + CoreUtils.SetRenderTarget(commands, _ColorTarget, _DepthTarget, ClearFlag.None); + } + public void Allocate(GraphicsFormat format) { + if (_Renderer.RenderBeforeTransparency && !_Renderer._NeedsColorTexture) + { + return; + } + // TODO: There may other settings we want to set or bring in. Not MSAA since this is a resolved texture. - _ColorTexture = RTHandles.Alloc + _ColorTexture ??= RTHandles.Alloc ( Vector2.one, TextureXR.slices, @@ -50,6 +61,11 @@ namespace WaveHarmonic.Crest public void ReAllocate(RenderTextureDescriptor descriptor) { + if (_Renderer.RenderBeforeTransparency && !_Renderer._NeedsColorTexture) + { + return; + } + // Descriptor will not have MSAA bound. RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _ColorTexture, descriptor, name: "_Crest_UnderwaterCameraColorTexture"); } @@ -62,22 +78,32 @@ namespace WaveHarmonic.Crest public void Execute(Camera camera, CommandBuffer buffer, RTHandle color, RTHandle depth, MaterialPropertyBlock mpb = null) { - _Renderer.UpdateEffectMaterial(camera, _FirstRender); + _Renderer.UpdateEffectMaterial(camera); _ColorTarget = color; _DepthTarget = depth; - CopyColorTexture(buffer); - buffer.SetGlobalTexture(UnderwaterRenderer.ShaderIDs.s_CameraColorTexture, _ColorTexture); + if (!_Renderer.RenderBeforeTransparency || _Renderer._NeedsColorTexture) + { + buffer.SetGlobalTexture(UnderwaterRenderer.ShaderIDs.s_CameraColorTexture, _ColorTexture); + } - _Renderer.ExecuteEffect(camera, buffer, _CopyColorTexture, mpb); + if (!_Renderer.RenderBeforeTransparency) + { + CopyColorTexture(buffer); + } + else + { + // TODO: needed for HDRP, but can set it on pass instead. + CoreUtils.SetRenderTarget(buffer, _ColorTarget, _DepthTarget, ClearFlag.None); + } + + _Renderer.ExecuteEffect(camera, buffer, _CopyColorTexture, _SetRenderTargetToBackBuffers, mpb); // The last pass (uber post) does not resolve the texture. // Although, this is wasteful if the pass after this does a resolve. // Possibly a bug with Unity? buffer.ResolveAntiAliasedSurface(color); - - _FirstRender = false; } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassHDRP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassHDRP.cs index a26516fa8..0fca57ca1 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassHDRP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassHDRP.cs @@ -7,7 +7,6 @@ using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; -using UnityEngine.Rendering.RendererUtils; namespace WaveHarmonic.Crest { @@ -17,13 +16,11 @@ namespace WaveHarmonic.Crest static UnderwaterRenderer s_Renderer; static UnderwaterEffectPass s_UnderwaterEffectPass; - static UnderwaterEffectPassHDRP s_Instance; + internal static UnderwaterEffectPassHDRP s_Instance; static CopyDepthBufferPassHDRP s_CopyDepthBufferPassHDRP; static ShaderTagId[] s_ForwardShaderTags; - GameObject _GameObject; - public static void Enable(UnderwaterRenderer renderer) { var gameObject = CustomPassHelpers.CreateOrUpdate @@ -37,25 +34,24 @@ namespace WaveHarmonic.Crest ( gameObject, ref s_CopyDepthBufferPassHDRP, - "Copy Depth Buffer", + UnderwaterRenderer.k_DrawVolume, CustomPassInjectionPoint.AfterOpaqueDepthAndNormal ); + var isBeforeTransparentPass = renderer.RenderBeforeTransparency; + CustomPassHelpers.CreateOrUpdate ( gameObject, ref s_Instance, - k_Name, - CustomPassInjectionPoint.BeforePostProcess + UnderwaterRenderer.k_DrawVolume, + GetInjectionPoint(isBeforeTransparentPass), + // Higher number (priority) means execute earlier. Volume executes first. + priority: 1 ); - s_Instance._GameObject = gameObject; - s_Renderer = renderer; s_UnderwaterEffectPass = new(renderer); - - RenderPipelineManager.beginCameraRendering -= s_Instance.OnBeginCameraRendering; - RenderPipelineManager.beginCameraRendering += s_Instance.OnBeginCameraRendering; } public static void Disable() @@ -68,9 +64,17 @@ namespace WaveHarmonic.Crest } } - void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + static CustomPassInjectionPoint GetInjectionPoint(bool isBeforeTransparentPass) + { + return isBeforeTransparentPass + ? CustomPassInjectionPoint.BeforeTransparent + : CustomPassInjectionPoint.BeforePostProcess; + } + + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { s_CopyDepthBufferPassHDRP.enabled = s_Renderer.UseStencilBuffer; + s_Instance._Volume.injectionPoint = GetInjectionPoint(s_Renderer.RenderBeforeTransparency); } protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) @@ -94,8 +98,6 @@ namespace WaveHarmonic.Crest protected override void Cleanup() { - RenderPipelineManager.beginCameraRendering -= s_Instance.OnBeginCameraRendering; - s_UnderwaterEffectPass?.Release(); } @@ -108,44 +110,15 @@ namespace WaveHarmonic.Crest return; } + // Allocate here in case user changes options and we skipped allocation in Setup. + s_UnderwaterEffectPass.Allocate(context.cameraColorBuffer.rt.graphicsFormat); + // Create a separate stencil buffer context by using a depth buffer copy if needed. var depthBuffer = s_Renderer.UseStencilBuffer ? s_CopyDepthBufferPassHDRP._DepthBufferCopy : context.cameraDepthBuffer; s_UnderwaterEffectPass.Execute(camera, context.cmd, context.cameraColorBuffer, depthBuffer, context.propertyBlock); - - // Renders transparent objects after the underwater effect. Using the correct - // shader, the above water portion of the object is rendered normally (in the - // transparent pass), and the below water portion is rendered here with underwater - // applied. - // See the following for reference: - // https://github.com/Unity-Technologies/Graphics/blob/master/Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/DrawRenderersCustomPass.cs - if (s_Renderer.EnableShaderAPI) - { - var renderConfig = HDUtils.GetRendererConfiguration - ( -#if UNITY_6000_0_OR_NEWER - context.hdCamera.frameSettings.IsEnabled(FrameSettingsField.AdaptiveProbeVolume), -#else - context.hdCamera.frameSettings.IsEnabled(FrameSettingsField.ProbeVolume), -#endif - context.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask) - ); - - var result = new RendererListDesc(s_ForwardShaderTags, context.cullingResults, context.hdCamera.camera) - { - rendererConfiguration = renderConfig, - renderQueueRange = GetRenderQueueRange(RenderQueueType.AllTransparent), - sortingCriteria = SortingCriteria.CommonTransparent, - excludeObjectMotionVectors = false, - layerMask = s_Renderer._TransparentObjectLayers, - }; - - context.cmd.EnableShaderKeyword(UnderwaterRenderer.k_KeywordUnderwaterObjects); - CoreUtils.DrawRendererList(context.renderContext, context.cmd, context.renderContext.CreateRendererList(result)); - context.cmd.DisableShaderKeyword(UnderwaterRenderer.k_KeywordUnderwaterObjects); - } } } @@ -166,13 +139,11 @@ namespace WaveHarmonic.Crest var buffer = context.cmd; - buffer.SetRenderTarget(BuiltinRenderTextureType.None, _DepthBufferCopy); - buffer.ClearRenderTarget(RTClearFlags.Depth, Color.black, 1, 0); - + // NOTE: previously we cleared the target depth first due to artifacts. buffer.CopyTexture(context.cameraDepthBuffer.rt, _DepthBufferCopy.rt); // Clear the stencil component just in case. - buffer.ClearRenderTarget(RTClearFlags.Stencil, Color.black, 1, 0); + CoreUtils.SetRenderTarget(buffer, BuiltinRenderTextureType.None, _DepthBufferCopy, ClearFlag.Stencil); } protected override void Cleanup() diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.RenderGraph.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.RenderGraph.cs index 1d664819a..209547f94 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.RenderGraph.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.RenderGraph.cs @@ -12,46 +12,16 @@ namespace WaveHarmonic.Crest { partial class UnderwaterEffectPassURP { - class PassData - { -#pragma warning disable IDE1006 // Naming Styles - public UniversalCameraData cameraData; - public RenderGraphHelper.Handle colorTargetHandle; - public RenderGraphHelper.Handle depthTargetHandle; -#pragma warning restore IDE1006 // Naming Styles - - public void Init(ContextContainer frameData, IUnsafeRenderGraphBuilder builder = null) - { - var resources = frameData.Get(); - cameraData = frameData.Get(); - - if (builder == null) - { -#pragma warning disable CS0618 // Type or member is obsolete - colorTargetHandle = cameraData.renderer.cameraColorTargetHandle; - depthTargetHandle = cameraData.renderer.cameraDepthTargetHandle; -#pragma warning restore CS0618 // Type or member is obsolete - } - else - { - colorTargetHandle = resources.activeColorTexture; - depthTargetHandle = resources.activeDepthTexture; - builder.UseTexture(colorTargetHandle, AccessFlags.ReadWrite); - builder.UseTexture(depthTargetHandle, AccessFlags.ReadWrite); - } - } - } - - readonly PassData _PassData = new(); + readonly RenderGraphHelper.PassData _PassData = new(); public override void RecordRenderGraph(RenderGraph graph, ContextContainer frame) { - using (var builder = graph.AddUnsafePass(k_Name, out var data)) + using (var builder = graph.AddUnsafePass(k_Name, out var data)) { data.Init(frame, builder); builder.AllowPassCulling(false); - builder.SetRenderFunc((data, context) => + builder.SetRenderFunc((data, context) => { var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); OnSetup(buffer, data); @@ -76,60 +46,6 @@ namespace WaveHarmonic.Crest context.ExecuteCommandBuffer(buffer); CommandBufferPool.Release(buffer); } - - partial class RenderObjectsWithoutFogPass - { - class PassData - { -#pragma warning disable IDE1006 // Naming Styles - public UniversalCameraData cameraData; - public UniversalLightData lightData; - public UniversalRenderingData renderingData; - public CullingResults cullResults; -#pragma warning restore IDE1006 // Naming Styles - - public void Init(ContextContainer frameData, IUnsafeRenderGraphBuilder builder = null) - { - cameraData = frameData.Get(); - lightData = frameData.Get(); - renderingData = frameData.Get(); - cullResults = renderingData.cullResults; - } - } - - readonly PassData _PassData = new(); - - public override void RecordRenderGraph(RenderGraph graph, ContextContainer frame) - { - using (var builder = graph.AddUnsafePass(k_Name, out var data)) - { - data.Init(frame, builder); - builder.AllowPassCulling(false); - - builder.SetRenderFunc((data, context) => - { - var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); - Execute(context.GetRenderContext(), buffer, data); - }); - } - } - - [System.Obsolete] - public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data) - { - _PassData.Init(data.GetFrameData()); - } - - [System.Obsolete] - public override void Execute(ScriptableRenderContext context, ref RenderingData data) - { - _PassData.Init(data.GetFrameData()); - var buffer = CommandBufferPool.Get(k_Name); - Execute(context, buffer, _PassData); - context.ExecuteCommandBuffer(buffer); - CommandBufferPool.Release(buffer); - } - } } partial class CopyDepthBufferPassURP @@ -150,11 +66,15 @@ namespace WaveHarmonic.Crest if (builder == null) { #pragma warning disable CS0618 // Type or member is obsolete + colorTargetHandle = cameraData.renderer.cameraColorTargetHandle; depthTargetHandle = cameraData.renderer.cameraDepthTargetHandle; #pragma warning restore CS0618 // Type or member is obsolete } else { + // We need reset render targets to these before the next pass, but we do not read + // or write to the color target. + colorTargetHandle = resources.activeColorTexture; depthTargetHandle = resources.activeDepthTexture; builder.UseTexture(depthTargetHandle, AccessFlags.ReadWrite); } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.cs index dd7a576de..c15d6c456 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterEffectPassURP.cs @@ -3,7 +3,6 @@ #if d_UnityURP -using System.Collections.Generic; using UnityEngine; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; @@ -13,12 +12,11 @@ namespace WaveHarmonic.Crest { sealed partial class UnderwaterEffectPassURP : ScriptableRenderPass { - const string k_Name = "Crest Underwater Effect"; + const string k_Name = "Crest.DrawWater/Volume"; UnderwaterRenderer _Renderer; - static UnderwaterEffectPassURP s_Instance; - RenderObjectsWithoutFogPass _ApplyFogToTransparentObjects; + internal static UnderwaterEffectPassURP s_Instance; UnderwaterEffectPass _UnderwaterEffectPass; CopyDepthBufferPassURP _CopyDepthBufferPass; @@ -27,7 +25,6 @@ namespace WaveHarmonic.Crest public UnderwaterEffectPassURP() { - renderPassEvent = RenderPassEvent.AfterRenderingTransparents; ConfigureInput(ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth); } @@ -38,18 +35,14 @@ namespace WaveHarmonic.Crest s_Instance = new(); s_Instance._Renderer = renderer; s_Instance._CopyDepthBufferPass = new(RenderPassEvent.AfterRenderingOpaques); - s_Instance._ApplyFogToTransparentObjects = new(); } - RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; - RenderPipelineManager.beginCameraRendering += s_Instance.EnqueuePass; RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; RenderPipelineManager.activeRenderPipelineTypeChanged += Disable; } public static void Disable() { - if (s_Instance != null) RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; s_Instance?._UnderwaterEffectPass?.Release(); @@ -57,13 +50,15 @@ namespace WaveHarmonic.Crest s_Instance = null; } - void EnqueuePass(ScriptableRenderContext context, Camera camera) + internal void EnqueuePass(ScriptableRenderContext context, Camera camera) { if (!_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Effect)) { return; } + s_Instance.renderPassEvent = _Renderer.RenderBeforeTransparency ? WaterRenderer.k_WaterRenderPassEvent : RenderPassEvent.AfterRenderingTransparents; + var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer; #if UNITY_EDITOR @@ -80,25 +75,40 @@ namespace WaveHarmonic.Crest _UnderwaterEffectPass ??= new(_Renderer); renderer.EnqueuePass(s_Instance); - - if (_Renderer.EnableShaderAPI) - { - renderer.EnqueuePass(_ApplyFogToTransparentObjects); - } } #if UNITY_6000_0_OR_NEWER - void OnSetup(CommandBuffer buffer, PassData data) + bool _ErrorMissingColorTarget; + + void OnSetup(CommandBuffer buffer, RenderGraphHelper.PassData data) { _ColorBuffer = data.colorTargetHandle.Texture; _DepthBuffer = data.depthTargetHandle.Texture; + // Unity bug + if (_ColorBuffer?.rt == null) + { + if (!_ErrorMissingColorTarget) + { + Debug.LogError($"Crest: Your current URP setup has a Unity bug which prevents underwater from rendering on this camera ({data.cameraData.camera.name}). It is too complicated for us to advise which combination of settings are the issue (sorry), but they will be on either the URP asset or renderer file."); + _ErrorMissingColorTarget = true; + } + + return; + } + // TODO: renderingData.cameraData.cameraTargetDescriptor? _UnderwaterEffectPass.ReAllocate(_ColorBuffer.rt.descriptor); } - void Execute(ScriptableRenderContext context, CommandBuffer buffer, PassData data) + void Execute(ScriptableRenderContext context, CommandBuffer buffer, RenderGraphHelper.PassData data) { + // Unity bug + if (_ColorBuffer?.rt == null) + { + return; + } + if (_Renderer.UseStencilBuffer) { _DepthBuffer = _CopyDepthBufferPass._DepthBufferCopy; @@ -131,120 +141,13 @@ namespace WaveHarmonic.Crest CommandBufferPool.Release(buffer); } #endif - - // Renders transparent objects after the underwater effect. Using the correct - // shader, the above water portion of the object is rendered normally (in the - // transparent pass), and the below water portion is rendered here with underwater - // applied. - sealed partial class RenderObjectsWithoutFogPass : ScriptableRenderPass - { - FilteringSettings _FilteringSettings; - - static readonly List s_ShaderTagIdList = new() - { - new("SRPDefaultUnlit"), - new("UniversalForward"), - new("UniversalForwardOnly"), - new("LightweightForward"), - }; - - public RenderObjectsWithoutFogPass() - { - renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; - _FilteringSettings = new(RenderQueueRange.transparent, 0); - } - -#if UNITY_6000_0_OR_NEWER - void Execute(ScriptableRenderContext context, CommandBuffer buffer, PassData renderingData) -#else - public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) -#endif - { - _FilteringSettings.layerMask = s_Instance._Renderer._TransparentObjectLayers; - -#if !UNITY_6000_0_OR_NEWER - var buffer = CommandBufferPool.Get("Crest Underwater Objects"); -#endif - - // Disable Unity's fog keywords as there is no option to ignore fog for the Shader Graph. - if (RenderSettings.fog) - { - switch (RenderSettings.fogMode) - { - case FogMode.Exponential: - buffer.DisableShaderKeyword("FOG_EXP"); - break; - case FogMode.Linear: - buffer.DisableShaderKeyword("FOG_LINEAR"); - break; - case FogMode.ExponentialSquared: - buffer.DisableShaderKeyword("FOG_EXP2"); - break; - } - } - - buffer.EnableShaderKeyword(UnderwaterRenderer.k_KeywordUnderwaterObjects); - // If we want anything to apply to DrawRenderers, it has to be executed before: - // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.DrawRenderers.html - context.ExecuteCommandBuffer(buffer); - buffer.Clear(); - -#if UNITY_6000_0_OR_NEWER - var drawingSettings = RenderingUtils.CreateDrawingSettings - ( - s_ShaderTagIdList, - renderingData.renderingData, - renderingData.cameraData, - renderingData.lightData, - SortingCriteria.CommonTransparent - ); - - var parameters = new RendererListParams(renderingData.cullResults, drawingSettings, _FilteringSettings); - var list = context.CreateRendererList(ref parameters); - - buffer.DrawRendererList(list); -#else - var drawingSettings = CreateDrawingSettings - ( - s_ShaderTagIdList, - ref renderingData, - SortingCriteria.CommonTransparent - ); - - context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _FilteringSettings); -#endif - - // Revert fog keywords. - if (RenderSettings.fog) - { - switch (RenderSettings.fogMode) - { - case FogMode.Exponential: - buffer.EnableShaderKeyword("FOG_EXP"); - break; - case FogMode.Linear: - buffer.EnableShaderKeyword("FOG_LINEAR"); - break; - case FogMode.ExponentialSquared: - buffer.EnableShaderKeyword("FOG_EXP2"); - break; - } - } - - buffer.DisableShaderKeyword(UnderwaterRenderer.k_KeywordUnderwaterObjects); - -#if !UNITY_6000_0_OR_NEWER - context.ExecuteCommandBuffer(buffer); - CommandBufferPool.Release(buffer); -#endif - } - } } // Copies the depth buffer to avoid conflicts when using the stencil buffer. sealed partial class CopyDepthBufferPassURP : ScriptableRenderPass { const string k_Name = "Crest Copy Depth Buffer"; + RTHandle _ColorBuffer; RTHandle _DepthBuffer; public RTHandle _DepthBufferCopy; @@ -264,9 +167,11 @@ namespace WaveHarmonic.Crest descriptor.bindMS = descriptor.msaaSamples > 1; #if UNITY_6000_0_OR_NEWER RenderingUtils.ReAllocateHandleIfNeeded(ref _DepthBufferCopy, descriptor, FilterMode.Point, name: "Crest Copied Depth Buffer"); + _ColorBuffer = data.colorTargetHandle; _DepthBuffer = data.depthTargetHandle; #else RenderingUtils.ReAllocateIfNeeded(ref _DepthBufferCopy, descriptor, FilterMode.Point, name: "Crest Copied Depth Buffer"); + _ColorBuffer = data.cameraData.renderer.cameraColorTargetHandle; _DepthBuffer = data.cameraData.renderer.cameraDepthTargetHandle; #endif } @@ -277,19 +182,26 @@ namespace WaveHarmonic.Crest public override void Execute(ScriptableRenderContext context, ref RenderingData data) #endif { + // Just in case. + if (_ColorBuffer == null || _DepthBuffer == null) + { + return; + } + #if !UNITY_6000_0_OR_NEWER var buffer = CommandBufferPool.Get(k_Name); #endif - // Must clear even though we are overwriting or there will be strange artifacts on new writes. - // This could be a Unity bug and may be worth reporting. - buffer.SetRenderTarget(BuiltinRenderTextureType.None, _DepthBufferCopy); - buffer.ClearRenderTarget(RTClearFlags.Depth, Color.black, 1, 0); - + // NOTE: previously we cleared the target depth first due to artifacts. buffer.CopyTexture(_DepthBuffer.rt, _DepthBufferCopy.rt); // Clear the stencil component just in case. - buffer.ClearRenderTarget(RTClearFlags.Stencil, Color.black, 1, 0); + // Previously we passed BuiltinRenderTextureType.None for color but this made the + // scene disappear in the scene view on DX11 only. + CoreUtils.SetRenderTarget(buffer, _ColorBuffer, _DepthBufferCopy, ClearFlag.Stencil); + + // Required for Unity 6+. + CoreUtils.SetRenderTarget(buffer, _ColorBuffer, _DepthBuffer); #if !UNITY_6000_0_OR_NEWER context.ExecuteCommandBuffer(buffer); diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPass.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPass.cs index 8b5f5c166..aa7e00f56 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPass.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPass.cs @@ -1,140 +1,2 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.Experimental.Rendering; - -namespace WaveHarmonic.Crest -{ - sealed class UnderwaterMaskPass - { - readonly UnderwaterRenderer _Renderer; -#if d_CrestPortals - readonly Portals.PortalRenderer _Portals; -#endif - - RTHandle _MaskTexture; - RTHandle _DepthTexture; - RenderTargetIdentifier _MaskTarget; - RenderTargetIdentifier _DepthTarget; - - public UnderwaterMaskPass(UnderwaterRenderer renderer) - { - _Renderer = renderer; -#if d_CrestPortals - _Portals = renderer._Portals; -#endif - } - - public void Allocate() - { - _MaskTexture = RTHandles.Alloc - ( - scaleFactor: Vector2.one, - slices: TextureXR.slices, - dimension: TextureXR.dimension, - depthBufferBits: DepthBits.None, - colorFormat: GraphicsFormat.R16_SFloat, - enableRandomWrite: true, - useDynamicScale: true, - name: "_Crest_WaterMask" - ); - - _MaskTarget = new(_MaskTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); - - _DepthTexture = RTHandles.Alloc - ( - scaleFactor: Vector2.one, - slices: TextureXR.slices, - dimension: TextureXR.dimension, - depthBufferBits: UnderwaterRenderer.k_DepthBits, - colorFormat: GraphicsFormat.None, - enableRandomWrite: false, - useDynamicScale: true, - name: "_Crest_WaterMaskDepth" - ); - -#if d_CrestPortals - // For HDRP we cannot allocate in OnEnable as RTHandle will complain. - if (_Portals.Active) - { - _Portals.Allocate(); - } -#endif - - _DepthTarget = new(_DepthTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); - - _Renderer.SetUpArtifactsShader(); - } - - // We should not have to reallocate, but URP will raise errors when an option like HDR is changed if we do not. - public void ReAllocate(RenderTextureDescriptor descriptor) - { - // Shared settings. Enabling MSAA might be a good idea except cannot enable random writes. Having a raster - // shader to remove artifacts is a workaround. - descriptor.bindMS = false; - descriptor.msaaSamples = 1; - - descriptor.graphicsFormat = GraphicsFormat.None; - - if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _DepthTexture, descriptor, name: "_Crest_WaterMaskDepth")) - { - _DepthTarget = new(_DepthTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); - } - -#if d_CrestPortals - if (_Portals.Active) - { - _Portals.ReAllocate(descriptor); - } -#endif - - descriptor.graphicsFormat = GraphicsFormat.R16_SFloat; - descriptor.enableRandomWrite = true; - descriptor.depthBufferBits = 0; - - if (RenderPipelineCompatibilityHelper.ReAllocateIfNeeded(ref _MaskTexture, descriptor, name: "_Crest_WaterMask")) - { - _MaskTarget = new(_MaskTexture, mipLevel: 0, CubemapFace.Unknown, depthSlice: -1); - } - } - - public void Release() - { - _MaskTexture?.Release(); - _DepthTexture?.Release(); - -#if d_CrestPortals - if (_Portals.Active) - { - _Portals.Release(); - } -#endif - } - - public void Execute(Camera camera, CommandBuffer buffer) - { -#if d_CrestPortals - // Populate water volume before mask so we can use the stencil. - if (_Portals.Active) - { - _Portals.RenderMask(camera, buffer, _Renderer._MaskMaterial); - _Portals.RenderStencil(buffer, _DepthTexture); - } -#endif - - // For HDRP software dynamic scaling to work. - CoreUtils.SetRenderTarget(buffer, _MaskTexture, _DepthTexture); - Helpers.ScaleViewport(camera, buffer, _MaskTexture); - - _Renderer.SetUpMask(buffer, _MaskTarget, _DepthTarget); - _Renderer.PopulateMask(buffer, camera); - - var size = _MaskTexture.GetScaledSize(_MaskTexture.rtHandleProperties.currentViewportSize); - var descriptor = _MaskTexture.rt.descriptor; - descriptor.width = size.x; descriptor.height = size.y; - _Renderer.FixMaskArtefacts(buffer, descriptor, _MaskTarget); - } - } -} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassHDRP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassHDRP.cs index fbe2b0235..aa7e00f56 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassHDRP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassHDRP.cs @@ -1,78 +1,2 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. - -#if d_UnityHDRP - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.Rendering.HighDefinition; - -namespace WaveHarmonic.Crest -{ - sealed class UnderwaterMaskPassHDRP : CustomPass - { - const string k_Name = "Underwater Mask"; - - static UnderwaterRenderer s_Renderer; - static UnderwaterMaskPass s_UnderwaterMaskPass; - static UnderwaterMaskPassHDRP s_Instance; - GameObject _GameObject; - - public static void Enable(UnderwaterRenderer renderer) - { - var gameObject = CustomPassHelpers.CreateOrUpdate - ( - parent: renderer._Water.Container.transform, - k_Name, - hide: !renderer._Water._Debug._ShowHiddenObjects - ); - - CustomPassHelpers.CreateOrUpdate - ( - gameObject, - ref s_Instance, - k_Name, - CustomPassInjectionPoint.BeforeRendering - ); - - s_Instance._GameObject = gameObject; - - s_Renderer = renderer; - s_UnderwaterMaskPass = new(renderer); - } - - public static void Disable() - { - // It should be safe to rely on this reference for this reference to fail. - if (s_Instance != null && s_Instance._GameObject != null) - { - // Will also trigger Cleanup below. - s_Instance._GameObject.SetActive(false); - } - } - - protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) - { - s_UnderwaterMaskPass.Allocate(); - } - - protected override void Cleanup() - { - s_UnderwaterMaskPass?.Release(); - } - - protected override void Execute(CustomPassContext context) - { - var camera = context.hdCamera.camera; - - if (!s_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Mask)) - { - return; - } - - s_UnderwaterMaskPass.Execute(camera, context.cmd); - } - } -} - -#endif // d_UnityHDRP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassURP.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassURP.cs index 36e5bc50f..aa7e00f56 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassURP.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterMaskPassURP.cs @@ -1,106 +1,2 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. - -#if d_UnityURP - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.Rendering.Universal; - -namespace WaveHarmonic.Crest -{ - sealed partial class UnderwaterMaskPassURP : ScriptableRenderPass - { - const string k_Name = "Crest Underwater Mask"; - static UnderwaterMaskPassURP s_Instance; - UnderwaterRenderer _Renderer; - UnderwaterMaskPass _UnderwaterMaskPass; - - public UnderwaterMaskPassURP() - { - // Will always execute and matrices will be ready. - renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses; - } - - public static void Enable(UnderwaterRenderer renderer) - { - s_Instance ??= new(); - s_Instance._Renderer = renderer; - - RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; - RenderPipelineManager.beginCameraRendering += s_Instance.EnqueuePass; - RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; - RenderPipelineManager.activeRenderPipelineTypeChanged += Disable; - } - - public static void Disable() - { - if (s_Instance != null) RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; - RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; - - s_Instance?._UnderwaterMaskPass?.Release(); - s_Instance = null; - } - - void EnqueuePass(ScriptableRenderContext context, Camera camera) - { - if (!_Renderer.ShouldRender(camera, UnderwaterRenderer.Pass.Mask)) - { - return; - } - - var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer; - -#if UNITY_EDITOR - if (renderer == null) return; -#endif - - if (_UnderwaterMaskPass == null) - { - _UnderwaterMaskPass = new(_Renderer); - _UnderwaterMaskPass.Allocate(); - } - - // Enqueue the pass. This happens every frame. - renderer.EnqueuePass(this); - } - -#if UNITY_6000_0_OR_NEWER - class PassData - { - public UniversalCameraData _CameraData; - public UnderwaterMaskPass _UnderwaterMaskPass; - } - - public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) - { - using (var builder = graph.AddUnsafePass(k_Name, out var data)) - { - builder.AllowPassCulling(false); - - data._CameraData = frame.Get(); - data._UnderwaterMaskPass = _UnderwaterMaskPass; - - builder.SetRenderFunc((data, context) => - { - var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); - data._UnderwaterMaskPass.ReAllocate(data._CameraData.cameraTargetDescriptor); - data._UnderwaterMaskPass.Execute(data._CameraData.camera, buffer); - }); - } - } - - [System.Obsolete] -#endif - public override void Execute(ScriptableRenderContext context, ref RenderingData data) - { - var buffer = CommandBufferPool.Get(k_Name); - _UnderwaterMaskPass.ReAllocate(data.cameraData.cameraTargetDescriptor); - _UnderwaterMaskPass.Execute(data.cameraData.camera, buffer); - context.ExecuteCommandBuffer(buffer); - CommandBufferPool.Release(buffer); - } - } -} - -#endif // d_UnityURP diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Editor.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Editor.cs index 1e481dd74..441f99118 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Editor.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Editor.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if UNITY_EDITOR diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Effect.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Effect.cs index d6bb51123..eb704d8fd 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Effect.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Effect.cs @@ -9,16 +9,16 @@ namespace WaveHarmonic.Crest { partial class UnderwaterRenderer { - const string k_KeywordFullScreenEffect = "_FULL_SCREEN_EFFECT"; + internal const string k_ShaderNameEffect = "Crest/Underwater"; + internal const string k_DrawVolume = "Crest.DrawWater/Volume"; const string k_KeywordDebugVisualizeMask = "_DEBUG_VISUALIZE_MASK"; const string k_KeywordDebugVisualizeStencil = "_DEBUG_VISUALIZE_STENCIL"; - internal const string k_KeywordUnderwaterObjects = "CREST_UNDERWATER_OBJECTS_PASS"; + internal const string k_SampleSphericalHarmonicsMarker = "Crest.UnderwaterRenderer.SampleSphericalHarmonics"; + + static readonly Unity.Profiling.ProfilerMarker s_SampleSphericalHarmonicsMarker = new(k_SampleSphericalHarmonicsMarker); static partial class ShaderIDs { - // Local - public static readonly int s_HorizonNormal = Shader.PropertyToID("_Crest_HorizonNormal"); - // Global public static readonly int s_CameraColorTexture = Shader.PropertyToID("_Crest_CameraColorTexture"); public static readonly int s_WaterVolumeStencil = Shader.PropertyToID("_Crest_WaterVolumeStencil"); @@ -26,9 +26,10 @@ namespace WaveHarmonic.Crest public static readonly int s_ExtinctionMultiplier = Shader.PropertyToID("_Crest_ExtinctionMultiplier"); public static readonly int s_UnderwaterEnvironmentalLightingWeight = Shader.PropertyToID("_Crest_UnderwaterEnvironmentalLightingWeight"); - // Built-ins - public static readonly int s_WorldSpaceLightPos0 = Shader.PropertyToID("_WorldSpaceLightPos0"); - public static readonly int s_LightColor0 = Shader.PropertyToID("_LightColor0"); + public static readonly int s_OutScatteringFactor = Shader.PropertyToID("_Crest_OutScatteringFactor"); + public static readonly int s_OutScatteringExtinctionFactor = Shader.PropertyToID("_Crest_OutScatteringExtinctionFactor"); + public static readonly int s_SunBoost = Shader.PropertyToID("_Crest_SunBoost"); + public static readonly int s_DataSliceOffset = Shader.PropertyToID("_Crest_DataSliceOffset"); } @@ -43,6 +44,7 @@ namespace WaveHarmonic.Crest Material _CurrentWaterMaterial; readonly UnderwaterSphericalHarmonicsData _SphericalHarmonicsData = new(); System.Action _CopyColor; + System.Action _SetRenderTargetToBackBuffers; RenderTargetIdentifier _ColorTarget = new ( @@ -66,12 +68,20 @@ namespace WaveHarmonic.Crest -1 ); + // Requested the temporary color texture. + internal bool _NeedsColorTexture; + sealed class UnderwaterSphericalHarmonicsData { internal Color[] _AmbientLighting = new Color[1]; internal Vector3[] _DirectionsSH = { new(0.0f, 0.0f, 0.0f) }; } + void SetRenderTargetToBackBuffers(CommandBuffer commands) + { + commands.SetRenderTarget(_ColorTarget); + } + void CopyColorTexture(CommandBuffer buffer) { // Use blit instead of CopyTexture as it will smooth out issues with format @@ -92,38 +102,28 @@ namespace WaveHarmonic.Crest { _EffectCommandBuffer ??= new() { - name = "Underwater Pass", + name = k_DrawVolume, }; _CopyColor ??= new(CopyColorTexture); + _SetRenderTargetToBackBuffers ??= new(SetRenderTargetToBackBuffers); } void OnPreRenderUnderwaterEffect(Camera camera) { -#if UNITY_EDITOR - // Do not use this to prevent the mask from rendering due to portals and volumes feature. - if (!IsFogEnabledForEditorCamera(camera)) - { - _EffectCommandBuffer?.Clear(); - return; - } -#endif - - var descriptor = XRHelpers.GetRenderTextureDescriptor(camera); + var descriptor = Rendering.BIRP.GetCameraTargetDescriptor(camera, _Water.FrameBufferFormatOverride); descriptor.useDynamicScale = camera.allowDynamicResolution; - // Format must be correct for CopyTexture to work. Hopefully this is good enough. - if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear) - { - descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(_Water.LikelyFrameBufferFormat); - } - - UpdateEffectMaterial(camera, _FirstRender); + UpdateEffectMaterial(camera); _EffectCommandBuffer.Clear(); - // No need to clear as Blit will overwrite everything. - _EffectCommandBuffer.GetTemporaryRT(ShaderIDs.s_CameraColorTexture, descriptor); + if (!RenderBeforeTransparency || _NeedsColorTexture) + { + // No need to clear as Blit will overwrite everything. + _EffectCommandBuffer.GetTemporaryRT(ShaderIDs.s_CameraColorTexture, descriptor); + _EffectCommandBuffer.SetGlobalTexture(ShaderIDs.s_CameraColorTexture, _ColorCopyTarget); + } var sun = RenderSettings.sun; if (sun != null) @@ -131,15 +131,16 @@ namespace WaveHarmonic.Crest // Unity does not set up lighting for us so we will get the last value which could incorrect. // SetGlobalColor is just an alias for SetGlobalVector (no color space conversion like Material.SetColor): // https://docs.unity3d.com/2017.4/Documentation/ScriptReference/Shader.SetGlobalColor.html - _EffectCommandBuffer.SetGlobalVector(ShaderIDs.s_LightColor0, sun.FinalColor()); - _EffectCommandBuffer.SetGlobalVector(ShaderIDs.s_WorldSpaceLightPos0, -sun.transform.forward); + _EffectCommandBuffer.SetGlobalVector(Crest.ShaderIDs.Unity.s_LightColor0, sun.FinalColor()); + _EffectCommandBuffer.SetGlobalVector(Crest.ShaderIDs.Unity.s_WorldSpaceLightPos0, -sun.transform.forward); + _EffectCommandBuffer.SetShaderKeyword("DIRECTIONAL_COOKIE", sun.cookie != null); } // Create a separate stencil buffer context by copying the depth texture. if (UseStencilBuffer) { descriptor.colorFormat = RenderTextureFormat.Depth; - descriptor.depthBufferBits = (int)k_DepthBits; + descriptor.depthBufferBits = (int)Helpers.k_DepthBits; // bindMS is necessary in this case for depth. descriptor.SetMSAASamples(camera); descriptor.bindMS = descriptor.msaaSamples > 1; @@ -152,150 +153,128 @@ namespace WaveHarmonic.Crest if (Helpers.IsMSAAEnabled(camera)) { // Blit with a depth write shader to populate the depth buffer. - Helpers.Blit(_EffectCommandBuffer, _DepthStencilTarget, Helpers.UtilityMaterial, (int)Helpers.UtilityPass.CopyDepth); + Helpers.Blit(_EffectCommandBuffer, _DepthStencilTarget, Rendering.BIRP.UtilityMaterial, (int)Rendering.BIRP.UtilityPass.CopyDepth); } else { - // Copy depth then clear stencil. + // Copy depth texture. Since this is not depth buffer, no need to clear stencil. + // SRPs copy the depth buffer, because they can. _EffectCommandBuffer.CopyTexture(BuiltinRenderTextureType.Depth, _DepthStencilTarget); - Helpers.Blit(_EffectCommandBuffer, _DepthStencilTarget, Helpers.UtilityMaterial, (int)Helpers.UtilityPass.ClearStencil); + CoreUtils.SetRenderTarget(_EffectCommandBuffer, _DepthStencilTarget); + } + + if (RenderBeforeTransparency) + { + _EffectCommandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget, _DepthStencilTarget); } } - CopyColorTexture(_EffectCommandBuffer); + if (!RenderBeforeTransparency) + { + CopyColorTexture(_EffectCommandBuffer); + } - _EffectCommandBuffer.SetGlobalTexture(ShaderIDs.s_CameraColorTexture, _ColorCopyTarget); + ExecuteEffect(camera, _EffectCommandBuffer, _CopyColor, _SetRenderTargetToBackBuffers); - ExecuteEffect(camera, _EffectCommandBuffer, _CopyColor); + if (!RenderBeforeTransparency || _NeedsColorTexture) + { + _EffectCommandBuffer.ReleaseTemporaryRT(ShaderIDs.s_CameraColorTexture); + } - _EffectCommandBuffer.ReleaseTemporaryRT(ShaderIDs.s_CameraColorTexture); if (UseStencilBuffer) { _EffectCommandBuffer.ReleaseTemporaryRT(ShaderIDs.s_WaterVolumeStencil); } } - internal void ExecuteEffect(Camera camera, CommandBuffer buffer, System.Action copyColor, MaterialPropertyBlock properties = null) + internal void ExecuteEffect(Camera camera, CommandBuffer buffer, System.Action copyColor, System.Action resetRenderTargets, MaterialPropertyBlock properties = null) { - if (camera.cameraType == CameraType.Reflection) - { - buffer.DrawProcedural - ( - Matrix4x4.identity, - _VolumeMaterial, - shaderPass: (int)EffectPass.Reflections, - MeshTopology.Triangles, - vertexCount: 3, - instanceCount: 1, - properties - ); - } + var isFullScreenRequired = true; + #if d_CrestPortals - else if (_Portals.Active && _Portals.Mode != Portals.PortalMode.Tunnel) + if (_Portals.Active) { - _Portals.RenderEffect(camera, buffer, _VolumeMaterial, copyColor, properties); + isFullScreenRequired = _Portals.RenderEffect(camera, buffer, _VolumeMaterial, copyColor, resetRenderTargets, properties); } #endif - else + + if (!isFullScreenRequired) { - buffer.DrawProcedural - ( - Matrix4x4.identity, - _VolumeMaterial, - shaderPass: (int)EffectPass.FullScreen, - MeshTopology.Triangles, - vertexCount: 3, - instanceCount: 1, - properties - ); + return; } + + buffer.DrawProcedural + ( + Matrix4x4.identity, + _VolumeMaterial, + shaderPass: (int)(camera.cameraType == CameraType.Reflection ? EffectPass.Reflections : EffectPass.FullScreen), + MeshTopology.Triangles, + vertexCount: 3, + instanceCount: 1, + properties + ); } - internal static void UpdateGlobals(Material waterMaterial) + internal static void UpdateGlobals(Material source) { // We will have the wrong color values if we do not use linear: // https://forum.unity.com/threads/fragment-shader-output-colour-has-incorrect-values-when-hardcoded.377657/ // _CrestAbsorption is already set as global in Water Renderer. - Shader.SetGlobalColor(WaterRenderer.ShaderIDs.s_Scattering, waterMaterial.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear()); - Shader.SetGlobalFloat(WaterRenderer.ShaderIDs.s_Anisotropy, waterMaterial.GetFloat(WaterRenderer.ShaderIDs.s_Anisotropy)); + Shader.SetGlobalColor(WaterRenderer.ShaderIDs.s_Scattering, source.GetColor(WaterRenderer.ShaderIDs.s_Scattering).MaybeLinear()); + Shader.SetGlobalFloat(WaterRenderer.ShaderIDs.s_Anisotropy, source.GetFloat(WaterRenderer.ShaderIDs.s_Anisotropy)); + Shader.SetGlobalFloat(WaterRenderer.ShaderIDs.s_AmbientTerm, source.GetFloat(WaterRenderer.ShaderIDs.s_AmbientTerm)); + Shader.SetGlobalFloat(WaterRenderer.ShaderIDs.s_DirectTerm, source.GetFloat(WaterRenderer.ShaderIDs.s_DirectTerm)); + Shader.SetGlobalFloat(WaterRenderer.ShaderIDs.s_ShadowsAffectsAmbientFactor, source.GetFloat(WaterRenderer.ShaderIDs.s_ShadowsAffectsAmbientFactor)); + + Shader.SetGlobalFloat(ShaderIDs.s_ExtinctionMultiplier, source.GetFloat(ShaderIDs.s_ExtinctionMultiplier)); + Shader.SetGlobalFloat(ShaderIDs.s_OutScatteringFactor, source.GetFloat(ShaderIDs.s_OutScatteringFactor)); + Shader.SetGlobalFloat(ShaderIDs.s_OutScatteringExtinctionFactor, source.GetFloat(ShaderIDs.s_OutScatteringExtinctionFactor)); + Shader.SetGlobalFloat(ShaderIDs.s_SunBoost, source.GetFloat(ShaderIDs.s_SunBoost)); + Shader.SetGlobalInteger(ShaderIDs.s_DataSliceOffset, source.GetInteger(ShaderIDs.s_DataSliceOffset)); } - internal void UpdateEffectMaterial(Camera camera, bool isFirstRender) + internal void UpdateEffectMaterial(Camera camera) { // Copy water material parameters to underwater material. + // WBs can change the material per camera, so disable optimization. + if (_MaterialLastUpdatedFrame < Time.frameCount || WaterBody.WaterBodies.Count > 0) { - var material = _SurfaceMaterial; - - if (_CopyWaterMaterialParametersEachFrame || isFirstRender || material != _CurrentWaterMaterial) + if (_CopyWaterMaterialParametersEachFrame || _SurfaceMaterial != _CurrentWaterMaterial) { - _CurrentWaterMaterial = material; + _CurrentWaterMaterial = _SurfaceMaterial; - if (material != null) + if (_SurfaceMaterial != null) { - _VolumeMaterial.CopyMatchingPropertiesFromMaterial(material); + _VolumeMaterial.CopyMatchingPropertiesFromMaterial(_SurfaceMaterial); - if (_EnableShaderAPI) + AfterCopyMaterial?.Invoke(_Water, _VolumeMaterial); + + // Make volume properties available to surface and meniscus. + if (RenderBeforeTransparency) { - UpdateGlobals(material); + UpdateGlobals(_VolumeMaterial); } } } + + // Enabling/disabling keywords each frame don't seem to have large measurable overhead + _VolumeMaterial.SetKeyword(k_KeywordDebugVisualizeMask, _Debug._VisualizeMask); + _VolumeMaterial.SetKeyword(k_KeywordDebugVisualizeStencil, _Debug._VisualizeStencil); + + // We use this for caustics to get the displacement. + _VolumeMaterial.SetInteger(Lod.ShaderIDs.s_LodIndex, 0); + + _MaterialLastUpdatedFrame = Time.frameCount; } - // Enabling/disabling keywords each frame don't seem to have large measurable overhead - _VolumeMaterial.SetKeyword(k_KeywordDebugVisualizeMask, _Debug._VisualizeMask); - _VolumeMaterial.SetKeyword(k_KeywordDebugVisualizeStencil, _Debug._VisualizeStencil); - - // We use this for caustics to get the displacement. - _VolumeMaterial.SetInteger(Lod.ShaderIDs.s_LodIndex, 0); - - if (!Portaled && camera.cameraType != CameraType.Reflection) + // Not applicable to reflection pass. + if (camera.cameraType != CameraType.Reflection) { - var seaLevel = _Water.SeaLevel; - - // We don't both setting the horizon value if we know we are going to be having to apply the effect - // full-screen anyway. - var forceFullShader = _Water.ViewerHeightAboveWater < -2f; - if (!forceFullShader) - { - var maxWaterVerticalDisplacement = _Water.MaximumVerticalDisplacement * 0.5f; - var cameraYPosition = camera.transform.position.y; - float nearPlaneFrustumWorldHeight; - { - var current = camera.ViewportToWorldPoint(new(0f, 0f, camera.nearClipPlane)).y; - float maxY = current, minY = current; - - current = camera.ViewportToWorldPoint(new(0f, 1f, camera.nearClipPlane)).y; - maxY = Mathf.Max(maxY, current); - minY = Mathf.Min(minY, current); - - current = camera.ViewportToWorldPoint(new(1f, 0f, camera.nearClipPlane)).y; - maxY = Mathf.Max(maxY, current); - minY = Mathf.Min(minY, current); - - current = camera.ViewportToWorldPoint(new(1f, 1f, camera.nearClipPlane)).y; - maxY = Mathf.Max(maxY, current); - minY = Mathf.Min(minY, current); - - nearPlaneFrustumWorldHeight = maxY - minY; - } - - forceFullShader = (cameraYPosition + nearPlaneFrustumWorldHeight + maxWaterVerticalDisplacement) <= seaLevel; - } - - _VolumeMaterial.SetKeyword(k_KeywordFullScreenEffect, forceFullShader); - } - - // Project water normal onto camera plane. - { - var projectedNormal = new Vector2 - ( - Vector3.Dot(Vector3.up, camera.transform.right), - Vector3.Dot(Vector3.up, camera.transform.up) - ); - - _VolumeMaterial.SetVector(ShaderIDs.s_HorizonNormal, projectedNormal); + // Skip work if camera is far enough below the surface. + var forceFullShader = !_Water.Surface.Enabled || (_Water._ViewerHeightAboveWaterPerCamera < -8f && !Portaled); + _VolumeMaterial.SetKeyword("d_Crest_NoMaskColor", forceFullShader); + _VolumeMaterial.SetKeyword("d_Crest_NoMaskDepth", !_Water.Surface.Enabled || RenderBeforeTransparency); } // Compute ambient lighting SH. @@ -304,11 +283,11 @@ namespace WaveHarmonic.Crest // at different position, as this would then thrash it and negate the priming functionality. We could create a dummy invis GO // with a dummy Renderer which might be enough, but this is hacky enough that we'll wait for it to become a problem // rather than add a pre-emptive hack. - UnityEngine.Profiling.Profiler.BeginSample("Crest: Underwater Sample Spherical Harmonics"); + s_SampleSphericalHarmonicsMarker.Begin(_Water); LightProbes.GetInterpolatedProbe(camera.transform.position, null, out var sphericalHarmonicsL2); sphericalHarmonicsL2.Evaluate(_SphericalHarmonicsData._DirectionsSH, _SphericalHarmonicsData._AmbientLighting); - Helpers.SetShaderVector(_VolumeMaterial, ShaderIDs.s_AmbientLighting, _SphericalHarmonicsData._AmbientLighting[0], _EnableShaderAPI); - UnityEngine.Profiling.Profiler.EndSample(); + Helpers.SetShaderVector(_VolumeMaterial, ShaderIDs.s_AmbientLighting, _SphericalHarmonicsData._AmbientLighting[0], RenderBeforeTransparency); + s_SampleSphericalHarmonicsMarker.End(); } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.EnvironmentalLighting.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.EnvironmentalLighting.cs index 69ae078e7..7795641eb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.EnvironmentalLighting.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.EnvironmentalLighting.cs @@ -58,6 +58,14 @@ namespace WaveHarmonic.Crest return; } +#if UNITY_EDITOR + // Only repaint, otherwise changes might persist. + if (Event.current.type != EventType.Repaint) + { + return; + } +#endif + // Restore lighting settings. if (_EnvironmentalLight != null) _EnvironmentalLight.intensity = _EnvironmentalLightIntensity; _EnvironmentalLight = null; @@ -77,7 +85,15 @@ namespace WaveHarmonic.Crest return; } - if (!_Water.Material.HasColor(WaterRenderer.ShaderIDs.s_AbsorptionColor)) +#if UNITY_EDITOR + // Only repaint, otherwise changes might persist. + if (Event.current.type != EventType.Repaint) + { + return; + } +#endif + + if (!_Water.Surface.Material.HasColor(WaterRenderer.ShaderIDs.s_AbsorptionColor)) { return; } @@ -94,7 +110,13 @@ namespace WaveHarmonic.Crest var density = extinction; _EnvironmentalAverageDensity = (density.x + density.y + density.z) / 3f; - var multiplier = Mathf.Exp(_EnvironmentalAverageDensity * Mathf.Min(height * k_DepthOutScattering, 0f) * _EnvironmentalLightingWeight); + var outScatteringFactor = 1f; + if (_VolumeMaterial.HasFloat(ShaderIDs.s_OutScatteringFactor)) + { + outScatteringFactor = _VolumeMaterial.GetFloat(ShaderIDs.s_OutScatteringFactor); + } + + var multiplier = Mathf.Exp(_EnvironmentalAverageDensity * Mathf.Min(height * k_DepthOutScattering * outScatteringFactor, 0f) * _EnvironmentalLightingWeight); // Darken environmental lighting when viewer underwater. if (_EnvironmentalLight != null) diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Legacy.cs index ddcd252b2..ab2ac04e4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Legacy.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Legacy.cs @@ -8,94 +8,49 @@ namespace WaveHarmonic.Crest { partial class UnderwaterRenderer { - bool _HasMaskCommandBuffersBeenRegistered; bool _HasEffectCommandBuffersBeenRegistered; void OnEnableLegacy() { - SetupMask(); - OnEnableMask(); SetupUnderwaterEffect(); - // Handle this internally rather than relying on Water Renderer. - Camera.onPreRender -= OnBeforeLegacyRender; - Camera.onPreRender += OnBeforeLegacyRender; - Camera.onPostRender -= OnAfterLegacyRender; - Camera.onPostRender += OnAfterLegacyRender; RenderPipelineManager.activeRenderPipelineTypeChanged -= OnDisableLegacy; RenderPipelineManager.activeRenderPipelineTypeChanged += OnDisableLegacy; } void OnDisableLegacy() { - Camera.onPreRender -= OnBeforeLegacyRender; - Camera.onPostRender -= OnAfterLegacyRender; RenderPipelineManager.activeRenderPipelineTypeChanged -= OnDisableLegacy; - - OnDisableMask(); - } - - internal void LateUpdate() - { - if (!Active) - { - return; - } - - if (!RenderPipelineHelper.IsLegacy) - { - return; - } - - Helpers.SetGlobalKeyword("CREST_UNDERWATER_BEFORE_TRANSPARENT", _EnableShaderAPI); } + // Listening to OnPreCull. Camera must have underwater layer. void OnBeforeLegacyRender(Camera camera) { - XRHelpers.Update(camera); - XRHelpers.SetInverseViewProjectionMatrix(camera); - - if (ShouldRender(camera, Pass.Mask)) - { - // It could be either one event. - camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, _MaskCommandBuffer); - camera.AddCommandBuffer(CameraEvent.BeforeDepthTexture, _MaskCommandBuffer); - OnPreRenderMask(camera); - _HasMaskCommandBuffersBeenRegistered = true; - } - if (ShouldRender(camera, Pass.Effect)) { - var @event = _EnableShaderAPI ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha; + _Water.UpdateMatrices(camera); + + _Water.OnBeginCameraOpaqueTexture(camera); + + var @event = RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha; camera.AddCommandBuffer(@event, _EffectCommandBuffer); OnPreRenderUnderwaterEffect(camera); _HasEffectCommandBuffersBeenRegistered = true; } - - _FirstRender = false; } void OnAfterLegacyRender(Camera camera) { - if (_HasMaskCommandBuffersBeenRegistered) - { - // It could be either one event. - camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, _MaskCommandBuffer); - camera.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, _MaskCommandBuffer); - _MaskCommandBuffer?.Clear(); - } - if (_HasEffectCommandBuffersBeenRegistered) { - var @event = _EnableShaderAPI ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha; + var @event = RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha; camera.RemoveCommandBuffer(@event, _EffectCommandBuffer); _EffectCommandBuffer?.Clear(); } - _HasMaskCommandBuffersBeenRegistered = false; - _HasEffectCommandBuffersBeenRegistered = false; + _Water.OnEndCameraOpaqueTexture(camera); - OnAfterCameraRender(camera); + _HasEffectCommandBuffersBeenRegistered = false; } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Mask.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Mask.cs index da197c38f..088fcf0d4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Mask.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.Mask.cs @@ -2,34 +2,21 @@ // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; -using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; -using WaveHarmonic.Crest.Internal; namespace WaveHarmonic.Crest { - partial class UnderwaterRenderer + partial class UnderwaterRenderer : MaskRenderer.IMaskReceiver, MaskRenderer.IMaskProvider { - // Adapted from: - // Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs -#if UNITY_SWITCH || UNITY_ANDROID || UNITY_EMBEDDED_LINUX || UNITY_QNX - internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D24_UNorm_S8_UInt; - internal const int k_DepthBufferBits = 24; - internal const DepthBits k_DepthBits = DepthBits.Depth24; -#else - internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D32_SFloat_S8_UInt; - internal const int k_DepthBufferBits = 32; - internal const DepthBits k_DepthBits = DepthBits.Depth32; -#endif + internal const string k_DrawMask = "Crest.DrawMask"; + const string k_DrawMaskHorizon = "Horizon"; + const string k_DrawMaskSurface = "Surface"; + + internal const int k_VolumeMaskQueue = 1000; internal const int k_ShaderPassWaterSurfaceMask = 0; internal const int k_ShaderPassWaterSurfaceDepth = 1; - internal const int k_ShaderPassWaterHorizonMask = 2; - - // NOTE: Must match CREST_MASK_BELOW_SURFACE in Constants.hlsl. - const float k_MaskBelowSurface = -1f; - // NOTE: Must match CREST_MASK_BELOW_SURFACE_CULLED in Constants.hlsl. - const float k_MaskBelowSurfaceCull = -2f; + internal const int k_ShaderPassWaterHorizonMask = 0; internal const string k_ComputeShaderKernelFillMaskArtefacts = "FillMaskArtefacts"; @@ -37,25 +24,10 @@ namespace WaveHarmonic.Crest { // Local public static readonly int s_FarPlaneOffset = Shader.PropertyToID("_Crest_FarPlaneOffset"); - public static readonly int s_MaskBelowSurface = Shader.PropertyToID("_Crest_MaskBelowSurface"); - - // Global - public static readonly int s_WaterMaskTexture = Shader.PropertyToID("_Crest_WaterMaskTexture"); - public static readonly int s_WaterMaskDepthTexture = Shader.PropertyToID("_Crest_WaterMaskDepthTexture"); - - public static readonly int s_StencilRef = Shader.PropertyToID("_StencilRef"); } internal Material _MaskMaterial; - - internal RenderTargetIdentifier _MaskTarget; - internal RenderTargetIdentifier _DepthTarget; - - internal readonly Plane[] _CameraFrustumPlanes = new Plane[6]; - CommandBuffer _MaskCommandBuffer; - - internal RenderTexture _MaskRT; - RenderTexture _DepthRT; + internal Material _HorizonMaskMaterial; ComputeShader _ArtifactsShader; bool _ArtifactsShaderInitialized; @@ -63,30 +35,19 @@ namespace WaveHarmonic.Crest uint _ArtifactsThreadGroupSizeX; uint _ArtifactsThreadGroupSizeY; - void SetupMask() - { - _MaskCommandBuffer ??= new() - { - name = "Crest: Underwater Mask", - }; - } - internal void OnEnableMask() { - // Create a reference to handle the RT. The RT properties will be replaced with a descriptor before the - // native object is created, and since it is lazy it is near zero cost. - Helpers.CreateRenderTargetTextureReference(ref _MaskRT, ref _MaskTarget); - _MaskRT.name = "_Crest_WaterMaskTexture"; - Helpers.CreateRenderTargetTextureReference(ref _DepthRT, ref _DepthTarget); - _DepthRT.name = "_Crest_WaterMaskDepthTexture"; + _Water._Mask.Add(this); + _Water._Mask.Add(k_VolumeMaskQueue, this); SetUpArtifactsShader(); } internal void OnDisableMask() { - if (_MaskRT != null) _MaskRT.Release(); - if (_DepthRT != null) _DepthRT.Release(); + if (_Water == null) return; + _Water._Mask?.Remove(this as MaskRenderer.IMaskReceiver); + _Water._Mask?.Remove(this as MaskRenderer.IMaskProvider); } internal void SetUpArtifactsShader() @@ -108,70 +69,69 @@ namespace WaveHarmonic.Crest _ArtifactsShaderInitialized = true; } - internal void SetUpMaskTextures(RenderTextureDescriptor descriptor) + void MaskRenderer.IMaskProvider.OnMaskPass(CommandBuffer commands, Camera camera, MaskRenderer mask) { - if (!Helpers.RenderTargetTextureNeedsUpdating(_MaskRT, descriptor)) + var color = mask.ColorRTH; + var depth = mask.DepthRTH; + + var size = color.GetScaledSize(color.rtHandleProperties.currentViewportSize); + var descriptor = color.rt.descriptor; + descriptor.width = size.x; descriptor.height = size.y; + + if (UseLegacyMask) + { + // Portals changes the target. + // When using the stencil we are already clearing depth and do not want to clear the stencil too. Clear + // color only when using the stencil as the horizon effectively clears it when not using it. + CoreUtils.SetRenderTarget(commands, color, depth, UseStencilBuffer ? ClearFlag.Color : ClearFlag.DepthStencil); + Helpers.ScaleViewport(camera, commands, color); + + PopulateMask(commands, camera); + FixMaskArtefacts(commands, descriptor, mask._ColorRTI); + } + // Portals have their own fitted to the portal bounds. + else +#if d_CrestPortals + if (!Portaled || _Water.Portals.RequiresFullScreenMask) +#endif + { + RenderLineMask(commands, camera, mask.ColorRT.descriptor, mask._ColorRTI); + } + } + + internal void RenderLineMask(CommandBuffer buffer, Camera camera, RenderTextureDescriptor descriptor, RenderTargetIdentifier target) + { + if (!_Water.Surface.Enabled) { return; } - // This will disable MSAA for our textures as MSAA will break sampling later on. This looks safe to do as - // Unity's CopyDepthPass does the same, but a possible better way or supporting MSAA is worth looking into. - descriptor.msaaSamples = 1; - - // @Memory: We could investigate making this an 8-bit texture instead to reduce GPU memory usage. - // @Memory: We could potentially try a half resolution mask as the mensicus could mask resolution issues. - // Intel iGPU for Metal and DirectX both had issues with R16. 2021.11.18 - descriptor.colorFormat = Helpers.IsIntelGPU() ? RenderTextureFormat.RFloat : RenderTextureFormat.RHalf; - descriptor.depthBufferBits = 0; - descriptor.enableRandomWrite = true; - - _MaskRT.Release(); - _MaskRT.descriptor = descriptor; - - descriptor.colorFormat = RenderTextureFormat.Depth; - descriptor.depthBufferBits = (int)k_DepthBits; - descriptor.enableRandomWrite = false; - - _DepthRT.Release(); - _DepthRT.descriptor = descriptor; - } - - void OnPreRenderMask(Camera camera) - { - _MaskCommandBuffer.Clear(); - - var descriptor = XRHelpers.GetRenderTextureDescriptor(camera); - - descriptor.useDynamicScale = camera.allowDynamicResolution; - - // Keywords and other things. - SetUpMaskTextures(descriptor); + var keep = false; #if d_CrestPortals - // Populate water volume before mask so we can use the stencil. - if (_Portals.Active) + if (_Water.Portals.Active) { - _Portals.ReAllocate(descriptor); - _Portals.RenderMask(camera, _MaskCommandBuffer, _MaskMaterial); - _Portals.RenderStencil(_MaskCommandBuffer, _DepthRT, _DepthTarget); + keep = _Water.Portals.RenderLineMask(buffer, target); } #endif - _MaskCommandBuffer.SetRenderTarget(_MaskTarget, _DepthTarget); - SetUpMask(_MaskCommandBuffer, _MaskTarget, _DepthTarget); - PopulateMask(_MaskCommandBuffer, camera); + var wrapper = new PropertyWrapperCompute(buffer, WaterResources.Instance.Compute._Mask, (int)RenderPipelineHelper.RenderPipeline); - FixMaskArtefacts(_MaskCommandBuffer, descriptor, _MaskTarget); - } + var parameters = _Water.Surface._SurfaceDataParameters; - internal void SetUpMask(CommandBuffer buffer, RenderTargetIdentifier maskTarget, RenderTargetIdentifier depthTarget) - { - // When using the stencil we are already clearing depth and do not want to clear the stencil too. Clear - // color only when using the stencil as the horizon effectively clears it when not using it. - buffer.ClearRenderTarget(!UseStencilBuffer, UseStencilBuffer, Color.black); - buffer.SetGlobalTexture(ShaderIDs.s_WaterMaskTexture, maskTarget); - buffer.SetGlobalTexture(ShaderIDs.s_WaterMaskDepthTexture, depthTarget); + wrapper.SetTexture(SurfaceRenderer.ShaderIDs.s_WaterLine, _Water.Surface.HeightRT); + wrapper.SetVector(SurfaceRenderer.ShaderIDs.s_WaterLineSnappedPosition, parameters._SnappedPosition); + wrapper.SetVector(SurfaceRenderer.ShaderIDs.s_WaterLineResolution, parameters._Resolution); + wrapper.SetFloat(SurfaceRenderer.ShaderIDs.s_WaterLineTexel, parameters._Texel); + + // Only write if not written (ie zero). + wrapper.SetKeyword(new(WaterResources.Instance.Compute._Mask, "d_KeepValue"), keep); + + // Setting this sets unity_CameraToWorld. + wrapper.SetMatrix(Crest.ShaderIDs.Unity.s_CameraToWorld, camera.cameraToWorldMatrix); + + // Viewport sizes are not perfect so round up to cover. + wrapper.Dispatch(Mathf.CeilToInt(descriptor.width / 8f), Mathf.CeilToInt(descriptor.height / 8f), descriptor.volumeDepth); } internal void FixMaskArtefacts(CommandBuffer buffer, RenderTextureDescriptor descriptor, RenderTargetIdentifier target) @@ -181,9 +141,16 @@ namespace WaveHarmonic.Crest return; } - buffer.SetComputeTextureParam(_ArtifactsShader, _ArtifactsKernel, ShaderIDs.s_WaterMaskTexture, target); - // XR SPI will have a volume depth of two. If using RTHandles, then set manually as will be two for all cameras. - _ArtifactsShader.SetKeyword("STEREO_INSTANCING_ON", descriptor.dimension == TextureDimension.Tex2DArray); + if (!_Water.Surface.Enabled && Portaled) + { + return; + } + + // This will not be set automatically unless we use they RP variant approach + // similar to Mask.compute. + _ArtifactsShader.SetKeyword(new LocalKeyword(_ArtifactsShader, "STEREO_INSTANCING_ON"), descriptor.dimension == TextureDimension.Tex2DArray); + + buffer.SetComputeTextureParam(_ArtifactsShader, _ArtifactsKernel, MaskRenderer.ShaderIDs.s_WaterMaskTexture, target); buffer.DispatchCompute ( @@ -200,54 +167,55 @@ namespace WaveHarmonic.Crest // be able to avoid this pass completely if we can reuse the camera depth after transparents are rendered. internal void PopulateMask(CommandBuffer commandBuffer, Camera camera) { + if (!_Water.Surface.Enabled && Portaled) + { + return; + } + // Render horizon into mask using a fullscreen triangle at the far plane. Horizon must be rendered first or // it will overwrite the mask with incorrect values. { var zBufferParameters = Helpers.GetZBufferParameters(camera); // Take 0-1 linear depth and convert non-linear depth. - _MaskMaterial.SetFloat(ShaderIDs.s_FarPlaneOffset, Helpers.LinearDepthToNonLinear(_FarPlaneMultiplier, zBufferParameters)); + _HorizonMaskMaterial.SetFloat(ShaderIDs.s_FarPlaneOffset, Helpers.LinearDepthToNonLinear(_FarPlaneMultiplier, zBufferParameters)); // Render fullscreen triangle with horizon mask pass. - commandBuffer.DrawProcedural(Matrix4x4.identity, _MaskMaterial, shaderPass: k_ShaderPassWaterHorizonMask, MeshTopology.Triangles, 3, 1); + commandBuffer.BeginSample(k_DrawMaskHorizon); + commandBuffer.DrawProcedural(Matrix4x4.identity, _HorizonMaskMaterial, shaderPass: k_ShaderPassWaterHorizonMask, MeshTopology.Triangles, 3, 1); + commandBuffer.EndSample(k_DrawMaskHorizon); } - GeometryUtility.CalculateFrustumPlanes(camera, _CameraFrustumPlanes); - // Get all water chunks and render them using cmd buffer, but with mask shader. if (!_Debug._DisableMask) { - // Spends approx 0.2-0.3ms here on 2018 Dell XPS 15. - foreach (var chunk in _Water.Chunks) - { - var renderer = chunk.Rend; - // Can happen in edit mode. - if (renderer == null) continue; - var bounds = renderer.bounds; - if (GeometryUtility.TestPlanesAABB(_CameraFrustumPlanes, bounds)) - { - if ((!chunk._WaterDataHasBeenBound) && chunk.enabled) - { - chunk.Bind(camera); - } - - // Handle culled tiles for when underwater is rendered before the transparent pass. - chunk._MaterialPropertyBlock.SetFloat(ShaderIDs.s_MaskBelowSurface, !_EnableShaderAPI || renderer.enabled ? k_MaskBelowSurface : k_MaskBelowSurfaceCull); - renderer.SetPropertyBlock(chunk._MaterialPropertyBlock); - - commandBuffer.DrawRenderer(renderer, _MaskMaterial, submeshIndex: 0, shaderPass: k_ShaderPassWaterSurfaceMask); - - chunk._Visible = true; - } - chunk._WaterDataHasBeenBound = false; - } - -#if d_CrestPortals - if (_Portals.Active) - { - _Portals.PopulateMask(commandBuffer, _MaskMaterial); - } -#endif // d_CrestPortals + commandBuffer.BeginSample(k_DrawMaskSurface); + _Water.Surface.Render(camera, commandBuffer, _MaskMaterial, k_ShaderPassWaterSurfaceMask); + commandBuffer.EndSample(k_DrawMaskSurface); } } + + internal bool _MaskRead; + bool _DoneMaskRead; + + MaskRenderer.MaskInput MaskRenderer.IMaskProvider.Allocate() + { + return MaskRenderer.MaskInput.Both; + } + + MaskRenderer.MaskInput MaskRenderer.IMaskReceiver.Allocate() + { + return MaskRenderer.MaskInput.Both; + } + + MaskRenderer.MaskInput MaskRenderer.IMaskProvider.Write(Camera camera) + { + if (!_DoneMaskRead) + { + _MaskRead = ShouldRender(camera, Pass.Mask); + _DoneMaskRead = true; + } + + return _MaskRead ? _Water.Surface.Enabled ? MaskRenderer.MaskInput.Both : MaskRenderer.MaskInput.Color : MaskRenderer.MaskInput.None; + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.cs index 6e6996e85..461a03eab 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Volume/UnderwaterRenderer.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; @@ -28,6 +28,8 @@ namespace WaveHarmonic.Crest [@DecoratedField, SerializeField] internal bool _Enabled = true; + // This is mainly for reflection probes (HDRP planar specifically). It gives + // developers the option to make a TIR probe which should not render the surface. [Tooltip("Any camera or probe with this layer in its culling mask will render underwater.")] [@Layer] [@GenerateAPI] @@ -35,8 +37,8 @@ namespace WaveHarmonic.Crest int _Layer = 4; // Water [Tooltip("The underwater material. The water surface material is copied into this material.")] - [@AttachMaterialEditor] - [@MaterialField("Crest/Underwater", name: "Underwater", title: "Create Underwater Material")] + [@AttachMaterialEditor(order: 2)] + [@MaterialField(k_ShaderNameEffect, name: "Underwater", title: "Create Underwater Material")] [@GenerateAPI] [SerializeField] internal Material _Material; @@ -68,21 +70,6 @@ namespace WaveHarmonic.Crest #endif - [@Heading("Shader API")] - - [Tooltip("Renders the underwater effect before the transparent pass (instead of after).\n\nSo one can apply the underwater fog themselves to transparent objects. Cannot be changed at runtime.")] - [@DecoratedField, SerializeField] - [HideInInspector] - bool _EnableShaderAPI = false; - internal bool EnableShaderAPI { get => _EnableShaderAPI; set => _EnableShaderAPI = value; } - - [@Predicated(nameof(_EnableShaderAPI))] - [@Predicated(RenderPipeline.Legacy, inverted: true, hide: true)] - [@DecoratedField, SerializeField] - [HideInInspector] - internal LayerMask _TransparentObjectLayers; - - [@Heading("Advanced")] [Tooltip("Whether to execute for all cameras.\n\nIf disabled, then additionally ignore any camera that is not the view camera or our reflection camera. It will require managing culling masks of all cameras.")] @@ -134,18 +121,33 @@ namespace WaveHarmonic.Crest internal bool _OnlyReflectionCameras; } + /// + /// Raised after copying the water material properties to the underwater material. + /// + public static System.Action AfterCopyMaterial { get; set; } + + // Always render before surface, unless legacy mode which always renders after transparency. +#if d_Crest_LegacyUnderwater + internal bool UseLegacyMask => true; + internal bool RenderBeforeTransparency => false; +#else + // Legacy mask works except for negative volumes. Not officially supported. + internal bool UseLegacyMask => _AllCameras; + internal bool RenderBeforeTransparency => true; +#endif + internal WaterRenderer _Water; #if d_CrestPortals // BUG: NonSerialized as Unity shows a serialization depth warning even though field is internal. [System.NonSerialized] internal Portals.PortalRenderer _Portals; - bool Portaled => _Portals.Active; + internal bool Portaled => _Portals.Active; #else bool Portaled => false; #endif - bool _FirstRender = true; + int _MaterialLastUpdatedFrame = -1; internal bool UseStencilBuffer { get; set; } @@ -168,9 +170,6 @@ namespace WaveHarmonic.Crest // Empty. } - // Disable underwater effect if height enough above surface. - internal bool Active => _Enabled && _Material != null && _ViewerWaterHeight < 2f || Portaled || _Debug._DisableHeightAboveWaterOptimization; - internal void OnEnable() { _VolumeMaterial = _Material; @@ -180,22 +179,27 @@ namespace WaveHarmonic.Crest _MaskMaterial = new(WaterResources.Instance.Shaders._UnderwaterMask); } + if (_HorizonMaskMaterial == null) + { + _HorizonMaskMaterial = new(WaterResources.Instance.Shaders._HorizonMask); + } + if (_ArtifactsShader == null) { _ArtifactsShader = WaterResources.Instance.Compute._UnderwaterArtifacts; } + OnEnableMask(); + if (RenderPipelineHelper.IsUniversal) { #if d_UnityURP - UnderwaterMaskPassURP.Enable(this); UnderwaterEffectPassURP.Enable(this); #endif } else if (RenderPipelineHelper.IsHighDefinition) { #if d_UnityHDRP - UnderwaterMaskPassHDRP.Enable(this); UnderwaterEffectPassHDRP.Enable(this); #endif } @@ -223,13 +227,13 @@ namespace WaveHarmonic.Crest { RenderPipelineManager.activeRenderPipelineTypeChanged -= OnActiveRenderPipelineTypeChanged; + OnDisableMask(); + #if d_UnityURP - UnderwaterMaskPassURP.Disable(); UnderwaterEffectPassURP.Disable(); #endif #if d_UnityHDRP - UnderwaterMaskPassHDRP.Disable(); UnderwaterEffectPassHDRP.Disable(); #endif @@ -243,27 +247,36 @@ namespace WaveHarmonic.Crest internal void OnDestroy() { Helpers.Destroy(_MaskMaterial); + Helpers.Destroy(_HorizonMaskMaterial); + // Without will cause exception in editor in play mode if disable Write Motion Vectors. + _MaskMaterial = null; + _HorizonMaskMaterial = null; } internal bool ShouldRender(Camera camera, Pass pass) { + if (!_Enabled || _Material == null) + { + return false; + } + if (_Water == null) { return false; } - if (!Helpers.MaskIncludesLayer(camera.cullingMask, _Layer)) + if (!WaterRenderer.ShouldRender(camera, _Layer)) + { + return false; + } + + // Skip entire mask pass if possible. + if (pass == Pass.Mask && !_Water.Surface.Enabled) { return false; } #if UNITY_EDITOR - // Do not execute when editor is not active to conserve power and prevent possible leaks. - if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) - { - return false; - } - if (GL.wireframe) { return false; @@ -275,16 +288,6 @@ namespace WaveHarmonic.Crest { return false; } - - if (_Water.IsProxyPlaneRendering) - { - return false; - } - - if (camera.cameraType == CameraType.Preview) - { - return false; - } #endif var isReflectionCamera = camera.cameraType == CameraType.Reflection; @@ -304,14 +307,20 @@ namespace WaveHarmonic.Crest // Otherwise, filtering depends on the camera's culling mask which is not always // accessible like with the global "Reflection Probes Camera". But whether those // cameras triggering camera events is a bug is TBD as it is intermittent. - if (!_AllCameras && camera != _Water.Viewer && camera.cameraType != CameraType.SceneView && camera != WaterReflections.CurrentCamera) + if (!_AllCameras && camera != _Water.GetViewer(includeSceneCamera: false) && camera.cameraType != CameraType.SceneView && camera != WaterReflections.CurrentCamera) { return false; } - if (pass != Pass.Culling && !Active) + if (!_Debug._DisableHeightAboveWaterOptimization && !Portaled) { - return false; + _Water.UpdatePerCameraHeight(camera); + _ViewerWaterHeight = _Water._ViewerHeightAboveWaterPerCamera; + + if (_ViewerWaterHeight > 2f) + { + return false; + } } return true; @@ -319,7 +328,7 @@ namespace WaveHarmonic.Crest void RevertCulling() { - foreach (var tile in _Water.Chunks) + foreach (var tile in _Water.Surface.Chunks) { if (tile.Rend == null || tile._Culled) { @@ -330,27 +339,65 @@ namespace WaveHarmonic.Crest } } - internal void OnBeforeCameraRender(Camera camera) + // Called by WaterRenderer. Camera must have water layer. + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + OnBeginCameraRendering(camera); + +#if UNITY_EDITOR + // Populated by this point. + if (_VolumeMaterial.shader != WaterResources.Instance.Shaders._UnderwaterEffect) + { + return; + } +#endif + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + UnderwaterEffectPassURP.s_Instance?.EnqueuePass(context, camera); + } + else +#endif + +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + UnderwaterEffectPassHDRP.s_Instance?.OnBeginCameraRendering(context, camera); + } + else +#endif + + { + OnBeforeLegacyRender(camera); + } + } + + internal void OnBeginCameraRendering(Camera camera) { if (!ShouldRender(camera, Pass.Culling)) { return; } - var viewpoint = camera.transform.position; - _SamplingHeightHelper.SampleHeight(System.HashCode.Combine(GetHashCode(), camera.GetHashCode()), viewpoint, out var height, allowMultipleCallsPerFrame: true); - _ViewerWaterHeight = viewpoint.y - height; - - // ShouldRender has a special case for this pass which skips the Active check so we - // can always continue sampling. - if (!Active) + // Only one camera supported due to LOD center dependency. + if (!UseLegacyMask && ShouldRender(camera, Pass.Mask) && camera == _Water.Viewer) { - return; + _Water.Surface.UpdateDisplacedSurfaceData(camera); } - _SurfaceMaterial = _Water.AboveOrBelowSurfaceMaterial; +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + _Water.UpdateHighDefinitionLighting(camera); + } +#endif + + _SurfaceMaterial = _Water.Surface.AboveOrBelowSurfaceMaterial; _VolumeMaterial = _Material; + var viewpoint = camera.transform.position; + // Grab material from a water body if camera is within its XZ bounds. foreach (var body in WaterBody.WaterBodies) { @@ -373,6 +420,13 @@ namespace WaveHarmonic.Crest } } +#if UNITY_EDITOR + if (_VolumeMaterial.shader != WaterResources.Instance.Shaders._UnderwaterEffect) + { + return; + } +#endif + var extinction = Vector3.zero; float minimumFogDensity = 0; @@ -405,7 +459,12 @@ namespace WaveHarmonic.Crest minimumFogDensity = Mathf.Max(minimumFogDensity, 0.0001f); } - UpdateEnvironmentalLighting(camera, extinction, _ViewerWaterHeight); + if (_EnvironmentalInitialized) + { + _Water.UpdatePerCameraHeight(camera); + _ViewerWaterHeight = _Water._ViewerHeightAboveWaterPerCamera; + UpdateEnvironmentalLighting(camera, extinction, _ViewerWaterHeight); + } if (Portaled || _ViewerWaterHeight > -5f) { @@ -415,7 +474,7 @@ namespace WaveHarmonic.Crest var extinctionLength = -Mathf.Log(_CullLimit) / minimumFogDensity; - foreach (var tile in _Water.Chunks) + foreach (var tile in _Water.Surface.Chunks) { if (tile.Rend == null || tile._Culled) { @@ -436,10 +495,16 @@ namespace WaveHarmonic.Crest } } - internal void OnAfterCameraRender(Camera camera) + internal void OnEndCameraRendering(Camera camera) { RestoreEnvironmentalLighting(); RevertCulling(); + _DoneMaskRead = false; + + if (RenderPipelineHelper.IsLegacy) + { + OnAfterLegacyRender(camera); + } } void SetEnabled(bool previous, bool current) diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Editor.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Editor.cs index 4c09e47b9..60350b53f 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Editor.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Editor.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if UNITY_EDITOR @@ -16,9 +16,11 @@ namespace WaveHarmonic.Crest { internal const string k_ProxyShader = "Hidden/Crest/Editor/WaterProxy"; internal GameObject _ProxyPlane; - internal bool IsProxyPlaneRendering => !Application.isPlaying && _ShowWaterProxyPlane; + private protected override bool CanRunInEditMode => !_ShowWaterProxyPlane; - internal static float LastUpdateEditorTime { get; set; } = -1f; + + internal static float EditorTime { get; set; } + internal static float EditorDeltaTime { get; set; } static int s_EditorFrames = 0; // Useful for rate limiting processes called outside of RunUpdate like camera events. @@ -34,6 +36,9 @@ namespace WaveHarmonic.Crest { _Underwater._Material = AssetDatabase.LoadAssetAtPath("Packages/com.waveharmonic.crest/Runtime/Materials/Water Volume.mat"); + _Surface.Reset(); + Meniscus.Reset(); + base.Reset(); } @@ -66,12 +71,13 @@ namespace WaveHarmonic.Crest if (!Application.isPlaying) { - if (EditorApplication.timeSinceStartup - LastUpdateEditorTime > 1f / Mathf.Clamp(Instance._EditModeFrameRate, 0.01f, 60f)) + if ((Time.time - EditorTime) >= (1f / Mathf.Clamp(Instance._EditModeFrameRate, 0.01f, 120f))) { s_EditorFrames++; s_EditorFramesSinceUpdate = 0; - LastUpdateEditorTime = (float)EditorApplication.timeSinceStartup; + EditorDeltaTime = Time.time - EditorTime; + EditorTime = Time.time; Instance.RunUpdate(); } @@ -90,6 +96,28 @@ namespace WaveHarmonic.Crest { AfterScriptReload(); } + + [@OnChange] + void OnChange(string path, object previous) + { + switch (path) + { + case nameof(_ExtentsSizeMultiplier): + case nameof(_GeometryDownSampleFactor): + Surface._Rebuild = true; + break; + case nameof(_ShowWaterProxyPlane): + SetShowProxyPlane((bool)previous, _ShowWaterProxyPlane); + break; + } + } + + void SetShowProxyPlane(bool previous, bool current) + { + if (previous == current) return; + if (!isActiveAndEnabled || Application.isPlaying) return; + if (!(runInEditMode = !_ShowWaterProxyPlane)) OnDisable(); + } } partial class WaterRenderer diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs new file mode 100644 index 000000000..bfe9c4b95 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs @@ -0,0 +1,306 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#if d_UnityHDRP + +using System.Reflection; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.HighDefinition; +using WaveHarmonic.Crest.Internal; + +namespace WaveHarmonic.Crest +{ + // High Definition Render Pipeline + partial class WaterRenderer + { + internal static partial class ShaderIDs + { + // High Definition Render Pipeline + public static readonly int s_PrimaryLightDirection = Shader.PropertyToID("g_Crest_PrimaryLightDirection"); + public static readonly int s_PrimaryLightIntensity = Shader.PropertyToID("g_Crest_PrimaryLightIntensity"); + } + + internal static bool s_CameraMSAA; + + bool _DoneHighDefinitionLighting; + + void OnBeginContextRendering(ScriptableRenderContext context, System.Collections.Generic.List cameras) + { + s_CameraMSAA = false; + } + + // This use to be in OnBeginContextRendering with comment: "Most compatible with + // lighting options if computed here". Cannot remember what that meant. + internal void UpdateHighDefinitionLighting(Camera camera) + { + if (_DoneHighDefinitionLighting) + { + return; + } + + var lightDirection = Vector3.zero; + var lightIntensity = Color.black; + var sun = PrimaryLight; + + if (sun != null && sun.isActiveAndEnabled && sun.TryGetComponent(out var data)) + { + lightDirection = -sun.transform.forward; + lightIntensity = Color.clear; + + // It was reported that Light.intensity causes flickering when updated with + // HDAdditionalLightData.SetIntensity, unless we get intensity from there. + { + // Adapted from Helpers.FinalColor. + var light = data; + var linear = GraphicsSettings.lightsUseLinearIntensity; + var color = linear ? light.color.linear : light.color; +#if UNITY_6000_0_OR_NEWER + color *= sun.intensity; +#else + color *= light.intensity; +#endif + if (linear && light.useColorTemperature) color *= Mathf.CorrelatedColorTemperatureToRGB(sun.colorTemperature); + if (!linear) color = color.MaybeLinear(); + lightIntensity = linear ? color.MaybeGamma() : color; + } + + // Transmittance is for Physically Based Sky. + var hdCamera = HDCamera.GetOrCreate(camera); + var settings = SkyManager.GetSkySetting(hdCamera.volumeStack); + var transmittance = settings != null + ? settings.EvaluateAtmosphericAttenuation(lightDirection, hdCamera.camera.transform.position) + : Vector3.one; + + lightIntensity *= transmittance.x; + lightIntensity *= transmittance.y; + lightIntensity *= transmittance.z; + } + + Shader.SetGlobalVector(ShaderIDs.s_PrimaryLightDirection, lightDirection); + Shader.SetGlobalVector(ShaderIDs.s_PrimaryLightIntensity, lightIntensity); + + _DoneHighDefinitionLighting = true; + } + } + + sealed class CrestInternalCopyToTextureCustomPass : CustomPass + { + const string k_Name = "Update Pyramids"; + + static CrestInternalCopyToTextureCustomPass s_Instance; + + WaterRenderer _Water; + + // Wraps depth pyramid, so we can use Blitter. + RTHandle _DepthPyramid; + + RenderTexture _DepthTexture; + RenderTexture _DepthTextureDynamic; + + public static void Enable(WaterRenderer renderer) + { + var gameObject = CustomPassHelpers.CreateOrUpdate + ( + parent: renderer.Container.transform, + k_Name, + hide: !renderer._Debug._ShowHiddenObjects + ); + + CustomPassHelpers.CreateOrUpdate + ( + gameObject, + ref s_Instance, + WaterRenderer.k_DrawWater, + renderer.RenderBeforeTransparency + ? CustomPassInjectionPoint.BeforeTransparent + : CustomPassInjectionPoint.BeforePostProcess, + priority: -1 + ); + + s_Instance._Water = renderer; + + RenderPipelineManager.beginCameraRendering -= s_Instance.OnBeginCameraRendering; + RenderPipelineManager.beginCameraRendering += s_Instance.OnBeginCameraRendering; + RenderPipelineManager.endCameraRendering -= s_Instance.OnEndCameraRendering; + RenderPipelineManager.endCameraRendering += s_Instance.OnEndCameraRendering; + } + + public static void Disable() + { + if (s_Instance != null) + { + RenderPipelineManager.beginCameraRendering -= s_Instance.OnBeginCameraRendering; + RenderPipelineManager.endCameraRendering -= s_Instance.OnEndCameraRendering; + } + + // It should be safe to rely on this reference for this reference to fail. + if (s_Instance != null && s_Instance._GameObject != null) + { + // Will also trigger Cleanup below. + s_Instance._GameObject.SetActive(false); + } + } + + void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) + { + s_Instance._Volume.injectionPoint = _Water.RenderBeforeTransparency + ? CustomPassInjectionPoint.BeforeTransparent + : CustomPassInjectionPoint.BeforePostProcess; + } + + void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) + { + if (this == null) return; + + if (!WaterRenderer.ShouldRender(camera, _Water.Surface.Layer)) + { + return; + } + + // TODO: Work out conditions where depth copy is needed when rendering during transparency. + if (!_Water.RenderBeforeTransparency) + { + return; + } + + var rt = Shader.GetGlobalTexture(Shader.PropertyToID("_CameraDepthTexture")) as RenderTexture; + var hdCamera = HDCamera.GetOrCreate(camera); + + if (hdCamera.allowDynamicResolution && hdCamera.canDoDynamicResolution) + { + _DepthTextureDynamic = rt; + } + else + { + _DepthTexture = rt; + } + } + + protected override void Cleanup() + { + base.Cleanup(); + // Unset internal RT to avoid release it. + _DepthPyramid?.SetRenderTexture(null); + _DepthPyramid?.Release(); + } + + MipGenerator MipGenerator => +#if UNITY_6000_OR_NEWER + (RenderPipelineManager.currentPipeline as HDRenderPipeline).m_MipGenerator +#else + s_MipGenerator.GetValue(RenderPipelineManager.currentPipeline) as MipGenerator; + static readonly FieldInfo s_MipGenerator = typeof(HDRenderPipeline).GetField("m_MipGenerator", BindingFlags.NonPublic | BindingFlags.Instance); +#endif + + static readonly MethodInfo s_UseScaling = typeof(RTHandle).GetProperty("useScaling", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).SetMethod; + static readonly object[] s_UseScalingParameters = { true }; + + static void UseScaling(RTHandle rt) + { + s_UseScaling.Invoke(rt, s_UseScalingParameters); + } + + protected override void Execute(CustomPassContext context) + { + // We cannot override _ColorPyramidTexture or _CameraDepthTexture with our own + // texture, so we write to these textures instead. Getting these textures has + // been tricky. Getting _ColorPyramidTexture with Shader.GetGlobalTexture does + // not always work, as it is replaced with the distortion color pyramid before + // we can grab it. + + var hdCamera = context.hdCamera; + var camera = hdCamera.camera; + var buffer = context.cmd; + + if (!WaterRenderer.ShouldRender(camera, _Water.Surface.Layer)) + { + return; + } + + if (_Water.Surface.Material == null) + { + return; + } + + if (!SurfaceRenderer.IsTransparent(_Water.Surface.Material)) + { + return; + } + + // Our reflections do not need them. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + if (context.hdCamera.msaaEnabled) + { + WaterRenderer.s_CameraMSAA = true; + return; + } + + if (!_Water.RenderBeforeTransparency && hdCamera.frameSettings.IsEnabled(FrameSettingsField.Distortion)) + { + return; + } + + if (_Water.WriteToColorTexture) + { + var colorTexture = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.ColorBufferMipChain); + + if (colorTexture != null) + { + buffer.BeginSample(WaterRenderer.k_DrawCopyColor); + + var pyramidSize = new Vector2Int(hdCamera.actualWidth, hdCamera.actualHeight); + Blitter.BlitCameraTexture(buffer, context.cameraColorBuffer, colorTexture); + MipGenerator.RenderColorGaussianPyramid(buffer, pyramidSize, context.cameraColorBuffer, colorTexture); + + buffer.EndSample(WaterRenderer.k_DrawCopyColor); + } + } + + // TODO: Work out conditions where depth copy is needed when rendering during transparency. + if (!_Water.RenderBeforeTransparency) + { + return; + } + + if (_Water.WriteToDepthTexture) + { + // Texture is not set yet, so we need to store it at the end of rendering. + // Textures may be different depending on configuration. + var depthTexture = hdCamera.allowDynamicResolution && hdCamera.canDoDynamicResolution ? _DepthTextureDynamic : _DepthTexture; + + if (depthTexture != null) + { + buffer.BeginSample(WaterRenderer.k_DrawCopyDepth); + + // Set up wrapper, so we can use Blitter. + _DepthPyramid ??= RTHandles.Alloc(depthTexture); + _DepthPyramid.SetRenderTexture(depthTexture); + UseScaling(_DepthPyramid); + + // Blit to the bottom of the depth atlas. + Blitter.BlitCameraTexture(buffer, context.cameraDepthBuffer, _DepthPyramid, new Rect(0, 0, hdCamera.actualWidth, hdCamera.actualHeight)); + + // Regenerate the depth pyramid. + MipGenerator.RenderMinDepthPyramid + ( + buffer, + depthTexture, + hdCamera.depthBufferMipChainInfo +#if !UNITY_6000_0_OR_NEWER + , mip1AlreadyComputed: false +#endif + ); + + buffer.EndSample(WaterRenderer.k_DrawCopyDepth); + } + } + } + } +} + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs.meta new file mode 100644 index 000000000..1e095ea14 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.HighDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b5f4ec80b27f479aa559923ae6ca939 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Legacy.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Legacy.cs index e457711c4..5bf33e026 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Legacy.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Legacy.cs @@ -1,161 +1,94 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; using UnityEngine.Rendering; -using UnityEngine.Experimental.Rendering; namespace WaveHarmonic.Crest { // Built-in Render Pipeline partial class WaterRenderer { + internal const string k_DrawWater = "Crest.DrawWater"; + internal const string k_DrawCopyColor = "CopyColor"; + internal const string k_DrawCopyDepth = "CopyDepth"; + partial class ShaderIDs { - public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture"); - public static readonly int s_ShadowMapTexture = Shader.PropertyToID("_ShadowMapTexture"); public static readonly int s_ScreenSpaceShadowTexture = Shader.PropertyToID("_Crest_ScreenSpaceShadowTexture"); + public static readonly int s_TemporaryDepthTexture = Shader.PropertyToID("_Crest_TemporaryDepthTexture"); + public static readonly int s_PrimaryLightHasCookie = Shader.PropertyToID("g_Crest_PrimaryLightHasCookie"); + + public static class Unity + { + public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture"); + } } - CommandBuffer _CopyColorTextureBuffer; - RenderTexture _CameraColorTexture; + bool _DoneMatrices; CommandBuffer _ScreenSpaceShadowMapBuffer; - CommandBuffer _DeferredShadowMapBuffer; + CommandBuffer _UpdateColorDepthTexturesBuffer; - internal DefaultFormat LikelyFrameBufferFormat + internal Rendering.BIRP.FrameBufferFormatOverride FrameBufferFormatOverride => + !_OverrideRenderHDR + ? Rendering.BIRP.FrameBufferFormatOverride.None + : _RenderHDR + ? Rendering.BIRP.FrameBufferFormatOverride.HDR + : Rendering.BIRP.FrameBufferFormatOverride.LDR; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] + static void InitializeOnLoad() { - get - { - if (_OverrideRenderHDR) - { - return _RenderHDR ? DefaultFormat.HDR : DefaultFormat.LDR; - } - -#if UNITY_EDITOR - var target = UnityEditor.EditorUserBuildSettings.activeBuildTarget; - if (target is UnityEditor.BuildTarget.Android or UnityEditor.BuildTarget.iOS or UnityEditor.BuildTarget.tvOS) - { - return DefaultFormat.LDR; - } -#endif - -#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS - return DefaultFormat.LDR; -#else - return DefaultFormat.HDR; -#endif - } + // Fixes error on first frame. + Shader.SetGlobalTexture(Crest.ShaderIDs.Unity.s_ShadowMapTexture, Texture2D.whiteTexture); } - void OnPreRenderCamera(Camera camera) + internal void UpdateMatrices(Camera camera) { -#if UNITY_EDITOR - UpdateLastActiveSceneCamera(camera); - - if (!Application.isPlaying) - { - OnPreRenderWaterLevelDepthTexture(camera); - } -#endif - - OnBeginCameraRendering(camera); - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer)) + if (_DoneMatrices) { return; } - XRHelpers.Update(camera); - XRHelpers.SetInverseViewProjectionMatrix(camera); + Rendering.BIRP.SetMatrices(camera); - _CopyColorTextureBuffer ??= new() { name = "Crest Copy Color Texture" }; - _DeferredShadowMapBuffer ??= new() { name = "Crest Deferred Shadow Data" }; - _ScreenSpaceShadowMapBuffer ??= new() { name = "Crest Screen-Space Shadow Data" }; - _CopyColorTextureBuffer.Clear(); - _DeferredShadowMapBuffer.Clear(); - _ScreenSpaceShadowMapBuffer.Clear(); + _DoneMatrices = true; + } - // Create or update RT. + void OnBeginCameraRenderingLegacy(Camera camera) + { + if (PrimaryLight == null) { - var descriptor = XRHelpers.GetRenderTextureDescriptor(camera); - - // Format must be correct for CopyTexture to work. Hopefully this is good enough. - if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear) - { - descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(LikelyFrameBufferFormat); - } - - // Occurred in a build and caused a black screen. - if (descriptor.width <= 0) - { - return; - } - - if (_CameraColorTexture == null) - { - _CameraColorTexture = new(descriptor); - } - else - { - _CameraColorTexture.Release(); - _CameraColorTexture.descriptor = descriptor; - } - - _CameraColorTexture.Create(); + return; } - var target = new RenderTargetIdentifier(_CameraColorTexture, 0, CubemapFace.Unknown, -1); - - // Use blit instead of CopyTexture as it will smooth out issues with format - // differences which is very hard to get right for BIRP. - _CopyColorTextureBuffer.Blit(BuiltinRenderTextureType.CameraTarget, target); - _CopyColorTextureBuffer.SetGlobalTexture(ShaderIDs.s_CameraOpaqueTexture, _CameraColorTexture); - - camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer); - - if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null) + // Force shadow map to remain for transparent pass and beyond. { + _ScreenSpaceShadowMapBuffer ??= new() { name = "Crest.CausticsOcclusion" }; + _ScreenSpaceShadowMapBuffer.Clear(); + // Make the screen-space shadow texture available for the water shader for caustic occlusion. _ScreenSpaceShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, BuiltinRenderTextureType.CurrentActive); PrimaryLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer); - // Call this regardless of rendering path as it has no negative consequences for forward. - _DeferredShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ShadowMapTexture, BuiltinRenderTextureType.CurrentActive); - PrimaryLight.AddCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer); - } - { // Always set these in case shadow maps are disabled in the graphics settings which // we cannot check at runtime. // Black for shadowed. White for unshadowed. - if (camera.stereoEnabled && XRHelpers.IsSinglePass) - { - Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, XRHelpers.WhiteTexture); - } - else - { - Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Texture2D.whiteTexture); - } + Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Rendering.BIRP.GetWhiteTexture(camera)); } + + Helpers.SetGlobalBoolean(ShaderIDs.s_PrimaryLightHasCookie, PrimaryLight.cookie != null); } - void OnPostRenderCamera(Camera camera) + void OnEndCameraRenderingLegacy(Camera camera) { -#if UNITY_EDITOR - if (!Application.isPlaying) - { - OnPostRenderWaterLevelDepthTexture(camera); - } -#endif + _DoneMatrices = false; + _DoneCameraOpaqueTexture = false; - if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer)) + if (_UpdateColorDepthTexturesBuffer != null) { - return; - } - - if (_CopyColorTextureBuffer != null) - { - camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer); + camera.RemoveCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, _UpdateColorDepthTexturesBuffer); } if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null) @@ -164,11 +97,153 @@ namespace WaveHarmonic.Crest { PrimaryLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer); } + } - if (_DeferredShadowMapBuffer != null) + Shader.SetGlobalTexture(ShaderIDs.Unity.s_CameraOpaqueTexture, Texture2D.grayTexture); + } + + // Needs to be separate, as it needs to run after the water volume pass. + void OnLegacyCopyPass(Camera camera) + { + if (!ShouldRender(camera, Surface.Layer)) + { + return; + } + + if (Surface.Material == null) + { + return; + } + + if (!SurfaceRenderer.IsTransparent(Surface.Material)) + { + return; + } + + // Our reflections do not need them. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + _UpdateColorDepthTexturesBuffer ??= new() { name = k_DrawWater }; + _UpdateColorDepthTexturesBuffer.Clear(); + + var buffer = _UpdateColorDepthTexturesBuffer; + + if (WriteToColorTexture) + { + UpdateCameraOpaqueTexture(camera, buffer); + } + + if (WriteToDepthTexture && Shader.GetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraDepthTexture) is RenderTexture depthRT) + { + buffer.BeginSample(k_DrawCopyDepth); + + // There is no way to update the depth texture with the depth buffer, as we cannot + // get a reference to it. We have to render water depth separately and then merge + // the results. + + var target = new RenderTargetIdentifier(depthRT, 0, CubemapFace.Unknown, -1); + + var id = ShaderIDs.s_TemporaryDepthTexture; + + buffer.GetTemporaryRT(id, depthRT.descriptor); + CoreUtils.SetRenderTarget(buffer, id, ClearFlag.Depth); + + Surface.Render(camera, buffer, pass: Surface.Material.FindPass("DepthOnly"), culled: true); + + buffer.SetGlobalTexture(Helpers.ShaderIDs.s_MainTexture, id); + + Helpers.Blit(buffer, target, Rendering.BIRP.UtilityMaterial, (int)Rendering.BIRP.UtilityPass.MergeDepth); + + // TODO: add debug toggle + // buffer.Blit(target, BuiltinRenderTextureType.CameraTarget); + + buffer.ReleaseTemporaryRT(id); + + buffer.EndSample(k_DrawCopyDepth); + } + + if (WriteToColorTexture || WriteToDepthTexture) + { + camera.AddCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, buffer); + } + } + } + + // Camera Opaque Texture. + partial class WaterRenderer + { + bool _DoneCameraOpaqueTexture; + RenderTexture _CameraOpaqueTexture; + CommandBuffer _CameraOpaqueTextureCommands; + + internal void UpdateCameraOpaqueTexture(Camera camera, CommandBuffer commands) + { + commands.BeginSample(k_DrawCopyColor); + + var target = new RenderTargetIdentifier(_CameraOpaqueTexture, 0, CubemapFace.Unknown, -1); + + // Use blit instead of CopyTexture as it will smooth out issues with format + // differences which is very hard to get right for BIRP. + commands.Blit(BuiltinRenderTextureType.CameraTarget, target); + + commands.EndSample(k_DrawCopyColor); + } + + internal void OnBeginCameraOpaqueTexture(Camera camera) + { + if (_DoneCameraOpaqueTexture) + { + return; + } + + var descriptor = Rendering.BIRP.GetCameraTargetDescriptor(camera, FrameBufferFormatOverride); + + // Occurred in a build and caused a black screen. + if (descriptor.width <= 0) + { + return; + } + + if (_CameraOpaqueTexture == null) + { + _CameraOpaqueTexture = new(descriptor) { - PrimaryLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer); - } + name = "_CameraOpaqueTexture", + }; + } + else + { + _CameraOpaqueTexture.Release(); + _CameraOpaqueTexture.descriptor = descriptor; + } + + _CameraOpaqueTexture.Create(); + + _CameraOpaqueTextureCommands ??= new() + { + name = "Crest.DrawWater", + }; + + _CameraOpaqueTextureCommands.Clear(); + + // Do every frame as we set to default texture at end of rendering. + _CameraOpaqueTextureCommands.SetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraOpaqueTexture, _CameraOpaqueTexture); + + UpdateCameraOpaqueTexture(camera, _CameraOpaqueTextureCommands); + + camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands); + + _DoneCameraOpaqueTexture = true; + } + + internal void OnEndCameraOpaqueTexture(Camera camera) + { + if (_CameraOpaqueTextureCommands != null) + { + camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands); } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs new file mode 100644 index 000000000..b011c44a3 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs @@ -0,0 +1,44 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +using UnityEngine; + +namespace WaveHarmonic.Crest +{ + partial class WaterRenderer : ISerializationCallbackReceiver + { + [SerializeField, HideInInspector] +#pragma warning disable 414 + int _Version = 1; +#pragma warning restore 414 + + /// + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + if (_Version < 1) + { +#pragma warning disable CS0618 // Type or member is obsolete + Surface._Layer = _Layer; + Surface._Material = _Material; + Surface._VolumeMaterial = _VolumeMaterial; + Surface._ChunkTemplate = _ChunkTemplate; + Surface._CastShadows = _CastShadows; + Surface._WaterBodyCulling = _WaterBodyCulling; + Surface._TimeSliceBoundsUpdateFrameCount = _TimeSliceBoundsUpdateFrameCount; + Surface._AllowRenderQueueSorting = _AllowRenderQueueSorting; + Surface._SurfaceSelfIntersectionFixMode = _SurfaceSelfIntersectionFixMode; +#pragma warning restore CS0618 // Type or member is obsolete + + _DepthLod._IncludeTerrainHeight = false; + + _Version = 1; + } + } + + /// + void ISerializationCallbackReceiver.OnBeforeSerialize() + { + + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs.meta b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs.meta new file mode 100644 index 000000000..8417133d7 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Migration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bf05888fe7e048428e9c1fb978a0d85 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.SerializedFields.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.SerializedFields.cs index b8c983533..88b93a1dd 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.SerializedFields.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.SerializedFields.cs @@ -14,6 +14,21 @@ namespace WaveHarmonic.Crest } #endif + /// + /// The render pass injection point. + /// + [@GenerateDoc] + public enum WaterInjectionPoint + { + /// + [Tooltip("Renders in the default pass.\n\nFor the water surface, this will be determined by the material (opaque or transparent). This pass is controlled by Unity, and is not compatible with certain features like soft particles.\n\nFor the water volume, this will be after transparency.")] + Default, + + /// + [Tooltip("Renders before the transparent pass.\n\nThis has advantages like being compatible with soft particles, refractive shaders, and possibly third-party fog.")] + BeforeTransparent, + } + partial class WaterRenderer { internal const float k_MaximumWindSpeedKPH = 150f; @@ -25,37 +40,64 @@ namespace WaveHarmonic.Crest [Tooltip("The camera which drives the water data.\n\nSetting this is optional. Defaults to the main camera.")] [@GenerateAPI(Getter.Custom, name: "Viewer")] [@DecoratedField, SerializeField] - Camera _Camera; + internal Camera _Camera; [Tooltip("Optional provider for time.\n\nCan be used to hard-code time for automation, or provide server time. Defaults to local Unity time.")] [@DecoratedField, SerializeField] internal TimeProvider _TimeProvider; - [Tooltip("Whether to override the automatic detection of framebuffer HDR rendering (BIRP only).\n\nRendering using HDR formats is optional, but there is no way for us to determine if HDR rendering is enabled in the Graphics Settings. We make an educated based on which platform is the target. If you see rendering issues, try disabling this.\n\n This has nothing to do with having an HDR monitor.")] - [@Predicated(RenderPipeline.Legacy, hide: true)] - [@GenerateAPI] - [@DecoratedField, SerializeField] - bool _OverrideRenderHDR; - - [Tooltip("Force HDR format usage (BIRP only).\n\nIf enabled, we assume the framebuffer is an HDR format, otherwise an LDR format.")] - [@Predicated(RenderPipeline.Legacy, hide: true)] - [@Predicated(nameof(_OverrideRenderHDR))] - [@GenerateAPI] - [@DecoratedField, SerializeField] - bool _RenderHDR = true; - [@Group("Environment", Group.Style.Accordian)] - [Tooltip("Base wind speed in km/h.\n\nControls wave conditions. Can be overridden on Shape* components.")] - [@Range(0, k_MaximumWindSpeedKPH, scale: 2f)] + [Tooltip("Uses a provided WindZone as the source of global wind.\n\nIt must be directional. Wind speed units are presumed to be in m/s.")] [@GenerateAPI] + [@DecoratedField, SerializeField] + WindZone _WindZone; + + [Tooltip("Whether to override the given wind zone's wind speed.")] + [@Predicated(nameof(_WindZone), hide: true)] + [@InlineToggle, SerializeField] + bool _OverrideWindZoneWindSpeed; + + [Tooltip("Base wind speed in km/h.\n\nControls wave conditions. Can be overridden on Shape* components.")] + [@Predicated(typeof(WaterRenderer), nameof(WindSpeedOverriden), inverted: true, hide: true)] + [@ShowComputedProperty(nameof(WindSpeed))] + [@Range(0, k_MaximumWindSpeedKPH, scale: 2f)] + [@GenerateAPI(Getter.Custom)] [SerializeField] internal float _WindSpeed = 10f; + [Tooltip("Whether to override the given wind zone's wind direction.")] + [@Predicated(nameof(_WindZone), hide: true)] + [@InlineToggle, SerializeField] + bool _OverrideWindZoneWindDirection; + + [Tooltip("Base wind direction in degrees.\n\nControls wave conditions. Can be overridden on Shape* components.")] + [@Predicated(typeof(WaterRenderer), nameof(WindDirectionOverriden), inverted: true, hide: true)] + [@ShowComputedProperty(nameof(WindDirection))] + [@Range(-180, 180)] + [@GenerateAPI(Getter.Custom)] + [SerializeField] + internal float _WindDirection; + + [Tooltip("Whether to override the given wind zone's wind turbulence.")] + [@Predicated(nameof(_WindZone), hide: true)] + [@InlineToggle, SerializeField] + bool _OverrideWindZoneWindTurbulence; + + [Tooltip("Base wind turbulence.\n\nControls wave conditions. Can be overridden on ShapeFFT components.")] + [@Predicated(typeof(WaterRenderer), nameof(WindTurbulenceOverriden), inverted: true, hide: true)] + [@ShowComputedProperty(nameof(WindTurbulence))] + [@Range(0, 1)] + [@GenerateAPI(Getter.Custom)] + [SerializeField] + internal float _WindTurbulence = 0.145f; + + [@Space(10)] + [Tooltip("Provide your own gravity value instead of Physics.gravity.")] [@GenerateAPI] - [@DecoratedField, SerializeField] + [@InlineToggle, SerializeField] bool _OverrideGravity; [@Label("Gravity")] @@ -71,50 +113,47 @@ namespace WaveHarmonic.Crest [SerializeField] float _GravityMultiplier = 1f; + [@Space(10)] + [Tooltip("The primary light that affects the water.\n\nSetting this is optional. This should be a directional light. Defaults to RenderSettings.sun.")] [@GenerateAPI(Getter.Custom)] [@DecoratedField, SerializeField] Light _PrimaryLight; - [@Group("Surface Renderer", Group.Style.Accordian)] +#if !d_Crest_LegacyUnderwater + [@Group("Rendering", Group.Style.Accordian)] +#else + [HideInInspector] +#endif - [Tooltip("The water chunk renderers will have this layer.")] - [@Layer] + [Tooltip("When in the render pipeline the water is rendered.\n\nDefault is the old behaviour which is controlled by Unity.\n\nBefore Transparency has advantages like being compatible with soft particles, refractive shaders, and possibly third-party atmospheric fog.")] [@GenerateAPI] - [SerializeField] - int _Layer = 4; // Water - - [Tooltip("Material to use for the water surface.")] - [@AttachMaterialEditor] - [@MaterialField("Crest/Water", name: "Water", title: "Create Water Material")] - [@GenerateAPI] - [SerializeField] - internal Material _Material = null; - - [Tooltip("Underwater will copy from this material if set.\n\nUseful for overriding properties for the underwater effect. To see what properties can be overriden, see the disabled properties on the underwater material. This does not affect the surface.")] - [@AttachMaterialEditor] - [@MaterialField("Crest/Water", name: "Water (Below)", title: "Create Water Material", parent: "_Material")] - [@GenerateAPI] - [SerializeField] - internal Material _VolumeMaterial = null; - - [Tooltip("Template for water chunks as a prefab.\n\nThe only requirements are that the prefab must contain a MeshRenderer at the root and not a MeshFilter or WaterChunkRenderer. MR values will be overwritten where necessary and the prefabs are linked in edit mode.")] - [@PrefabField(title: "Create Chunk Prefab", name: "Water Chunk")] - [SerializeField] - internal GameObject _ChunkTemplate; + [@DecoratedField, SerializeField] + WaterInjectionPoint _InjectionPoint; +#if !d_Crest_LegacyUnderwater [@Space(10)] +#else + [@Group("Rendering", Group.Style.Accordian)] +#endif - [Tooltip("Have the water surface cast shadows for albedo (both foam and custom).")] - [@Predicated(RenderPipeline.Legacy, inverted: true, hide: true)] + [@Label("Color Texture")] + [Tooltip("Whether to write the water surface color to the color/opaque texture.\n\nThis is likely only beneficial if the water injection point is before transparency, and there are shaders which need it (like refraction).")] + [@Predicated(nameof(_InjectionPoint), inverted: false, nameof(WaterInjectionPoint.Default))] [@GenerateAPI(Getter.Custom)] [@DecoratedField, SerializeField] - internal bool _CastShadows; + internal bool _WriteToColorTexture = true; + + [@Label("Depth Texture")] + [Tooltip("Whether to write the water surface depth to the depth texture.\n\nThe water surface writes to the depth buffer, but Unity does not copy it to the depth texture for post-processing effects like Depth of Field (or refraction). This will copy the depth buffer to the depth texture.\n\nIf the water injection point is in the transparent pass, be wary that it will include all transparent objects that write to depth. Furthermore, other third parties may already be doing this, and we do not check whether it is necessary to copy or not.\n\nThis feature has a considerable overhead if using the built-in render pipeline, as it requires rendering the surface depth another time.")] + [@Predicated(nameof(_Surface) + "." + nameof(SurfaceRenderer._Enabled))] + [@GenerateAPI(Getter.Custom)] + [@DecoratedField, SerializeField] + internal bool _WriteToDepthTexture = true; [@Label("Motion Vectors")] [Tooltip("Whether to enable motion vector support.")] - [@Predicated(RenderPipeline.Legacy, inverted: true, hide: true)] #if !UNITY_6000_0_OR_NEWER [@Predicated(RenderPipeline.Universal, inverted: true, hide: true)] #endif @@ -122,36 +161,28 @@ namespace WaveHarmonic.Crest [@DecoratedField, SerializeField] internal bool _WriteMotionVectors = true; - [Tooltip("Whether to write the water surface depth to the depth texture (URP only).\n\nThe water surface writes to the depth buffer, but Unity does not copy it to the depth texture for post-processing effects like Depth of Field. This will copy the depth buffer to the depth texture.\n\nBe wary that it will include all transparent objects that write to depth. Furthermore, other third parties may already be doing this, and we do not check whether it is necessary to copy or not.")] - [@Predicated(RenderPipeline.Universal, hide: true)] + [@Space(10)] + + [Tooltip("Whether to override the automatic detection of framebuffer HDR rendering (BIRP only).\n\nRendering using HDR formats is optional, but there is no way for us to determine if HDR rendering is enabled in the Graphics Settings. We make an educated based on which platform is the target. If you see rendering issues, try disabling this.\n\n This has nothing to do with having an HDR monitor.")] + [@Predicated(RenderPipeline.Legacy, hide: true)] + [@GenerateAPI] + [@InlineToggle, SerializeField] + bool _OverrideRenderHDR; + + [Tooltip("Force HDR format usage (BIRP only).\n\nIf enabled, we assume the framebuffer is an HDR format, otherwise an LDR format.")] + [@Predicated(RenderPipeline.Legacy, hide: true)] + [@Predicated(nameof(_OverrideRenderHDR))] [@GenerateAPI] [@DecoratedField, SerializeField] - internal bool _WriteToDepthTexture = true; + bool _RenderHDR = true; - [@Heading("Culling")] - [Tooltip("Whether 'Water Body' components will cull the water tiles.\n\nDisable if you want to use the 'Material Override' feature and still have an ocean.")] - [@GenerateAPI] - [@DecoratedField, SerializeField] - bool _WaterBodyCulling = true; + [@Group(isCustomFoldout: true)] - [Tooltip("How many frames to distribute the chunk bounds calculation.\n\nThe chunk bounds are calculated per frame to ensure culling is correct when using inputs that affect displacement. Some performance can be saved by distributing the load over several frames. The higher the frames, the longer it will take - lowest being instant.")] - [@Range(1, 30, Range.Clamp.Minimum)] - [@GenerateAPI] - [SerializeField] - int _TimeSliceBoundsUpdateFrameCount = 1; - - [@Heading("Advanced")] - - [Tooltip("How to handle self-intersections of the water surface.\n\nThey can be caused by choppy waves which can cause a flipped underwater effect. When not using the portals/volumes, this fix is only applied when within 2 metres of the water surface. Automatic will disable the fix if portals/volumes are used which is the recommend setting.")] - [@DecoratedField, SerializeField] - SurfaceSelfIntersectionFixMode _SurfaceSelfIntersectionFixMode = SurfaceSelfIntersectionFixMode.Automatic; - - [Tooltip("Whether to allow sorting using the render queue.\n\nIf you need to change the minor part of the render queue (eg +100), then enable this option. As a side effect, it will also disable the front-to-back rendering optimization for Crest. This option does not affect changing the major part of the render queue (eg AlphaTest, Transparent), as that is always allowed.\n\nRender queue sorting is required for some third-party integrations.")] - [@Predicated(RenderPipeline.HighDefinition, inverted: true, hide: true)] - [@GenerateAPI] - [@DecoratedField, SerializeField] - bool _AllowRenderQueueSorting; + [Tooltip("The water surface renderer.")] + [@GenerateAPI(Setter.None)] + [@DecoratedField(isCustomFoldout: true), SerializeReference] + SurfaceRenderer _Surface = new(); [@Group("Level of Detail", Group.Style.Accordian)] @@ -174,7 +205,7 @@ namespace WaveHarmonic.Crest [@Range(2, Lod.k_MaximumSlices)] [@GenerateAPI(name: "LodLevels")] [SerializeField] - int _Slices = 7; + int _Slices = 9; [@Label("Resolution")] [Tooltip("The resolution of the various water LOD data.\n\nThis includes mesh density, displacement textures, foam data, dynamic wave simulation, etc. Sets the 'detail' present in the water - larger values give more detail at increased run-time expense. This value can be overriden per LOD in their respective settings except for Animated Waves which is tied to this value.")] @@ -204,6 +235,12 @@ namespace WaveHarmonic.Crest [@DecoratedField, SerializeField] Transform _Viewpoint; + [@Label("Displacement Correction")] + [Tooltip("Keep the center of detail from drifting from the viewpoint.\n\nLarge horizontal displacement can displace the center of detail. This uses queries to keep the center of detail aligned.")] + [@GenerateAPI] + [@DecoratedField, SerializeField] + bool _CenterOfDetailDisplacementCorrection = true; + [Tooltip("Also checks terrain height when determining the scale.\n\nThe scale is changed based on the viewer's height above the water surface. This can be a problem with varied water level, as the viewer may not be directly over the higher water level leading to a height difference, and thus incorrect scale.")] [Predicated(nameof(_Viewpoint), inverted: true)] [@GenerateAPI] @@ -307,6 +344,14 @@ namespace WaveHarmonic.Crest internal UnderwaterRenderer _Underwater = new(); + [@Group(isCustomFoldout: true)] + + [Tooltip("The meniscus module.")] + [@GenerateAPI(Setter.None)] + [@DecoratedField(isCustomFoldout: true), SerializeReference] + internal Meniscus _Meniscus = new(); + + #if !d_CrestPortals // Hide if package is not present. Fallback to dummy script. [HideInInspector] @@ -372,18 +417,6 @@ namespace WaveHarmonic.Crest public bool _DestroyResourcesInOnDisable; #if CREST_DEBUG - [Tooltip("Whether to disable chunk generation.")] - [@DecoratedField, SerializeField] - public bool _DisableChunks; - - [Tooltip("Whether to generate water geometry tiles uniformly (with overlaps).")] - [@DecoratedField, SerializeField] - public bool _UniformTiles; - - [Tooltip("Disable generating a wide strip of triangles at the outer edge to extend water to edge of view frustum.")] - [@DecoratedField, SerializeField] - public bool _DisableSkirt; - [@DecoratedField, SerializeField] public bool _DrawLodOutline; @@ -416,10 +449,6 @@ namespace WaveHarmonic.Crest [@Heading("Server")] - [Tooltip("Emulate batch mode which models running without a display (but with a GPU available). Equivalent to running standalone build with -batchmode argument.")] - [@DecoratedField, SerializeField] - public bool _ForceBatchMode; - [Tooltip("Emulate running on a client without a GPU. Equivalent to running standalone with -nographics argument.")] [@DecoratedField, SerializeField] public bool _ForceNoGraphics; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Universal.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Universal.cs index f767fc349..3280db98e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Universal.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.Universal.cs @@ -1,8 +1,13 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityURP +#if !UNITY_6000_3_OR_NEWER +#define URP_COMPATIBILITY_MODE +#endif + +using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; @@ -12,98 +17,26 @@ namespace WaveHarmonic.Crest // Universal Render Pipeline partial class WaterRenderer { - sealed class ConfigureUniversalRenderer : ScriptableRenderPass + internal const RenderPassEvent k_WaterRenderPassEvent = RenderPassEvent.BeforeRenderingTransparents; + + internal sealed class CopyTargetsRenderPass : ScriptableRenderPass { readonly WaterRenderer _Water; - public static ConfigureUniversalRenderer Instance { get; set; } - - public ConfigureUniversalRenderer(WaterRenderer water) - { - _Water = water; - renderPassEvent = RenderPassEvent.BeforeRenderingTransparents; - ConfigureInput(ScriptableRenderPassInput.Color | ScriptableRenderPassInput.Depth); - } - - public static void Enable(WaterRenderer water) - { -#if UNITY_EDITOR - var data = water.Viewer != null ? water.Viewer.GetUniversalAdditionalCameraData() : null; - - // Type is internal. - if (data != null && data.scriptableRenderer.GetType().Name == "Renderer2D") - { - UnityEditor.EditorUtility.DisplayDialog - ( - "Crest Error!", - "The project has been detected as a URP 2D project. Crest only supports 3D projects. " + - "You may see errors from Crest in the console, and other issues.", - "Ok" - ); - } -#endif - - Instance = new ConfigureUniversalRenderer(water); - RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; - RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; - } - - public static void Disable() - { - RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; - } - - static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) - { - // May cause assertions/exceptions for reflection camera. - if (camera.cameraType == CameraType.Reflection) return; - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, Instance._Water.Layer)) - { - return; - } - - // TODO: Could also check RenderType. Which is better? - if (!Instance._Water.Material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")) - { - return; - } - - camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(Instance); - } - -#if UNITY_6000_0_OR_NEWER - sealed class PassData { } - - public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) - { - using (var builder = graph.AddUnsafePass("Crest Register Color/Depth Requirements.", out var data)) - { - builder.AllowPassCulling(false); - builder.SetRenderFunc((data, context) => { }); - } - } - - [System.Obsolete] -#endif - public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) - { - // Blank - } - } - - internal sealed class UniversalCopyWaterSurfaceDepth : ScriptableRenderPass - { - readonly WaterRenderer _Water; - public static UniversalCopyWaterSurfaceDepth Instance { get; set; } + public static CopyTargetsRenderPass Instance { get; set; } readonly UnityEngine.Rendering.Universal.Internal.CopyDepthPass _CopyDepthPass; readonly Shader _CopyDepthShader; readonly Material _CopyDepthMaterial; - public UniversalCopyWaterSurfaceDepth(WaterRenderer water) + static readonly System.Reflection.FieldInfo s_OpaqueColor = typeof(UniversalRenderer).GetField("m_OpaqueColor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + static readonly System.Reflection.FieldInfo s_ActiveRenderPassQueue = typeof(ScriptableRenderer).GetField("m_ActiveRenderPassQueue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + readonly UnityEngine.Rendering.Universal.Internal.CopyColorPass _CopyColorPass; + readonly Material _CopyColorMaterial; + readonly Material _SampleColorMaterial; + + public CopyTargetsRenderPass(WaterRenderer water) { _Water = water; - renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; _CopyDepthShader = Shader.Find("Hidden/Universal Render Pipeline/CopyDepth"); #if !UNITY_6000_0_OR_NEWER @@ -112,7 +45,7 @@ namespace WaveHarmonic.Crest _CopyDepthPass = new ( - RenderPassEvent.BeforeRenderingPostProcessing, + renderPassEvent, #if UNITY_6000_0_OR_NEWER _CopyDepthShader, #else @@ -122,52 +55,77 @@ namespace WaveHarmonic.Crest copyToDepth: true, copyResolvedDepth: RenderingUtils.MultisampleDepthResolveSupported(), shouldClear: false +#if UNITY_6000_0_OR_NEWER + , customPassName: "Crest.DrawWater" +#endif + ); + + _CopyColorMaterial = new(Shader.Find("Hidden/Universal/CoreBlit")); + _SampleColorMaterial = new(Shader.Find("Hidden/Universal Render Pipeline/Sampling")); + + _CopyColorPass = new + ( + renderPassEvent, + _SampleColorMaterial, + _CopyColorMaterial +#if UNITY_6000_0_OR_NEWER + , customPassName: "Crest.DrawWater" +#endif ); } public static void Enable(WaterRenderer water) { - Instance = new UniversalCopyWaterSurfaceDepth(water); - RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; - RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; + Instance = new(water); } - public static void Disable() + internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { - RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; - } + var water = _Water; - static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) - { - // May cause assertions/exceptions for reflection camera. - if (camera.cameraType == CameraType.Reflection) return; - - if (!Instance._Water._WriteToDepthTexture) + if (!ShouldRender(camera, water.Surface.Layer)) { return; } - if (!Helpers.MaskIncludesLayer(camera.cullingMask, Instance._Water.Layer)) + // Our reflections do not need them. + if (camera == WaterReflections.CurrentCamera) + { + return; + } + + + if (!water.WriteToColorTexture && !water.WriteToDepthTexture) + { + return; + } + + if (water.Surface.Material == null) { return; } // TODO: Could also check RenderType. Which is better? - if (!Instance._Water.Material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")) + if (!SurfaceRenderer.IsTransparent(water.Surface.Material)) { return; } + renderPassEvent = water.RenderBeforeTransparency ? RenderPassEvent.BeforeRenderingTransparents : RenderPassEvent.AfterRenderingTransparents; + _CopyColorPass.renderPassEvent = renderPassEvent; + _CopyDepthPass.renderPassEvent = renderPassEvent; + var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer; // Needed for OnCameraSetup. - renderer.EnqueuePass(Instance); + renderer.EnqueuePass(this); #if UNITY_6000_0_OR_NEWER // Copy depth pass does not support RG directly. if (GraphicsSettings.GetRenderPipelineSettings().enableRenderCompatibilityMode) #endif { - renderer.EnqueuePass(Instance._CopyDepthPass); + if (water.WriteToColorTexture) renderer.EnqueuePass(_CopyColorPass); + if (water.WriteToDepthTexture) renderer.EnqueuePass(_CopyDepthPass); } } @@ -176,9 +134,18 @@ namespace WaveHarmonic.Crest { var resources = frame.Get(); var descriptor = resources.cameraDepthTexture.GetDescriptor(graph); - // Whether we a writing to color or depth format. - _CopyDepthPass.CopyToDepth = descriptor.colorFormat == UnityEngine.Experimental.Rendering.GraphicsFormat.None; - _CopyDepthPass.Render(graph, frame, resources.cameraDepthTexture, resources.cameraDepth); + + if (_Water.WriteToColorTexture) + { + _CopyColorPass.RenderToExistingTexture(graph, frame, resources.cameraOpaqueTexture, resources.cameraColor, UniversalRenderPipeline.asset.opaqueDownsampling); + } + + if (_Water.WriteToDepthTexture) + { + // Whether we a writing to color or depth format. + _CopyDepthPass.CopyToDepth = descriptor.colorFormat == UnityEngine.Experimental.Rendering.GraphicsFormat.None; + _CopyDepthPass.Render(graph, frame, resources.cameraDepthTexture, resources.cameraDepth); + } } [System.Obsolete] @@ -186,9 +153,20 @@ namespace WaveHarmonic.Crest public override void OnCameraSetup(CommandBuffer buffer, ref RenderingData data) { var renderer = (UniversalRenderer)data.cameraData.renderer; + var opaqueColorHandle = s_OpaqueColor.GetValue(renderer) as RTHandle; + // Also check internal RT because it can be null on Vulkan for some reason. + if (renderer.cameraColorTargetHandle?.rt != null && opaqueColorHandle?.rt != null) + { + _CopyColorPass.Setup(renderer.cameraColorTargetHandle, opaqueColorHandle, UniversalRenderPipeline.asset.opaqueDownsampling); + } + else + { + var queue = s_ActiveRenderPassQueue.GetValue(renderer) as List; + queue.Remove(_CopyColorPass); + } - +#if URP_COMPATIBILITY_MODE // Also check internal RT because it can be null on Vulkan for some reason. if (renderer.cameraDepthTargetHandle?.rt != null && renderer.m_DepthTexture?.rt != null) { @@ -197,6 +175,12 @@ namespace WaveHarmonic.Crest _CopyDepthPass.m_CopyResolvedDepth = false; _CopyDepthPass.Setup(renderer.cameraDepthTargetHandle, renderer.m_DepthTexture); } + else +#endif + { + var queue = s_ActiveRenderPassQueue.GetValue(renderer) as List; + queue.Remove(_CopyDepthPass); + } } #if UNITY_6000_0_OR_NEWER diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.WaterLevelDepth.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.WaterLevelDepth.cs index 2d6b5b960..aa7e00f56 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.WaterLevelDepth.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.WaterLevelDepth.cs @@ -1,273 +1,2 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. - -// FIXME: Broken for BIRP on MacOS. Either platform specific problem or bug in Unity. - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.Rendering.HighDefinition; -using UnityEngine.Rendering.Universal; - -namespace WaveHarmonic.Crest -{ - partial class WaterRenderer - { - CommandBuffer _WaterLevelDepthBuffer; - RenderTexture _WaterLevelDepthTexture; - internal RenderTexture WaterLevelDepthTexture => _WaterLevelDepthTexture; - RenderTargetIdentifier _WaterLevelDepthTarget; - Material _WaterLevelDepthMaterial; - internal readonly Plane[] _CameraFrustumPlanes = new Plane[6]; - - const string k_WaterLevelDepthTextureName = "Crest Water Level Depth Texture"; - - void RenderWaterSurface(CommandBuffer buffer, Camera camera, Material material) - { - GeometryUtility.CalculateFrustumPlanes(camera, _CameraFrustumPlanes); - - // Spends approx 0.2-0.3ms here on 2018 Dell XPS 15. - foreach (var chunk in Chunks) - { - var renderer = chunk.Rend; - // Can happen in edit mode. - if (renderer == null) continue; - - var bounds = renderer.bounds; - if (GeometryUtility.TestPlanesAABB(_CameraFrustumPlanes, bounds)) - { - if ((!chunk._WaterDataHasBeenBound) && chunk.enabled) - { - chunk.Bind(camera); - } - - renderer.SetPropertyBlock(chunk._MaterialPropertyBlock); - - // Assume correct pass is zero. Use to be k_ShaderPassWaterSurfaceMask. - buffer.DrawRenderer(renderer, material, submeshIndex: 0, shaderPass: 0); - } - - chunk._WaterDataHasBeenBound = false; - } - } - - void ExecuteWaterLevelDepthTexture(Camera camera, CommandBuffer buffer) - { - Helpers.CreateRenderTargetTextureReference(ref _WaterLevelDepthTexture, ref _WaterLevelDepthTarget); - _WaterLevelDepthTexture.name = k_WaterLevelDepthTextureName; - - if (_WaterLevelDepthMaterial == null) - { - _WaterLevelDepthMaterial = new(Shader.Find("Hidden/Crest/Editor/Water Level (Depth)")); - } - - var descriptor = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight) - { - graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.None, - depthBufferBits = 32, - }; - - // Depth texture. - // Always release to handle screen size changes. - _WaterLevelDepthTexture.Release(); - descriptor.graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat; - descriptor.depthBufferBits = 0; - Helpers.SafeCreateRenderTexture(ref _WaterLevelDepthTexture, descriptor); - _WaterLevelDepthTexture.Create(); - - // Depth buffer. - buffer.GetTemporaryRT(Helpers.ShaderIDs.s_MainTexture, descriptor); - buffer.SetRenderTarget(Helpers.ShaderIDs.s_MainTexture); - buffer.ClearRenderTarget(true, false, Color.clear); - - RenderWaterSurface(buffer, camera, _WaterLevelDepthMaterial); - - // Convert. - Helpers.Blit(buffer, _WaterLevelDepthTarget, Helpers.UtilityMaterial, (int)Helpers.UtilityPass.Copy); - - buffer.ReleaseTemporaryRT(Helpers.ShaderIDs.s_MainTexture); - - } - - void EnableWaterLevelDepthTexture() - { - if (Application.isPlaying) return; - -#if d_UnityURP - if (RenderPipelineHelper.IsUniversal) - { - WaterLevelDepthTextureURP.Enable(); - } -#endif - -#if d_UnityHDRP - if (RenderPipelineHelper.IsHighDefinition) - { - WaterLevelDepthTextureHDRP.Enable(); - } -#endif - } - - void DisableWaterLevelDepthTexture() - { - if (Application.isPlaying) return; - -#if d_UnityURP - WaterLevelDepthTextureURP.Disable(); -#endif - -#if d_UnityHDRP - WaterLevelDepthTextureHDRP.Disable(); -#endif - } - - void OnPreRenderWaterLevelDepthTexture(Camera camera) - { - if (camera.cameraType != CameraType.SceneView || camera != Viewer) - { - return; - } - - _WaterLevelDepthBuffer ??= new() { name = k_WaterLevelDepthTextureName }; - _WaterLevelDepthBuffer.Clear(); - - ExecuteWaterLevelDepthTexture(camera, _WaterLevelDepthBuffer); - - // Both forward and deferred. - camera.AddCommandBuffer(CameraEvent.BeforeDepthTexture, _WaterLevelDepthBuffer); - camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, _WaterLevelDepthBuffer); - } - - void OnPostRenderWaterLevelDepthTexture(Camera camera) - { - if (_WaterLevelDepthBuffer != null) - { - // Both forward and deferred. - camera.RemoveCommandBuffer(CameraEvent.BeforeDepthTexture, _WaterLevelDepthBuffer); - camera.RemoveCommandBuffer(CameraEvent.BeforeGBuffer, _WaterLevelDepthBuffer); - } - } - -#if d_UnityURP - sealed class WaterLevelDepthTextureURP : ScriptableRenderPass - { - static WaterLevelDepthTextureURP s_Instance; - - internal WaterLevelDepthTextureURP() - { - // Will always execute and matrices will be ready. - renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses; - } - - internal static void Enable() - { - s_Instance ??= new(); - - RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; - RenderPipelineManager.beginCameraRendering += s_Instance.EnqueuePass; - RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; - RenderPipelineManager.activeRenderPipelineTypeChanged += Disable; - } - - internal static void Disable() - { - // FIXME: Out of range exception when no null check but shouldn't be necessary. - if (s_Instance != null) RenderPipelineManager.beginCameraRendering -= s_Instance.EnqueuePass; - RenderPipelineManager.activeRenderPipelineTypeChanged -= Disable; - } - - void EnqueuePass(ScriptableRenderContext context, Camera camera) - { - if (camera.cameraType != CameraType.SceneView || camera != Instance.Viewer) - { - return; - } - - // Enqueue the pass. This happens every frame. - camera.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(this); - } - -#if UNITY_6000_0_OR_NEWER - class PassData - { - public UniversalCameraData _CameraData; - } - - public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame) - { - using (var builder = graph.AddUnsafePass(k_WaterLevelDepthTextureName, out var data)) - { - builder.AllowPassCulling(false); - - data._CameraData = frame.Get(); - - builder.SetRenderFunc((data, context) => - { - var buffer = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd); - Instance.ExecuteWaterLevelDepthTexture(data._CameraData.camera, buffer); - }); - } - } - - [System.Obsolete] -#endif - public override void Execute(ScriptableRenderContext context, ref RenderingData data) - { - var buffer = CommandBufferPool.Get(k_WaterLevelDepthTextureName); - Instance.ExecuteWaterLevelDepthTexture(data.cameraData.camera, buffer); - context.ExecuteCommandBuffer(buffer); - CommandBufferPool.Release(buffer); - } - } -#endif - -#if d_UnityHDRP - sealed class WaterLevelDepthTextureHDRP : CustomPass - { - static WaterLevelDepthTextureHDRP s_Instance; - GameObject _GameObject; - - internal static void Enable() - { - var gameObject = CustomPassHelpers.CreateOrUpdate - ( - parent: Instance.Container.transform, - k_WaterLevelDepthTextureName, - hide: !Instance._Debug._ShowHiddenObjects - ); - - CustomPassHelpers.CreateOrUpdate - ( - gameObject, - ref s_Instance, - k_WaterLevelDepthTextureName, - CustomPassInjectionPoint.BeforeRendering - ); - - s_Instance._GameObject = gameObject; - } - - public static void Disable() - { - // It should be safe to rely on this reference for this reference to fail. - if (s_Instance != null && s_Instance._GameObject != null) - { - // Will also trigger Cleanup below. - s_Instance._GameObject.SetActive(false); - } - } - - protected override void Execute(CustomPassContext context) - { - var camera = context.hdCamera.camera; - - if (camera.cameraType != CameraType.SceneView || camera != Instance.Viewer) - { - return; - } - - Instance.ExecuteWaterLevelDepthTexture(camera, context.cmd); - } - } -#endif - } -} diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.cs index f8e0c5af2..be3ba8393 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterRenderer.cs @@ -1,11 +1,10 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; -using UnityEngine.Rendering.HighDefinition; using WaveHarmonic.Crest.Internal; using WaveHarmonic.Crest.RelativeSpace; using WaveHarmonic.Crest.Utility; @@ -22,10 +21,9 @@ namespace WaveHarmonic.Crest /// public sealed partial class WaterRenderer : ManagerBehaviour { - [SerializeField, HideInInspector] -#pragma warning disable 414 - int _Version = 0; -#pragma warning restore 414 + internal const string k_RunUpdateMarker = "Crest.WaterRenderer.RunUpdate"; + + static readonly Unity.Profiling.ProfilerMarker s_RunUpdateMarker = new(k_RunUpdateMarker); internal static partial class ShaderIDs { @@ -37,15 +35,15 @@ namespace WaveHarmonic.Crest public static readonly int s_LodChange = Shader.PropertyToID("g_Crest_LodChange"); public static readonly int s_MeshScaleLerp = Shader.PropertyToID("g_Crest_MeshScaleLerp"); public static readonly int s_LodCount = Shader.PropertyToID("g_Crest_LodCount"); - public static readonly int s_LodAlphaBlackPointFade = Shader.PropertyToID("g_Crest_LodAlphaBlackPointFade"); - public static readonly int s_LodAlphaBlackPointWhitePointFade = Shader.PropertyToID("g_Crest_LodAlphaBlackPointWhitePointFade"); - public static readonly int s_ForceUnderwater = Shader.PropertyToID("g_Crest_ForceUnderwater"); // Shader Properties public static readonly int s_AbsorptionColor = Shader.PropertyToID("_Crest_AbsorptionColor"); public static readonly int s_Absorption = Shader.PropertyToID("_Crest_Absorption"); public static readonly int s_Scattering = Shader.PropertyToID("_Crest_Scattering"); public static readonly int s_Anisotropy = Shader.PropertyToID("_Crest_Anisotropy"); + public static readonly int s_AmbientTerm = Shader.PropertyToID("_Crest_AmbientTerm"); + public static readonly int s_DirectTerm = Shader.PropertyToID("_Crest_DirectTerm"); + public static readonly int s_ShadowsAffectsAmbientFactor = Shader.PropertyToID("_Crest_ShadowsAffectsAmbientFactor"); public static readonly int s_PlanarReflectionsEnabled = Shader.PropertyToID("_Crest_PlanarReflectionsEnabled"); public static readonly int s_Occlusion = Shader.PropertyToID("_Crest_Occlusion"); public static readonly int s_OcclusionUnderwater = Shader.PropertyToID("_Crest_OcclusionUnderwater"); @@ -56,16 +54,6 @@ namespace WaveHarmonic.Crest // Underwater public static readonly int s_VolumeExtinctionLength = Shader.PropertyToID("_Crest_VolumeExtinctionLength"); - - - // High Definition Render Pipeline - public static readonly int s_PrimaryLightDirection = Shader.PropertyToID("g_Crest_PrimaryLightDirection"); - public static readonly int s_PrimaryLightIntensity = Shader.PropertyToID("g_Crest_PrimaryLightIntensity"); - - // URP Motion Vectors - public static readonly int s_Surface = Shader.PropertyToID("_Surface"); - public static readonly int s_SrcBlend = Shader.PropertyToID("_SrcBlend"); - public static readonly int s_DstBlend = Shader.PropertyToID("_DstBlend"); } @@ -97,10 +85,10 @@ namespace WaveHarmonic.Crest return null; } - Camera GetViewer() + internal Camera GetViewer(bool includeSceneCamera = true) { #if UNITY_EDITOR - if (!Application.isPlaying && _FollowSceneCamera && SceneView.lastActiveSceneView != null && IsSceneViewActive) + if (includeSceneCamera && !Application.isPlaying && _FollowSceneCamera && SceneView.lastActiveSceneView != null && IsSceneViewActive) { return SceneView.lastActiveSceneView.camera; } @@ -118,6 +106,8 @@ namespace WaveHarmonic.Crest // Cache the ViewCamera property for internal use. Camera _ViewCameraCached; + readonly SampleCollisionHelper _CenterOfDetailDisplacementCorrectionHelper = new(); + // // Viewer Height @@ -152,7 +142,7 @@ namespace WaveHarmonic.Crest readonly SampleCollisionHelper _SampleHeightHelper = new(); readonly SampleDepthHelper _SampleDepthHelper = new(); - float _ViewerHeightAboveWaterPerCamera; + internal float _ViewerHeightAboveWaterPerCamera; readonly SampleCollisionHelper _SampleHeightHelperPerCamera = new(); @@ -172,22 +162,44 @@ namespace WaveHarmonic.Crest #endif // - // Serialized Fields + // Wind // internal float WindSpeedKPH => _WindSpeed; + bool WindSpeedOverriden => _WindZone == null || _OverrideWindZoneWindSpeed; + bool WindDirectionOverriden => _WindZone == null || _OverrideWindZoneWindDirection; + bool WindTurbulenceOverriden => _WindZone == null || _OverrideWindZoneWindTurbulence; + + float GetWindSpeed() + { + return _OverrideWindZoneWindSpeed || _WindZone == null ? _WindSpeed : _WindZone.windMain * 3.6f; + } + + float GetWindDirection() + { + var wind = _WindZone != null ? _WindZone.transform : null; + return _OverrideWindZoneWindDirection || wind == null + ? _WindDirection + : Mathf.Atan2(wind.forward.z, wind.forward.x) * Mathf.Rad2Deg; + } + + float GetWindTurbulence() + { + return _OverrideWindZoneWindTurbulence || _WindZone == null ? _WindTurbulence : _WindZone.windTurbulence; + } + // // Transform // - internal Transform Root { get; private set; } + internal Vector3 Position { get; private set; } internal GameObject Container { get; private set; } /// /// Sea level is given by y coordinate of GameObject with WaterRenderer script. /// - public float SeaLevel => Root.position.y; + public float SeaLevel => Position.y; // Anything higher (minus 1 for near plane) will be clipped. const float k_RenderAboveSeaLevel = 10000f; @@ -248,34 +260,72 @@ namespace WaveHarmonic.Crest // Rendering // - internal Material AboveOrBelowSurfaceMaterial => _VolumeMaterial == null ? _Material : _VolumeMaterial; + // Used as an extra check to prevent null exceptions, as the events raised when an + // RP change happen too late for some things. + RenderPipeline _SetUpFor; -#if UNITY_6000_0_OR_NEWER - internal Material _MotionVectorsMaterial; + internal bool RenderBeforeTransparency => +#if d_Crest_LegacyUnderwater + false; +#else + _InjectionPoint == WaterInjectionPoint.BeforeTransparent; #endif - enum SurfaceSelfIntersectionFixMode - { - Off, - ForceBelowWater, - ForceAboveWater, - On, - Automatic, - } - #if d_CrestPortals - bool Portaled => _Portals.Active; + internal bool Portaled => _Portals.Active; #else - bool Portaled => false; + internal bool Portaled => false; #endif - bool GetCastShadows() => _CastShadows && !RenderPipelineHelper.IsLegacy; - bool GetWriteMotionVectors() => _WriteMotionVectors && -#if UNITY_6000_0_OR_NEWER - !RenderPipelineHelper.IsLegacy; -#else - RenderPipelineHelper.IsHighDefinition; + internal MaskRenderer _Mask; + + // Flags + bool _DonePerCameraHeight; + + bool GetWriteMotionVectors() => +#if !UNITY_6000_0_OR_NEWER + !RenderPipelineHelper.IsUniversal && #endif + _WriteMotionVectors; + + bool GetWriteToColorTexture() + { + return (_WriteToColorTexture && RenderBeforeTransparency) || Meniscus.RequiresOpaqueTexture; + } + + bool GetWriteToDepthTexture() + { + return _WriteToDepthTexture && Surface.Enabled; + } + + internal static bool ShouldRender(Camera camera) + { +#if UNITY_EDITOR + // Preview camera are for preview game view, preview panes, material previews etc. + if (camera.cameraType == CameraType.Preview) + { + return false; + } +#endif + + return true; + } + + internal static bool ShouldRender(Camera camera, int layer) + { + if (!ShouldRender(camera)) + { + return false; + } + + if (!Helpers.MaskIncludesLayer(camera.cullingMask, layer)) + { + return false; + } + + return true; + } + // // Material @@ -320,20 +370,6 @@ namespace WaveHarmonic.Crest internal List Simulations { get; } = new(); - // - // Water Chunks - // - - internal List Chunks { get; } = new(); - - - // - // Water Chunk Culling - // - - bool _CanSkipCulling; - - // // Instance // @@ -373,17 +409,14 @@ namespace WaveHarmonic.Crest /// /// Is runtime environment non-interactive (not displaying to user). /// - public static bool RunningHeadless => Application.isBatchMode || (Instance != null && Instance._Debug._ForceBatchMode); - - internal bool IsRunningHeadless => Application.isBatchMode || _Debug._ForceBatchMode; + [System.Obsolete("We no longer care whether Unity is running in non-interactive mode.")] + public static bool RunningHeadless => false; // // Frame Timing // - internal int LastUpdateFrame { get; private set; } = -1; - /// /// The frame count for Crest. /// @@ -409,28 +442,22 @@ namespace WaveHarmonic.Crest // Level of Detail // - // We are computing these values to be optimal based on the base mesh vertex density. - float _LodAlphaBlackPointFade; - float _LodAlphaBlackPointWhitePointFade; - + internal const string k_DrawLodData = "Crest.LodData"; internal CommandBuffer SimulationBuffer { get; private set; } + // Scale, Weight, MaximumWaveLength, Unused internal BufferedData _CascadeData; - internal struct PerCascadeInstanceData - { - public float _MeshScaleLerp; - public float _FarNormalsWeight; - public float _GeometryGridWidth; - public Vector2 _NormalScrollSpeeds; - } - - internal BufferedData _PerCascadeInstanceData; internal int BufferSize { get; private set; } internal float MaximumWavelength(int slice) { - var maximumDiameter = 4f * Scale * Mathf.Pow(2f, slice); + return MaximumWavelength(CalcLodScale(slice)); + } + + internal float MaximumWavelength(float scale) + { + var maximumDiameter = 4f * scale; // TODO: Do we need to pass in resolution? Could resolution mismatch with animated // and dynamic waves be an issue? var maximumTexelSize = maximumDiameter / LodResolution; @@ -453,11 +480,11 @@ namespace WaveHarmonic.Crest /// /// Could the water horizontal scale increase (for e.g. if the viewpoint gains altitude). Will be false if water already at maximum scale. /// - internal bool ScaleCouldIncrease => _ScaleRange.y < Mathf.Infinity || Root.localScale.x < _ScaleRange.y * 0.99f; + internal bool ScaleCouldIncrease => _ScaleRange.y == Mathf.Infinity || Scale < _ScaleRange.y * 0.99f; /// /// Could the water horizontal scale decrease (for e.g. if the viewpoint drops in altitude). Will be false if water already at minimum scale. /// - internal bool ScaleCouldDecrease => Root.localScale.x > _ScaleRange.x * 1.01f; + internal bool ScaleCouldDecrease => Scale > _ScaleRange.x * 1.01f; internal int ScaleDifferencePower2 { get; private set; } @@ -517,15 +544,30 @@ namespace WaveHarmonic.Crest { base.Initialize(); + _SetUpFor = RenderPipelineHelper.RenderPipeline; + _IsFirstFrameSinceEnabled = true; _ViewCameraCached = Viewer; + // Recompiled in play mode. + if (_Mask == null) + { + _Initialized = false; + } + if (_Initialized) { Enable(); return; } + Utility.RTHandles.Initialize(); + + _Mask = MaskRenderer.Instantiate(this); + + Meniscus.Initialize(this); + + Surface._Water = this; _Reflections._Water = this; _Reflections._UnderWater = _Underwater; _Underwater._Water = this; @@ -581,7 +623,7 @@ namespace WaveHarmonic.Crest SimulationBuffer ??= new() { - name = "Crest.LodData", + name = k_DrawLodData, }; Container = new() @@ -611,42 +653,16 @@ namespace WaveHarmonic.Crest BufferSize = Mathf.Max(BufferSize, simulation.BufferCount); } - - _PerCascadeInstanceData = new(BufferSize, () => new PerCascadeInstanceData[Lod.k_MaximumSlices]); - // The extra LOD accounts for reading off the cascade (eg CurrentIndex + LodChange + 1). _CascadeData = new(BufferSize, () => new Vector4[Lod.k_MaximumSlices + 1]); _ProjectionMatrix = new Matrix4x4[LodLevels]; - // Resolution is 4 tiles across. - var baseMeshDensity = _Resolution * 0.25f / _GeometryDownSampleFactor; - // 0.4f is the "best" value when base mesh density is 8. Scaling down from there produces results similar to - // hand crafted values which looked good when the water is flat. - _LodAlphaBlackPointFade = 0.4f / (baseMeshDensity / 8f); - // We could calculate this in the shader, but we can save two subtractions this way. - _LodAlphaBlackPointWhitePointFade = 1f - _LodAlphaBlackPointFade - _LodAlphaBlackPointFade; - -#if CREST_DEBUG - if (_Debug._DisableChunks) - { - Root = new GameObject("Root").transform; - } - else -#endif - { - Root = WaterBuilder.GenerateMesh(this, Chunks, _Resolution, _GeometryDownSampleFactor, _Slices); - } - - Root.SetParent(Container.transform, worldPositionStays: false); - if (Application.isPlaying && _Debug._AttachDebugGUI && !TryGetComponent(out _)) { gameObject.AddComponent().hideFlags = HideFlags.DontSave; } - _CanSkipCulling = false; - _GeneratedSettingsHash = CalculateSettingsHash(); // Prevent MVs from popping on first frame. @@ -656,13 +672,20 @@ namespace WaveHarmonic.Crest LateUpdateScale(); } -#if UNITY_6000_0_OR_NEWER - // Set up motion vector material. - if (RenderPipelineHelper.IsUniversal && WriteMotionVectors && _Material != null) + WritePerFrameMaterialParams(); + + if (Surface.Enabled) { - SetUpMotionVectorsMaterial(); + Surface.Initialize(); + } + + foreach (var body in WaterBody.WaterBodies) + { + if (body._Material != null) + { + Surface.UpdateMaterial(body._Material, ref body._MotionVectorMaterial); + } } -#endif Enable(); _Initialized = true; @@ -719,6 +742,19 @@ namespace WaveHarmonic.Crest { base.Enable(); +#if UNITY_EDITOR + EditorTime = Time.time; + EditorDeltaTime = 0; + + EditorApplication.update -= EditorUpdate; + EditorApplication.update += EditorUpdate; +#endif + + // Needs to be first or will get assertions etc. Unity bug likely. + RenderPipelineManager.activeRenderPipelineTypeChanged -= OnActiveRenderPipelineTypeChanged; + RenderPipelineManager.activeRenderPipelineTypeChanged += OnActiveRenderPipelineTypeChanged; + + // Needs to run even without graphics to initialize provider. foreach (var simulation in Simulations) { simulation.SetGlobals(enable: true); @@ -726,14 +762,17 @@ namespace WaveHarmonic.Crest simulation.Enable(); } + if (IsRunningWithoutGraphics) + { + // We need nothing from here on. + return; + } + #if d_WaveHarmonic_Crest_ShiftingOrigin ShiftingOrigin.OnShift -= OnOriginShift; ShiftingOrigin.OnShift += OnOriginShift; #endif - // Needs to be first or will get assertions etc. Unity bug likely. - RenderPipelineManager.activeRenderPipelineTypeChanged -= OnActiveRenderPipelineTypeChanged; - RenderPipelineManager.activeRenderPipelineTypeChanged += OnActiveRenderPipelineTypeChanged; RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; @@ -743,30 +782,64 @@ namespace WaveHarmonic.Crest // when using scene filtering. if (RenderPipelineHelper.IsLegacy) { - Camera.onPreCull -= OnPreRenderCamera; - Camera.onPreCull += OnPreRenderCamera; - Camera.onPostRender -= OnPostRenderCamera; - Camera.onPostRender += OnPostRenderCamera; + Camera.onPreCull -= OnBeginCameraRendering; + Camera.onPreCull += OnBeginCameraRendering; + Camera.onPostRender -= OnEndCameraRendering; + Camera.onPostRender += OnEndCameraRendering; } + #if d_UnityURP - else if (RenderPipelineHelper.IsUniversal) + if (RenderPipelineHelper.IsUniversal) { - ConfigureUniversalRenderer.Enable(this); - UniversalCopyWaterSurfaceDepth.Enable(this); + // Always enable as it sets requirements. + SurfaceRenderer.WaterSurfaceRenderPass.Enable(this); } #endif +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + if (RenderBeforeTransparency) + { + SurfaceRenderer.WaterSurfaceCustomPass.Enable(this); + } + + CrestInternalCopyToTextureCustomPass.Enable(this); + } + #if UNITY_EDITOR - EnableWaterLevelDepthTexture(); + if (RenderPipelineHelper.IsHighDefinition) + { + RenderPipelineManager.beginContextRendering -= OnBeginContextRendering; + RenderPipelineManager.beginContextRendering += OnBeginContextRendering; + } +#endif #endif Container.SetActive(true); + _Mask.Enable(); + if (_Underwater._Enabled) { _Underwater.OnEnable(); } + if (Meniscus.Enabled) + { + Meniscus.Enable(); + } + +#if d_UnityURP + if (RenderPipelineHelper.IsUniversal) + { + if (WriteToColorTexture || WriteToDepthTexture) + { + CopyTargetsRenderPass.Enable(this); + } + } +#endif + #if d_CrestPortals if (_Portals._Enabled) { @@ -778,123 +851,217 @@ namespace WaveHarmonic.Crest { _Reflections.OnEnable(); } - -#if UNITY_EDITOR - EditorApplication.update -= EditorUpdate; - EditorApplication.update += EditorUpdate; -#endif } - internal ScriptableRenderContext _Context; - - void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) - { -#if UNITY_EDITOR - UpdateLastActiveSceneCamera(camera); -#endif - - _Context = context; - - OnBeginCameraRendering(camera); - } + // Because we cannot pass null when using built-in render pipeline. + // Being a struct there should not be any side effects. + internal ScriptableRenderContext _Context = new(); void OnBeginCameraRendering(Camera camera) { - if (_Underwater._Enabled) - { - _Underwater.OnBeforeCameraRender(camera); - } - -#if d_UnityHDRP - // This use to be in OnBeginContextRendering with comment: - // "Most compatible with lighting options if computed here" - // Cannot remember what that meant… - if (RenderPipelineHelper.IsHighDefinition) - { - var lightDirection = Vector3.zero; - var lightIntensity = Color.black; - var sun = PrimaryLight; - - if (sun != null && sun.isActiveAndEnabled && sun.TryGetComponent(out var data)) - { - lightDirection = -sun.transform.forward; - lightIntensity = Color.clear; - - // It was reported that Light.intensity causes flickering when updated with - // HDAdditionalLightData.SetIntensity, unless we get intensity from there. - { - // Adapted from Helpers.FinalColor. - var light = data; - var linear = GraphicsSettings.lightsUseLinearIntensity; - var color = linear ? light.color.linear : light.color; -#if UNITY_6000_0_OR_NEWER - color *= sun.intensity; -#else - color *= light.intensity; -#endif - if (linear && light.useColorTemperature) color *= Mathf.CorrelatedColorTemperatureToRGB(sun.colorTemperature); - if (!linear) color = color.MaybeLinear(); - lightIntensity = linear ? color.MaybeGamma() : color; - } - - // Transmittance is for Physically Based Sky. - var hdCamera = HDCamera.GetOrCreate(camera); - var settings = SkyManager.GetSkySetting(hdCamera.volumeStack); - var transmittance = settings != null - ? settings.EvaluateAtmosphericAttenuation(lightDirection, hdCamera.camera.transform.position) - : Vector3.one; - - lightIntensity *= transmittance.x; - lightIntensity *= transmittance.y; - lightIntensity *= transmittance.z; - } - - Shader.SetGlobalVector(ShaderIDs.s_PrimaryLightDirection, lightDirection); - Shader.SetGlobalVector(ShaderIDs.s_PrimaryLightIntensity, lightIntensity); - } -#endif - - if (_Reflections._Enabled) - { - _Reflections.OnPreRenderCamera(camera); - } - - if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer)) + if (_SetUpFor != RenderPipelineHelper.RenderPipeline) { return; } - var viewpoint = camera.transform.position; - _SampleHeightHelperPerCamera.SampleHeight(System.HashCode.Combine(GetHashCode(), camera.GetHashCode()), viewpoint, out var height, allowMultipleCallsPerFrame: true); - _ViewerHeightAboveWaterPerCamera = viewpoint.y - height; + if (!_Initialized || _IsFirstFrameSinceEnabled) + { + return; + } - WritePerCameraMaterialParameters(); + Utility.RTHandles.OnBeginCameraRendering(camera); + + OnBeginCameraRendering(_Context, camera); } - void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) + // OnBeginCameraRendering or OnPreCull + void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { - OnEndCameraRendering(camera); + // Guard against being called before the RP change events are raised. + if (_SetUpFor != RenderPipelineHelper.RenderPipeline) + { + return; + } + + if (!_Initialized || _IsFirstFrameSinceEnabled) + { + return; + } + +#if UNITY_EDITOR + UpdateLastActiveSceneCamera(camera); +#endif + + if (!ShouldRender(camera)) + { + return; + } + + var noSurface = !Surface.Enabled || !Helpers.MaskIncludesLayer(camera.cullingMask, Surface.Layer); + var noVolume = !Underwater.Enabled || !Helpers.MaskIncludesLayer(camera.cullingMask, Underwater.Layer); + + // Nothing to render to this camera. + if (noSurface && noVolume) + { + return; + } + + // Must render first so that we do not overwrite work below for game camera. + // Reflections only make sense with an active surface. + if (_Reflections._Enabled && Surface.Enabled) + { + _Reflections.OnBeginCameraRendering(context, camera); + } + + if (_Mask.Enabled) + { + _Mask.OnBeginCameraRendering(camera); + } + + // Water lighting etc. +#if d_UnityHDRP + if (RenderPipelineHelper.IsHighDefinition) + { + UpdateHighDefinitionLighting(camera); + } + else +#endif + + if (RenderPipelineHelper.IsLegacy) + { + OnBeginCameraRenderingLegacy(camera); + } + + // Always execute before surface, as order is only important when rendering volume + // before surface. + if (Underwater._Enabled) + { + Underwater.OnBeginCameraRendering(context, camera); + } + +#if d_CrestPortals + // Call between volume and surface. Sets water line uniforms. + if (Portals.Enabled) + { + Portals.OnBeginCameraRendering(camera); + } +#endif + + if (Surface.Enabled) + { + Surface.OnBeginCameraRendering(context, camera); + } + +#if d_UnityURP + // Always execute after surface. + if (RenderPipelineHelper.IsUniversal) + { + CopyTargetsRenderPass.Instance?.OnBeginCameraRendering(context, camera); + } + else +#endif + + if (RenderPipelineHelper.IsLegacy) + { + OnLegacyCopyPass(camera); + } + + // Execute after copy pass in case refraction. + if (Meniscus.Enabled) + { + Meniscus.Renderer.OnBeginCameraRendering(camera); + } + + if (_ShadowLod.Enabled) + { + _ShadowLod.OnBeginCameraRendering(context, camera); + } } void OnEndCameraRendering(Camera camera) { - if (_Underwater._Enabled) + OnEndCameraRendering(_Context, camera); + } + + void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) + { + _DonePerCameraHeight = false; + +#if d_UnityHDRP + _DoneHighDefinitionLighting = false; +#endif + + if (RenderPipelineHelper.IsLegacy) { - _Underwater.OnAfterCameraRender(camera); + OnEndCameraRenderingLegacy(camera); + } + + if (_Mask.Enabled) + { + _Mask.OnEndCameraRendering(camera); + } + + if (Meniscus.Enabled) + { + Meniscus.Renderer.OnEndCameraRendering(camera); + } + + if (Underwater._Enabled) + { + Underwater.OnEndCameraRendering(camera); + } + + if (Surface.Enabled) + { + Surface.OnEndCameraRendering(camera); } if (_Reflections._Enabled) { - _Reflections.OnAfterCameraRender(camera); + _Reflections.OnEndCameraRendering(camera); } + + if (_ShadowLod.Enabled) + { + _ShadowLod.OnEndCameraRendering(camera); + } + +#if d_CrestPortals + if (_Portals.Enabled) + { + _Portals.OnEndCameraRendering(camera); + } +#endif + } + + internal void UpdatePerCameraHeight(Camera camera) + { + if (_DonePerCameraHeight) + { + return; + } + + // This will be 1-frame behind. + var viewpoint = camera.transform.position; + _SampleHeightHelperPerCamera.SampleHeight(System.HashCode.Combine(GetHashCode(), camera.GetHashCode()), viewpoint, out var height, allowMultipleCallsPerFrame: true); + _ViewerHeightAboveWaterPerCamera = viewpoint.y - height; + + _DonePerCameraHeight = true; } void OnActiveRenderPipelineTypeChanged() { + _Mask?.Destroy(); + _Mask = MaskRenderer.Instantiate(this); + + Meniscus.OnActiveRenderPipelineTypeChanged(); + if (isActiveAndEnabled) { + // Must destroy as there is still some state left like buffer count. Disable(); - Enable(); + Destroy(); + Initialize(); } } @@ -946,33 +1113,18 @@ namespace WaveHarmonic.Crest var settingsHash = Hash.CreateHash(); // Add all the settings that require rebuilding.. - Hash.AddInt(_Layer, ref settingsHash); Hash.AddInt(_Resolution, ref settingsHash); - Hash.AddInt(_GeometryDownSampleFactor, ref settingsHash); Hash.AddInt(_Slices, ref settingsHash); - Hash.AddFloat(_ExtentsSizeMultiplier, ref settingsHash); - Hash.AddBool(AllowRenderQueueSorting, ref settingsHash); - Hash.AddBool(CastShadows, ref settingsHash); Hash.AddBool(WriteMotionVectors, ref settingsHash); - Hash.AddBool(_Debug._ForceBatchMode, ref settingsHash); Hash.AddBool(_Debug._ForceNoGraphics, ref settingsHash); Hash.AddBool(_Debug._ShowHiddenObjects, ref settingsHash); -#if CREST_DEBUG - Hash.AddBool(_Debug._DisableChunks, ref settingsHash); - Hash.AddBool(_Debug._DisableSkirt, ref settingsHash); - Hash.AddBool(_Debug._UniformTiles, ref settingsHash); -#endif - if (_ChunkTemplate != null) - { - Hash.AddObject(_ChunkTemplate, ref settingsHash); - } return settingsHash; } void RunUpdate() { - UnityEngine.Profiling.Profiler.BeginSample("Crest.WaterRenderer.RunUpdate"); + s_RunUpdateMarker.Begin(this); // Rebuild if needed. Needs to run in builds (for MVs at the very least). if (CalculateSettingsHash() != _GeneratedSettingsHash) @@ -980,87 +1132,73 @@ namespace WaveHarmonic.Crest Rebuild(); } - _ViewCameraCached = Viewer; - - // Reset displacement reporting values. - // This is written to in Update, and read in LateUpdate (chunk) and LateUpdateScale. - MaximumHorizontalDisplacement = MaximumVerticalDisplacement = _MaximumVerticalDisplacementFromWaves = 0f; - - BroadcastUpdate(); - - if (!_Debug._DisableFollowViewpoint && _ViewCameraCached != null) + if (RunningWithoutGraphics) { - LateUpdatePosition(); - LateUpdateViewerHeight(); - LateUpdateScale(); + // All we need for servers. + BroadcastUpdate(); + Position = new(0f, transform.position.y, 0f); + base.LateUpdate(); } - - // Set global shader params - Shader.SetGlobalFloat(ShaderIDs.s_Time, CurrentTime); - Shader.SetGlobalFloat(ShaderIDs.s_LodCount, LodLevels); - Shader.SetGlobalFloat(ShaderIDs.s_LodAlphaBlackPointFade, _LodAlphaBlackPointFade); - Shader.SetGlobalFloat(ShaderIDs.s_LodAlphaBlackPointWhitePointFade, _LodAlphaBlackPointWhitePointFade); - - // HDRP will automatically disable this pass for the water shader for unknown reasons. It might be that we - // are sampling from the depth texture does not work with shadow casting. - if (RenderPipelineHelper.IsHighDefinition && Material != null) + else { - Material.SetShaderPassEnabled("ShadowCaster", CastShadows); - } + _ViewCameraCached = Viewer; -#if UNITY_6000_0_OR_NEWER - // Motion Vectors (URP). Shader Graph introduced the necessary toggle in U6. - if (Application.isPlaying && RenderPipelineHelper.IsUniversal && WriteMotionVectors && _Material != null) - { - if (_MotionVectorsMaterial.shader != _Material.shader) + // Reset displacement reporting values. + // This is written to in Update, and read in LateUpdate (chunk) and LateUpdateScale. + MaximumHorizontalDisplacement = MaximumVerticalDisplacement = _MaximumVerticalDisplacementFromWaves = 0f; + + BroadcastUpdate(); + + if (!_Debug._DisableFollowViewpoint && _ViewCameraCached != null) { - SetUpMotionVectorsMaterial(); + LateUpdatePosition(); + LateUpdateViewerHeight(); + LateUpdateScale(); + } + else + { + Position = new(0f, transform.position.y, 0f); } - _MotionVectorsMaterial.CopyMatchingPropertiesFromMaterial(_Material); - _MotionVectorsMaterial.renderQueue = (int)RenderQueue.Geometry; - _MotionVectorsMaterial.SetOverrideTag("RenderType", "Opaque"); - _MotionVectorsMaterial.SetFloat(ShaderIDs.s_Surface, 0); // SurfaceType.Opaque - _MotionVectorsMaterial.SetFloat(ShaderIDs.s_SrcBlend, 1); - _MotionVectorsMaterial.SetFloat(ShaderIDs.s_DstBlend, 0); - } -#endif + // Set global shader params + Shader.SetGlobalFloat(ShaderIDs.s_Time, CurrentTime); + Shader.SetGlobalFloat(ShaderIDs.s_LodCount, LodLevels); - // Needs updated transform values like scale. - WritePerFrameMaterialParams(); + // Needs updated transform values like scale. + WritePerFrameMaterialParams(); - SimulationBuffer.Clear(); - - // Construct the command buffer and attach it to the camera so that it will be executed in the render. -#if UNITY_EDITOR - if (Application.isPlaying || !_ShowWaterProxyPlane) -#endif - { - foreach (var simulation in Simulations) + // Construct the command buffer and attach it to the camera so that it will be executed in the render. { - if (!simulation.Enabled) continue; - simulation.BuildCommandBuffer(this, SimulationBuffer); - } + SimulationBuffer.Clear(); - // This will execute at the beginning of the frame before the graphics queue. - Graphics.ExecuteCommandBuffer(SimulationBuffer); + foreach (var simulation in Simulations) + { + if (!simulation.Enabled) continue; + simulation.BuildCommandBuffer(this, SimulationBuffer); + } + + // This will execute at the beginning of the frame before the graphics queue. + Graphics.ExecuteCommandBuffer(SimulationBuffer); + + foreach (var simulation in Simulations) + { + if (!simulation.Enabled) continue; + simulation.AfterExecute(); + } + } base.LateUpdate(); // Call after LateUpdate so chunk bounds are updated. - LateUpdateTiles(); - - if (_Underwater._Enabled) + if (Surface.Enabled) { - _Underwater.LateUpdate(); + Surface.LateUpdate(); } if (_Reflections._Enabled && !_Reflections.SupportsRecursiveRendering) { - _Reflections.LateUpdate(); + _Reflections.LateUpdate(_Context); } - - LastUpdateFrame = FrameCount; } // Run queries at end of update. For CollProviderBakedFFT calling this kicks off @@ -1074,133 +1212,66 @@ namespace WaveHarmonic.Crest _IsFirstFrameSinceEnabled = false; - UnityEngine.Profiling.Profiler.EndSample(); - } - - void WritePerCameraMaterialParameters() - { - if (Material != null) - { - // Override isFrontFace when camera is far enough from the water surface to fix self-intersecting waves. - // Hack - due to SV_IsFrontFace occasionally coming through as true for back faces, - // add a param here that forces water to be in underwater state. I think the root - // cause here might be imprecision or numerical issues at water tile boundaries, although - // i'm not sure why cracks are not visible in this case. - var height = _ViewerHeightAboveWaterPerCamera; - var value = (int)_SurfaceSelfIntersectionFixMode; - - switch (_SurfaceSelfIntersectionFixMode) - { - case SurfaceSelfIntersectionFixMode.On: - value = height < -2f ? 1 : height > 2f ? 2 : 0; - break; - case SurfaceSelfIntersectionFixMode.Automatic: - // Skip for portals as it is possible to see both sides of the surface at any position. - value = Portaled ? 0 : height < -2f ? 1 : height > 2f ? 2 : 0; - break; - } - - Shader.SetGlobalInteger(ShaderIDs.s_ForceUnderwater, value); - } + s_RunUpdateMarker.End(); } void WritePerFrameMaterialParams() { _CascadeData.Flip(); + var current = _CascadeData.Current; + // Update rendering parameters. { - for (var slice = 0; slice < LodLevels; slice++) + var levels = LodLevels; + + for (var slice = 0; slice < levels; slice++) { var scale = CalcLodScale(slice); - _CascadeData.Current[slice].x = scale; - _CascadeData.Current[slice].y = 1f; - _CascadeData.Current[slice].z = MaximumWavelength(slice); + current[slice] = new Vector4(scale, 1f, MaximumWavelength(scale), 0f); _ProjectionMatrix[slice] = Matrix4x4.Ortho(-2f * scale, 2f * scale, -2f * scale, 2f * scale, 1f, k_RenderAboveSeaLevel + k_RenderBelowSeaLevel); if (slice == 0) Shader.SetGlobalFloat(ShaderIDs.s_Scale, scale); } // Duplicate last element so that things can safely read off the end of the cascades - _CascadeData.Current[LodLevels] = _CascadeData.Current[LodLevels - 1]; - _CascadeData.Current[LodLevels].y = 0f; + current[levels] = current[levels - 1].XNZW(0f); } - Shader.SetGlobalVectorArray(ShaderIDs.s_CascadeData, _CascadeData.Current); + Shader.SetGlobalVectorArray(ShaderIDs.s_CascadeData, current); Shader.SetGlobalVectorArray(ShaderIDs.s_CascadeDataSource, _CascadeData.Previous(1)); - - _PerCascadeInstanceData.Flip(); - WritePerCascadeInstanceData(_PerCascadeInstanceData); } - void WritePerCascadeInstanceData(BufferedData instanceData) - { - for (var lodIdx = 0; lodIdx < LodLevels; lodIdx++) - { - // blend LOD 0 shape in/out to avoid pop, if the water might scale up later (it is smaller than its maximum scale) - var needToBlendOutShape = lodIdx == 0 && ScaleCouldIncrease; - instanceData.Current[lodIdx]._MeshScaleLerp = needToBlendOutShape ? ViewerAltitudeLevelAlpha : 0f; - - // blend furthest normals scale in/out to avoid pop, if scale could reduce - var needToBlendOutNormals = lodIdx == LodLevels - 1 && ScaleCouldDecrease; - instanceData.Current[lodIdx]._FarNormalsWeight = needToBlendOutNormals ? ViewerAltitudeLevelAlpha : 1f; - - // geometry data - // compute grid size of geometry. take the long way to get there - make sure we land exactly on a power of two - // and not inherit any of the lossy-ness from lossyScale. - var scale = CalcLodScale(lodIdx); - instanceData.Current[lodIdx]._GeometryGridWidth = scale / (0.25f * _Resolution / _GeometryDownSampleFactor); - - var mul = 1.875f; // fudge 1 - var pow = 1.4f; // fudge 2 - var texelWidth = instanceData.Current[lodIdx]._GeometryGridWidth / _GeometryDownSampleFactor; - instanceData.Current[lodIdx]._NormalScrollSpeeds[0] = Mathf.Pow(Mathf.Log(1f + 2f * texelWidth) * mul, pow); - instanceData.Current[lodIdx]._NormalScrollSpeeds[1] = Mathf.Pow(Mathf.Log(1f + 4f * texelWidth) * mul, pow); - } - } - -#if UNITY_6000_0_OR_NEWER - void SetUpMotionVectorsMaterial() - { - if (_MotionVectorsMaterial != null) Helpers.Destroy(_MotionVectorsMaterial); - _MotionVectorsMaterial = CoreUtils.CreateEngineMaterial(_Material.shader); - _MotionVectorsMaterial.SetShaderPassEnabled("UniversalForward", false); - _MotionVectorsMaterial.SetShaderPassEnabled("UniversalGBuffer", false); - _MotionVectorsMaterial.SetShaderPassEnabled("ShadowCaster", false); - _MotionVectorsMaterial.SetShaderPassEnabled("DepthOnly", false); - _MotionVectorsMaterial.SetShaderPassEnabled("DepthNormals", false); - _MotionVectorsMaterial.SetShaderPassEnabled("Meta", false); - _MotionVectorsMaterial.SetShaderPassEnabled("SceneSelectionPass", false); - _MotionVectorsMaterial.SetShaderPassEnabled("Picking", false); - _MotionVectorsMaterial.SetShaderPassEnabled("Universal2D", false); - _MotionVectorsMaterial.SetShaderPassEnabled("MotionVectors", true); - } -#endif - void LateUpdatePosition() { - var pos = Viewpoint.position; + var position = Viewpoint.position; + + // This will cause artifacts in motion vectors debug view, but are likely negligible. + if (_CenterOfDetailDisplacementCorrection && _CenterOfDetailDisplacementCorrectionHelper.SampleDisplacement(position, out var displacement)) + { + position = new(position.x - displacement.x, position.y, position.z - displacement.z); + } // maintain y coordinate - sea level - pos.y = Root.position.y; + position.y = transform.position.y; // Don't land very close to regular positions where things are likely to snap to, because different tiles might // land on either side of a snap boundary due to numerical error and snap to the wrong positions. Nudge away from // common by using increments of 1/60 which have lots of factors. // :WaterGridPrecisionErrors - if (Mathf.Abs(pos.x * 60f - Mathf.Round(pos.x * 60f)) < 0.001f) + if (Mathf.Abs(position.x * 60f - Mathf.Round(position.x * 60f)) < 0.001f) { - pos.x += 0.002f; + position.x += 0.002f; } - if (Mathf.Abs(pos.z * 60f - Mathf.Round(pos.z * 60f)) < 0.001f) + if (Mathf.Abs(position.z * 60f - Mathf.Round(position.z * 60f)) < 0.001f) { - pos.z += 0.002f; + position.z += 0.002f; } - Shader.SetGlobalVector(ShaderIDs.s_CenterDelta, pos - Root.position); + Shader.SetGlobalVector(ShaderIDs.s_CenterDelta, (position - Position).XZ()); - Root.position = pos; - Shader.SetGlobalVector(ShaderIDs.s_Center, Root.position); + Position = position; + Shader.SetGlobalVector(ShaderIDs.s_Center, Position); } void LateUpdateScale() @@ -1242,7 +1313,7 @@ namespace WaveHarmonic.Crest if (ratio != 1f) { EditorApplication.isPaused = EditorApplication.isPaused || _Debug._PauseOnScaleChange; - if (_Debug._LogScaleChange) Debug.Log($"Scale Change: {newScale} / {Scale} = {ratio}"); + if (_Debug._LogScaleChange) Debug.Log($"Scale Change: {newScale} / {Scale} = {ratio}. LOD Change: {ScaleDifferencePower2}"); } #endif #endif @@ -1250,8 +1321,6 @@ namespace WaveHarmonic.Crest Scale = newScale; - Root.localScale = new(Scale, 1f, Scale); - // LOD 0 is blended in/out when scale changes, to eliminate pops. Here we set it as // a global, whereas in WaterChunkRenderer it is applied to LOD0 tiles only through // instance data. This global can be used in compute, where we only apply this @@ -1276,6 +1345,7 @@ namespace WaveHarmonic.Crest ViewerHeightAboveWater = viewer.position.y - waterHeight; } +#if d_Unity_Terrain // Also use terrain height for scale. Viewpoint is absolute if set. if (_SampleTerrainHeightForScale && LevelLod.Enabled && _Viewpoint == null) { @@ -1301,6 +1371,7 @@ namespace WaveHarmonic.Crest viewerHeightAboveWaterOrTerrain = viewerHeightAboveTerrain; } } +#endif // d_Unity_Terrain // Calculate teleport distance and create window for height queries to return a height change. { @@ -1351,90 +1422,6 @@ namespace WaveHarmonic.Crest ViewerDistanceToShoreline = distance; } - void LateUpdateTiles() - { - var canSkipCulling = WaterBody.WaterBodies.Count == 0 && _CanSkipCulling; - - foreach (var tile in Chunks) - { - if (tile.Rend == null) - { - continue; - } - - tile._Culled = false; - tile.MaterialOverridden = false; - - // If there are local bodies of water, this will do overlap tests between the water tiles - // and the water bodies and turn off any that don't overlap. - if (!canSkipCulling) - { - var chunkBounds = tile.Rend.bounds; - var chunkUndisplacedBoundsXZ = tile.UnexpandedBoundsXZ; - - var largestOverlap = 0f; - var overlappingOne = false; - foreach (var body in WaterBody.WaterBodies) - { - // If tile has already been excluded from culling, then skip this iteration. But finish this - // iteration if the water body has a material override to work out most influential water body. - if (overlappingOne && body.AboveSurfaceMaterial == null) - { - continue; - } - - var bounds = body.AABB; - - var overlapping = - bounds.max.x > chunkBounds.min.x && bounds.min.x < chunkBounds.max.x && - bounds.max.z > chunkBounds.min.z && bounds.min.z < chunkBounds.max.z; - if (overlapping) - { - overlappingOne = true; - - if (body.AboveSurfaceMaterial != null) - { - var overlap = 0f; - { - // Use the unexpanded bounds to prevent leaking as generally this feature will be - // for an inland body of water where hopefully there is attenuation between it and - // the water to handle the water's displacement. The inland water body will unlikely - // have large displacement but can be mitigated with a decent buffer zone. - var xMin = Mathf.Max(bounds.min.x, chunkUndisplacedBoundsXZ.min.x); - var xMax = Mathf.Min(bounds.max.x, chunkUndisplacedBoundsXZ.max.x); - var zMin = Mathf.Max(bounds.min.z, chunkUndisplacedBoundsXZ.min.y); - var zMax = Mathf.Min(bounds.max.z, chunkUndisplacedBoundsXZ.max.y); - if (xMin < xMax && zMin < zMax) - { - overlap = (xMax - xMin) * (zMax - zMin); - } - } - - // If this water body has the most overlap, then the chunk will get its material. - if (overlap > largestOverlap) - { - tile.Rend.sharedMaterial = body.AboveSurfaceMaterial; - tile.MaterialOverridden = true; - largestOverlap = overlap; - } - } - else - { - tile.MaterialOverridden = false; - } - } - } - - tile._Culled = _WaterBodyCulling && !overlappingOne && WaterBody.WaterBodies.Count > 0; - } - - tile.Rend.enabled = !tile._Culled; - } - - // Can skip culling next time around if water body count stays at 0 - _CanSkipCulling = WaterBody.WaterBodies.Count == 0; - } - void Destroy() { foreach (var simulation in Simulations) @@ -1444,16 +1431,17 @@ namespace WaveHarmonic.Crest } Simulations.Clear(); + _Mask?.Destroy(); + + Meniscus.Destroy(); + // Clean up modules. #if d_CrestPortals _Portals.OnDestroy(); #endif _Underwater.OnDestroy(); _Reflections.OnDestroy(); - - // Clean up everything created through the Water Builder. - WaterBuilder.CleanUp(this); - Root = null; + Surface.OnDestroy(); if (Container) { @@ -1461,12 +1449,6 @@ namespace WaveHarmonic.Crest Container = null; } - Chunks.Clear(); - -#if UNITY_6000_0_OR_NEWER - Helpers.Destroy(_MotionVectorsMaterial); -#endif - _Initialized = false; } @@ -1482,19 +1464,22 @@ namespace WaveHarmonic.Crest if (RenderPipelineHelper.IsLegacy && Viewer != null) { // Need to call to prevent crash. - OnPostRenderCamera(Viewer); + OnEndCameraRenderingLegacy(Viewer); } #if UNITY_EDITOR EditorApplication.update -= EditorUpdate; #endif - Camera.onPreCull -= OnPreRenderCamera; - Camera.onPostRender -= OnPostRenderCamera; + Camera.onPreCull -= OnBeginCameraRendering; + Camera.onPostRender -= OnEndCameraRendering; -#if d_UnityURP - ConfigureUniversalRenderer.Disable(); - UniversalCopyWaterSurfaceDepth.Disable(); +#if d_UnityHDRP + SurfaceRenderer.WaterSurfaceCustomPass.Disable(); + CrestInternalCopyToTextureCustomPass.Disable(); +#if UNITY_EDITOR + RenderPipelineManager.beginContextRendering -= OnBeginContextRendering; +#endif #endif #if d_WaveHarmonic_Crest_ShiftingOrigin @@ -1505,15 +1490,18 @@ namespace WaveHarmonic.Crest RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; RenderPipelineManager.activeRenderPipelineTypeChanged -= OnActiveRenderPipelineTypeChanged; + _Mask?.Disable(); + #if d_CrestPortals if (_Portals._Enabled) _Portals.OnDisable(); #endif if (_Underwater._Enabled) _Underwater.OnDisable(); if (_Reflections._Enabled) _Reflections.OnDisable(); -#if UNITY_EDITOR - DisableWaterLevelDepthTexture(); -#endif + if (Meniscus.Enabled) + { + Meniscus.Disable(); + } if (Container != null) { @@ -1523,6 +1511,7 @@ namespace WaveHarmonic.Crest base.Disable(); } +#if d_WaveHarmonic_Crest_ShiftingOrigin /// /// Notify water of origin shift /// @@ -1534,6 +1523,7 @@ namespace WaveHarmonic.Crest simulation.SetOrigin(newOrigin); } } +#endif /// /// Clears persistent LOD data. Some simulations have persistent data which can linger for a little while after diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterResources.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterResources.cs index db46dce27..b70d64458 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterResources.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaterResources.cs @@ -33,7 +33,9 @@ namespace WaveHarmonic.Crest public Shader _UnderwaterEffect; public Shader _UnderwaterMask; + public Shader _HorizonMask; public Shader _Portals; + public Shader _PortalsMask; public Shader _ClipConvexHull; @@ -41,11 +43,15 @@ namespace WaveHarmonic.Crest public Shader _DebugTextureArray; public Shader _Blit; + + public Shader _ForceShadows; + public Shader _CaptureShadowMatrices; } [Serializable] public sealed class ComputeResources { + public ComputeShader _Mask; public ComputeShader _UnderwaterArtifacts; public ComputeShader _ShapeWavesTransfer; @@ -60,6 +66,7 @@ namespace WaveHarmonic.Crest public ComputeShader _ShorelineColor; public ComputeShader _UpdateDynamicWaves; public ComputeShader _UpdateFoam; + public ComputeShader _UpdateShadow; public ComputeShader _PackLevel; public ComputeShader _AbsorptionTexture; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Watercraft/Controller.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Watercraft/Controller.cs index ef9ad0f66..1d79d38c4 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Watercraft/Controller.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Watercraft/Controller.cs @@ -70,7 +70,7 @@ namespace WaveHarmonic.Crest.Watercraft { if (!_FloatingObject.InWater) return; - UnityEngine.Profiling.Profiler.BeginSample("WaveHarmonic.Crest.Watercraft.Controller.FixedUpdate"); + UnityEngine.Profiling.Profiler.BeginSample("Crest.Watercraft.Controller.FixedUpdate"); var input = _Control.Input; var rb = _FloatingObject.RigidBody; diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaveHarmonic.Crest.asmdef b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaveHarmonic.Crest.asmdef index 1c2fcf618..1ac204578 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/WaveHarmonic.Crest.asmdef +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/WaveHarmonic.Crest.asmdef @@ -26,6 +26,11 @@ "expression": "", "define": "d_ModuleUnityDirector" }, + { + "name": "com.unity.modules.terrain", + "expression": "", + "define": "d_Unity_Terrain" + }, { "name": "com.unity.modules.vr", "expression": "", @@ -56,6 +61,11 @@ "expression": "", "define": "d_CrestPaint" }, + { + "name": "com.waveharmonic.crest.cpu-queries", + "expression": "", + "define": "d_WaveHarmonic_Crest_CPUQueries" + }, { "name": "com.waveharmonic.crest.splines", "expression": "", diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/FFTCompute.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/FFTCompute.cs index a7a950da1..10ce19661 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/FFTCompute.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/FFTCompute.cs @@ -85,8 +85,9 @@ namespace WaveHarmonic.Crest public readonly float _WindDirectionRadians; public readonly float _WindTurbulence; public readonly float _WindAlignment; + public readonly float _Gravity; - public Parameters(WaveSpectrum spectrum, int resolution, float period, float speed, float direction, float turbulence, float alignment) + public Parameters(WaveSpectrum spectrum, int resolution, float period, float speed, float direction, float turbulence, float alignment, float gravity) { _Spectrum = spectrum; _Resolution = resolution; @@ -95,17 +96,18 @@ namespace WaveHarmonic.Crest _WindDirectionRadians = direction; _WindTurbulence = turbulence; _WindAlignment = alignment; + _Gravity = gravity; } // Implement custom or incur allocations. public override int GetHashCode() { - return System.HashCode.Combine(_Spectrum, _LoopPeriod, _WindSpeed, _WindDirectionRadians, _WindTurbulence, _WindAlignment, _Resolution); + return System.HashCode.Combine(_Spectrum, _LoopPeriod, _WindSpeed, _WindDirectionRadians, _WindTurbulence, _WindAlignment, _Gravity, _Resolution); } public int GetHashCode(int resolution) { - return System.HashCode.Combine(_Spectrum, _LoopPeriod, _WindSpeed, _WindDirectionRadians, _WindTurbulence, _WindAlignment, resolution); + return System.HashCode.Combine(_Spectrum, _LoopPeriod, _WindSpeed, _WindDirectionRadians, _WindTurbulence, _WindAlignment, _Gravity, resolution); } } @@ -279,7 +281,7 @@ namespace WaveHarmonic.Crest wrapper.SetFloat(ShaderIDs.s_WindSpeed, _Parameters._WindSpeed); wrapper.SetFloat(ShaderIDs.s_Turbulence, _Parameters._WindTurbulence); wrapper.SetFloat(ShaderIDs.s_Alignment, _Parameters._WindAlignment); - wrapper.SetFloat(ShaderIDs.s_Gravity, WaterRenderer.Instance.Gravity); + wrapper.SetFloat(ShaderIDs.s_Gravity, _Parameters._Gravity); wrapper.SetFloat(ShaderIDs.s_Period, period < Mathf.Infinity ? period : -1); wrapper.SetVector(ShaderIDs.s_WindDir, new(Mathf.Cos(_Parameters._WindDirectionRadians), Mathf.Sin(_Parameters._WindDirectionRadians))); wrapper.SetTexture(ShaderIDs.s_SpectrumControls, _Parameters._Spectrum.ControlsTexture); @@ -417,9 +419,9 @@ namespace WaveHarmonic.Crest DebugGUI.DrawTextureArray(WaveBuffers, 8, 0.5f, 20f); } - if (_Parameters._Spectrum != null && _Parameters._Spectrum.ControlsTexture != null) + if (_Parameters._Spectrum != null) { - GUI.DrawTexture(new(0f, 0f, 100f, 10f), _Parameters._Spectrum.ControlsTexture); + _Parameters._Spectrum.OnGUI(); } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/WaveSpectrum.cs b/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/WaveSpectrum.cs index 067e535e6..8943cc586 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/WaveSpectrum.cs +++ b/Packages/com.waveharmonic.crest/Runtime/Scripts/Waves/WaveSpectrum.cs @@ -88,9 +88,10 @@ namespace WaveHarmonic.Crest /// Wavelength in m /// How many waves we're sampling, used to conserve energy for different sampling rates /// Wind speed in m/s + /// Gravity /// The energy of the wave in J /// The amplitude of the wave in m - internal float GetAmplitude(float wavelength, float componentsPerOctave, float windSpeed, out float power) + internal float GetAmplitude(float wavelength, float componentsPerOctave, float windSpeed, float gravity, out float power) { Debug.AssertFormat(wavelength > 0f, this, "Crest: {0} wavelength must be > 0.", nameof(WaveSpectrum)); @@ -121,15 +122,18 @@ namespace WaveHarmonic.Crest var hasNextIndex = nextIndex < _PowerLogarithmicScales.Length; var nextPower = hasNextIndex && !_PowerDisabled[nextIndex] ? _PowerLogarithmicScales[nextIndex] : s_MinimumPowerLog; + // Empirical wind influence based on alpha-beta spectrum that underlies empirical spectra + gravity *= _GravityScale; + // The amplitude calculation follows this nice paper from Frechot: // https://hal.archives-ouvertes.fr/file/index/docid/307938/filename/frechot_realistic_simulation_of_ocean_surface_using_wave_spectra.pdf var wl_lo = Mathf.Pow(2f, Mathf.Floor(wl_pow2)); var k_lo = 2f * Mathf.PI / wl_lo; - var c_lo = ComputeWaveSpeed(wl_lo); + var c_lo = ComputeWaveSpeed(wl_lo, gravity); var omega_lo = k_lo * c_lo; var wl_hi = 2f * wl_lo; var k_hi = 2f * Mathf.PI / wl_hi; - var c_hi = ComputeWaveSpeed(wl_hi); + var c_hi = ComputeWaveSpeed(wl_hi, gravity); var omega_hi = k_hi * c_hi; var domega = (omega_lo - omega_hi) / componentsPerOctave; @@ -141,9 +145,6 @@ namespace WaveHarmonic.Crest power = hasNextIndex ? Mathf.Lerp(thisPower, nextPower, alpha) : thisPower; power = Mathf.Pow(10f, power); - // Empirical wind influence based on alpha-beta spectrum that underlies empirical spectra - var gravity = _GravityScale * WaterRenderer.Instance.Gravity; - // Zero gravity will cause NaNs, and they have always been flat. if (gravity <= 0f) return 0f; @@ -163,11 +164,11 @@ namespace WaveHarmonic.Crest return a * _Multiplier; } - static float ComputeWaveSpeed(float wavelength, float gravityMultiplier = 1f) + static float ComputeWaveSpeed(float wavelength, float gravity, float gravityMultiplier = 1f) { // wave speed of deep sea water waves: https://en.wikipedia.org/wiki/Wind_wave // https://en.wikipedia.org/wiki/Dispersion_(water_waves)#Wave_propagation_and_dispersion - var g = WaterRenderer.Instance.Gravity * gravityMultiplier; + var g = gravity * gravityMultiplier; var k = 2f * Mathf.PI / wavelength; //float h = max(depth, 0.01); //float cp = sqrt(abs(tanh_clamped(h * k)) * g / k); @@ -209,10 +210,8 @@ namespace WaveHarmonic.Crest } // This applies the correct PM spectrum powers, validated against a separate implementation - internal void ApplyPiersonMoskowitzSpectrum() + internal void ApplyPiersonMoskowitzSpectrum(float gravity) { - var gravity = WaterRenderer.Instance != null ? WaterRenderer.Instance.Gravity : Mathf.Abs(Physics.gravity.y); - for (var octave = 0; octave < k_NumberOfOctaves; octave++) { var wl = SmallWavelength(octave); diff --git a/Packages/com.waveharmonic.crest/Runtime/Settings/Resources.asset b/Packages/com.waveharmonic.crest/Runtime/Settings/Resources.asset index 3b2778fd4..bc9c7caa8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Settings/Resources.asset +++ b/Packages/com.waveharmonic.crest/Runtime/Settings/Resources.asset @@ -24,14 +24,20 @@ MonoBehaviour: _UpdateShadow: {fileID: 4800000, guid: 6195b173b90b246ac9f5300b7e2aa482, type: 3} _UnderwaterEffect: {fileID: 4800000, guid: 034b985bd9c344992af148e26d2cdb24, type: 3} _UnderwaterMask: {fileID: 4800000, guid: edb653e62cc924b99b0a1086ffb39be7, type: 3} + _HorizonMask: {fileID: 4800000, guid: 80a81e5410296461d827cd6eed939b81, type: 3} _Portals: {fileID: 4800000, guid: 370ffa403718b4982a8a3e0101263093, type: 3} + _PortalsMask: {fileID: 4800000, guid: 3e6aaf795e0984bacb7a9fc4785f1f6a, type: 3} _ClipConvexHull: {fileID: 4800000, guid: 1f5d1e029c7564da8855bf97e3b9247a, type: 3} _ShallowWaterSimulationVisualizer: {fileID: 4800000, guid: 613caf76dccc3ea45b0501b731a55ec2, type: 3} _DebugTextureArray: {fileID: 4800000, guid: 9984e3507dd424fd49ce01182989250a, type: 3} _Blit: {fileID: 4800000, guid: b9836aaab4b1f45e4bd4fc4e6bcc7e74, type: 3} + _ForceShadows: {fileID: 4800000, guid: c9f384b6b84e943ed83161cb82d95b2e, type: 3} + _CaptureShadowMatrices: {fileID: 4800000, guid: 17feb724c7e004b4e8e418931db7eff3, + type: 3} _Compute: + _Mask: {fileID: 7200000, guid: 51ffca485396f4d8dbf07883c9303f3c, type: 3} _UnderwaterArtifacts: {fileID: 7200000, guid: 08549c36146ad4899a07193754b21ea2, type: 3} _ShapeWavesTransfer: {fileID: 7200000, guid: 3a487d04e47a14907809657d5ccf1917, @@ -46,6 +52,7 @@ MonoBehaviour: _UpdateDynamicWaves: {fileID: 7200000, guid: 0ba116507793f45b5ba3f016f0837660, type: 3} _UpdateFoam: {fileID: 7200000, guid: 1149a28b1712c464fbc3d96bea0bc34d, type: 3} + _UpdateShadow: {fileID: 7200000, guid: c47c6200534474da18e1134965c102f3, type: 3} _PackLevel: {fileID: 7200000, guid: 62854cc297743429aa087d7708d221c0, type: 3} _AbsorptionTexture: {fileID: 7200000, guid: 82d4c3f5aac084c2bad20d0a31f1168a, type: 3} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AbsorptionColor.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AbsorptionColor.shader index 9da1693c7..24a4c2446 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AbsorptionColor.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AbsorptionColor.shader @@ -20,10 +20,12 @@ Shader "Crest/Inputs/Absorption/Color" SubShader { + ZTest Always + ZWrite Off + Pass { Blend SrcAlpha OneMinusSrcAlpha - ZWrite Off ColorMask RGB CGPROGRAM diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AlbedoColor.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AlbedoColor.shader index 39980c051..f3dec03a7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AlbedoColor.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AlbedoColor.shader @@ -19,12 +19,13 @@ Shader "Crest/Inputs/Albedo/Color" } SubShader { + ZTest Always + ZWrite Off + Pass { Blend [_Crest_BlendModeSource] [_Crest_BlendModeTarget] - ZWrite Off - CGPROGRAM #pragma vertex Vertex #pragma fragment Fragment diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesAddFromTexture.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesAddFromTexture.shader index c30c3db99..d82dd9635 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesAddFromTexture.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesAddFromTexture.shader @@ -18,6 +18,8 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" SubShader { Blend One One + ZTest Always + ZWrite Off Pass { @@ -25,7 +27,7 @@ Shader "Crest/Inputs/Animated Waves/Add From Texture" #pragma vertex Vert #pragma fragment Frag - #pragma shader_feature_local d_HeightsOnly + #pragma shader_feature_local_fragment d_HeightsOnly #include "UnityCG.cginc" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesRemoveGeometry.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesRemoveGeometry.shader index 245b58a0f..93f42d0cc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesRemoveGeometry.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesRemoveGeometry.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Push water under the geometry. Needs to be rendered into all LODs - set Octave Wave length to 0. @@ -13,6 +13,9 @@ Shader "Crest/Inputs/Animated Waves/Push Water Under Convex Hull" SubShader { + ZTest Always + ZWrite Off + Pass { BlendOp Min diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesSetHeightToGeometry.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesSetHeightToGeometry.shader index 9b7a2653f..b7631f614 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesSetHeightToGeometry.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesSetHeightToGeometry.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // This writes straight into the displacement texture and sets the water height to the y value of the geometry. @@ -16,6 +16,9 @@ Shader "Crest/Inputs/Animated Waves/Set Water Height Using Geometry" SubShader { + ZTest Always + ZWrite Off + Pass { Blend Off diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesWaveParticle.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesWaveParticle.shader index 58787b4dd..d63ae2f5a 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesWaveParticle.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/AnimatedWavesWaveParticle.shader @@ -16,6 +16,9 @@ Shader "Crest/Inputs/Animated Waves/Wave Particle" { Tags { "DisableBatching" = "True" } + ZTest Always + ZWrite Off + Pass { Blend One One diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesAddBump.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesAddBump.shader index b7db88de3..41382e785 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesAddBump.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesAddBump.shader @@ -14,6 +14,9 @@ Shader "Crest/Inputs/Dynamic Waves/Add Bump" SubShader { + ZTest Always + ZWrite Off + Pass { Blend One One diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesDampenCircle.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesDampenCircle.shader index e399baa9a..482554979 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesDampenCircle.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/DynamicWavesDampenCircle.shader @@ -14,6 +14,9 @@ Shader "Crest/Inputs/Dynamic Waves/Dampen Circle" SubShader { + ZTest Always + ZWrite Off + Pass { Blend SrcAlpha OneMinusSrcAlpha diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowAddFromTexture.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowAddFromTexture.shader index 43491ebd7..6976c20c7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowAddFromTexture.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowAddFromTexture.shader @@ -26,6 +26,8 @@ Shader "Crest/Inputs/Flow/Add From Texture" SubShader { Blend One One + ZTest Always + ZWrite Off Pass { @@ -33,10 +35,10 @@ Shader "Crest/Inputs/Flow/Add From Texture" #pragma vertex Vert #pragma fragment Frag - #pragma shader_feature_local d_FlipX - #pragma shader_feature_local d_FlipZ - #pragma shader_feature_local d_Feather - #pragma shader_feature_local d_NegativeValues + #pragma shader_feature_local_fragment d_FlipX + #pragma shader_feature_local_fragment d_FlipZ + #pragma shader_feature_local_fragment d_Feather + #pragma shader_feature_local_fragment d_NegativeValues #include "UnityCG.cginc" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowFixedDirection.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowFixedDirection.shader index a5049ebca..55988abb2 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowFixedDirection.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FlowFixedDirection.shader @@ -21,6 +21,9 @@ Shader "Crest/Inputs/Flow/Fixed Direction" SubShader { + ZTest Always + ZWrite Off + Pass { CGPROGRAM @@ -28,7 +31,7 @@ Shader "Crest/Inputs/Flow/Fixed Direction" #pragma fragment Frag #pragma shader_feature_local d_Feather - #pragma shader_feature_local d_ApplyRotation + #pragma shader_feature_local_fragment d_ApplyRotation #include "UnityCG.cginc" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromTexture.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromTexture.shader index d0c888986..69e9edc19 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromTexture.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromTexture.shader @@ -15,6 +15,8 @@ Shader "Crest/Inputs/Foam/Add From Texture" SubShader { Blend One One + ZTest Always + ZWrite Off Pass { diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromVertexColor.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromVertexColor.shader index 6325f7a5e..602cd3dd8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromVertexColor.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/FoamAddFromVertexColor.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. Shader "Crest/Inputs/Foam/Add From Vertex Colors" @@ -14,6 +14,8 @@ Shader "Crest/Inputs/Foam/Add From Vertex Colors" SubShader { Blend One One + ZTest Always + ZWrite Off Pass { diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/AbsorptionTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/AbsorptionTexture.compute index a0f1ff939..875c9c10e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/AbsorptionTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/AbsorptionTexture.compute @@ -18,6 +18,7 @@ RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) int _Crest_Blend; float _Crest_Weight; +float4 _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -42,7 +43,7 @@ void Execute(uint3 id) return; } - const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0); + const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0) * _Crest_Multiplier; const half3 target = _Crest_Target[id]; weight *= source.a; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipConvexHull.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipConvexHull.shader index 8e6560bcf..ef5a18bbf 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipConvexHull.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipConvexHull.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Renders convex hull to the clip surface texture. @@ -70,8 +70,9 @@ Shader "Hidden/Crest/Inputs/Clip/Convex Hull" SubShader { - ZWrite Off ColorMask R + ZTest Always + ZWrite Off Pass { diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipTexture.compute index 705ad0a05..3a25bfe9b 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ClipTexture.compute @@ -18,6 +18,7 @@ Texture2D _Crest_Texture; RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) +float _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -36,7 +37,7 @@ void Execute(uint3 id) return; } - const float result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x; + const float result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x * _Crest_Multiplier; // Painted clip defines a minimum value of the clip. _Crest_Target[id] = max(_Crest_Target[id], result); diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/DepthTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/DepthTexture.compute index 3abedee1a..e1076e044 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/DepthTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/DepthTexture.compute @@ -29,6 +29,7 @@ Texture2D _Crest_Texture; RWTexture2DArray _Crest_Target; CBUFFER_START(CrestInputTexture) +float2 _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -50,7 +51,7 @@ void Execute(uint3 id) } m_CrestType current = _Crest_Target[id]; - m_CrestType result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0); + m_CrestType result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0) * _Crest_Multiplier; result.x += _Crest_HeightOffset; // Take highest terrain height. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FlowTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FlowTexture.compute index 2df0e9fd2..72fe8af50 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FlowTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FlowTexture.compute @@ -20,6 +20,7 @@ RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) int _Crest_Blend; float _Crest_Weight; +float2 _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -53,6 +54,8 @@ void Execute(uint3 id) source = source * 2.0 - 1.0; } + source *= _Crest_Multiplier; + if (_Crest_Blend == m_CrestBlendAlpha) { weight *= saturate(length(source)); diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FoamTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FoamTexture.compute index 8c5a66d46..e92268b28 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FoamTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/FoamTexture.compute @@ -20,6 +20,7 @@ RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) int _Crest_Blend; float _Crest_Weight; +float _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -45,7 +46,7 @@ void Execute(uint3 id) return; } - const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x; + const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x * _Crest_Multiplier; const float target = _Crest_Target[id]; _Crest_Target[id] = Blend(_Crest_Blend, weight, _Crest_SimDeltaTime, source, target); diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/JumpFloodSDF.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/JumpFloodSDF.compute index 16da02205..679d2fa46 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/JumpFloodSDF.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/JumpFloodSDF.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // An implementation of the Jump Flood algorithm by Rong and Tan diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/LevelTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/LevelTexture.compute index e1d328bb0..be546e691 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/LevelTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/LevelTexture.compute @@ -23,6 +23,7 @@ RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) int _Crest_Blend; float _Crest_Weight; +float _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -48,10 +49,11 @@ void Execute(uint3 id) } #if d_CatmullRom - const float source = Utility::SampleTextureCatmullRom(_Crest_Texture, LODData_linear_clamp_sampler, uv, _Crest_Resolution).x; + const float source = Utility::SampleTextureCatmullRom(_Crest_Texture, LODData_linear_clamp_sampler, uv, _Crest_Resolution) #else - const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0.0).x; + const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0.0) #endif + .x * _Crest_Multiplier; const float target = _Crest_Target[id]; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ScatteringTexture.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ScatteringTexture.compute index 8d981dcd4..e44e43f5b 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ScatteringTexture.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Hidden/ScatteringTexture.compute @@ -18,6 +18,7 @@ RWTexture2DArray _Crest_Target; CBUFFER_START(CrestPerMaterial) int _Crest_Blend; float _Crest_Weight; +float4 _Crest_Multiplier; float2 _Crest_TextureSize; float2 _Crest_TexturePosition; float2 _Crest_TextureRotation; @@ -42,7 +43,7 @@ void Execute(uint3 id) return; } - const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0); + const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0) * _Crest_Multiplier; const half3 target = _Crest_Target[id]; weight *= source.a; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Override.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Override.shader index bb55e2d0e..c8def22ae 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Override.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Override.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. Shader "Crest/Inputs/All/Override" @@ -15,11 +15,13 @@ Shader "Crest/Inputs/All/Override" SubShader { + ZTest Always + ZWrite Off + Pass { Blend Off ColorMask [_Crest_ColorMask] - ZWrite Off CGPROGRAM #pragma vertex Vertex diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Scale.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Scale.shader index f3890f2bb..688709428 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Scale.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Scale.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // 0-1 scaling of existing water data using multiplicative blending. @@ -32,6 +32,9 @@ Shader "Crest/Inputs/All/Scale" SubShader { + ZTest Always + ZWrite Off + Pass { // Multiply @@ -42,8 +45,8 @@ Shader "Crest/Inputs/All/Scale" #pragma fragment Frag #pragma shader_feature_local d_Texture - #pragma shader_feature_local d_Invert #pragma shader_feature_local d_Feather + #pragma shader_feature_local_fragment d_Invert #include "UnityCG.cginc" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ScatteringColor.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ScatteringColor.shader index 0eb03e0f4..a26d04371 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ScatteringColor.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ScatteringColor.shader @@ -17,10 +17,12 @@ Shader "Crest/Inputs/Scattering/Color" SubShader { + ZTest Always + ZWrite Off + Pass { Blend SrcAlpha OneMinusSrcAlpha - ZWrite Off ColorMask RGB CGPROGRAM diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ShapeWavesFromGeometry.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ShapeWavesFromGeometry.shader index 13ba48457..270a413d6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ShapeWavesFromGeometry.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/ShapeWavesFromGeometry.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Generates waves from geometry that is rendered into the water simulation from a top down camera. Expects @@ -39,7 +39,7 @@ Shader "Crest/Inputs/Shape Waves/Add From Geometry" #pragma fragment Fragment // #pragma enable_d3d11_debug_symbols - #pragma shader_feature_local d_Feather + #pragma shader_feature_local_fragment d_Feather #include "UnityCG.cginc" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Utility.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Utility.shader index 46df5d243..d250ac2ef 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Utility.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/Utility.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. Shader "Crest/Inputs/All/Utility" @@ -17,12 +17,14 @@ Shader "Crest/Inputs/All/Utility" SubShader { + ZTest Always + ZWrite Off + Pass { Blend [_Crest_BlendModeSource] [_Crest_BlendModeTarget] BlendOp [_Crest_BlendOperation] ColorMask [_Crest_ColorMask] - ZWrite Off CGPROGRAM #pragma vertex Vertex diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterDepthFromGeometry.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterDepthFromGeometry.shader index 455acf4b1..cc8279cbe 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterDepthFromGeometry.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterDepthFromGeometry.shader @@ -12,6 +12,9 @@ Shader "Crest/Inputs/Depth/Water Depth From Geometry" SubShader { + ZTest Always + ZWrite Off + Pass { BlendOp Max diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterLevelFromGeometry.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterLevelFromGeometry.shader index bb7f60a7a..d21749aa1 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterLevelFromGeometry.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Input/WaterLevelFromGeometry.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // This sets base water height to Y value of geometry. @@ -17,6 +17,9 @@ Shader "Crest/Inputs/Level/Water Level From Geometry" SubShader { + ZTest Always + ZWrite Off + Pass { Blend [_Crest_BlendSource] [_Crest_BlendTarget] diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/PackLevel.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/PackLevel.compute index d9736ebe6..51a96d4ef 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/PackLevel.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/PackLevel.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #pragma kernel CrestPackLevel diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/Query.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/Query.compute index ec2e00192..f327e7ff1 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/Query.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/Query.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #pragma kernel CrestQueryDisplacement d_CrestDisplacement diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryDisplacements.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryDisplacements.compute index 542a4af0b..8991294cb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryDisplacements.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryDisplacements.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Merged into Query.compute. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryFlow.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryFlow.compute index 542a4af0b..8991294cb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryFlow.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/QueryFlow.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Merged into Query.compute. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShapeCombine.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShapeCombine.compute index 13401d40d..30efd0ffa 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShapeCombine.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShapeCombine.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Compute shader to perform combine of displacements. Reads and writes to texture array which saves @@ -14,6 +14,7 @@ #pragma kernel ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON _FLOW_ON _DYNAMIC_WAVE_SIM_ON #pragma kernel ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE _FLOW_ON _DYNAMIC_WAVE_SIM_ON _DISABLE_COMBINE #pragma kernel ShapeCombineDynamicWaves +#pragma kernel ShapeCombineDynamicWaves_DISABLE_COMBINE _DISABLE_COMBINE #pragma kernel ShapeCombineCopyDynamicWaves #include "HLSLSupport.cginc" @@ -107,6 +108,7 @@ void ShapeCombineBase(uint3 id) #endif // _FLOW_ON } + // Disabled for last LOD. #if !_DISABLE_COMBINE { const Cascade cascade = Cascade::MakeAnimatedWaves(slice0 + 1); @@ -136,14 +138,19 @@ void ShapeCombineDynamicWaves(uint3 id) const float2 positionWSXZ = cascade.UVToWorld(uv); float3 result = 0.0; + // Disabled for last LOD. +#if !_DISABLE_COMBINE { - const Cascade cascade = Cascade::MakeDynamicWaves(slice0 + 1); + // We are sampling from the target which matches Animated Waves descriptor. + const Cascade cascade = Cascade::MakeAnimatedWaves(slice0 + 1); const float3 uv = cascade.WorldToUV(positionWSXZ); // Waves to combine down from the next lod up the chain. SampleDisplacementsCompute(_Crest_DynamicWavesTarget, cascade._Resolution, uv, 1.0, result); } +#endif { + // We are sampling from Dynamic Waves. const Cascade cascade = Cascade::MakeDynamicWaves(slice0); const float3 uv = cascade.WorldToUV(positionWSXZ); result += cascade.SampleDynamicWavesDisplacement(uv, _Crest_HorizontalDisplace, _Crest_DisplaceClamp); @@ -168,4 +175,5 @@ m_CrestNameSpaceEnd [numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); } [numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); } [numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineDynamicWaves(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineDynamicWaves(id); } +[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineDynamicWaves_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineDynamicWaves(id); } [numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineCopyDynamicWaves(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineCopyDynamicWaves(id); } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShorelineColor.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShorelineColor.compute index 926792aaa..46dff08e6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShorelineColor.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/ShorelineColor.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #pragma kernel CrestShorelineColor diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateDynamicWaves.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateDynamicWaves.compute index 2f6a7c1a2..466ac359c 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateDynamicWaves.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateDynamicWaves.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Solves 2D wave equation @@ -40,10 +40,11 @@ void UpdateDynamicWaves(uint3 id) const float sliceIndexSource = id.z + _Crest_LodChange; const Cascade cascadeSource = Cascade::MakeDynamicWavesSource(sliceIndexSource); - // Off either end of the cascade - not useful to sample anything from previous frame. Always initialise - // with 0 values. - if (sliceIndexSource < 0.0 || sliceIndexSource >= cascadeSource._Count - 1.0) + // Off either end of the cascade. Not useful to sample anything from previous + // frame, as we do not produce any new data from sources of waves. + if (sliceIndexSource < 0.0 || sliceIndexSource >= cascadeSource._Count) { + // Always initialise with 0 values. _Crest_Target[id] = (float2)0; return; } @@ -91,21 +92,14 @@ void UpdateDynamicWaves(uint3 id) const float3 X = float3(1.0, 0.0, 0.0); const float3 Y = float3(-X.y, X.x, 0.0); - // no border wrap mode for RTs in unity it seems, - // so make any off-array reads 0 manually - const bool insideTarget = sliceIndexSource <= cascadeSource._Count && sliceIndexSource >= 0; - float fxm, fym, fxp, fyp; float2 ft_v; ft_v = fxm = fym = fxp = fyp = 0.0; - if (insideTarget) - { - fxm = cascadeSource.SampleDynamicWaves(uv_source - e * X).x; // x minus - fym = cascadeSource.SampleDynamicWaves(uv_source - e * Y).x; // y minus - fxp = cascadeSource.SampleDynamicWaves(uv_source + e * X).x; // x plus - fyp = cascadeSource.SampleDynamicWaves(uv_source + e * Y).x; // y plus - ft_v = cascadeSource.SampleDynamicWaves(uv_source); - } + fxm = cascadeSource.SampleDynamicWaves(uv_source - e * X).x; // x minus + fym = cascadeSource.SampleDynamicWaves(uv_source - e * Y).x; // y minus + fxp = cascadeSource.SampleDynamicWaves(uv_source + e * X).x; // x plus + fyp = cascadeSource.SampleDynamicWaves(uv_source + e * Y).x; // y plus + ft_v = cascadeSource.SampleDynamicWaves(uv_source); // wave propagation diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateFoam.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateFoam.compute index 2b64d0afb..3adf4376f 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateFoam.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateFoam.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #pragma kernel CrestUpdateFoam diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute new file mode 100644 index 000000000..4388987d8 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute @@ -0,0 +1,154 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// Soft shadow term is red, hard shadow term is green. + +#pragma kernel CrestUpdateShadowsBRP _BRP +#pragma kernel CrestUpdateShadowsHRP _HRP +#pragma kernel CrestUpdateShadowsURP _URP + +// Both BIRP. +#pragma multi_compile __ SHADOWS_SPLIT_SPHERES +#pragma multi_compile __ SHADOWS_SINGLE_CASCADE + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl" + +// Noise functions used for jitter. +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Noise/Noise.hlsl" + + +// JitterDiameterSoft, JitterDiameterHard, CurrentFrameWeightSoft, CurrentFrameWeightHard +float4 _Crest_JitterDiameters_CurrentFrameWeights; +float _Crest_SimDeltaTime; +float4x4 _Crest_MainCameraProjectionMatrix; + +bool _Crest_SampleColorMap; +float3 _Crest_Absorption; +float3 _Crest_Scattering; + +RWTexture2DArray _Crest_Target; + + +m_CrestNameSpace + +half ComputeShadow(const float4 i_positionWS, const float i_jitterDiameter, const half i_terrainHeight, const uint i_LodIndex) +{ + float4 positionWS = i_positionWS; + bool noShadows = false; + + if (i_jitterDiameter > 0.0) + { + // Add jitter. + positionWS.xz += i_jitterDiameter * (hash33(uint3(abs(positionWS.xz * 10.0), _Time.y * 120.0)) - 0.5).xy; + + // Shadow Bleeding. + // If we are not within a terrain, then check for shadow bleeding. + if (i_positionWS.y > i_terrainHeight) + { + // WorldToSafeUV + half terrainHeight = Cascade::MakeDepth(i_LodIndex).SampleSceneHeight(positionWS.xz); + + // If our current position is below the jittered terrain height, then we have landed within a terrain and + // we do not want to sample those shadows. + if (i_positionWS.y < terrainHeight) + { + // Return no shadows. + noShadows = true; + } + } + } + + return noShadows ? 1.0 : Utility::SampleShadows(positionWS); +} + +void UpdateShadows(const uint3 id) +{ + const uint slice0 = id.z; + const Cascade cascade = Cascade::MakeShadow(slice0); + const float2 worldPosXZ = cascade.IDToWorld(id.xy); + + float4 positionWS = 1.0; + positionWS.xz = worldPosXZ; + positionWS.y = g_Crest_WaterCenter.y; + + // Shadow from last frame. Manually implement black border. + const float sliceIndexSource = clamp((int)slice0 + g_Crest_LodChange, 0.0, g_Crest_LodCount - 1.0); + half2 shadow = Cascade::MakeShadowSource(sliceIndexSource).SampleShadowOverflow(positionWS.xz, 1.0); + + // Add displacement so shorelines do not receive shadows incorrectly. + positionWS.xyz += Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(positionWS.xz); + + // This was calculated in vertex but we have to sample sea level offset in fragment. + float4 mainCameraCoordinates = mul(_Crest_MainCameraProjectionMatrix, positionWS); + + // Check if the current sample is visible in the main camera (and therefore the shadow map can be sampled). This is + // required as the shadow buffer is world aligned and surrounds viewer. + float3 projected = mainCameraCoordinates.xyz / mainCameraCoordinates.w; + if (projected.z < 1.0 && projected.z > 0.0 && abs(projected.x) < 1.0 && abs(projected.y) < 1.0) + { + half2 shadowThisFrame = 1.0; + +#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) + positionWS.xyz -= _WorldSpaceCameraPos.xyz; +#endif + + half terrainHeight = Cascade::MakeDepth(slice0).SampleSceneHeight(positionWS.xz); + + half softJitter = _Crest_JitterDiameters_CurrentFrameWeights[CREST_SHADOW_INDEX_SOFT]; + + if (_Crest_SampleColorMap) + { + half3 absorption = _Crest_Absorption; + half3 scattering = _Crest_Scattering; + + if (g_Crest_SampleAbsorptionSimulation) + { + absorption = Cascade::MakeAbsorption(slice0).SampleAbsorption(positionWS.xz); + } + + if (g_Crest_SampleScatteringSimulation) + { + scattering = Cascade::MakeScattering(slice0).SampleScattering(positionWS.xz); + } + + half3 extinction = absorption + scattering; + half factor = saturate(min(min(extinction.x, extinction.y), extinction.z) * g_Crest_DynamicSoftShadowsFactor); + softJitter = (1.0 - factor) * k_Crest_MaximumShadowJitter; + } + + // Add soft shadowing data. + shadowThisFrame[CREST_SHADOW_INDEX_SOFT] = ComputeShadow + ( + positionWS, + softJitter, + terrainHeight, + slice0 + ); + + // Add hard shadowing data. + shadowThisFrame[CREST_SHADOW_INDEX_HARD] = ComputeShadow + ( + positionWS, + _Crest_JitterDiameters_CurrentFrameWeights[CREST_SHADOW_INDEX_HARD], + terrainHeight, + slice0 + ); + + shadowThisFrame = (half2)1.0 - saturate(shadowThisFrame + Utility::ComputeShadowFade(positionWS)); + + shadow = lerp(shadow, shadowThisFrame, _Crest_JitterDiameters_CurrentFrameWeights.zw * _Crest_SimDeltaTime * 60.0); + } + + _Crest_Target[id] = shadow; +} + +m_CrestNameSpaceEnd + +m_CrestKernelXRP(UpdateShadows) diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute.meta new file mode 100644 index 000000000..9c7b48536 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c47c6200534474da18e1134965c102f3 +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl index 05e595cff..d58bb60cf 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl @@ -100,7 +100,8 @@ half2 Fragment(Varyings input) float4 positionWS = float4(input.positionWS.xyz, 1.0); // Shadow from last frame. Manually implement black border. - half2 shadow = Cascade::MakeShadowSource(_Crest_LodIndex + g_Crest_LodChange).SampleShadowOverflow(positionWS.xz, 1.0); + const float sliceIndexSource = clamp((int)_Crest_LodIndex + g_Crest_LodChange, 0.0, g_Crest_LodCount - 1.0); + half2 shadow = Cascade::MakeShadowSource(sliceIndexSource).SampleShadowOverflow(positionWS.xz, 1.0); // Add displacement so shorelines do not receive shadows incorrectly. positionWS.xyz += Cascade::MakeAnimatedWaves(_Crest_LodIndex).SampleDisplacement(positionWS.xz); diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.shader index 069f8c60b..ed611f956 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.shader @@ -1,170 +1,7 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. -// Soft shadow term is red, hard shadow term is green. - -Shader "Hidden/Crest/Simulation/Update Shadow" +Shader "Hidden/Crest/Obsolete/Simulation/Update Shadow" { - SubShader - { - PackageRequirements - { - "com.unity.render-pipelines.high-definition" - } - - Tags { "RenderPipeline"="HDRenderPipeline" } - - Pass - { - HLSLPROGRAM - #pragma vertex Vertex - #pragma fragment Fragment - - // #pragma enable_d3d11_debug_symbols - - // SHADOW_ULTRA_LOW uses Gather which is 4.5. HDRP minimum is 5.0 so this is fine. - #pragma target 4.5 - - // TODO: We might be able to expose this to give developers the option. - // #pragma multi_compile SHADOW_ULTRA_LOW SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH - - // Ultra low uses Gather to filter which should be same cost as not filtering. See algorithms per keyword: - // Runtime/Lighting/Shadow/HDShadowAlgorithms.hlsl - #define SHADOW_ULTRA_LOW - #define AREA_SHADOW_LOW - #define PUNCTUAL_SHADOW_ULTRA_LOW - #define DIRECTIONAL_SHADOW_ULTRA_LOW - - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" - #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl" - - float4x4 _Crest_ViewProjectionMatrix; - - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl" - - m_CrestNameSpace - - half SampleShadows(const float4 i_positionWS) - { - // Get directional light data. By definition we only have one directional light casting shadow. - DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex]; - HDShadowContext context = InitShadowContext(); - - // Zeros are for screen space position and world space normal which are for filtering and normal bias - // respectively. They did not appear to have an impact. - half shadows = GetDirectionalShadowAttenuation(context, 0, i_positionWS.xyz, 0, _DirectionalShadowIndex, -light.forward); - // Apply shadow strength from main light. - shadows = LerpWhiteTo(shadows, light.shadowDimmer); - - return shadows; - } - - half ComputeShadowFade(const float4 i_positionWS) - { - // TODO: Work out shadow fade. - return 0.0; - } - - m_CrestNameSpaceEnd - ENDHLSL - } - } - - SubShader - { - PackageRequirements - { - "com.unity.render-pipelines.universal" - } - - Tags { "RenderPipeline"="UniversalPipeline" } - - Pass - { - HLSLPROGRAM - - #pragma vertex Vertex - #pragma fragment Fragment - // #pragma enable_d3d11_debug_symbols - - // Maybe this is the equivalent of the SHADOW_COLLECTOR_PASS define? Inspired from com.unity.render-pipelines.universal/Shaders/Utils/ScreenSpaceShadows.shader - #define _MAIN_LIGHT_SHADOWS_CASCADE - #define MAIN_LIGHT_CALCULATE_SHADOWS - - #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" - #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" - - #define CREST_SAMPLE_SHADOW_HARD - - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl" - - m_CrestNameSpace - - half SampleShadows(const float4 i_positionWS) - { - // Includes soft shadows if _SHADOWS_SOFT is defined (requires multi-compile pragma). - return MainLightRealtimeShadow(TransformWorldToShadowCoord(i_positionWS.xyz)); - } - - half ComputeShadowFade(const float4 i_positionWS) - { - return GetShadowFade(i_positionWS.xyz); - } - - m_CrestNameSpaceEnd - ENDHLSL - } - } - - SubShader - { - Pass - { - HLSLPROGRAM - #pragma vertex Vertex - #pragma fragment Fragment - - #pragma multi_compile_shadowcollector - - // #pragma enable_d3d11_debug_symbols - - #define CREST_SAMPLE_SHADOW_HARD - #define d_Crest_ReceiveShadowsTransparent 1 - - #include "UnityCG.cginc" - - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl" - - m_CrestNameSpace - - half SampleShadows(const float4 i_positionWS) - { - // NOTE: "Shadow Projection > Close Fit" can still produce artefacts when away from caster, but this - // appears to be an improvement over the compute shader. - float4 shadowCoord = GET_SHADOW_COORDINATES(i_positionWS); - half shadows = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, shadowCoord); - if (_Crest_ClearShadows) shadows = 1.0; - shadows = lerp(_LightShadowData.r, 1.0, shadows); - - return shadows; - } - - half ComputeShadowFade(const float4 i_positionWS) - { - float z = dot(i_positionWS.xyz - _WorldSpaceCameraPos.xyz, unity_CameraToWorld._m02_m12_m22); - float fadeDistance = UnityComputeShadowFadeDistance(i_positionWS.xyz, z); - float fade = UnityComputeShadowFade(fadeDistance); - return fade; - } - - m_CrestNameSpaceEnd - ENDHLSL - } - } + // Replaced with UpdateShadow.compute. } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl index 5184fb453..fbdb22702 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl @@ -106,7 +106,7 @@ { \ result = Sample##name(uv); \ } \ - else if (_Index < _Count) \ + else if ((_Index + 1) < _Count) \ { \ const Cascade cascade = Cascade::Make##name(_Index + 1, this); \ const float3 uv = cascade.WorldToUV(i_Position); \ @@ -128,7 +128,7 @@ { \ result = Sample##name(i_UV); \ } \ - else if (_Index < _Count) \ + else if ((_Index + 1) < _Count) \ { \ const Cascade cascade = Cascade::Make##name(_Index + 1, this); \ const float3 uv = cascade.WorldToUV(UVToWorld(i_UV)); \ diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl index 10994c83e..772ec85e0 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl @@ -42,9 +42,6 @@ #define CREST_SSS_MAXIMUM 0.6 #define CREST_SSS_RANGE 0.12 -// Note: Must match k_MaskBelowSurfaceCull in UnderwaterRenderer.Mask.cs. -// Fog rendered from below and before transparents and water tile is culled. -#define CREST_MASK_BELOW_SURFACE_CULLED -2.0 // Note: Must match k_MaskBelowSurface in UnderwaterRenderer.Mask.cs. // Fog rendered from below. #define CREST_MASK_BELOW_SURFACE -1.0 @@ -62,6 +59,7 @@ // used to scale the meniscus as it is calculate using a pixel offset which can make the meniscus large at a distance. #define MENISCUS_MAXIMUM_DISTANCE 15.0 +#define k_Crest_MaskInsidePortal 5 #if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON) #define CREST_HANDLE_XR 1 diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl index 62d606fee..c2e1b0a44 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl @@ -12,6 +12,8 @@ SamplerState LODData_linear_clamp_sampler; SamplerState LODData_point_clamp_sampler; SamplerState sampler_Crest_linear_repeat; +SamplerState _Crest_linear_clamp_sampler; + CBUFFER_START(CrestPerFrame) float3 g_Crest_WaterCenter; float g_Crest_WaterScale; @@ -31,6 +33,7 @@ int g_Crest_ForceUnderwater; float3 g_Crest_PrimaryLightDirection; float3 g_Crest_PrimaryLightIntensity; +bool g_Crest_PrimaryLightHasCookie; float g_Crest_DynamicSoftShadowsFactor; @@ -39,7 +42,7 @@ bool g_Crest_SampleScatteringSimulation; // Motion Vector Parameters float g_Crest_WaterScaleChange; -float3 g_Crest_WaterCenterDelta; +float2 g_Crest_WaterCenterDelta; // Shifting Origin #if (CREST_SHIFTING_ORIGIN != 0) diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl index 5b5746656..3bc7b279c 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl @@ -90,21 +90,27 @@ void PosToSliceIndices } } -bool IsUnderwater(const bool i_FrontFace, const int i_ForceUnderwater) +bool IsUnderWater(const bool i_FrontFace, const int i_ForceUnderwater) { + bool underwater = false; + // We are well below water. if (i_ForceUnderwater == 1) { - return true; + underwater = true; } - // We are well above water. - if (i_ForceUnderwater == 2) + else if (i_ForceUnderwater == 2) { - return false; + underwater = false; + } + // Use facing. + else + { + underwater = !i_FrontFace; } - return !i_FrontFace; + return underwater; } float FeatherWeightFromUV(const float2 i_uv, const half i_featherWidth) diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl index 9271bdf1b..99be4866e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl @@ -9,15 +9,10 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" -CBUFFER_START(CrestChunkInstanceData) -uint _Crest_LodIndex; -float _Crest_ChunkMeshScaleAlpha; -float _Crest_ChunkMeshScaleAlphaSource; -float _Crest_ChunkGeometryGridWidth; -float _Crest_ChunkGeometryGridWidthSource; -float _Crest_ChunkFarNormalsWeight; -float2 _Crest_ChunkNormalScrollSpeed; -CBUFFER_END +// NOTE: Unity does not recognize uint in FrameDebugger. It will be under Floats +// with incorrect values. Change to int for debugging. +uint _Crest_LodIndex; + Texture2DArray g_Crest_CascadeAbsorption; m_DisplacementTexture(Texture2DArray, 4) g_Crest_CascadeAnimatedWaves; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl index ea3410778..48bb0e5e7 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl @@ -31,6 +31,12 @@ type Fragment(m_Crest::Varyings i_Input) : SV_Target \ return m_Crest::Fragment(i_Input); \ } +#define m_CrestFragmentVariant(type, name) \ +type Fragment(m_Crest::Varyings i_Input) : SV_Target \ +{ \ + return m_Crest::name(i_Input); \ +} + #define m_CrestFragmentWithFrontFace(type) \ type Fragment(m_Crest::Varyings i_Input, const bool i_IsFrontFace : SV_IsFrontFace) : SV_Target \ { \ @@ -69,4 +75,10 @@ void Crest##name(uint3 id : SV_DispatchThreadID) \ m_Crest::name(uint3(id.xy, g_Crest_LodCount - 1 - id.z)); \ } +// Cross render pipeline kernels. +#define m_CrestKernelXRP(name) \ +[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void Crest##name##BRP(uint3 id : SV_DispatchThreadID) { m_Crest::name(id); } \ +[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void Crest##name##HRP(uint3 id : SV_DispatchThreadID) { m_Crest::name(id); } \ +[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void Crest##name##URP(uint3 id : SV_DispatchThreadID) { m_Crest::name(id); } \ + #endif // CREST_MACROS_H diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl index 755738913..e0fe16020 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl @@ -7,10 +7,13 @@ // // WaveHarmonic.Crest.Editor.ShaderSettings: static fields // +#define CREST_PACKAGE_HDRP (1) +#define CREST_PACKAGE_URP (1) #define CREST_PORTALS (0) #define CREST_SHIFTING_ORIGIN (0) -#define CREST_SHADOWS_BUILT_IN_RENDER_PIPELINE (1) #define CREST_FULL_PRECISION_DISPLACEMENT (1) +#define CREST_DISCARD_ATMOSPHERIC_SCATTERING (1) +#define CREST_LEGACY_UNDERWATER (0) #endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl new file mode 100644 index 000000000..e94a647fb --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl @@ -0,0 +1,48 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Utility_Helpers +#define d_WaveHarmonic_Utility_Helpers + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Macros.hlsl" + +m_UtilityNameSpace + +void Swap(inout float a, inout float b) +{ + float t = a; a = b; b = t; +} + +// Adapted from: +// https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf +float3 ScreenSpaceDither(const float2 i_ScreenPosition) +{ + // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. + float3 dither = dot(float2(171.0, 231.0), i_ScreenPosition.xy); + dither.rgb = frac(dither.rgb / float3(103.0, 71.0, 97.0)) - float3(0.5, 0.5, 0.5); + return (dither.rgb / 255.0); +} + +float2 WorldNormalToScreenDirection(const float3 i_PositionWS, const float3 i_NormalWS, const float4x4 i_MatrixVP, const float i_Offset) +{ + const float3 p0 = i_PositionWS; + const float3 p1 = p0 + i_NormalWS * i_Offset; + + const float4 clip0 = mul(i_MatrixVP, float4(p0, 1)); + const float4 clip1 = mul(i_MatrixVP, float4(p1, 1)); + + const float2 uv0 = (clip0.xy / clip0.w) * 0.5 + 0.5; + const float2 uv1 = (clip1.xy / clip1.w) * 0.5 + 0.5; + + float2 direction = normalize(uv1 - uv0); + +#if UNITY_UV_STARTS_AT_TOP + direction.y = -direction.y; +#endif + + return direction; +} + +m_UtilityNameSpaceEnd + +#endif // d_WaveHarmonic_Utility_Helpers diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl.meta new file mode 100644 index 000000000..5057f0e50 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 90443daddb561477ca109fbfe1d80fdd +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl index 3515e6fcf..0fc2a485a 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl @@ -1,257 +1,4 @@ // Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. -// This file is subject to the Unity Companion License: -// https://github.com/Unity-Technologies/Graphics/blob/7ff8fd444c179fd9bb380d61f4865be6935b47dd/LICENSE.md - -// Adds functions from SRP. - -// Adapted from: -// https://github.com/Unity-Technologies/Graphics/blob/8f54e6591e93fb3bf8e9879a0e43665dfbe2f629/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl - -#ifndef UNITY_COMMON_INCLUDED -#define UNITY_COMMON_INCLUDED - -// Add "real" alias for "fixed". Helps with including files downstream. - -#define real fixed -#define real2 fixed2 -#define real3 fixed3 -#define real4 fixed4 - -// Commented lines have no "fixed" equivalent. - -#define real2x2 fixed2x2 -// #define real2x3 fixed2x3 -// #define real2x4 fixed2x4 -// #define real3x2 fixed3x2 -#define real3x3 fixed3x3 -// #define real3x4 fixed3x4 -// #define real4x3 fixed4x3 -#define real4x4 fixed4x4 - -// -// MACROS -// - -#define ZERO_INITIALIZE(type, name) UNITY_INITIALIZE_OUTPUT(type,name) -#define TransformObjectToHClip(positionOS) UnityObjectToClipPos(float4(positionOS, 1.0)) - -// Taken from: -// com.unity.render-pipelines.core@10.5.0/ShaderLibrary/API/D3D11.hlsl -// com.unity.render-pipelines.core@10.5.0/ShaderLibrary/API/Metal.hlsl -// com.unity.render-pipelines.core@10.5.0/ShaderLibrary/API/Switch.hlsl -// com.unity.render-pipelines.core@10.5.0/ShaderLibrary/API/Vulkan.hlsl - -// GameCore, PSSL etc require an NDA so hard to confirm how some of these APIs are implemented, but the PPv2 package has -// some of APIs (the ones we use) and they are the same: -// com.unity.postprocessing/PostProcessing/Shaders/API/ - -// Texture abstraction. - -#define TEXTURE2D(textureName) UNITY_DECLARE_TEX2D_NOSAMPLER(textureName) -#define TEXTURE2D_ARRAY(textureName) UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(textureName) -#define TEXTURECUBE(textureName) UNITY_DECLARE_TEXCUBE_NOSAMPLER(textureName) -// #define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName -// #define TEXTURE3D(textureName) Texture3D textureName - -// #ifdef SHADER_API_D3D11 - -// #define TEXTURE2D_FLOAT(textureName) TEXTURE2D(textureName) -// #define TEXTURE2D_ARRAY_FLOAT(textureName) TEXTURE2D_ARRAY(textureName) -// #define TEXTURECUBE_FLOAT(textureName) TEXTURECUBE(textureName) -// #define TEXTURECUBE_ARRAY_FLOAT(textureName) TEXTURECUBE_ARRAY(textureName) -// #define TEXTURE3D_FLOAT(textureName) TEXTURE3D(textureName) - -// #define TEXTURE2D_HALF(textureName) TEXTURE2D(textureName) -// #define TEXTURE2D_ARRAY_HALF(textureName) TEXTURE2D_ARRAY(textureName) -// #define TEXTURECUBE_HALF(textureName) TEXTURECUBE(textureName) -// #define TEXTURECUBE_ARRAY_HALF(textureName) TEXTURECUBE_ARRAY(textureName) -// #define TEXTURE3D_HALF(textureName) TEXTURE3D(textureName) - -// #else // !SHADER_API_D3D11 - -// #define TEXTURE2D_FLOAT(textureName) Texture2D_float textureName -// #define TEXTURE2D_ARRAY_FLOAT(textureName) Texture2DArray_float textureName -// #define TEXTURECUBE_FLOAT(textureName) TextureCube_float textureName -// #define TEXTURECUBE_ARRAY_FLOAT(textureName) TextureCubeArray_float textureName -// #define TEXTURE3D_FLOAT(textureName) Texture3D_float textureName - -// #define TEXTURE2D_HALF(textureName) Texture2D_half textureName -// #define TEXTURE2D_ARRAY_HALF(textureName) Texture2DArray_half textureName -// #define TEXTURECUBE_HALF(textureName) TextureCube_half textureName -// #define TEXTURECUBE_ARRAY_HALF(textureName) TextureCubeArray_half textureName -// #define TEXTURE3D_HALF(textureName) Texture3D_half textureName - -// #endif // SHADER_API_D3D11 - -// #define TEXTURE2D_SHADOW(textureName) TEXTURE2D(textureName) -// #define TEXTURE2D_ARRAY_SHADOW(textureName) TEXTURE2D_ARRAY(textureName) -// #define TEXTURECUBE_SHADOW(textureName) TEXTURECUBE(textureName) -// #define TEXTURECUBE_ARRAY_SHADOW(textureName) TEXTURECUBE_ARRAY(textureName) - -#define RW_TEXTURE2D(type, textureName) RWTexture2D textureName -#define RW_TEXTURE2D_ARRAY(type, textureName) RWTexture2DArray textureName -// #define RW_TEXTURE3D(type, textureName) RWTexture3D textureName - -#define SAMPLER(samplerName) SamplerState samplerName -// #define SAMPLER_CMP(samplerName) SamplerComparisonState samplerName -// #define ASSIGN_SAMPLER(samplerName, samplerValue) samplerName = samplerValue - -// #define TEXTURE2D_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER(samplerName) -// #define TEXTURE2D_ARRAY_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER(samplerName) -// #define TEXTURECUBE_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER(samplerName) -// #define TEXTURECUBE_ARRAY_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER(samplerName) -// #define TEXTURE3D_PARAM(textureName, samplerName) TEXTURE3D(textureName), SAMPLER(samplerName) - -// #define TEXTURE2D_SHADOW_PARAM(textureName, samplerName) TEXTURE2D(textureName), SAMPLER_CMP(samplerName) -// #define TEXTURE2D_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURE2D_ARRAY(textureName), SAMPLER_CMP(samplerName) -// #define TEXTURECUBE_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE(textureName), SAMPLER_CMP(samplerName) -// #define TEXTURECUBE_ARRAY_SHADOW_PARAM(textureName, samplerName) TEXTURECUBE_ARRAY(textureName), SAMPLER_CMP(samplerName) - -// #define TEXTURE2D_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURE2D_ARRAY_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURECUBE_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURECUBE_ARRAY_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURE3D_ARGS(textureName, samplerName) textureName, samplerName - -// #define TEXTURE2D_SHADOW_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURE2D_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURECUBE_SHADOW_ARGS(textureName, samplerName) textureName, samplerName -// #define TEXTURECUBE_ARRAY_SHADOW_ARGS(textureName, samplerName) textureName, samplerName - -// We cannot use Unity's macros because they change the samplerName and it needs to be unchanged. -#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2) -#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod) -// #define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias) -// #define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy) -#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index)) -// #define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod) -// #define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias) -// #define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy) -// #define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) -// #define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) -// #define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias) -// #define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index)) -// #define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod) -// #define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias) -// #define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3) -// #define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod) - -// #define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z) -// #define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z) -// #define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord4).xyz, (coord4).w) -// #define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w) - -#undef SAMPLE_DEPTH_TEXTURE -// #undef SAMPLE_DEPTH_TEXTURE_LOD -#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r -// #define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r - -#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0)) -// #define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) textureName.Load(int3(unCoord2, lod)) -// #define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex) -#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) textureName.Load(int4(unCoord2, index, 0)) -// #ifndef SHADER_API_SWITCH -// #define LOAD_TEXTURE2D_ARRAY_MSAA(textureName, unCoord2, index, sampleIndex) textureName.Load(int3(unCoord2, index), sampleIndex) -// #endif -// #define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) textureName.Load(int4(unCoord2, index, lod)) -// #define LOAD_TEXTURE3D(textureName, unCoord3) textureName.Load(int4(unCoord3, 0)) -// #define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod)) - -// #define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2) -// #define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index)) -// #define GATHER_TEXTURECUBE(textureName, samplerName, coord3) textureName.Gather(samplerName, coord3) -// #define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index)) -// #define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2) -// #define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2) -// #define GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherBlue(samplerName, coord2) -// #define GATHER_ALPHA_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherAlpha(samplerName, coord2) - -// Generates a triangle in homogeneous clip space, s.t. -// v0 = (-1, -1, 1), v1 = (3, -1, 1), v2 = (-1, 3, 1). -float2 GetFullScreenTriangleTexCoord(uint vertexID) -{ -#if UNITY_UV_STARTS_AT_TOP - return float2((vertexID << 1) & 2, 1.0 - (vertexID & 2)); -#else - return float2((vertexID << 1) & 2, vertexID & 2); -#endif -} - -float4 GetFullScreenTriangleVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE) -{ - float2 uv = float2((vertexID << 1) & 2, vertexID & 2); - return float4(uv * 2.0 - 1.0, z, 1.0); -} - -#endif // UNITY_COMMON_INCLUDED - -// -// FUNCTIONS -// - -// Keep the following unguarded - -// Taken and modified from: -// com.unity.render-pipelines.core@12.0.0/ShaderLibrary/Common.hlsl -float4 CrestComputeClipSpacePosition(float2 positionNDC, float deviceDepth) -{ - float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0); - // positionCS.y was flipped here but that is SRP specific to solve flip baked into matrix. - return positionCS; -} - -// Taken and modified from: -// com.unity.render-pipelines.core@12.0.0/ShaderLibrary/Common.hlsl -float3 CrestComputeWorldSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invViewProjMatrix) -{ - float4 positionCS = CrestComputeClipSpacePosition(positionNDC, deviceDepth); - float4 hpositionWS = mul(invViewProjMatrix, positionCS); - return hpositionWS.xyz / hpositionWS.w; -} - -// Taken from: -// com.unity.render-pipelines.core@12.0.0/ShaderLibrary/Common.hlsl -float3 CrestComputeWorldSpacePosition(float4 positionCS, float4x4 invViewProjMatrix) -{ - float4 hpositionWS = mul(invViewProjMatrix, positionCS); - return hpositionWS.xyz / hpositionWS.w; -} - -#undef ComputeClipSpacePosition -#undef ComputeWorldSpacePosition - -// Replace these with our own as ComputeClipSpacePosition flips the Y which is not correct for BIRP. -#define ComputeClipSpacePosition CrestComputeClipSpacePosition -#define ComputeWorldSpacePosition CrestComputeWorldSpacePosition - -// Taken from: -// com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl -real3 CrestUnpackNormalmapRGorAG(real4 packednormal) -{ - // This do the trick - packednormal.x *= packednormal.w; - - real3 normal; - normal.xy = packednormal.xy * 2 - 1; - normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy))); - return normal; -} - -// Taken from: -// com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl -inline real3 CrestUnpackNormal(real4 packednormal) -{ -#if defined(UNITY_NO_DXT5nm) - return packednormal.xyz * 2 - 1; -#elif defined(UNITY_ASTC_NORMALMAP_ENCODING) - return UnpackNormalDXT5nm(packednormal); -#else - return CrestUnpackNormalmapRGorAG(packednormal); -#endif -} - -#undef UnpackNormal - -// Replace these to solve Unity bug "ambiguous call to 'UnpackNormalmapRGorAG'" -#define UnpackNormal CrestUnpackNormal +// Empty. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl index a07e1025f..8d2de128c 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl @@ -1,75 +1,35 @@ // Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. -// This file is subject to the Unity Companion License: -// https://github.com/Unity-Technologies/Graphics/blob/7ff8fd444c179fd9bb380d61f4865be6935b47dd/LICENSE.md +// Builds on Unity's shim for Shader Graph. -// Adds functions from SRP. +#define BUILTIN_TARGET_API 1 -// Adapted from: -// https://github.com/Unity-Technologies/Graphics/blob/8f54e6591e93fb3bf8e9879a0e43665dfbe2f629/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Core.hlsl -// https://github.com/Unity-Technologies/Graphics/blob/7ff8fd444c179fd9bb380d61f4865be6935b47dd/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/TextureXR.hlsl +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/ShaderPass.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl" +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Shim/Shims.hlsl" +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Core.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" -#ifndef BUILTIN_PIPELINE_CORE_INCLUDED -#define BUILTIN_PIPELINE_CORE_INCLUDED +#ifndef d_WaveHarmonic_Utility_LegacyCore +#define d_WaveHarmonic_Utility_LegacyCore -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl" -// Stereo-related bits -#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +// +// Inputs +// - #define SLICE_ARRAY_INDEX unity_StereoEyeIndex +#undef UNITY_MATRIX_I_VP - #define COORD_TEXTURE2D_X(pixelCoord) uint3(pixelCoord, SLICE_ARRAY_INDEX) - - #define TEXTURE2D_X(textureName) TEXTURE2D_ARRAY(textureName) - // #define TEXTURE2D_X_PARAM(textureName, samplerName) TEXTURE2D_ARRAY_PARAM(textureName, samplerName) - // #define TEXTURE2D_X_ARGS(textureName, samplerName) TEXTURE2D_ARRAY_ARGS(textureName, samplerName) - // #define TEXTURE2D_X_HALF(textureName) TEXTURE2D_ARRAY_HALF(textureName) - // #define TEXTURE2D_X_FLOAT(textureName) TEXTURE2D_ARRAY_FLOAT(textureName) - - #define RW_TEXTURE2D_X(type, textureName) RW_TEXTURE2D_ARRAY(type, textureName) - - #define LOAD_TEXTURE2D_X(textureName, unCoord2) LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, SLICE_ARRAY_INDEX) - // #define LOAD_TEXTURE2D_X_LOD(textureName, unCoord2, lod) LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, SLICE_ARRAY_INDEX, lod) - #define SAMPLE_TEXTURE2D_X(textureName, samplerName, coord2) SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, SLICE_ARRAY_INDEX) - // #define SAMPLE_TEXTURE2D_X_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, SLICE_ARRAY_INDEX, lod) - // #define GATHER_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, SLICE_ARRAY_INDEX) - // #define GATHER_RED_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_RED_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX)) - // #define GATHER_GREEN_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_GREEN_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX)) - // #define GATHER_BLUE_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_BLUE_TEXTURE2D(textureName, samplerName, float3(coord2, SLICE_ARRAY_INDEX)) - -#else // UNITY_STEREO - - #define SLICE_ARRAY_INDEX 0 - - #define COORD_TEXTURE2D_X(pixelCoord) pixelCoord - - #define TEXTURE2D_X(textureName) TEXTURE2D(textureName) - // #define TEXTURE2D_X_PARAM(textureName, samplerName) TEXTURE2D_PARAM(textureName, samplerName) - // #define TEXTURE2D_X_ARGS(textureName, samplerName) TEXTURE2D_ARGS(textureName, samplerName) - // #define TEXTURE2D_X_HALF(textureName) TEXTURE2D_HALF(textureName) - // #define TEXTURE2D_X_FLOAT(textureName) TEXTURE2D_FLOAT(textureName) - - #define RW_TEXTURE2D_X RW_TEXTURE2D - - #define LOAD_TEXTURE2D_X(textureName, unCoord2) LOAD_TEXTURE2D(textureName, unCoord2) - // #define LOAD_TEXTURE2D_X_LOD(textureName, unCoord2, lod) LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) - #define SAMPLE_TEXTURE2D_X(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2) - // #define SAMPLE_TEXTURE2D_X_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) - // #define GATHER_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_TEXTURE2D(textureName, samplerName, coord2) - // #define GATHER_RED_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) - // #define GATHER_GREEN_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) - // #define GATHER_BLUE_TEXTURE2D_X(textureName, samplerName, coord2) GATHER_BLUE_TEXTURE2D(textureName, samplerName, coord2) - -#endif // UNITY_STEREO - -// Helper macro to assign view index during compute/ray pass (usually from SV_DispatchThreadID or DispatchRaysIndex()) -#if defined(SHADER_STAGE_COMPUTE) || defined(SHADER_STAGE_RAY_TRACING) - #if defined(UNITY_STEREO_INSTANCING_ENABLED) - #define UNITY_XR_ASSIGN_VIEW_INDEX(viewIndex) unity_StereoEyeIndex = viewIndex; - #else - #define UNITY_XR_ASSIGN_VIEW_INDEX(viewIndex) - #endif +#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON) +float4x4 _Crest_StereoInverseViewProjection[2]; +#define UNITY_MATRIX_I_VP _Crest_StereoInverseViewProjection[unity_StereoEyeIndex] +#else +float4x4 _Crest_InverseViewProjection; +#define UNITY_MATRIX_I_VP _Crest_InverseViewProjection #endif -#endif // BUILTIN_PIPELINE_CORE_INCLUDED +// Not set and _ScreenParams.zw is "1.0 + 1.0 / _ScreenParams.xy" +#define _ScreenSize float4(_ScreenParams.xy, float2(1.0, 1.0) / _ScreenParams.xy) + +#endif // d_WaveHarmonic_Utility_LegacyCore diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl new file mode 100644 index 000000000..f7c590f2f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl @@ -0,0 +1,111 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Utility_ShaderGraphDefines +#define d_WaveHarmonic_Utility_ShaderGraphDefines + +// +// Defines +// + +#ifdef _BUILTIN_SPECULAR_SETUP +#define _SPECULAR_SETUP _BUILTIN_SPECULAR_SETUP +#endif + +#ifdef _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS +#define _TRANSPARENT_RECEIVES_SHADOWS _BUILTIN_TRANSPARENT_RECEIVES_SHADOWS +#endif + + +// +// Passes +// + +#define SHADERPASS_FORWARD_ADD (20) +#define SHADERPASS_DEFERRED (21) +#define SHADERPASS_MOTION_VECTORS (22) + + +// +// Deferred Fix +// + +#if (defined(SHADER_API_GLES3) && !defined(SHADER_API_DESKTOP)) || defined(SHADER_API_GLES) || defined(SHADER_API_N3DS) + #define UNITY_ALLOWED_MRT_COUNT 4 +#else + #define UNITY_ALLOWED_MRT_COUNT 8 +#endif + +// Required on Windows (and possibly others) to prevent tiling. +#undef UNITY_SAMPLE_FULL_SH_PER_PIXEL +#define UNITY_SAMPLE_FULL_SH_PER_PIXEL 1 + + +// +// Stereo Instancing Fix +// + +#if defined(STEREO_INSTANCING_ON) && (defined(SHADER_API_D3D11) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE) || defined(SHADER_API_PSSL) || defined(SHADER_API_VULKAN) || (defined(SHADER_API_METAL) && !defined(UNITY_COMPILER_DXC))) +#define UNITY_STEREO_INSTANCING_ENABLED +#endif + +#if defined(STEREO_MULTIVIEW_ON) && (defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE) || defined(SHADER_API_VULKAN)) && !(defined(SHADER_API_SWITCH)) +#define UNITY_STEREO_MULTIVIEW_ENABLED +#endif + +// Redeclared their includes to insert shadow declarations at the right spot. +// Adapted from: +// Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Shim/Shims.hlsl + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + +// Duplicate define in Macros.hlsl +#if defined (TRANSFORM_TEX) +#undef TRANSFORM_TEX +#endif + +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) +#undef GLOBAL_CBUFFER_START +#if defined(UNITY_STEREO_MULTIVIEW_ENABLED) || ((defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_STEREO_INSTANCING_ENABLED)) && (defined(SHADER_API_GLCORE) || defined(SHADER_API_GLES3) || defined(SHADER_API_METAL))) + #define GLOBAL_CBUFFER_START(name) cbuffer name { + #define GLOBAL_CBUFFER_END } +#else + #define GLOBAL_CBUFFER_START(name) CBUFFER_START(name) + #define GLOBAL_CBUFFER_END CBUFFER_END +#endif +#endif + +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Shim/HLSLSupportShim.hlsl" + +// Fix wrong definitions. +#undef UNITY_SAMPLE_TEX2DARRAY +#define UNITY_SAMPLE_TEX2DARRAY(tex,coord) SAMPLE_TEXTURE2D_ARRAY(tex, sampler##tex, coord.xy, coord.z) + + +// +// Transparent Objects Receives Shadows +// + +#if _SURFACE_TYPE_TRANSPARENT +#if _TRANSPARENT_RECEIVES_SHADOWS +#if SHADERPASS == SHADERPASS_FORWARD || SHADERPASS == SHADERPASS_FORWARD_ADD +#if DIRECTIONAL || DIRECTIONAL_COOKIE +#if !SHADOWS_SCREEN + +StructuredBuffer _Crest_WorldToShadow; + +// Declarations for shadow collector. +UNITY_DECLARE_SHADOWMAP(_ShadowMapTexture); +float4 _ShadowMapTexture_TexelSize; +#define SHADOWMAPSAMPLER_DEFINED 1 +#define SHADOWMAPSAMPLER_AND_TEXELSIZE_DEFINED 1 + +#define d_Crest_ShadowsOverriden 1 + +#endif +#endif +#endif +#endif +#endif + +#endif // d_WaveHarmonic_Utility_ShaderGraphDefines diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl.meta new file mode 100644 index 000000000..a33dbe022 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d26727ac31d94682896ffbfdc685804 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl index 7b40cd953..0fc2a485a 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl @@ -1,18 +1,4 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. -// Defines missing inputs. - -float4x4 _Crest_InverseViewProjection; -float4x4 _Crest_InverseViewProjectionRight; - -#undef UNITY_MATRIX_I_VP - -#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON) -#define UNITY_MATRIX_I_VP (unity_StereoEyeIndex == 0 ? _Crest_InverseViewProjection : _Crest_InverseViewProjectionRight) -#else -#define UNITY_MATRIX_I_VP _Crest_InverseViewProjection -#endif - -// Not set and _ScreenParams.zw is "1.0 + 1.0 / _ScreenParams.xy" -#define _ScreenSize float4(_ScreenParams.xy, float2(1.0, 1.0) / _ScreenParams.xy) +// Empty. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl new file mode 100644 index 000000000..ff204997f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl @@ -0,0 +1,109 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/LegacyBuilding.hlsl" + +// +// Transparent Objects Receives Shadows +// + +#if d_Crest_ShadowsOverriden + +#define unity_WorldToShadow _Crest_WorldToShadow + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl" + +#if defined(SHADER_API_MOBILE) +#define m_UnitySampleShadowmap_PCF UnitySampleShadowmap_PCF5x5 +#else +#define m_UnitySampleShadowmap_PCF UnitySampleShadowmap_PCF7x7 +#endif + +// Same as UnityComputeShadowFadeDistance, except it uses keywords. +float ComputeShadowFadeDistance(float3 positionWS, float viewZ) +{ + // Use keyword instead of unity_ShadowFadeCenterAndType.w, as we are already + // dependent on keywords anyway. + return +#if SHADOWS_SPLIT_SPHERES + distance(positionWS, unity_ShadowFadeCenterAndType.xyz); +#else + viewZ; +#endif +} + +float GetShadows(float3 positionWS, float4 uvLightMap) +{ + float viewZ = -UnityWorldToViewPos(positionWS).z; + float4 weights = GET_CASCADE_WEIGHTS(positionWS, viewZ); + float4 coordinates = GET_SHADOW_COORDINATES(float4(positionWS, 1.0), weights); +#if SHADOWS_SOFT + half shadow = m_UnitySampleShadowmap_PCF(coordinates, 0); +#else + half shadow = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, coordinates); +#endif + shadow = lerp(_LightShadowData.r, 1.0, shadow); + + // Shadow Mask + mixed sun + static +#if LIGHTMAP_ON && SHADOWS_SHADOWMASK && LIGHTMAP_SHADOW_MIXING + float fade = UnityComputeShadowFade(ComputeShadowFadeDistance(positionWS, viewZ)); + half mask = UnitySampleBakedOcclusion(uvLightMap.xy, positionWS); + shadow = UnityMixRealtimeAndBakedShadows(shadow, mask, fade); +#endif + + return shadow; +} + +#ifdef DIRECTIONAL +#undef UNITY_LIGHT_ATTENUATION +#define UNITY_LIGHT_ATTENUATION(destName, input, worldPos) \ + fixed destName = GetShadows(worldPos, input.lmap); +#endif + +#ifdef DIRECTIONAL_COOKIE +#undef UNITY_LIGHT_ATTENUATION +#define UNITY_LIGHT_ATTENUATION(destName, input, worldPos) \ + DECLARE_LIGHT_COORD(input, worldPos); \ + fixed destName = tex2D(_LightTexture0, lightCoord).w * GetShadows(worldPos, input.lmap); +#endif + +#endif // d_Crest_ShadowsOverriden + + +// +// Specular +// + +#ifdef _SPECULAR_SETUP +#define SurfaceOutputStandard SurfaceOutputStandardSpecular +#define BuildStandardSurfaceOutput BuildStandardSpecularSurfaceOutput +#define LightingStandard LightingStandardSpecular +#define LightingStandard_GI LightingStandardSpecular_GI +#define LightingStandard_Deferred LightingStandardSpecular_Deferred + +#if SHADERPASS == SHADERPASS_FORWARD_ADD +#undef LightingStandard +#define LightingStandard(x, y, z) LightingStandardSpecular(x, y, z); c.rgb += o.Emission; +#endif +#endif + +#ifndef _SPECULAR_SETUP +#if SHADERPASS == SHADERPASS_FORWARD_ADD +#define LightingStandard(x, y, z) LightingStandard(x, y, z); c.rgb += o.Emission; +#endif // SHADERPASS_FORWARD_ADD +#endif // _SPECULAR_SETUP + +SurfaceOutputStandardSpecular BuildStandardSpecularSurfaceOutput(SurfaceDescription surfaceDescription, InputData inputData) +{ + SurfaceData surface = SurfaceDescriptionToSurfaceData(surfaceDescription); + + SurfaceOutputStandardSpecular o = (SurfaceOutputStandardSpecular)0; + o.Albedo = surface.albedo; + o.Normal = inputData.normalWS; + o.Specular = surface.specular; + o.Smoothness = surface.smoothness; + o.Occlusion = surface.occlusion; + o.Emission = surface.emission; + o.Alpha = surface.alpha; + return o; +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl.meta new file mode 100644 index 000000000..8ca1507d1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/LegacyBuilding.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5eab24690c4a74ceca26a143da611306 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl new file mode 100644 index 000000000..6c7b065b0 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl @@ -0,0 +1,51 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// TODO: +// #if defined(USING_STEREO_MATRICES) +// float4x4 _StereoNonJitteredVP[2]; +// float4x4 _StereoPreviousVP[2]; +// #else +// float4x4 _NonJitteredVP; +// float4x4 _PreviousVP; +// #endif + +float4x4 _PreviousM; +float4x4 _PreviousVP; +float4x4 _NonJitteredVP; + +bool _HasLastPositionData; +bool _ForceNoMotion; +float _MotionVectorDepthBias; + +#undef UNITY_PREV_MATRIX_M +#define UNITY_PREV_MATRIX_M _PreviousM +#define _PrevViewProjMatrix _PreviousVP +#define _NonJitteredViewProjMatrix _NonJitteredVP + +// X : Use last frame positions (right now skinned meshes are the only objects that use this +// Y : Force No Motion +// Z : Z bias value +const static float4 unity_MotionVectorsParams = float4(_HasLastPositionData, !_ForceNoMotion, _MotionVectorDepthBias, 0); + +// Unity will populate this, but could not see when in source. +float4 _LastTime; + +// We want to gather some internal data from the BuildVaryings call to +// avoid rereading and recalculating these values again in the ShaderGraph motion vector pass +struct MotionVectorPassOutput +{ + float3 positionOS; + float3 positionWS; +}; + +SurfaceDescription BuildSurfaceDescription(Varyings varyings) +{ + SurfaceDescriptionInputs surfaceDescriptionInputs = BuildSurfaceDescriptionInputs(varyings); + SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs); + return surfaceDescription; +} + +// Very hacky, but works! +#define BuildVaryings(content) BuildVaryings(content, inout MotionVectorPassOutput motionVectorOutput) +#define TransformObjectToWorld(content) TransformObjectToWorld(content); motionVectorOutput.positionOS = input.positionOS; motionVectorOutput.positionWS = positionWS; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl.meta new file mode 100644 index 000000000..b1712a873 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorCommon.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1eacca53c60984c4a8cadb624777e644 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl new file mode 100644 index 000000000..1db22e6a3 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl @@ -0,0 +1,159 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// Adapted from: +// Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/MotionVectorPass.hlsl + +// This file is subject to the Unity Companion License: +// https://github.com/Unity-Technologies/Graphics/blob/61584ec20cf305929dae85cec7b94ff2ed3942f3/LICENSE.md + +#ifndef SG_MOTION_VECTORS_PASS_INCLUDED +#define SG_MOTION_VECTORS_PASS_INCLUDED + +#undef BuildVaryings +#undef TransformObjectToWorld + +float2 CalcNdcMotionVectorFromCsPositions(float4 posCS, float4 prevPosCS) +{ + // Note: unity_MotionVectorsParams.y is 0 is forceNoMotion is enabled + bool forceNoMotion = unity_MotionVectorsParams.y == 0.0; + if (forceNoMotion) + return float2(0.0, 0.0); + + // Non-uniform raster needs to keep the posNDC values in float to avoid additional conversions + // since uv remap functions use floats + float2 posNDC = posCS.xy * rcp(posCS.w); + float2 prevPosNDC = prevPosCS.xy * rcp(prevPosCS.w); + + float2 velocity; + { + // Calculate forward velocity + velocity = (posNDC.xy - prevPosNDC.xy); + #if UNITY_UV_STARTS_AT_TOP + velocity.y = -velocity.y; + #endif + + // Convert velocity from NDC space (-1..1) to UV 0..1 space + // Note: It doesn't mean we don't have negative values, we store negative or positive offset in UV space. + // Note: ((posNDC * 0.5 + 0.5) - (prevPosNDC * 0.5 + 0.5)) = (velocity * 0.5) + velocity.xy *= 0.5; + } + + return velocity; +} + +struct MotionVectorPassAttributes +{ + float3 previousPositionOS : TEXCOORD4; // Contains previous frame local vertex position (for skinned meshes) +}; + +// Note: these will have z == 0.0f in the pixel shader to save on bandwidth +struct MotionVectorPassVaryings +{ + float4 positionCSNoJitter; + float4 previousPositionCSNoJitter; +}; + +struct PackedMotionVectorPassVaryings +{ + float3 positionCSNoJitter : CLIP_POSITION_NO_JITTER; + float3 previousPositionCSNoJitter : PREVIOUS_CLIP_POSITION_NO_JITTER; +}; + +PackedMotionVectorPassVaryings PackMotionVectorVaryings(MotionVectorPassVaryings regularVaryings) +{ + PackedMotionVectorPassVaryings packedVaryings; + packedVaryings.positionCSNoJitter = regularVaryings.positionCSNoJitter.xyw; + packedVaryings.previousPositionCSNoJitter = regularVaryings.previousPositionCSNoJitter.xyw; + return packedVaryings; +} + +MotionVectorPassVaryings UnpackMotionVectorVaryings(PackedMotionVectorPassVaryings packedVaryings) +{ + MotionVectorPassVaryings regularVaryings; + regularVaryings.positionCSNoJitter = float4(packedVaryings.positionCSNoJitter.xy, 0, packedVaryings.positionCSNoJitter.z); + regularVaryings.previousPositionCSNoJitter = float4(packedVaryings.previousPositionCSNoJitter.xy, 0, packedVaryings.previousPositionCSNoJitter.z); + return regularVaryings; +} + +float3 GetLastFrameDeformedPosition(Attributes input, MotionVectorPassOutput currentFrameMvData, float3 previousPositionOS) +{ + Attributes lastFrameInputAttributes = input; + lastFrameInputAttributes.positionOS = previousPositionOS; + + VertexDescriptionInputs lastFrameVertexDescriptionInputs = BuildVertexDescriptionInputs(lastFrameInputAttributes); +#if defined(AUTOMATIC_TIME_BASED_MOTION_VECTORS) && defined(GRAPH_VERTEX_USES_TIME_PARAMETERS_INPUT) + lastFrameVertexDescriptionInputs.TimeParameters = _LastTime.yxz; +#endif + + VertexDescription lastFrameVertexDescription = VertexDescriptionFunction(lastFrameVertexDescriptionInputs); + previousPositionOS = lastFrameVertexDescription.Position.xyz; + + return previousPositionOS; +} + +// ------------------------------------- +// Vertex +void vert( + Attributes input, + MotionVectorPassAttributes passInput, + out PackedMotionVectorPassVaryings packedMvOutput, + out PackedVaryings packedOutput) +{ + Varyings output = (Varyings)0; + MotionVectorPassVaryings mvOutput = (MotionVectorPassVaryings)0; + MotionVectorPassOutput currentFrameMvData = (MotionVectorPassOutput)0; + output = BuildVaryings(input, currentFrameMvData); + packedOutput = PackVaryings(output); + + const bool forceNoMotion = unity_MotionVectorsParams.y == 0.0; + + if (!forceNoMotion) + { + const bool hasDeformation = unity_MotionVectorsParams.x == 1; // Mesh has skinned deformation + float3 previousPositionOS = hasDeformation ? passInput.previousPositionOS : input.positionOS; + + #if defined(AUTOMATIC_TIME_BASED_MOTION_VECTORS) && defined(GRAPH_VERTEX_USES_TIME_PARAMETERS_INPUT) + const bool applyDeformation = true; + #else + const bool applyDeformation = hasDeformation; + #endif + +#if defined(FEATURES_GRAPH_VERTEX) + if (applyDeformation) + previousPositionOS = GetLastFrameDeformedPosition(input, currentFrameMvData, previousPositionOS); + else + previousPositionOS = currentFrameMvData.positionOS; + + #if defined(FEATURES_GRAPH_VERTEX_MOTION_VECTOR_OUTPUT) + previousPositionOS -= currentFrameMvData.motionVector; + #endif +#endif + + mvOutput.positionCSNoJitter = mul(_NonJitteredViewProjMatrix, float4(currentFrameMvData.positionWS, 1.0f)); + mvOutput.previousPositionCSNoJitter = mul(_PrevViewProjMatrix, mul(UNITY_PREV_MATRIX_M, float4(previousPositionOS, 1.0f))); + } + + packedMvOutput = PackMotionVectorVaryings(mvOutput); +} + +// ------------------------------------- +// Fragment +float4 frag( + // Note: packedMvInput needs to be before packedInput as otherwise we get the following error in the speed tree 8 SG: + // "Non system-generated input signature parameter () cannot appear after a system generated value" + PackedMotionVectorPassVaryings packedMvInput, + PackedVaryings packedInput) : SV_Target +{ + Varyings input = UnpackVaryings(packedInput); + MotionVectorPassVaryings mvInput = UnpackMotionVectorVaryings(packedMvInput); + UNITY_SETUP_INSTANCE_ID(input); + SurfaceDescription surfaceDescription = BuildSurfaceDescription(input); + +#if defined(_ALPHATEST_ON) + clip(surfaceDescription.Alpha - surfaceDescription.AlphaClipThreshold); +#endif + + return float4(CalcNdcMotionVectorFromCsPositions(mvInput.positionCSNoJitter, mvInput.previousPositionCSNoJitter), 0, 0); +} +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl.meta new file mode 100644 index 000000000..10831fff1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/MotionVectorPass.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ae5323918c4b24b5c87c6f941810e225 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl index 7c67b1b50..7fd90a7fe 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl @@ -1,4 +1,5 @@ // Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. // Copyright (c) 2016 Unity Technologies // @@ -19,24 +20,9 @@ // 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. -// Screen-space shadow helpers. - -// Taken and adapted from: +// Taken from: // 2020.3.12f1/DefaultResourcesExtra/Internal-ScreenSpaceShadows.shader -// Main changes is that now only world position is required. Specialised for the shadow LOD data. - -// Add multi_compile_shadowcollector pragma to get SHADOWS_SPLIT_SPHERES and SHADOWS_SINGLE_CASCADE. -// https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html - -// SHADOWS_SCREEN + SHADOWS_CUBE will never be triggered for transparency, but -// Unity still compiles the variant which causes compiler errors. -#if defined(_SURFACE_TYPE_TRANSPARENT) && !defined(SHADERGRAPH_PREVIEW) && !defined(SHADOWS_SCREEN) && !defined(SHADOWS_CUBE) -#define d_Crest_ReceiveShadowsTransparent 1 -#endif - -#if d_Crest_ReceiveShadowsTransparent - #include "UnityShadowLibrary.cginc" #ifndef SHADOWMAPSAMPLER_DEFINED @@ -49,30 +35,27 @@ float4 _ShadowMapTexture_TexelSize; #endif #endif - // // Keywords based defines // #if defined (SHADOWS_SPLIT_SPHERES) - #define GET_CASCADE_WEIGHTS(wpos) getCascadeWeights_splitSpheres(wpos) + #define GET_CASCADE_WEIGHTS(wpos, z) getCascadeWeights_splitSpheres(wpos) #else - #define GET_CASCADE_WEIGHTS(wpos) getCascadeWeights(wpos) + #define GET_CASCADE_WEIGHTS(wpos, z) getCascadeWeights( wpos, z ) #endif #if defined (SHADOWS_SINGLE_CASCADE) - #define GET_SHADOW_COORDINATES(wpos) getShadowCoord_SingleCascade(wpos) + #define GET_SHADOW_COORDINATES(wpos,cascadeWeights) getShadowCoord_SingleCascade(wpos) #else - #define GET_SHADOW_COORDINATES(wpos) getShadowCoord(wpos) + #define GET_SHADOW_COORDINATES(wpos,cascadeWeights) getShadowCoord(wpos,cascadeWeights) #endif /** * Gets the cascade weights based on the world position of the fragment. * Returns a float4 with only one component set that corresponds to the appropriate cascade. */ -inline fixed4 getCascadeWeights(float3 wpos) +inline fixed4 getCascadeWeights(float3 wpos, float z) { - // Calculate depth. Normally this would be depth from the depth buffer. - float z = dot(wpos - _WorldSpaceCameraPos.xyz, unity_CameraToWorld._m02_m12_m22); fixed4 zNear = float4( z >= _LightSplitsNear ); fixed4 zFar = float4( z < _LightSplitsFar ); fixed4 weights = zNear * zFar; @@ -99,9 +82,8 @@ inline fixed4 getCascadeWeights_splitSpheres(float3 wpos) * Returns the shadowmap coordinates for the given fragment based on the world position and z-depth. * These coordinates belong to the shadowmap atlas that contains the maps for all cascades. */ -inline float4 getShadowCoord(float4 wpos) +inline float4 getShadowCoord( float4 wpos, fixed4 cascadeWeights ) { - fixed4 cascadeWeights = GET_CASCADE_WEIGHTS(wpos.xyz); float3 sc0 = mul (unity_WorldToShadow[0], wpos).xyz; float3 sc1 = mul (unity_WorldToShadow[1], wpos).xyz; float3 sc2 = mul (unity_WorldToShadow[2], wpos).xyz; @@ -119,7 +101,5 @@ inline float4 getShadowCoord(float4 wpos) */ inline float4 getShadowCoord_SingleCascade( float4 wpos ) { - return float4(mul(unity_WorldToShadow[0], wpos).xyz, 0); + return float4( mul (unity_WorldToShadow[0], wpos).xyz, 0); } - -#endif // d_Crest_ReceiveShadowsTransparent diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl index 2f1fc1d3b..a96a589f8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl @@ -9,55 +9,54 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" -TEXTURE2D_X(_Crest_ScreenSpaceShadowTexture); -float4 _Crest_ScreenSpaceShadowTexture_TexelSize; - #if CREST_URP #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" // Unity renamed keyword. #ifdef USE_FORWARD_PLUS #define USE_CLUSTER_LIGHT_LOOP USE_FORWARD_PLUS +#endif // USE_FORWARD_PLUS + +#ifdef FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK +#define CLUSTER_LIGHT_LOOP_SUBTRACTIVE_LIGHT_CHECK FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK +#endif // FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK + +#if UNITY_VERSION >= 60000000 +#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON) +#if _ALPHATEST_ON +#if !USE_CLUSTER_LIGHT_LOOP +// If not clustered and additional light shadows and XR, the shading model +// completely breaks. It is like shadow attenuation is NaN or some obscure +// compiler issue. For 2022.3, it is broken for forward+ only, but cannot be fixed. +#define d_ShadowMaskBroken 1 +#else +#if _RECEIVE_SHADOWS_OFF +// Right eye broken rendering similar to above. +#define d_AdditionalLightsBroken 1 #endif +#endif +#endif +#endif +#endif + #endif // CREST_URP #if CREST_HDRP #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" -#ifndef SHADERGRAPH_PREVIEW -#if CREST_HDRP_FORWARD_PASS -#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl" -#endif -#endif - #if UNITY_VERSION < 202310 #define GetMeshRenderingLayerMask GetMeshRenderingLightLayer -#endif +#endif // UNITY_VERSION #if UNITY_VERSION < 60000000 #if PROBE_VOLUMES_L1 #define AMBIENT_PROBE_BUFFER 1 -#endif +#endif // PROBE_VOLUMES_L1 +#endif // UNITY_VERSION #endif // CREST_HDRP m_CrestNameSpace -// TODO: Move -void ApplyIndirectLightingMultiplier -( - inout half3 io_AmbientLight -) -{ - // Allows control of baked lighting through volume framework. -#ifndef SHADERGRAPH_PREVIEW - // We could create a BuiltinData struct which would have rendering layers on it, but it seems more complicated. - io_AmbientLight *= GetIndirectDiffuseMultiplier(GetMeshRenderingLayerMask()); -#endif -} -#else // CREST_HDRP -m_CrestNameSpace -#endif - void PrimaryLight ( const float3 i_PositionWS, @@ -82,72 +81,46 @@ void PrimaryLight o_Direction = normalize(UnityWorldSpaceLightDir(i_PositionWS)); #else o_Direction = _WorldSpaceLightPos0.xyz; + // Prevents divide by zero. + if (all(o_Direction == 0)) o_Direction = half3(0.0, 1.0, 0.0); #endif o_Color = _LightColor0.rgb; +#if SHADERPASS == SHADERPASS_FORWARD_ADD +#if !SHADOWS_SCREEN + // FIXME: undeclared identifier 'IN' in Pass: BuiltIn ForwardAdd, Vertex program with DIRECTIONAL SHADOWS_SCREEN + UNITY_LIGHT_ATTENUATION(attenuation, IN, i_PositionWS) + o_Color *= attenuation; +#endif +#endif #endif } -void AmbientLight(out half3 o_AmbientLight) +half3 AmbientLight(const half3 i_AmbientLight) +{ + half3 ambient = i_AmbientLight; + +#ifndef SHADERGRAPH_PREVIEW +#if CREST_HDRP + // Allows control of baked lighting through volume framework. + // We could create a BuiltinData struct which would have rendering layers on it, but it seems more complicated. + ambient *= GetIndirectDiffuseMultiplier(GetMeshRenderingLayerMask()); +#endif // CREST_HDRP +#endif // SHADERGRAPH_PREVIEW + + return ambient; +} + +half3 AmbientLight() { // Use the constant term (0th order) of SH stuff - this is the average. - o_AmbientLight = + const half3 ambient = #if AMBIENT_PROBE_BUFFER half3(_AmbientProbeData[0].w, _AmbientProbeData[1].w, _AmbientProbeData[2].w); #else half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w); #endif -#if CREST_HDRP - ApplyIndirectLightingMultiplier(o_AmbientLight); -#endif -} - -// Position: SRP = WS / BIRP = SS (z ignored) -half PrimaryLightShadows(const float3 i_Position) -{ - // Unshadowed. - half shadow = 1; - -#if CREST_URP - // We could skip GetMainLight but this is recommended approach which is likely more robust to API changes. - float4 shadowCoord = TransformWorldToShadowCoord(i_Position); - Light light = GetMainLight(TransformWorldToShadowCoord(i_Position)); - shadow = light.shadowAttenuation; -#endif - -#ifndef SHADERGRAPH_PREVIEW -#if CREST_HDRP_FORWARD_PASS - DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex]; - HDShadowContext context = InitShadowContext(); - context.directionalShadowData = _HDDirectionalShadowData[_DirectionalShadowIndex]; - - float3 positionWS = GetCameraRelativePositionWS(i_Position); - // From Unity: - // > With XR single-pass and camera-relative: offset position to do lighting computations from the combined center view (original camera matrix). - // > This is required because there is only one list of lights generated on the CPU. Shadows are also generated once and shared between the instanced views. - ApplyCameraRelativeXR(positionWS); - - // TODO: Pass in screen space position and scene normal. - shadow = GetDirectionalShadowAttenuation - ( - context, - 0, // positionSS - positionWS, - 0, // normalWS - light.shadowIndex, - -light.forward - ); - - // Apply shadow strength from main light. - shadow = LerpWhiteTo(shadow, light.shadowDimmer); -#endif // CREST_HDRP_FORWARD_PASS -#endif // SHADERGRAPH_PREVIEW - -#if CREST_BIRP - shadow = LOAD_TEXTURE2D_X(_Crest_ScreenSpaceShadowTexture, min(i_Position.xy, _Crest_ScreenSpaceShadowTexture_TexelSize.zw - 1.0)).r; -#endif - - return shadow; + return AmbientLight(ambient); } half3 AdditionalLighting(const float3 i_PositionWS, const float4 i_ScreenPosition, const float2 i_StaticLightMapUV) @@ -156,32 +129,38 @@ half3 AdditionalLighting(const float3 i_PositionWS, const float4 i_ScreenPositio #if CREST_URP #if defined(_ADDITIONAL_LIGHTS) + InputData inputData = (InputData)0; + inputData.normalizedScreenSpaceUV = i_ScreenPosition.xy / i_ScreenPosition.w; + inputData.positionWS = i_PositionWS; // Shadowmask. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON) - half4 shadowMask = SAMPLE_SHADOWMASK(i_StaticLightMapUV); -#elif !defined(LIGHTMAP_ON) - half4 shadowMask = unity_ProbesOcclusion; -#else - half4 shadowMask = half4(1, 1, 1, 1); + inputData.shadowMask = SAMPLE_SHADOWMASK(i_StaticLightMapUV); #endif + const half4 shadowMask = CalculateShadowMask(inputData); + + // No AO, but we need the struct. + AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData.normalizedScreenSpaceUV, 0.0); + uint pixelLightCount = GetAdditionalLightsCount(); #ifdef _LIGHT_LAYERS uint meshRenderingLayers = GetMeshRenderingLayer(); #endif -#if USE_CLUSTER_LIGHT_LOOP - InputData inputData = (InputData)0; - // For Foward+ LIGHT_LOOP_BEGIN macro uses inputData.normalizedScreenSpaceUV and inputData.positionWS. - inputData.normalizedScreenSpaceUV = i_ScreenPosition.xy / i_ScreenPosition.w; - inputData.positionWS = i_PositionWS; -#endif - LIGHT_LOOP_BEGIN(pixelLightCount) // Includes shadows and cookies. - Light light = GetAdditionalLight(lightIndex, i_PositionWS, shadowMask); + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); + +#if d_ShadowMaskBroken + light.shadowAttenuation = 1.0; +#endif + +#if d_AdditionalLightsBroken + light.color = 0.0; +#endif + #ifdef _LIGHT_LAYERS if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) #endif @@ -189,9 +168,29 @@ LIGHT_LOOP_BEGIN(pixelLightCount) color += light.color * (light.distanceAttenuation * light.shadowAttenuation); } LIGHT_LOOP_END + +#if USE_CLUSTER_LIGHT_LOOP + // Additional directional lights. + [loop] for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++) + { + CLUSTER_LIGHT_LOOP_SUBTRACTIVE_LIGHT_CHECK + + Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor); + +#ifdef _LIGHT_LAYERS + if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers)) +#endif + { + color += light.color * (light.distanceAttenuation * light.shadowAttenuation); + } + } +#endif // USE_CLUSTER_LIGHT_LOOP #endif // _ADDITIONAL_LIGHTS #endif // CREST_URP + // HDRP todo. + // BIRP has additional lights as additional passes. Handled elsewhere. + return color; } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP.meta new file mode 100644 index 000000000..3d9a0b0c4 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a381e15a67ba0474ea0e685cc27a6f8a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl new file mode 100644 index 000000000..587d65f48 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl @@ -0,0 +1,71 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Utility_RenderPipeline_Compute +#define d_WaveHarmonic_Utility_RenderPipeline_Compute + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" + +// Compute does not have an equivalent of PackageRequirements. +// We must handle it ourselves. + +// Fallback to BIRP if HDRP package missing. +#if _HRP +#if (CREST_PACKAGE_HDRP != 1) +#undef _HRP +#define _BRP 1 +#endif +#endif + +// Fallback to BIRP if URP package missing. +#if _URP +#if (CREST_PACKAGE_URP != 1) +#undef _URP +#define _BRP 1 +#endif +#endif + +#if _BRP +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" +#endif + +#if _HRP +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" +#endif + +#if _URP +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" +#endif + + +// +// Stereo Rendering +// + +// Unity 6 only, but had compilation errors for non HDRP anyway: +// #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureXR.hlsl" + +#ifndef RW_TEXTURE2D_X +#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) + #define COORD_TEXTURE2D_X(pixelCoord) uint3(pixelCoord, SLICE_ARRAY_INDEX) + #define RW_TEXTURE2D_X(type, textureName) RW_TEXTURE2D_ARRAY(type, textureName) +#else // UNITY_STEREO + #define COORD_TEXTURE2D_X(pixelCoord) pixelCoord + #define RW_TEXTURE2D_X RW_TEXTURE2D +#endif // UNITY_STEREO +#endif // RW_TEXTURE2D_X + +#ifndef UNITY_XR_ASSIGN_VIEW_INDEX +// Helper macro to assign view index during compute/ray pass (usually from SV_DispatchThreadID or DispatchRaysIndex()) +#if defined(SHADER_STAGE_COMPUTE) || defined(SHADER_STAGE_RAY_TRACING) + #if defined(UNITY_STEREO_INSTANCING_ENABLED) + #define UNITY_XR_ASSIGN_VIEW_INDEX(viewIndex) unity_StereoEyeIndex = viewIndex; + #else + #define UNITY_XR_ASSIGN_VIEW_INDEX(viewIndex) + #endif +#endif +#endif // UNITY_XR_ASSIGN_VIEW_INDEX + +#endif // d_WaveHarmonic_Utility_RenderPipeline_Compute diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl.meta new file mode 100644 index 000000000..3c17dd1c9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 68cb1a44e787e45bd9de666d527b10f2 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP.meta new file mode 100644 index 000000000..a54fbc993 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de25b8cb31cac9b4db1835b9632de8db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl new file mode 100644 index 000000000..d67b0eb4e --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl @@ -0,0 +1,12 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Utility_RenderPipeline_HDRP_Common +#define d_WaveHarmonic_Utility_RenderPipeline_HDRP_Common + +#define LoadSceneColor LoadCameraColor +#define LoadSceneDepth LoadCameraDepth +#define SampleSceneColor SampleCameraColor +#define SampleSceneDepth SampleCameraDepth + +#endif // d_WaveHarmonic_Utility_RenderPipeline_HDRP_Common diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl.meta new file mode 100644 index 000000000..1e5e64663 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 327c164f365e1468789c5950ac945e17 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl new file mode 100644 index 000000000..df7900179 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl @@ -0,0 +1,107 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Utility_RenderPipeline_Shadows +#define d_WaveHarmonic_Utility_RenderPipeline_Shadows + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Macros.hlsl" + +#if _BRP +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl" + +bool _Crest_ClearShadows; +#endif + +#if _HRP +// TODO: We might be able to expose this to give developers the option. +// #pragma multi_compile SHADOW_ULTRA_LOW SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH + +// Ultra low uses Gather to filter which should be same cost as not filtering. See algorithms per keyword: +// Runtime/Lighting/Shadow/HDShadowAlgorithms.hlsl +#define SHADOW_ULTRA_LOW +#define AREA_SHADOW_LOW +#define PUNCTUAL_SHADOW_ULTRA_LOW +#define DIRECTIONAL_SHADOW_ULTRA_LOW + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl" +#endif + +#if _URP +// Maybe this is the equivalent of the SHADOW_COLLECTOR_PASS define? +// Inspired from com.unity.render-pipelines.universal/Shaders/Utils/ScreenSpaceShadows.shader +#define _MAIN_LIGHT_SHADOWS_CASCADE +#define MAIN_LIGHT_CALCULATE_SHADOWS + +#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" +#endif + +m_UtilityNameSpace + +#if _BRP +half SampleShadows(const float4 i_positionWS) +{ + // NOTE: "Shadow Projection > Close Fit" can still produce artefacts when away from caster, but this + // appears to be an improvement over the compute shader. + + // Calculate depth. Normally this would be depth from the depth buffer. + float z = dot(i_positionWS.xyz - _WorldSpaceCameraPos.xyz, unity_CameraToWorld._m02_m12_m22); + + float4 weights = GET_CASCADE_WEIGHTS(i_positionWS.xyz, z); + float4 shadowCoord = GET_SHADOW_COORDINATES(i_positionWS, weights); + half shadows = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, shadowCoord); + if (_Crest_ClearShadows) shadows = 1.0; + shadows = lerp(_LightShadowData.r, 1.0, shadows); + + return shadows; +} + +half ComputeShadowFade(const float4 i_positionWS) +{ + float z = dot(i_positionWS.xyz - _WorldSpaceCameraPos.xyz, unity_CameraToWorld._m02_m12_m22); + float fadeDistance = UnityComputeShadowFadeDistance(i_positionWS.xyz, z); + float fade = UnityComputeShadowFade(fadeDistance); + return fade; +} +#endif + +#if _HRP +half SampleShadows(const float4 i_positionWS) +{ + // Get directional light data. By definition we only have one directional light casting shadow. + DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex]; + HDShadowContext context = InitShadowContext(); + + // Zeros are for screen space position and world space normal which are for filtering and normal bias + // respectively. They did not appear to have an impact. + half shadows = GetDirectionalShadowAttenuation(context, 0, i_positionWS.xyz, 0, _DirectionalShadowIndex, -light.forward); + // Apply shadow strength from main light. + shadows = LerpWhiteTo(shadows, light.shadowDimmer); + + return shadows; +} + +half ComputeShadowFade(const float4 i_positionWS) +{ + // TODO: Work out shadow fade. + return 0.0; +} +#endif + +#if _URP +half SampleShadows(const float4 i_positionWS) +{ + // Includes soft shadows if _SHADOWS_SOFT is defined (requires multi-compile pragma). + return MainLightRealtimeShadow(TransformWorldToShadowCoord(i_positionWS.xyz)); +} + +half ComputeShadowFade(const float4 i_positionWS) +{ + return GetShadowFade(i_positionWS.xyz); +} +#endif + +m_UtilityNameSpaceEnd + +#endif // d_WaveHarmonic_Utility_RenderPipeline_Shadows diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl.meta new file mode 100644 index 000000000..db96a6b5c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 07d6b2cd79ac04fa5b56cffd5fb1bb31 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl new file mode 100644 index 000000000..c5e7193bd --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl @@ -0,0 +1,85 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef CREST_SHADOWS_H +#define CREST_SHADOWS_H + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" + +#if CREST_BIRP +TEXTURE2D_X(_Crest_ScreenSpaceShadowTexture); +float4 _Crest_ScreenSpaceShadowTexture_TexelSize; +#endif // CREST_BIRP + +#if CREST_URP +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" +#endif // CREST_URP + +#if CREST_HDRP +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + +#ifndef SHADERGRAPH_PREVIEW +#if CREST_HDRP_FORWARD_PASS +#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl" +#endif // CREST_HDRP_FORWARD_PASS +#endif // SHADERGRAPH_PREVIEW +#endif // CREST_HDRP + +m_CrestNameSpace + +// Position: SRP = WS / BIRP = SS (z ignored) +half PrimaryLightShadows(const float3 i_Position, const float2 i_ScreenPosition) +{ + // Unshadowed. + half shadow = 1; + +#if CREST_URP + // We could skip GetMainLight but this is recommended approach which is likely more robust to API changes. + float4 shadowCoord = TransformWorldToShadowCoord(i_Position); + Light light = GetMainLight(TransformWorldToShadowCoord(i_Position)); + shadow = light.shadowAttenuation; +#endif + +#ifndef SHADERGRAPH_PREVIEW +#if CREST_HDRP_FORWARD_PASS + DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex]; + HDShadowContext context = InitShadowContext(); + context.directionalShadowData = _HDDirectionalShadowData[_DirectionalShadowIndex]; + + float3 positionWS = GetCameraRelativePositionWS(i_Position); + // From Unity: + // > With XR single-pass and camera-relative: offset position to do lighting computations from the combined center view (original camera matrix). + // > This is required because there is only one list of lights generated on the CPU. Shadows are also generated once and shared between the instanced views. + ApplyCameraRelativeXR(positionWS); + + // TODO: Pass in screen space position and scene normal. + shadow = GetDirectionalShadowAttenuation + ( + context, + 0, // positionSS + positionWS, + 0, // normalWS + light.shadowIndex, + -light.forward + ); + + // Apply shadow strength from main light. + shadow = LerpWhiteTo(shadow, light.shadowDimmer); +#endif // CREST_HDRP_FORWARD_PASS +#endif // SHADERGRAPH_PREVIEW + +#if CREST_BIRP + shadow = LOAD_TEXTURE2D_X(_Crest_ScreenSpaceShadowTexture, min(i_ScreenPosition, _Crest_ScreenSpaceShadowTexture_TexelSize.zw - 1.0)).r; +#if DIRECTIONAL_COOKIE + const half attenuation = tex2D(_LightTexture0, mul(unity_WorldToLight, float4(i_Position, 1.0)).xy).w; + shadow = min(attenuation, shadow); +#endif +#endif + + return shadow; +} + +m_CrestNameSpaceEnd + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl.meta new file mode 100644 index 000000000..974f25f9a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b4623a51d04ef4e9c82e9196bf28e48d +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus.meta new file mode 100644 index 000000000..9bb1541c0 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7bf6aebdc1c0f3f47bad2841e2a11446 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl new file mode 100644 index 000000000..3eaf2374f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl @@ -0,0 +1,69 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_Meniscus +#define d_WaveHarmonic_Crest_Meniscus + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" + +float2 _Crest_HorizonNormal; + +TEXTURE2D_X(_Crest_WaterMaskTexture); + +m_CrestNameSpace + +struct Attributes +{ + uint id : SV_VertexID; + UNITY_VERTEX_INPUT_INSTANCE_ID +}; + +struct Varyings +{ + float4 positionCS : SV_POSITION; + UNITY_VERTEX_OUTPUT_STEREO +}; + +Varyings Vertex(Attributes input) +{ + Varyings output; + ZERO_INITIALIZE(Varyings, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + output.positionCS = GetFullScreenTriangleVertexPosition(input.id, UNITY_RAW_FAR_CLIP_VALUE); + return output; +} + +half4 Fragment(Varyings input) +{ + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + + const uint2 positionSS = input.positionCS.xy; + const float mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).x; + const float2 offset = -((float2)mask) * _Crest_HorizonNormal; + float weight = 1.0; + + // Sample three pixels along the normal. If the sample is different than the + // current mask, apply meniscus. Offset must be added to positionSS as floats. + [unroll] + for (int i = 1; i <= 3; i++) + { + const float2 uv = positionSS + offset * (float)i; + const float newMask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, uv).r; + weight *= newMask != mask && newMask != 0.0 ? 0.9 : 1.0; + } + + return weight; +} + +m_CrestNameSpaceEnd + +m_CrestVertex +m_CrestFragment(half4) + +#endif // d_WaveHarmonic_Crest_Meniscus diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl.meta new file mode 100644 index 000000000..048c390b2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0d256485a6a0c40f291276367afcede2 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl new file mode 100644 index 000000000..509a8c7d9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl @@ -0,0 +1,245 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_Meniscus +#define d_WaveHarmonic_Crest_Meniscus + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl" + +#if d_Masked +TEXTURE2D_X(_Crest_WaterMaskTexture); +#endif + +#if d_Crest_Lighting +// Surface/Volume parameters. +half4 _Crest_Absorption; +half4 _Crest_Scattering; +half _Crest_Anisotropy; +half _Crest_DirectTerm; +half _Crest_AmbientTerm; +half _Crest_ShadowsAffectsAmbientFactor; + +// Volume parameters. +half _Crest_SunBoost; +half3 _Crest_AmbientLighting; +int _Crest_DataSliceOffset; +#endif + +half _Crest_Radius; +half _Crest_RefractionStrength; + +m_CrestNameSpace + +struct Attributes +{ +#if d_Crest_Geometry + float3 positionOS : POSITION; +#else + uint id : SV_VertexID; +#endif + UNITY_VERTEX_INPUT_INSTANCE_ID +}; + +struct Varyings +{ + float4 positionCS : SV_POSITION; +#if d_Crest_Geometry + float3 positionWS : TEXCOORD; +#else + float2 uv : TEXCOORD; +#endif + UNITY_VERTEX_OUTPUT_STEREO +}; + +Varyings Vertex(Attributes input) +{ + Varyings output; + ZERO_INITIALIZE(Varyings, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + +#if d_Crest_Geometry + output.positionCS = TransformObjectToHClip(input.positionOS); + output.positionWS = TransformObjectToWorld(input.positionOS); +#else + output.positionCS = GetFullScreenTriangleVertexPosition(input.id); + output.uv = GetFullScreenTriangleTexCoord(input.id); +#endif + + return output; +} + +half4 Fragment(Varyings input) +{ + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + +#if d_Masked + // Prevent rendering inside of new portal modules. + if (LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, input.positionCS.xy).r == k_Crest_MaskInsidePortal) + { + discard; + } +#endif + + float3 positionWS; + float3 directionWS; + float2 uv; + +#if d_Crest_Geometry + { + positionWS = input.positionWS; +#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) + positionWS.xyz += _WorldSpaceCameraPos.xyz; +#endif + directionWS = GetWorldSpaceNormalizeViewDir(positionWS); + uv = input.positionCS.xy / _ScreenSize.xy; + } +#else + { + positionWS = ComputeWorldSpacePosition(input.uv, UNITY_NEAR_CLIP_VALUE, UNITY_MATRIX_I_VP); + +#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) + positionWS.xyz += _WorldSpaceCameraPos.xyz; +#endif + + directionWS = GetWorldSpaceNormalizeViewDir(positionWS); + + uv = input.uv; + } +#endif + + const float height = SampleWaterLineHeight(positionWS.xz).r; + + // Double as we half it if below. + float radius = _Crest_Radius * 2.0; + +#if d_Crest_Refraction + // Double the radius as aggressive falloff makes it much smaller. + radius *= 2.0; +#endif + + float signedDistance = positionWS.y - height; + + float3 viewDirWS = normalize(_WorldSpaceCameraPos - positionWS); + + const float distance = abs(signedDistance); + + if (signedDistance < 0) + { + radius = max(0.002, radius * 0.25); + } + + if (distance > radius) + { + discard; + } + + half3 color = 0.0; + +#if d_Crest_Lighting + { + half3 absorption = _Crest_Absorption.xyz; + half3 scattering = _Crest_Scattering.xyz; + + // Keep the same as the volume. + const int sliceIndex = clamp(_Crest_DataSliceOffset, 0, g_Crest_LodCount - 2); + + if (g_Crest_SampleAbsorptionSimulation) absorption = Cascade::MakeAbsorption(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz; + if (g_Crest_SampleScatteringSimulation) scattering = Cascade::MakeScattering(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz; + + float3 lightDirection; float3 lightColor; + PrimaryLight(positionWS, lightColor, lightDirection); + + const half3 extinction = VolumeExtinction(absorption, scattering); + + half opacity = 1.0; +#if !d_Crest_Refraction + // Meniscus can look too dark in shallow water. + { + const float depth = Cascade::MakeDepth(sliceIndex).SampleSignedDepthFromSeaLevel(_WorldSpaceCameraPos.xz); + opacity = VolumeOpacity(extinction, depth * 0.25); + } +#endif + + half shadow = 1.0; + { + // Soft in red, hard in green. But hard not computed in HDRP. + shadow = 1.0 - Cascade::MakeShadow(sliceIndex).SampleShadow(_WorldSpaceCameraPos.xz).x; + } + + half3 lighting = VolumeLighting + ( + extinction, + scattering, + _Crest_Anisotropy, + shadow, + lerp(half3(0, 1, 0), directionWS, opacity), + AmbientLight(_Crest_AmbientLighting), + lerp(half3(0, -1, 0), lightDirection, opacity), + lightColor, + half3(0.0, 0.0, 0.0), // Additional lights + _Crest_AmbientTerm, + _Crest_DirectTerm, + _Crest_SunBoost, + _Crest_ShadowsAffectsAmbientFactor + ); + +#if CREST_HDRP + lighting *= GetCurrentExposureMultiplier(); +#endif + + color = lighting; + } +#endif + + const float falloff = 1.0 - smoothstep(0.0, radius, distance); + +#if d_Crest_Refraction + { + const half3 normal = SampleWaterLineNormal(positionWS.xz, height); + float2 dir = Utility::WorldNormalToScreenDirection(positionWS, normal, UNITY_MATRIX_VP, 0.01); + + const float aspect = _ScreenParams.x / _ScreenParams.y; + dir.x /= aspect; + + const float2 uvRefracted = uv - dir * falloff * _Crest_RefractionStrength; + + half3 scene = SampleSceneColor(uvRefracted); + + if (signedDistance >= 0) + { + // Blend back in with original. Cannot seem to do this with alpha without losing + // some lighting. + scene = lerp + ( + scene, + SampleSceneColor(uv), + saturate((distance / radius) * 5.0) + ); + } + + color = lerp(color, scene, 0.5); + } +#endif + + return float4(color, falloff); +} + +m_CrestNameSpaceEnd + +m_CrestVertex +m_CrestFragment(half4) + +#endif // d_WaveHarmonic_Crest_Meniscus diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl.meta new file mode 100644 index 000000000..533fe5966 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f9eca4b9660d6423d89353a4148e9191 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader new file mode 100644 index 000000000..65de4fa0f --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader @@ -0,0 +1,594 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +Shader "Crest/Meniscus" +{ + Properties + { + _Crest_Radius("Radius", Range(0.001, 0.1)) = 0.01 + + [Space(10)] + + [Toggle(d_Crest_Refraction)] + _Crest_RefractionEnabled("Refraction", Integer) = 1 + _Crest_RefractionStrength("Refraction Strength", Range(0, 1)) = 0.2 + + [Space(10)] + + [Toggle(d_Crest_Lighting)] + _Crest_LightingEnabled("Lighting", Integer) = 1 + } + + HLSLINCLUDE + #pragma vertex Vertex + #pragma fragment Fragment + + // #pragma enable_d3d11_debug_symbols + ENDHLSL + + SubShader + { + PackageRequirements + { + "com.unity.render-pipelines.high-definition" + } + + Tags { "RenderPipeline"="HDRenderPipeline" } + + Blend SrcAlpha OneMinusSrcAlpha + ColorMask RGB + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Meniscus" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl" + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Masked)" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl" + + #define d_Masked 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front Face)" + + Cull Back + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl" + + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back Face)" + + Cull Front + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl" + + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + + // + // Obsolete. Depends on the raster mask. + // + + Pass + { + Name "Meniscus" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Portal)" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + + // Full-screen only applicable portals with back-faces. + #define d_Crest_HasBackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front Face)" + + Blend DstColor Zero + Cull Back + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_FrontFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back Face)" + + Blend DstColor Zero + Cull Front + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_BackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + } + + SubShader + { + PackageRequirements + { + "com.unity.render-pipelines.universal" + } + + Tags { "RenderPipeline"="UniversalPipeline" } + + Blend SrcAlpha OneMinusSrcAlpha + ColorMask RGB + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Meniscus" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Masked)" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" + + #define d_Masked 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front Face)" + + Cull Back + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" + + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back Face)" + + Cull Front + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" + + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + + // + // Obsolete. Depends on the raster mask. + // + + Pass + { + Name "Meniscus" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Portal)" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + + // Full-screen only applicable portals with back-faces. + #define d_Crest_HasBackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front Face)" + + Blend DstColor Zero + Cull Back + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_FrontFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back Face)" + + Blend DstColor Zero + Cull Front + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_BackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + } + + SubShader + { + Blend SrcAlpha OneMinusSrcAlpha + ColorMask RGB + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Meniscus" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareOpaqueTexture.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Masked)" + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + + #define d_Masked 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareOpaqueTexture.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front)" + + Cull Back + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareOpaqueTexture.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back)" + + Cull Front + ZTest LEqual + + HLSLPROGRAM + #pragma shader_feature_local_fragment _ d_Crest_Refraction + #pragma shader_feature_local_fragment _ d_Crest_Lighting + #define d_Crest_Geometry 1 + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareOpaqueTexture.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.hlsl" + ENDHLSL + } + + + // + // Obsolete. Depends on the raster mask. + // + + Pass + { + Name "Meniscus" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.Obsolete.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Portal)" + + Blend DstColor Zero + + HLSLPROGRAM + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + + // Full-screen only applicable portals with back-faces. + #define d_Crest_HasBackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Front Face)" + + Blend DstColor Zero + Cull Back + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_FrontFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Meniscus (Back Face)" + + Blend DstColor Zero + Cull Front + ZTest LEqual + + HLSLPROGRAM + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + + #define d_Crest_Geometry 1 + #define d_Crest_BackFace 1 + + #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Meniscus.hlsl" + ENDHLSL + } + } + + CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI" +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader.meta new file mode 100644 index 000000000..7660dcd08 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Meniscus/Meniscus.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ec7c774912c6f4b3cb6d73444cdedeca +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl new file mode 100644 index 000000000..42a6da350 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl @@ -0,0 +1,41 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_SurfaceData +#define d_WaveHarmonic_Crest_SurfaceData + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Utility.hlsl" + +TEXTURE2D_FLOAT(_Crest_WaterLine); +float _Crest_WaterLineTexel; +float2 _Crest_WaterLineResolution; +float2 _Crest_WaterLineSnappedPosition; + +m_CrestNameSpace + +float SampleWaterLineHeight(const float2 i_PositionWS) +{ + const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5; + return _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv, 0).r + g_Crest_WaterCenter.y; +} + +half3 SampleWaterLineNormal(const float2 i_PositionWS, const float i_Height) +{ + const float2 uv = (i_PositionWS - _Crest_WaterLineSnappedPosition) / (_Crest_WaterLineTexel * _Crest_WaterLineResolution) + 0.5; + const float3 dd = float3(1.0 / _Crest_WaterLineResolution.xy, 0.0); + const float xOffset = _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv + dd.xz, 0).r; + const float zOffset = _Crest_WaterLine.SampleLevel(_Crest_linear_clamp_sampler, uv + dd.zy, 0).r; + + return normalize(half3 + ( + (xOffset - i_Height) / _Crest_WaterLineTexel, + 1.0, + (zOffset - i_Height) / _Crest_WaterLineTexel + )); +} + +m_CrestNameSpaceEnd + +#endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl.meta new file mode 100644 index 000000000..367339736 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 23b1ac5d9553947b69f3b3cfa0e3551d +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl new file mode 100644 index 000000000..4148dc64a --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl @@ -0,0 +1,35 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_SurfaceFacing +#define d_WaveHarmonic_Crest_SurfaceFacing + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl" + +TEXTURE2D_X(_Crest_WaterMaskTexture); + +m_CrestNameSpace + +bool IsUnderWater(const bool i_FrontFace, const int i_ForceUnderwater, const uint2 i_PositionSS) +{ + bool underwater = false; + + // Use mask. + if (i_ForceUnderwater == 0) + { + underwater = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, i_PositionSS).r <= CREST_MASK_BELOW_SURFACE; + } + else + { + underwater = IsUnderWater(i_FrontFace, i_ForceUnderwater); + } + + return underwater; +} + +m_CrestNameSpaceEnd + +#endif // d_WaveHarmonic_Crest_SurfaceFacing diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl.meta new file mode 100644 index 000000000..9837f09f1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e6b28bd595bf6434facba01c0b5d41b9 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl new file mode 100644 index 000000000..fec0aeb9b --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl @@ -0,0 +1,67 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_SurfaceFog +#define d_WaveHarmonic_Crest_SurfaceFog + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" + +#define d_Crest_WaterSurface 1 + +#if (CREST_LEGACY_UNDERWATER != 1) +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl" +#endif + +m_CrestNameSpace + +#if (CREST_LEGACY_UNDERWATER != 0) +static bool s_IsUnderWater; +#endif + +void SetUpFog(bool i_Underwater, float3 i_PositionWS, float i_Multiplier, float i_FogDistance, half3 i_ViewWS, float2 i_PositionSS) +{ + s_IsUnderWater = i_Underwater; + +#if (CREST_LEGACY_UNDERWATER != 1) + s_PositionSS = i_PositionSS; + s_PositionWS = i_PositionWS; + s_ViewWS = i_ViewWS; + s_FogDistance = i_FogDistance; + s_DepthRaw = 0; + s_FogMultiplier = i_Multiplier; +#endif +} + +m_CrestNameSpaceEnd + +#if (CREST_LEGACY_UNDERWATER != 0) +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING != 0) + +#if CREST_BIRP +#ifdef UNITY_PASS_FORWARDADD +#define m_Unity_FogColor fixed4(0, 0, 0, 0) +#else +#define m_Unity_FogColor unity_FogColor +#endif // UNITY_PASS_FORWARDADD + +#undef UNITY_APPLY_FOG +#define UNITY_APPLY_FOG(coord, color) \ +if (!m_Crest::s_IsUnderWater) \ +{ \ + UNITY_APPLY_FOG_COLOR(coord, color, m_Unity_FogColor); \ +} +#endif // CREST_BIRP + +#if CREST_HDRP +#define EvaluateAtmosphericScattering(i, V, color) m_Crest::s_IsUnderWater ? color : EvaluateAtmosphericScattering(i, V, color) +#endif + +#if CREST_URP +#define MixFog(color, coord) m_Crest::s_IsUnderWater ? color : MixFog(color, coord) +#endif + +#endif // CREST_DISCARD_ATMOSPHERIC_SCATTERING +#endif // CREST_LEGACY_UNDERWATER + +#endif // d_WaveHarmonic_Crest_SurfaceFog diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl.meta new file mode 100644 index 000000000..9742b21d1 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 944710ebd91d247cca9b0a31307f6b87 +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fragment.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fragment.hlsl index 7878db793..0360294b8 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fragment.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fragment.hlsl @@ -30,6 +30,8 @@ // Guard against Shader Graph preview. #ifndef SHADERGRAPH_PREVIEW +#define d_Crest_WaterSurface 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" @@ -45,6 +47,8 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Flow.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Facing.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Normal.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Reflection.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl" @@ -53,19 +57,12 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fresnel.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Foam.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Alpha.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fog.hlsl" #if (CREST_PORTALS != 0) #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl" #endif -#if (CREST_SHADOWS_BUILT_IN_RENDER_PIPELINE != 0) -#if CREST_BIRP -#define SHADOWS_SPLIT_SPHERES 1 -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Shadows.hlsl" -#endif -#endif - bool _Crest_DrawBoundaryXZ; float4 _Crest_BoundaryXZ; @@ -92,6 +89,7 @@ void Fragment(m_Properties) o_Occlusion = 1.0; o_Alpha = 1.0; + const float2 positionSS = i_ScreenPosition.xy * _ScreenSize.xy; // Editor only. There is no defined editor symbol. if (_Crest_DrawBoundaryXZ) @@ -107,7 +105,7 @@ void Fragment(m_Properties) } } - const bool underwater = IsUnderwater(i_Facing, g_Crest_ForceUnderwater); + bool underwater = IsUnderWater(i_Facing, g_Crest_ForceUnderwater, positionSS); // TODO: Should we use PosToSIs or check for overflow? float slice0 = _Crest_LodIndex; @@ -121,6 +119,7 @@ void Fragment(m_Properties) const Cascade cascade1 = Cascade::Make(slice1); float sceneRawZ = i_SceneDepthRaw; + float negativeFog = _ProjectionParams.y; #if (CREST_PORTALS != 0) #ifndef CREST_SHADOWPASS @@ -128,7 +127,7 @@ void Fragment(m_Properties) if (m_CrestPortal) { const float pixelRawZ = i_ScreenPositionRaw.z / i_ScreenPositionRaw.w; - if (OutsideOfPortal(i_ScreenPosition.xy, pixelRawZ, sceneRawZ)) + if (Portal::EvaluateSurface(i_ScreenPosition.xy, pixelRawZ, i_PositionWS, underwater, sceneRawZ, negativeFog)) { o_Alpha = 0.0; return; @@ -242,15 +241,6 @@ void Fragment(m_Properties) // Normal. { - WaterNormal - ( - i_WaterLevelDerivatives, - i_ViewDirectionWS, - _Crest_MinimumReflectionDirectionY, - underwater, - o_NormalWS - ); - if (_Crest_NormalMapEnabled) { o_NormalWS.xz += SampleNormalMaps @@ -268,6 +258,17 @@ void Fragment(m_Properties) o_NormalWS = normalize(o_NormalWS); + WaterNormal + ( + i_WaterLevelDerivatives, + i_ViewDirectionWS, + _Crest_MinimumReflectionDirectionY, + underwater, + o_NormalWS + ); + + o_NormalWS = normalize(o_NormalWS); + o_NormalWS.xz *= _Crest_NormalsStrengthOverall; o_NormalWS.y = lerp(1.0, o_NormalWS.y, _Crest_NormalsStrengthOverall); @@ -282,11 +283,7 @@ void Fragment(m_Properties) float sceneDistance = 1000.0; float3 scenePositionWS = 0.0; - half3 ambientLight = 0.0; - AmbientLight - ( - ambientLight - ); + const half3 ambientLight = AmbientLight(); float3 lightIntensity = 0.0; half3 lightDirection = 0.0; @@ -300,15 +297,8 @@ void Fragment(m_Properties) half3 additionalLight = AdditionalLighting(i_PositionWS, i_ScreenPositionRaw, i_StaticLightMapUV); -#if d_Crest_ReceiveShadowsTransparent - // Sample shadow maps. - float4 shadowCoord = GET_SHADOW_COORDINATES(float4(i_PositionWS, 1.0)); - half shadows = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, shadowCoord); - shadows = lerp(_LightShadowData.r, 1.0, shadows); - shadows = min(shadow.y, shadows); -#endif - #if d_Transparent +#ifndef d_SkipRefraction bool caustics; RefractedScene ( @@ -325,11 +315,24 @@ void Fragment(m_Properties) scenePositionWS, caustics ); -#endif - float refractedSeaLevel = 0; - float3 refractedSurfacePosition = 0; - if (!underwater) +#if CREST_BIRP +#if SHADERPASS == SHADERPASS_FORWARD_BASE + if (g_Crest_PrimaryLightHasCookie) + { + // If light has a cookie, it is zero for the ForwardBase pass. We need to split + // emission over ForwardBase and ForwardAdd. Ambient is done in the former, while + // direct (eg caustics) is done in ForwardAdd. + o_Emission = 0; + } +#endif +#endif +#endif // d_SkipRefraction +#endif // d_Transparent + + float refractedSeaLevel = g_Crest_WaterCenter.y; + float3 refractedSurfacePosition = float3(0, refractedSeaLevel, 0); + if (!underwater && slice1 < g_Crest_LodCount) { // Sample larger slice to avoid the first slice. float4 displacement = Cascade::MakeAnimatedWaves(slice1).Sample(scenePositionWS.xz); @@ -347,15 +350,11 @@ void Fragment(m_Properties) } #if d_Transparent +#ifndef d_SkipRefraction // Caustics if (_Crest_CausticsEnabled && !underwater && caustics) { - float3 position = scenePositionWS; -#if CREST_BIRP - position = float3(i_ScreenPosition.xy * _ScreenSize.xy, 0); -#endif - - half lightOcclusion = PrimaryLightShadows(position); + half lightOcclusion = PrimaryLightShadows(scenePositionWS, positionSS); half blur = 0.0; #ifdef CREST_FLOW_ON @@ -384,7 +383,8 @@ void Fragment(m_Properties) underwater ); } -#endif +#endif // d_SkipRefraction +#endif // d_Transparent half3 sss = 0.0; @@ -404,11 +404,11 @@ void Fragment(m_Properties) } // Volume Lighting - half3 volumeLight = 0.0; - half3 volumeOpacity = 0.0; - VolumeLighting + const half3 extinction = VolumeExtinction(absorption, scattering); + const half3 volumeOpacity = VolumeOpacity(extinction, sceneDistance); + const half3 volumeLight = VolumeLighting ( - absorption, + extinction, scattering, _Crest_Anisotropy, shadow.x, @@ -419,11 +419,8 @@ void Fragment(m_Properties) additionalLight, _Crest_AmbientTerm, _Crest_DirectTerm, - sceneDistance, sss, - _Crest_ShadowsAffectsAmbientFactor, - volumeLight, - volumeOpacity + _Crest_ShadowsAffectsAmbientFactor ); // Fresnel @@ -531,11 +528,6 @@ void Fragment(m_Properties) half3 intensity = _Crest_FoamIntensityAlbedo; -#if d_Crest_ReceiveShadowsTransparent - // @HACK: Scale intensity as BIRP does not support shadows for transparent objects. - intensity = max(_Crest_FoamIntensityAlbedo * saturate(ShadeSH9(float4(o_NormalWS, 1.0))), _Crest_FoamIntensityAlbedo * shadows); -#endif - ApplyFoamToSurface ( albedo, @@ -589,12 +581,15 @@ void Fragment(m_Properties) o_Alpha = min(o_Alpha, 1.0); } -#if d_Crest_ReceiveShadowsTransparent - // @HACK: Dull highlights as BIRP does not support shadows for transparent objects. - o_Smoothness *= lerp(1, shadows, foam * 100); - // @FIXME: 0.2 to difference when high. Likely incorrect shadow sampling. - o_Specular = shadows < 0.2 ? 1.0 - max(shadows, 0.3) : o_Specular; -#endif + SetUpFog + ( + underwater, + i_PositionWS, + 1.0, // N/A: multiplier for fog nodes + sceneDistance - negativeFog, + i_ViewDirectionWS, + positionSS + ); } m_CrestNameSpaceEnd diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl index 4779d6706..8cd0366e3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl @@ -8,6 +8,14 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl" +// These are per cascade, set per chunk instance. +CBUFFER_START(CrestChunkGeometryData) +float _Crest_ChunkMeshScaleAlpha; +float _Crest_ChunkMeshScaleAlphaSource; +float _Crest_ChunkGeometryGridWidth; +float _Crest_ChunkGeometryGridWidthSource; +CBUFFER_END + m_CrestNameSpace // i_meshScaleAlpha is passed in as it is provided per tile and is set only for LOD0 @@ -49,7 +57,8 @@ void SnapAndTransitionVertLayout(in const float4x4 i_objectMatrix, in const floa objectPosXZWS += _WorldSpaceCameraPos.xz; #endif - io_worldPos.xz -= frac(objectPosXZWS / GRID_SIZE_2) * GRID_SIZE_2; // caution - sign of frac might change in non-hlsl shaders + const float2 gridOffset = frac(objectPosXZWS / GRID_SIZE_2) * GRID_SIZE_2; + io_worldPos.xz -= gridOffset; // caution - sign of frac might change in non-hlsl shaders // compute lod transition alpha o_lodAlpha = ComputeLodAlpha(io_worldPos, i_meshScaleAlpha, i_cascadeData0); @@ -63,6 +72,20 @@ void SnapAndTransitionVertLayout(in const float4x4 i_objectMatrix, in const floa const float minRadius = 0.375; if (abs(offset.x) < minRadius) io_worldPos.x += offset.x * o_lodAlpha * GRID_SIZE_4; if (abs(offset.y) < minRadius) io_worldPos.z += offset.y * o_lodAlpha * GRID_SIZE_4; + +#if SHADER_API_VULKAN +#if CREST_HDRP +#if _TRANSPARENT_WRITES_MOTION_VEC + // Fixes artifacts where parts of the surface appear to be clipped. It appears to + // be a precision issue (LOD resolution not power of 2), but only when the MV code + // path is active - even though it writes to a separate target. + if (any(isinf(gridOffset))) + { + o_lodAlpha = 0.0; + } +#endif +#endif +#endif } void SnapAndTransitionVertLayout(in const float i_meshScaleAlpha, in const Cascade i_cascadeData0, in const float i_geometryGridSize, inout float3 io_worldPos, out float o_lodAlpha) diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Normal.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Normal.hlsl index bbeadbc45..416bdaea5 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Normal.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Normal.hlsl @@ -13,6 +13,10 @@ #include "Packages/com.waveharmonic.crest.shifting-origin/Runtime/Shaders/ShiftingOrigin.hlsl" #endif +// These are per cascade, set per chunk instance. +float _Crest_ChunkFarNormalsWeight; +float2 _Crest_ChunkNormalScrollSpeed; + m_CrestNameSpace half2 SampleNormalMaps diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl index 0439dfff3..06962c1ed 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl @@ -65,7 +65,7 @@ void RefractedScene #if (CREST_PORTALS != 0) #if _ALPHATEST_ON // Portals - ApplyPortalRefractions(positionNDCRefracted, i_SceneZRaw, i_Underwater, sceneDepthRawRefracted, o_Caustics); + Portal::EvaluateRefraction(positionNDCRefracted, i_SceneZRaw, i_Underwater, sceneDepthRawRefracted, o_Caustics); #endif #endif diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl index 3e71f9b7c..2626b6cdc 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl @@ -10,13 +10,12 @@ #ifndef CREST_SHADERGRAPH_CONSTANTS_H #define CREST_SHADERGRAPH_CONSTANTS_H +// "pow(f,e) will not work for negative f" +#pragma warning (disable : 3571) + #ifdef UNIVERSAL_PIPELINE_CORE_INCLUDED #define CREST_URP 1 - #if (SHADERPASS == SHADERPASS_SHADOWCASTER) - #define CREST_SHADOWPASS 1 - #endif - #if _SURFACE_TYPE_TRANSPARENT #define d_Transparent 1 #endif @@ -24,18 +23,11 @@ #elif BUILTIN_TARGET_API #define CREST_BIRP 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" #if _BUILTIN_SURFACE_TYPE_TRANSPARENT #define d_Transparent 1 #endif - - // SHADERPASS is currently broken: - // https://forum.unity.com/threads/built-in-renderer-shaderpass-include-in-wrong-place.1444156/ - // #if (SHADERPASS == SHADERPASS_SHADOWCASTER) - // #define CREST_SHADOWPASS 1 - // #endif #else // HDRP does not appear to have a reliable keyword to target. #define CREST_HDRP 1 @@ -49,8 +41,21 @@ #endif #endif +#if defined(CREST_BIRP) || defined(CREST_URP) +#if (SHADERPASS == SHADERPASS_SHADOWCASTER) +#define CREST_SHADOWPASS 1 +#endif +#endif + #if defined(CREST_HDRP) && (SHADERPASS == SHADERPASS_FORWARD) #define CREST_HDRP_FORWARD_PASS 1 #endif +#if defined(CREST_BIRP) && (SHADERPASS == SHADERPASS_FORWARD_ADD) +#ifndef DIRECTIONAL_COOKIE +#define d_SkipRefraction 1 +#define d_IsAdditionalLight 1 +#endif +#endif + #endif // CREST_SHADERGRAPH_CONSTANTS_H diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Vertex.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Vertex.hlsl index 95a65140d..098a6bdf6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Vertex.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Vertex.hlsl @@ -29,14 +29,14 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" -#if CREST_URP +#ifndef CREST_HDRP #if (SHADERPASS == SHADERPASS_MOTION_VECTORS) #define _TRANSPARENT_WRITES_MOTION_VEC 1 #endif #endif #if _TRANSPARENT_WRITES_MOTION_VEC -#define m_Slice clamp(_Crest_LodIndex + (isMotionVectors ? g_Crest_LodChange : 0), 0, g_Crest_LodCount) +#define m_Slice clamp((int)_Crest_LodIndex + (isMotionVectors ? g_Crest_LodChange : 0), 0, g_Crest_LodCount) #define m_Make(slice) Make(slice, isMotionVectors) #else #define m_Slice _Crest_LodIndex @@ -146,7 +146,7 @@ void Vertex(m_Properties) o_PositionWS.xz -= g_Crest_WaterCenter.xz; o_PositionWS.xz *= g_Crest_WaterScaleChange; o_PositionWS.xz += g_Crest_WaterCenter.xz; - o_PositionWS += g_Crest_WaterCenterDelta; + o_PositionWS.xz += g_Crest_WaterCenterDelta; } #endif } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl index 36950af6f..c2616afdb 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl @@ -18,9 +18,22 @@ float SchlickPhase(float phaseG, float cosTheta) return (1.0 - schlickK * schlickK) / (4.0 * PI * phaseFactor * phaseFactor); } -void VolumeLighting +half3 VolumeExtinction(const half3 i_Absorption, const half3 i_Scattering) +{ + // Extinction is light absorbed plus light scattered out. + return i_Absorption + i_Scattering; +} + +half3 VolumeOpacity(const half3 i_Extinction, const half i_WaterRayLength) +{ + // Like 'alpha' value or obscurance. Volume light needs multiplying by this value + // to be correct in shallows. + return 1.0 - exp(-i_Extinction * max(0.0, i_WaterRayLength)); +} + +half3 VolumeLighting ( - const half3 i_Absorption, + const half3 i_Extinction, const half3 i_Scattering, const half i_PhaseG, const half i_DirectionalLightShadow, @@ -31,15 +44,11 @@ void VolumeLighting const half3 i_AdditionalLight, const half i_AmbientLightingTerm, const half i_PrimaryLightingTerm, - const half i_WaterRayLength, const half3 i_SunBoost, - const half i_ShadowsAffectAmbientLightingFactor, - out half3 o_VolumeLight, - out half3 o_VolumeOpacity + const half i_ShadowsAffectAmbientLightingFactor ) { - // Extinction is light absorbed plus light scattered out. - const half3 extinction = i_Absorption + i_Scattering; + const half3 extinction = i_Extinction; const float ambientLightShadow = lerp ( @@ -48,6 +57,9 @@ void VolumeLighting saturate(min(min(extinction.x, extinction.y), extinction.z) * i_ShadowsAffectAmbientLightingFactor * g_Crest_DynamicSoftShadowsFactor) ); +#ifdef d_IsAdditionalLight + const float3 inscattered = i_PrimaryLightIntensity; +#else // Sun const float sunPhase = SchlickPhase(i_PhaseG, dot(i_PrimaryLightDirection, i_ViewDirectionWS)); const float3 inScatteredSun = (1.0 + i_SunBoost) * sunPhase * i_PrimaryLightIntensity * i_PrimaryLightingTerm; @@ -55,11 +67,11 @@ void VolumeLighting // Total inscattered const float3 inscattered = (inScatteredAmbient + i_AdditionalLight + inScatteredSun * i_DirectionalLightShadow); - const float3 scatteringAmount = saturate(i_Scattering / max(extinction, 0.00001)); - o_VolumeLight = inscattered * scatteringAmount; +#endif - // Like 'alpha' value or obscurance. Volume light needs multiplying by this value to be correct in shallows. - o_VolumeOpacity = 1.0 - exp(-extinction * max(0.0, i_WaterRayLength)); + const float3 scatteringAmount = saturate(i_Scattering / max(extinction, 0.00001)); + + return inscattered * scatteringAmount; } half PinchSSS diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Water.shadergraph b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Water.shadergraph index 89206abdb..8a2f25858 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Water.shadergraph +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Water.shadergraph @@ -522,20 +522,6 @@ "m_SlotId": 0 } }, - { - "m_OutputSlot": { - "m_Node": { - "m_Id": "6fb510b9ca124cf881fe849664df5924" - }, - "m_SlotId": 2 - }, - "m_InputSlot": { - "m_Node": { - "m_Id": "8e8aee51883445f1b08bfbec696cb18d" - }, - "m_SlotId": 0 - } - }, { "m_OutputSlot": { "m_Node": { @@ -862,10 +848,10 @@ "m_Id": "4bb923e45f9f48bab142707a3af6e4bd" }, { - "m_Id": "8e8aee51883445f1b08bfbec696cb18d" + "m_Id": "b7891fe7e5a34f03adebd8a45505c5fc" }, { - "m_Id": "b7891fe7e5a34f03adebd8a45505c5fc" + "m_Id": "8e8aee51883445f1b08bfbec696cb18d" }, { "m_Id": "e207931e020242bba83058a59f3fb07d" @@ -1170,7 +1156,7 @@ "m_ObjectId": "0b12e9fc0b164611b7fa17e0c6955043", "m_Title": "Interpolators", "m_Position": { - "x": 590.9999389648438, + "x": 591.0, "y": 208.5 } } @@ -2458,7 +2444,7 @@ "m_SGVersion": 0, "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.SystemData", "m_ObjectId": "4d02d98ad13c416c989fa4a1c65d2550", - "m_MaterialNeedsUpdateHash": 279864, + "m_MaterialNeedsUpdateHash": 279880, "m_SurfaceType": 1, "m_RenderingPass": 4, "m_BlendMode": 0, @@ -2483,7 +2469,7 @@ "m_TessellationShapeFactor": 0.75, "m_TessellationBackFaceCullEpsilon": -0.25, "m_TessellationMaxDisplacement": 0.009999999776482582, - "m_Version": 1, + "m_Version": 2, "inspectorFoldoutMask": 11 } @@ -3382,7 +3368,7 @@ "overrideHLSLDeclaration": false, "hlslDeclarationOverride": 0, "m_Hidden": false, - "m_Value": 0.0, + "m_Value": 0.03, "m_FloatType": 1, "m_RangeValues": { "x": -1.0, @@ -3677,7 +3663,7 @@ "overrideHLSLDeclaration": false, "hlslDeclarationOverride": 0, "m_Hidden": false, - "m_Value": 0.4000000059604645, + "m_Value": 0.8, "m_FloatType": 1, "m_RangeValues": { "x": 0.0, @@ -4620,7 +4606,7 @@ "m_SGVersion": 2, "m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalLitSubTarget", "m_ObjectId": "a52dd0dd7c42405cabd2b96b877532a3", - "m_WorkflowMode": 0, + "m_WorkflowMode": 1, "m_NormalDropOffSpace": 2, "m_ClearCoat": false, "m_BlendModePreserveSpecular": false @@ -5096,10 +5082,11 @@ { "m_SGVersion": 0, - "m_Type": "UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInLitSubTarget", + "m_Type": "WaveHarmonic.Crest.Editor.ShaderGraph.BuiltInLitSubTarget", "m_ObjectId": "bb3b0e5f6ef041aebb81194f38a5d07c", "m_WorkflowMode": 1, - "m_NormalDropOffSpace": 2 + "m_NormalDropOffSpace": 2, + "m_TransparentReceiveShadows": true } { @@ -5349,7 +5336,7 @@ "overrideHLSLDeclaration": false, "hlslDeclarationOverride": 0, "m_Hidden": false, - "m_Value": 10.0, + "m_Value": 3.0, "m_FloatType": 0, "m_RangeValues": { "x": 0.0, @@ -5433,7 +5420,8 @@ "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitData", "m_ObjectId": "cee72db709954dd38e8039e087fe5744", "m_RayTracing": false, - "m_MaterialType": 4, + "m_MaterialType": 0, + "m_MaterialTypeMask": 18, "m_RefractionModel": 1, "m_SSSTransmission": true, "m_EnergyConservingSpecular": false, diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Blit.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Blit.shader index d72425c7d..3d8389a10 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Blit.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Blit.shader @@ -1,19 +1,15 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Provides utility passes for rendering like clearing the stencil buffer. -Shader "Hidden/Crest/Utility/Blit" +Shader "Hidden/Crest/Legacy/Blit" { HLSLINCLUDE #pragma vertex Vertex #pragma fragment Fragment - #include "UnityCG.cginc" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" struct Attributes @@ -44,28 +40,10 @@ Shader "Hidden/Crest/Utility/Blit" SubShader { - Cull Off ZWrite On ZTest Always - - Pass - { - // Copies the color texture. - Name "Copy Color" - - ZWrite Off - ZTest Always - Cull Off - - HLSLPROGRAM - TEXTURE2D_X(_CameraColorTexture); - - float4 Fragment(Varyings input) : SV_Target - { - // We need this when sampling a screenspace texture. - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - return LOAD_TEXTURE2D_X(_CameraColorTexture, input.positionCS.xy); - } - ENDHLSL - } + Blend Off + Cull Off + ZTest Always + ZWrite Off Pass { @@ -73,8 +51,6 @@ Shader "Hidden/Crest/Utility/Blit" Name "Copy Depth / Clear Stencil" ZWrite On - ZTest Always - Cull Off Stencil { @@ -94,52 +70,9 @@ Shader "Hidden/Crest/Utility/Blit" ENDHLSL } - Pass - { - // Clears the depth buffer without clearing the stencil. - Name "Clear Depth" - - ZWrite On - ZTest Always - Cull Off - - HLSLPROGRAM - float Fragment(Varyings input) : SV_Depth - { - return 0.0; - } - ENDHLSL - } - - Pass - { - // Clears the stencil buffer without clearing depth - Name "Clear Stencil" - - ZWrite Off - ZTest Always - Cull Off - Blend Zero One - - Stencil - { - Ref 0 - Comp Always - Pass Replace - } - - HLSLPROGRAM - float Fragment(Varyings input) : SV_Target - { - return 0.0; - } - ENDHLSL - } - Pass { Name "Copy" - Blend Off HLSLPROGRAM TEXTURE2D(_Utility_MainTexture); @@ -150,5 +83,23 @@ Shader "Hidden/Crest/Utility/Blit" } ENDHLSL } + + Pass + { + Name "Merge Depth" + + // All is required to merge depth. + ZTest Less + ZWrite On + + HLSLPROGRAM + TEXTURE2D_X(_Utility_MainTexture); + float Fragment(Varyings input) : SV_Depth + { + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + return LOAD_DEPTH_TEXTURE_X(_Utility_MainTexture, input.positionCS.xy); + } + ENDHLSL + } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Clear.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Clear.compute index 0f2948f03..4103fa5be 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Clear.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Clear.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Clear specific components using a mask. diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy.meta new file mode 100644 index 000000000..9dc073d4c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c6a37fe33f609947b680abac9e850cc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader new file mode 100644 index 000000000..f8a208110 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader @@ -0,0 +1,42 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +Shader "Hidden/Crest/Legacy/CaptureShadowMatrices" +{ + SubShader + { + Blend Off + ColorMask 0 + Cull Off + ZTest Always + ZWrite Off + + Pass + { + HLSLPROGRAM + #pragma target 4.5 + #pragma vertex Vertex + #pragma fragment Fragment + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + + RWStructuredBuffer _Crest_WorldToShadow; + float4x4 unity_WorldToShadow[4]; + + float4 Vertex(uint id : SV_VertexID) : SV_POSITION + { + return GetFullScreenTriangleVertexPosition(id); + } + + float4 Fragment(float4 pos : SV_POSITION) : SV_Target + { + _Crest_WorldToShadow[0] = unity_WorldToShadow[0]; + _Crest_WorldToShadow[1] = unity_WorldToShadow[1]; + _Crest_WorldToShadow[2] = unity_WorldToShadow[2]; + _Crest_WorldToShadow[3] = unity_WorldToShadow[3]; + return 0; + } + ENDHLSL + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader.meta new file mode 100644 index 000000000..41896e7c9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/CaptureShadowMatrices.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 17feb724c7e004b4e8e418931db7eff3 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader new file mode 100644 index 000000000..8ecec738d --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader @@ -0,0 +1,51 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +Shader "Hidden/Crest/Legacy/ForceShadows" +{ + CGINCLUDE + #pragma vertex Vertex + #pragma fragment Fragment + + fixed4 Vertex(fixed4 v : POSITION) : SV_POSITION + { + return 0; + } + + fixed4 Fragment(fixed4 i : SV_POSITION) : SV_Target + { + return 0; + } + ENDCG + + SubShader + { + ZTest Always + ZWrite Off + ColorMask 0 + + Pass + { + Tags + { + "LightMode" = "ForwardBase" + } + + CGPROGRAM + #pragma multi_compile_fwdbase + ENDCG + } + + Pass + { + Tags + { + "LightMode" = "ForwardAdd" + } + + CGPROGRAM + #pragma multi_compile_fwdadd_fullshadows + ENDCG + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader.meta new file mode 100644 index 000000000..3bc8c34d2 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/Legacy/ForceShadows.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c9f384b6b84e943ed83161cb82d95b2e +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/TextureArray.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/TextureArray.shader index 3a164ca90..444996aa3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/TextureArray.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Utility/TextureArray.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Renders a specific slice of a 2D Texture Array diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl new file mode 100644 index 000000000..5257b0443 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl @@ -0,0 +1,44 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#ifndef d_WaveHarmonic_Crest_VolumeDebug +#define d_WaveHarmonic_Crest_VolumeDebug + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Macros.hlsl" + +m_CrestNameSpace + +float4 DebugRenderWaterMask(const bool isWaterSurface, const bool isUnderwater, const float mask, const float3 sceneColour) +{ + // Red: surface front face when above water + // Green: surface back face when below water + // Cyan: background when above water + // Magenta: background when below water + if (isWaterSurface) + { + return float4(sceneColour * float3(mask >= CREST_MASK_ABOVE_SURFACE, mask <= CREST_MASK_BELOW_SURFACE, 0.0), 1.0); + } + else + { + return float4(sceneColour * float3(isUnderwater * 0.5, (1.0 - isUnderwater) * 0.5, 1.0), 1.0); + } +} + +float4 DebugRenderStencil(float3 sceneColour) +{ + float3 stencil = 1.0; +#if d_Crest_Portal +#if d_Crest_FogAfter + stencil = float3(1.0, 0.0, 0.0); +#elif d_Crest_FogBefore + stencil = float3(0.0, 1.0, 0.0); +#else + stencil = float3(0.0, 0.0, 1.0); +#endif +#endif + return float4(sceneColour * stencil, 1.0); +} + +m_CrestNameSpaceEnd + +#endif // d_WaveHarmonic_Crest_VolumeDebug diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl.meta new file mode 100644 index 000000000..d228a295c --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f174da407e60e4ed1b24dd11f44c9cdc +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph.meta new file mode 100644 index 000000000..9e65d2abb --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 557d66ce32c8ea44dba2cb2ff07dd49d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph new file mode 100644 index 000000000..2db46d16b --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph @@ -0,0 +1,1262 @@ +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.GraphData", + "m_ObjectId": "fa6863a20fe5453f84da2aefdcd78727", + "m_Properties": [ + { + "m_Id": "5d923c2657794970996af7cb7159276f" + }, + { + "m_Id": "0640f7e405ca4ded9cced0944e419139" + }, + { + "m_Id": "a0af5588d47b44b5b24f875b67acf31a" + } + ], + "m_Keywords": [], + "m_Dropdowns": [], + "m_CategoryData": [ + { + "m_Id": "943e9ca00d7248afba41cc8024d2542a" + } + ], + "m_Nodes": [ + { + "m_Id": "dd5931412c824c66b095fb7819859502" + }, + { + "m_Id": "c0989029cf9b440b8d920d94483be2d4" + }, + { + "m_Id": "9ab1f5c4a6894323899049b311181b3f" + }, + { + "m_Id": "1e6912026741481fb3338b2e9c85a203" + }, + { + "m_Id": "3a66a62e50224c799de45b25a67a41c8" + }, + { + "m_Id": "bb35f5be46ba4350a77ad73886c2d67a" + }, + { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + { + "m_Id": "73c08bc2c7be45559da717ae630500f6" + }, + { + "m_Id": "6893ffaca70848d693feacf5b9a166ec" + }, + { + "m_Id": "b5b57b89f263474f8d5d5ffa3f3b30ec" + } + ], + "m_GroupDatas": [ + { + "m_Id": "1100f19ecd45464ca732f01d9e3a3cc4" + } + ], + "m_StickyNoteDatas": [], + "m_Edges": [ + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "1e6912026741481fb3338b2e9c85a203" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "3a66a62e50224c799de45b25a67a41c8" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3a66a62e50224c799de45b25a67a41c8" + }, + "m_SlotId": 3 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bb35f5be46ba4350a77ad73886c2d67a" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3a66a62e50224c799de45b25a67a41c8" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bb35f5be46ba4350a77ad73886c2d67a" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dd5931412c824c66b095fb7819859502" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 8 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "dd5931412c824c66b095fb7819859502" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "6893ffaca70848d693feacf5b9a166ec" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 3 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "73c08bc2c7be45559da717ae630500f6" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 6 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "9ab1f5c4a6894323899049b311181b3f" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 1 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "b5b57b89f263474f8d5d5ffa3f3b30ec" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 7 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "bb35f5be46ba4350a77ad73886c2d67a" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 2 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "c0989029cf9b440b8d920d94483be2d4" + }, + "m_SlotId": 0 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "480703a4ce624a52bc7256f8e37a06d0" + }, + "m_SlotId": 0 + } + } + ], + "m_VertexContext": { + "m_Position": { + "x": 0.0, + "y": 0.0 + }, + "m_Blocks": [] + }, + "m_FragmentContext": { + "m_Position": { + "x": 0.0, + "y": 0.0 + }, + "m_Blocks": [] + }, + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}", + "m_Guid": "" + }, + "preventRotation": false + }, + "m_Path": "Crest", + "m_GraphPrecision": 0, + "m_PreviewMode": 2, + "m_OutputNode": { + "m_Id": "dd5931412c824c66b095fb7819859502" + }, + "m_SubDatas": [], + "m_ActiveTargets": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty", + "m_ObjectId": "0640f7e405ca4ded9cced0944e419139", + "m_Guid": { + "m_GuidSerialized": "33f7abbf-d481-4327-84fd-12645ebd2beb" + }, + "m_Name": "Multiplier", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Vector1_0640f7e405ca4ded9cced0944e419139", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": 1.0, + "m_FloatType": 0, + "m_RangeValues": { + "x": 0.0, + "y": 1.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "100759169f234f728c4532414590b1a0", + "m_Id": 7, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.GroupData", + "m_ObjectId": "1100f19ecd45464ca732f01d9e3a3cc4", + "m_Title": "Device Depth", + "m_Position": { + "x": -590.5, + "y": -78.5 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode", + "m_ObjectId": "1e6912026741481fb3338b2e9c85a203", + "m_Group": { + "m_Id": "1100f19ecd45464ca732f01d9e3a3cc4" + }, + "m_Name": "Screen Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -565.4999389648438, + "y": -19.999958038330079, + "width": 145.0, + "height": 128.5 + } + }, + "m_Slots": [ + { + "m_Id": "997795b49fd142219f3c653b993006cb" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_ScreenSpaceType": 1 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "26ad05e7cf2e4a4ea25b5c24de47805b", + "m_Id": 0, + "m_DisplayName": "Multiplier", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "33b7e1b838534e1eb917b8dddc09da10", + "m_Id": 1, + "m_DisplayName": "World_Space_Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "World_Space_Position", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "3869cf8b70444512bb57c08b049d8040", + "m_Id": 6, + "m_DisplayName": "Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SplitNode", + "m_ObjectId": "3a66a62e50224c799de45b25a67a41c8", + "m_Group": { + "m_Id": "1100f19ecd45464ca732f01d9e3a3cc4" + }, + "m_Name": "Split", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -421.0, + "y": -20.0, + "width": 118.49996948242188, + "height": 101.0 + } + }, + "m_Slots": [ + { + "m_Id": "4b4a7611530e497b9aaf382ee1cb46e9" + }, + { + "m_Id": "d34c200c1e724ad58b511315e02a7adf" + }, + { + "m_Id": "aa670f1389b24b7a96377c5aa3ff2940" + }, + { + "m_Id": "6e8de798030b4e1a8c098766d08a075f" + }, + { + "m_Id": "807219348c604b578c843be8e94a292c" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "3be2aeeddcce4175abdff791fdd9f5a5", + "m_Id": 3, + "m_DisplayName": "Multiplier", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Multiplier", + "m_StageCapability": 3, + "m_Value": 1.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "3d98351741854538b14ba5d65b699de0", + "m_Id": 1, + "m_DisplayName": "B", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": { + "x": 2.0, + "y": 2.0, + "z": 2.0, + "w": 2.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", + "m_ObjectId": "480703a4ce624a52bc7256f8e37a06d0", + "m_Group": { + "m_Id": "" + }, + "m_Name": "CrestNodeIntegrateWaterVolume (Custom Function)", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 289.0000305175781, + "y": -64.49995422363281, + "width": 331.5, + "height": 190.0 + } + }, + "m_Slots": [ + { + "m_Id": "fc76576996d147a6a18fa6e16a54409e" + }, + { + "m_Id": "33b7e1b838534e1eb917b8dddc09da10" + }, + { + "m_Id": "d82e7faaa0814772ac2d904701df5add" + }, + { + "m_Id": "3be2aeeddcce4175abdff791fdd9f5a5" + }, + { + "m_Id": "3869cf8b70444512bb57c08b049d8040" + }, + { + "m_Id": "100759169f234f728c4532414590b1a0" + }, + { + "m_Id": "be7a86b7ce45469dbaa830426ed7bf5c" + }, + { + "m_Id": "53b91b3c1d284b088db3b0ddd55fe57a" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SourceType": 0, + "m_FunctionName": "CrestNodeIntegrateWaterVolume", + "m_FunctionSource": "d71d6be33f63546ff8a3e48fa55faa5f", + "m_FunctionBody": "Enter function body here..." +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "4b4a7611530e497b9aaf382ee1cb46e9", + "m_Id": 0, + "m_DisplayName": "In", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "In", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "53b91b3c1d284b088db3b0ddd55fe57a", + "m_Id": 8, + "m_DisplayName": "Out_Emission", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out_Emission", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 3, + "m_Type": "UnityEditor.ShaderGraph.Internal.ColorShaderProperty", + "m_ObjectId": "5d923c2657794970996af7cb7159276f", + "m_Guid": { + "m_GuidSerialized": "4e700f9f-71e1-44ca-82f1-a15c46d60057" + }, + "m_Name": "Color", + "m_DefaultRefNameVersion": 0, + "m_RefNameGeneratedByDisplayName": "", + "m_DefaultReferenceName": "Color_5d923c2657794970996af7cb7159276f", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "r": 0.0, + "g": 0.0, + "b": 0.0, + "a": 0.0 + }, + "isMainColor": false, + "m_ColorMode": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "613443e60dfe4a6c8242f655a5c0ebe1", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "6893ffaca70848d693feacf5b9a166ec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -39.0, + "y": 57.5, + "width": 123.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "26ad05e7cf2e4a4ea25b5c24de47805b" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "0640f7e405ca4ded9cced0944e419139" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "6e8de798030b4e1a8c098766d08a075f", + "m_Id": 3, + "m_DisplayName": "B", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "B", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "6e9dfffa8dd44af49ecd03bc70b53e3b", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "70cc196430a942c28a78823efac0213b", + "m_Id": 0, + "m_DisplayName": "A", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "73c08bc2c7be45559da717ae630500f6", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -21.0, + "y": 91.5, + "width": 105.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "e2f3904697a242ec8f265071d93e8591" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "5d923c2657794970996af7cb7159276f" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "807219348c604b578c843be8e94a292c", + "m_Id": 4, + "m_DisplayName": "A", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "A", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "8f9a320d616344e09bcb1f5e368c99c9", + "m_Id": 2, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "914b3ad544bc4c57b1b5d9b955d533c0", + "m_Id": 0, + "m_DisplayName": "Emission", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.CategoryData", + "m_ObjectId": "943e9ca00d7248afba41cc8024d2542a", + "m_Name": "", + "m_ChildObjectList": [ + { + "m_Id": "5d923c2657794970996af7cb7159276f" + }, + { + "m_Id": "a0af5588d47b44b5b24f875b67acf31a" + }, + { + "m_Id": "0640f7e405ca4ded9cced0944e419139" + } + ] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "997795b49fd142219f3c653b993006cb", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.PositionNode", + "m_ObjectId": "9ab1f5c4a6894323899049b311181b3f", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Position", + "m_DrawState": { + "m_Expanded": false, + "m_Position": { + "serializedVersion": "2", + "x": -122.0, + "y": -96.5, + "width": 206.0, + "height": 129.5 + } + }, + "m_Slots": [ + { + "m_Id": "dd9559ce5f2644919ef9122d4f557df6" + } + ], + "synonyms": [], + "m_Precision": 1, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 2, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Space": 2, + "m_PositionSource": 0 +} + +{ + "m_SGVersion": 1, + "m_Type": "UnityEditor.ShaderGraph.Internal.Vector3ShaderProperty", + "m_ObjectId": "a0af5588d47b44b5b24f875b67acf31a", + "m_Guid": { + "m_GuidSerialized": "bebcb4b2-70d3-4426-b192-1c54922e3a4a" + }, + "m_Name": "Emission", + "m_DefaultRefNameVersion": 1, + "m_RefNameGeneratedByDisplayName": "Emission", + "m_DefaultReferenceName": "_Emission", + "m_OverrideReferenceName": "", + "m_GeneratePropertyBlock": true, + "m_UseCustomSlotLabel": false, + "m_CustomSlotLabel": "", + "m_DismissedVersion": 0, + "m_Precision": 0, + "overrideHLSLDeclaration": false, + "hlslDeclarationOverride": 0, + "m_Hidden": false, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "aa670f1389b24b7a96377c5aa3ff2940", + "m_Id": 2, + "m_DisplayName": "G", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "G", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot", + "m_ObjectId": "aec8c45ce53547629ca39ff1eae3bc15", + "m_Id": 2, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.PropertyNode", + "m_ObjectId": "b5b57b89f263474f8d5d5ffa3f3b30ec", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Property", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -39.0, + "y": 125.5, + "width": 123.0, + "height": 34.0 + } + }, + "m_Slots": [ + { + "m_Id": "914b3ad544bc4c57b1b5d9b955d533c0" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_Property": { + "m_Id": "a0af5588d47b44b5b24f875b67acf31a" + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.DivideNode", + "m_ObjectId": "bb35f5be46ba4350a77ad73886c2d67a", + "m_Group": { + "m_Id": "1100f19ecd45464ca732f01d9e3a3cc4" + }, + "m_Name": "Divide", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -302.5, + "y": -20.0, + "width": 126.0, + "height": 118.0 + } + }, + "m_Slots": [ + { + "m_Id": "70cc196430a942c28a78823efac0213b" + }, + { + "m_Id": "3d98351741854538b14ba5d65b699de0" + }, + { + "m_Id": "aec8c45ce53547629ca39ff1eae3bc15" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + } +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "be7a86b7ce45469dbaa830426ed7bf5c", + "m_Id": 4, + "m_DisplayName": "Out_Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out_Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode", + "m_ObjectId": "c0989029cf9b440b8d920d94483be2d4", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Screen Position", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -61.000003814697269, + "y": -224.99993896484376, + "width": 145.0, + "height": 128.5 + } + }, + "m_Slots": [ + { + "m_Id": "613443e60dfe4a6c8242f655a5c0ebe1" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_ScreenSpaceType": 0 +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d34c200c1e724ad58b511315e02a7adf", + "m_Id": 1, + "m_DisplayName": "R", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "R", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "d82e7faaa0814772ac2d904701df5add", + "m_Id": 2, + "m_DisplayName": "Device_Depth", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Device_Depth", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubGraphOutputNode", + "m_ObjectId": "dd5931412c824c66b095fb7819859502", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Output", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": 720.5, + "y": -64.5, + "width": 101.0, + "height": 101.0 + } + }, + "m_Slots": [ + { + "m_Id": "6e9dfffa8dd44af49ecd03bc70b53e3b" + }, + { + "m_Id": "8f9a320d616344e09bcb1f5e368c99c9" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": true, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "IsFirstSlotValid": true +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "dd9559ce5f2644919ef9122d4f557df6", + "m_Id": 0, + "m_DisplayName": "Out", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "e2f3904697a242ec8f265071d93e8591", + "m_Id": 0, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Out", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot", + "m_ObjectId": "fc76576996d147a6a18fa6e16a54409e", + "m_Id": 0, + "m_DisplayName": "Screen_Position", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Screen_Position", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0 + }, + "m_Labels": [] +} + diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph.meta new file mode 100644 index 000000000..e6ee048a8 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/Integrate Water Volume.shadersubgraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: df63a8d198812478985b6d0a5d68a59a +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 60072b568d64c40a485e0fc55012dc9f, type: 3} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl new file mode 100644 index 000000000..561f33e06 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl @@ -0,0 +1,224 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +// NOTE: It is important that everything has a Crest prefix to avoid possible conflicts. +// NOTE: No keywords so no mask color/depth variants not available. + +#ifndef d_WaveHarmonic_Crest_ApplyWaterVolumeFog +#define d_WaveHarmonic_Crest_ApplyWaterVolumeFog + +#ifndef SHADERGRAPH_PREVIEW + +// TODO: enable dithering? +#define k_DisableCaustics +#define k_DisableDithering + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" + +#if (CREST_PORTALS != 0) +#define d_Crest_Portal 1 +#endif + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl" + +// Uses SHADERPASS which is broken for everyone else. +#undef d_IsAdditionalLight + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl" + +m_CrestNameSpace + +static bool s_IsUnderWater; +static float s_FogDistance; +static half s_FogMultiplier; + +static float2 s_PositionSS; +static float3 s_PositionWS; +static half3 s_ViewWS; +static float s_DepthRaw; + +float3 ApplyFog(float3 color) +{ +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING == 0) + if (!s_IsUnderWater) + { + return color; + } +#endif + + return ApplyUnderwaterEffect + ( + color, + s_DepthRaw, + 0, // Caustics only + s_FogDistance, + s_ViewWS, + s_PositionSS, + s_PositionWS, + false, // No caustics + true, // TODO: implement + true, // TODO: implement + s_FogMultiplier + ); +} + +float3 NoFog(float3 color) +{ + return color; +} + +void SetUpFog(const float2 i_PositionNDC, const float3 i_PositionWS, const float i_DepthRaw, const half i_Multiplier) +{ +#if !CREST_BIRP +// Uses SHADERPASS which is broken for everyone else. +#if CREST_SHADOWPASS + return; +#endif +#endif + + const float2 positionSS = i_PositionNDC.xy * _ScreenSize.xy; + + const half mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).r; + + // Skip if not underwater. We could also "&& rawSurfaceDepth < i_DepthRaw" to + // exclude objects behind the front-faces from receiving atmospheric fog, but we + // are using transparent blending which leaves a bright outline due to the edges + // receiving insufficient fog. Excluding these objects from atmospheric fog gives + // little benefit. + if (mask >= CREST_MASK_NO_FOG && mask < CREST_MASK_ABOVE_SURFACE_KEPT) + { + return; + } + +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING != 0) +#if !d_Transparent + // FIXME: Find alternative solution for new mask. + const float rawSurfaceDepth = LOAD_DEPTH_TEXTURE_X(_Crest_WaterMaskDepthTexture, positionSS).r; + + // Skip discarding fog if opaque object is behind back-faces. + if (mask < CREST_MASK_NO_FOG && mask > CREST_MASK_BELOW_SURFACE_KEPT && i_DepthRaw < rawSurfaceDepth) + { + return; + } +#endif +#endif + + // Get the largest distance. + float rawFogDistance = i_DepthRaw; + float fogDistanceOffset = _ProjectionParams.y; + float fogDistance = 0.0; + +#if (CREST_PORTALS != 0) + if (!Portal::EvaluateFog(i_PositionNDC, mask, rawFogDistance, fogDistanceOffset)) + { + return; + } + else +#endif + { + fogDistance = Utility::CrestLinearEyeDepth(rawFogDistance) - fogDistanceOffset; + } + + s_IsUnderWater = true; + s_PositionSS = positionSS; + s_PositionWS = i_PositionWS; + s_ViewWS = GetWorldSpaceNormalizeViewDir(i_PositionWS); + s_FogDistance = fogDistance; + s_DepthRaw = i_DepthRaw; + s_FogMultiplier = i_Multiplier; +} + +m_CrestNameSpaceEnd + +#if d_Transparent +#define ApplyFog(x) ApplyFog(x) +#else +#define ApplyFog(x) NoFog(x) +#endif + +#if CREST_BIRP +#ifdef UNITY_PASS_FORWARDADD +#define m_Unity_FogColor fixed4(0, 0, 0, 0) +#else +#define m_Unity_FogColor unity_FogColor +#endif // UNITY_PASS_FORWARDADD + +#undef UNITY_APPLY_FOG +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING != 0) +#define UNITY_APPLY_FOG(coord, color) \ +if (m_Crest::s_IsUnderWater) \ +{ \ + color.rgb = m_Crest::ApplyFog(color.rgb); \ +} \ +else \ +{ \ + UNITY_APPLY_FOG_COLOR(coord, color, m_Unity_FogColor); \ +} +#else +#define UNITY_APPLY_FOG(coord, color) \ +UNITY_APPLY_FOG_COLOR(coord, color, m_Unity_FogColor); \ +color.rgb = m_Crest::ApplyFog(color.rgb); +#endif // CREST_DISCARD_ATMOSPHERIC_SCATTERING +#endif // CREST_BIRP + +#if CREST_HDRP +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING != 0) +#define EvaluateAtmosphericScattering(i, V, color) m_Crest::s_IsUnderWater ? float4(m_Crest::ApplyFog(color.rgb), color.a) : EvaluateAtmosphericScattering(i, V, color) +#else +#define EvaluateAtmosphericScattering(i, V, color) EvaluateAtmosphericScattering(i, V, color); color.rgb = m_Crest::ApplyFog(color.rgb) +#endif +#endif + +#if CREST_URP +#if (CREST_DISCARD_ATMOSPHERIC_SCATTERING != 0) +#define MixFog(color, coord) m_Crest::s_IsUnderWater ? m_Crest::ApplyFog(color) : MixFog(color, coord) +#else +#define MixFog(color, coord) MixFog(color, coord); color.rgb = m_Crest::ApplyFog(color.rgb) +#endif +#endif + +#endif // SHADERGRAPH_PREVIEW + +void CrestNodeIntegrateWaterVolume_half +( + const float2 i_PositionNDC, + const float3 i_PositionWS, + const float i_DepthRaw, + const half i_Multiplier, + const half4 i_Color, + const half3 i_Emission, + out half4 o_Color, + out half3 o_Emission +) +{ + o_Color = i_Color; + o_Emission = i_Emission; + +#ifndef SHADERGRAPH_PREVIEW + m_Crest::SetUpFog(i_PositionNDC, i_PositionWS, i_DepthRaw, i_Multiplier); +#endif +} + +void CrestNodeIntegrateWaterVolume_float +( + const float2 i_PositionNDC, + const float3 i_PositionWS, + const float i_DepthRaw, + const half i_Multiplier, + const float4 i_Color, + const float3 i_Emission, + out float4 o_Color, + out float3 o_Emission +) +{ + o_Color = i_Color; + o_Emission = i_Emission; + +#ifndef SHADERGRAPH_PREVIEW + m_Crest::SetUpFog(i_PositionNDC, i_PositionWS, i_DepthRaw, i_Multiplier); +#endif +} + +#endif // d_WaveHarmonic_Crest_ApplyWaterVolumeFog diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl.meta new file mode 100644 index 000000000..0316ff200 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Graph/IntegrateWaterVolume.hlsl.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d71d6be33f63546ff8a3e48fa55faa5f +ShaderIncludeImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader new file mode 100644 index 000000000..6631876c9 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader @@ -0,0 +1,104 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +Shader "Hidden/Crest/Volume/Horizon Mask" +{ + SubShader + { + PackageRequirements + { + "com.unity.render-pipelines.high-definition" + } + + Tags { "RenderPipeline"="HDRenderPipeline" } + + Blend Off + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Water Horizon Mask" + + Stencil + { + Ref [_Crest_StencilReference] + Comp [_Crest_StencilComparison] + } + + HLSLPROGRAM + #pragma vertex Vertex + #pragma fragment Fragment + + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" + #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" + ENDHLSL + } + } + + SubShader + { + PackageRequirements + { + "com.unity.render-pipelines.universal" + } + + Tags { "RenderPipeline"="UniversalPipeline" } + + Blend Off + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Water Horizon Mask" + + Stencil + { + Ref [_Crest_StencilReference] + Comp [_Crest_StencilComparison] + } + + HLSLPROGRAM + #pragma vertex Vertex + #pragma fragment Fragment + + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" + ENDHLSL + } + } + + SubShader + { + Blend Off + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Water Horizon Mask" + + Stencil + { + Ref [_Crest_StencilReference] + Comp [_Crest_StencilComparison] + } + + HLSLPROGRAM + #pragma vertex Vertex + #pragma fragment Fragment + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" + ENDHLSL + } + } +} diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader.meta new file mode 100644 index 000000000..67a7f17ac --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Horizon.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 80a81e5410296461d827cd6eed939b81 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute new file mode 100644 index 000000000..8399f625d --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute @@ -0,0 +1,51 @@ +// Crest Water System +// Copyright © 2024 Wave Harmonic. All rights reserved. + +#pragma kernel CrestWaterLineBRP _BRP +#pragma kernel CrestWaterLineHRP _HRP +#pragma kernel CrestWaterLineURP _URP + +// Not every RP handles this. HDRP seems to. +#pragma multi_compile _ STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON + +#pragma multi_compile_local _ d_KeepValue + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl" + +RW_TEXTURE2D_X(float, _Crest_WaterMaskTexture); + +m_CrestNameSpace + +void WaterLine(const uint3 id) +{ + UNITY_XR_ASSIGN_VIEW_INDEX(id.z); + +#if d_KeepValue + // Prevent rendering inside of portals. + if (_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)] != 0) + { + return; + } +#endif + + float3 position = ComputeWorldSpacePosition(id.xy / _ScreenSize.xy, UNITY_NEAR_CLIP_VALUE, UNITY_MATRIX_I_VP); + +#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) + position.xyz += _WorldSpaceCameraPos.xyz; +#endif + + const float height = SampleWaterLineHeight(position.xz).x; + + _Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)] = position.y <= height ? -1 : 1; +} + +m_CrestNameSpaceEnd + +m_CrestKernelXRP(WaterLine) diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute.meta b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute.meta new file mode 100644 index 000000000..f30c04809 --- /dev/null +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 51ffca485396f4d8dbf07883c9303f3c +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl index 16bbf6d5c..a8369cdb9 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl @@ -1,8 +1,8 @@ // Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. -#ifndef CREST_UNDERWATER_MASK_SHARED_INCLUDED -#define CREST_UNDERWATER_MASK_SHARED_INCLUDED +#ifndef d_WaveHarmonic_Crest_Mask +#define d_WaveHarmonic_Crest_Mask #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" @@ -18,43 +18,45 @@ #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl" #endif -// Variable mask for when fog is applied before transparent pass and water tile might be culled. -half _Crest_MaskBelowSurface; - m_CrestNameSpace struct Attributes { // The old unity macros require this name and type. - float4 vertex : POSITION; + float4 positionCS : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; +#if d_LodInput + float3 positionWS : TEXCOORD; +#endif UNITY_VERTEX_OUTPUT_STEREO }; -Varyings Vertex(Attributes v) +Varyings Vertex(const Attributes i_Input) { // This will work for all pipelines. Varyings output = (Varyings)0; - UNITY_SETUP_INSTANCE_ID(v); + UNITY_SETUP_INSTANCE_ID(i_Input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); - const Cascade cascade0 = Cascade::Make(_Crest_LodIndex); - const Cascade cascade1 = Cascade::Make(_Crest_LodIndex + 1); + const uint slice0 = _Crest_LodIndex; + const uint slice1 = _Crest_LodIndex + 1; - float3 worldPos = mul(UNITY_MATRIX_M, float4(v.vertex.xyz, 1.0)).xyz; + const Cascade cascade0 = Cascade::Make(slice0); + const Cascade cascade1 = Cascade::Make(slice1); + + float3 positionWS = mul(UNITY_MATRIX_M, float4(i_Input.positionCS.xyz, 1.0)).xyz; #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) - worldPos.xz += _WorldSpaceCameraPos.xz; + positionWS.xz += _WorldSpaceCameraPos.xz; #endif - // Vertex snapping and lod transition - float lodAlpha; - SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, worldPos, lodAlpha); + float alpha; + SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, positionWS, alpha); { // Scale up by small "epsilon" to solve numerical issues. Expand slightly about tile center. @@ -64,83 +66,82 @@ Varyings Vertex(Attributes v) tileCenterXZ += _WorldSpaceCameraPos.xz; #endif const float2 cameraPositionXZ = abs(_WorldSpaceCameraPos.xz); - // Scale "epsilon" by distance from zero. There is an issue where overlaps can cause SV_IsFrontFace - // to be flipped (needs to be investigated). Gaps look bad from above surface, and overlaps look bad - // from below surface. We want to close gaps without introducing overlaps. A fixed "epsilon" will - // either not solve gaps at large distances or introduce too many overlaps at small distances. Even - // with scaling, there are still unsolvable overlaps underwater (especially at large distances). - // 100,000 (0.00001) is the maximum position before Unity warns the user of precision issues. - worldPos.xz = lerp(tileCenterXZ, worldPos.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001)); + positionWS.xz = lerp(tileCenterXZ, positionWS.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001)); } - // Calculate sample weights. params.z allows shape to be faded out (used on last lod to support pop-less scale transitions) - const float wt_smallerLod = (1.0 - lodAlpha) * cascade0._Weight; - const float wt_biggerLod = (1.0 - wt_smallerLod) * cascade1._Weight; - // Sample displacement textures, add results to current world pos / normal / foam - const float2 positionWS_XZ_before = worldPos.xz; + const float weight0 = (1.0 - alpha) * cascade0._Weight; + const float weight1 = (1.0 - weight0) * cascade1._Weight; - // Data that needs to be sampled at the undisplaced position - if (wt_smallerLod > m_CrestSampleLodThreshold) + const float2 positionXZ = positionWS.xz; + + // Data that needs to be sampled at the undisplaced position. + if (weight0 > m_CrestSampleLodThreshold) { - Cascade::MakeAnimatedWaves(_Crest_LodIndex).SampleDisplacement(positionWS_XZ_before, wt_smallerLod, worldPos); + Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(positionXZ, weight0, positionWS); } - if (wt_biggerLod > m_CrestSampleLodThreshold) + if (weight1 > m_CrestSampleLodThreshold) { - Cascade::MakeAnimatedWaves(_Crest_LodIndex + 1).SampleDisplacement(positionWS_XZ_before, wt_biggerLod, worldPos); + Cascade::MakeAnimatedWaves(slice1).SampleDisplacement(positionXZ, weight1, positionWS); } #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) - worldPos.xz -= _WorldSpaceCameraPos.xz; + positionWS.xz -= _WorldSpaceCameraPos.xz; #endif - output.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0)); + output.positionCS = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0)); + +#if d_LodInput + output.positionWS = positionWS; +#endif return output; } -half4 Fragment(const Varyings input, const bool i_isFrontFace) +half4 Fragment(const Varyings i_Input, const bool i_FrontFace) { - UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); + UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i_Input); - half4 result = 0.0; +#if d_LodInput + return half4(i_Input.positionWS.y - g_Crest_WaterCenter.y, 0, 0, 1); +#endif + + half result = 0.0; #if (CREST_PORTALS != 0) #if !d_Tunnel - bool masked = false; - if (m_CrestPortal) { - masked = ApplyVolumeToWaterMask(input.positionCS); + Portal::EvaluateMask(i_Input.positionCS); } #endif #endif - if (IsUnderwater(i_isFrontFace, g_Crest_ForceUnderwater)) + if (IsUnderWater(i_FrontFace, g_Crest_ForceUnderwater)) { - result = (half4)_Crest_MaskBelowSurface; + result = CREST_MASK_BELOW_SURFACE; } else { - result = (half4)CREST_MASK_ABOVE_SURFACE; + result = CREST_MASK_ABOVE_SURFACE; } #if (CREST_PORTALS != 0) +#if d_Crest_NegativeVolumePass + result = Portal::FixMaskForNegativeVolume(result, i_Input.positionCS.xy); +#endif + #if d_Tunnel - const float rawFrontFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeFrontFaceTexture, input.positionCS.xy); - const float rawBackFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, input.positionCS.xy); - if (rawFrontFaceZ <= 0.0 && rawBackFaceZ > 0.0) + const float2 positionSS = i_Input.positionCS.xy; + const float ffz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogBeforeTexture, positionSS); + const float bfz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogAfterTexture, positionSS); + if (ffz <= 0.0 && bfz > 0.0) { - result = (half4)CREST_MASK_ABOVE_SURFACE; - } -#else - if (m_CrestPortal) - { - result *= masked ? 2 : 1; + result = CREST_MASK_ABOVE_SURFACE; } #endif #endif - return result; + return (half4)result; } m_CrestNameSpaceEnd @@ -148,4 +149,4 @@ m_CrestNameSpaceEnd m_CrestVertex m_CrestFragmentWithFrontFace(half4) -#endif // CREST_UNDERWATER_MASK_SHARED_INCLUDED +#endif // d_WaveHarmonic_Crest_Mask diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.shader index 3a3b715fa..c853ffa25 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.shader @@ -21,7 +21,7 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Stencil { - Ref [_StencilRef] + Ref [_Crest_StencilReference] Comp [_Crest_StencilComparison] } @@ -31,7 +31,7 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" // for VFACE #pragma target 3.0 - #pragma multi_compile_local __ d_Tunnel + #pragma multi_compile_local_fragment __ d_Tunnel #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" @@ -42,9 +42,8 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Pass { - Name "Water Surface Mask (Depth Only)" + Name "Water Surface Mask (Negative Volume)" Cull Off - ColorMask 0 HLSLPROGRAM #pragma vertex Vertex @@ -52,7 +51,9 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" // for VFACE #pragma target 3.0 - #define m_Discard discard + #define m_Return discard + + #define d_Crest_NegativeVolumePass 1 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" @@ -63,26 +64,21 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Pass { - Name "Water Horizon Mask" - Cull Off - ZWrite Off - // Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed. - ZTest Always - - Stencil - { - Ref [_StencilRef] - Comp [_Crest_StencilComparison] - } + Name "Water Surface Data" + Cull Back HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment + #pragma target 3.0 + + #define d_LodInput 1 + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl" ENDHLSL } } @@ -105,7 +101,7 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Stencil { - Ref [_StencilRef] + Ref [_Crest_StencilReference] Comp [_Crest_StencilComparison] } @@ -115,7 +111,7 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" // for VFACE #pragma target 3.0 - #pragma multi_compile_local __ d_Tunnel + #pragma multi_compile_local_fragment __ d_Tunnel #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" @@ -125,9 +121,8 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Pass { - Name "Water Surface Mask (Depth Only)" + Name "Water Surface Mask (Negative Volume)" Cull Off - ColorMask 0 HLSLPROGRAM #pragma vertex Vertex @@ -135,7 +130,9 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" // for VFACE #pragma target 3.0 - #define m_Discard discard + #define m_Return discard + + #define d_Crest_NegativeVolumePass 1 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" @@ -145,25 +142,20 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Pass { - Name "Water Horizon Mask" - Cull Off - ZWrite Off - // Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed. - ZTest Always - - Stencil - { - Ref [_StencilRef] - Comp [_Crest_StencilComparison] - } + Name "Water Surface Data" + Cull Back HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment + #pragma target 3.0 + + #define d_LodInput 1 + #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl" ENDHLSL } } @@ -179,75 +171,62 @@ Shader "Hidden/Crest/Underwater/Water Surface Mask" Stencil { - Ref [_StencilRef] + Ref [_Crest_StencilReference] Comp [_Crest_StencilComparison] } - CGPROGRAM + HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment // for VFACE #pragma target 3.0 - #pragma multi_compile_local __ d_Tunnel - - #include "UnityCG.cginc" + #pragma multi_compile_local_fragment __ d_Tunnel #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl" - ENDCG + ENDHLSL } Pass { - Name "Water Surface Mask (Depth Only)" + Name "Water Surface Mask (Negative Volume)" Cull Off - ColorMask 0 - CGPROGRAM + HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment // for VFACE #pragma target 3.0 - #define m_Discard discard + #define m_Return discard - #include "UnityCG.cginc" + #define d_Crest_NegativeVolumePass 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl" - ENDCG + ENDHLSL } Pass { - Name "Water Horizon Mask" - Cull Off - ZWrite Off - // Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed. - ZTest Always + Name "Water Surface Data" + Cull Back - Stencil - { - Ref [_StencilRef] - Comp [_Crest_StencilComparison] - } - - CGPROGRAM + HLSLPROGRAM #pragma vertex Vertex #pragma fragment Fragment - #include "UnityCG.cginc" + #pragma target 3.0 + + #define d_LodInput 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl" - ENDCG + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl" + ENDHLSL } } } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskArtifacts.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskArtifacts.compute index 1ba4a4689..86ea8139d 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskArtifacts.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskArtifacts.compute @@ -4,13 +4,12 @@ // Checks both orthogonal and diagonal pixels to fill artefacts in the mask. If checked pixels are all the same then it // assumes that the current pixel should also be the same and fixes it. -#pragma kernel FillMaskArtefacts +#pragma kernel FillMaskArtefacts _BRP // Built-in will not handle this for us unlike other RPs. -#pragma multi_compile __ STEREO_INSTANCING_ON +#pragma multi_compile _ STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON -#include "UnityCG.cginc" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl" RW_TEXTURE2D_X(float, _Crest_WaterMaskTexture); diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl index b6484c346..6dd5d5eb6 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl @@ -8,7 +8,6 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" // Driven by scripting. It is a non-linear converted from a linear 0-1 value. float _Crest_FarPlaneOffset; diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl index b8bc28969..dcac03cb5 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl @@ -3,16 +3,32 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl" #ifndef SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER #define FoveatedRemapLinearToNonUniform(uv) uv #endif +#if (CREST_LEGACY_UNDERWATER != 0) || d_Crest_CustomColorTexture +TEXTURE2D_X(_Crest_CameraColorTexture); +#endif + +#if d_Crest_ComputeMask +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl" +#endif + m_CrestNameSpace +#if (CREST_LEGACY_UNDERWATER != 0) +float3 SampleSceneColor(float2 i_UV) +{ + return LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, i_UV * _ScreenSize.xy).rgb; +} +#endif + struct Attributes { -#if CREST_WATER_VOLUME +#if d_Crest_Geometry float3 positionOS : POSITION; #else uint id : SV_VertexID; @@ -23,6 +39,9 @@ struct Attributes struct Varyings { float4 positionCS : SV_POSITION; +#if d_Crest_ComputeMask + float3 positionWS : TEXCOORD; +#endif UNITY_VERTEX_OUTPUT_STEREO }; @@ -33,9 +52,12 @@ Varyings Vertex(Attributes input) UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); -#if CREST_WATER_VOLUME +#if d_Crest_Geometry // Use actual geometry instead of full screen triangle. output.positionCS = TransformObjectToHClip(input.positionOS); +#if d_Crest_ComputeMask + output.positionWS = TransformObjectToWorld(input.positionOS); +#endif #else output.positionCS = GetFullScreenTriangleVertexPosition(input.id, UNITY_RAW_FAR_CLIP_VALUE); #endif @@ -48,53 +70,70 @@ half4 Fragment(Varyings input) UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); uint2 positionSS = input.positionCS.xy; - float mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).x; + const float2 positionNDC = (positionSS + 0.5) / _ScreenSize.xy; + float mask = -1.0; - const float2 uv = FoveatedRemapLinearToNonUniform(positionSS / _ScreenSize.xy); +#if !d_Crest_NoMaskColor +#if d_Crest_ComputeMask + { + float3 positionWS = input.positionWS; +#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) + positionWS.xyz += _WorldSpaceCameraPos.xyz; +#endif + mask = positionWS.y <= SampleWaterLineHeight(positionWS.xz) ? -1 : 1; + } +#else + mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).x; +#endif #if !_DEBUG_VISUALIZE_MASK -#if !d_Meniscus // Preserve alpha channel. if (mask > CREST_MASK_BELOW_SURFACE) { discard; } #endif -#endif +#endif // !d_Crest_NoMaskColor - float rawDepth = LoadCameraDepth(positionSS); - half3 sceneColour = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb; + float rawDepth = LoadSceneDepth(positionSS); + + half3 sceneColour; + +#if d_Crest_CustomColorTexture + if (m_CrestPortalNegativeVolume) + { + sceneColour = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb; + } + else +#endif + { + // Use sample in case texture is downsampled. + sceneColour = SampleSceneColor(positionNDC).rgb; + } + +#if d_Crest_NoMaskDepth + const float rawMaskDepth = 0.0; +#else const float rawMaskDepth = LOAD_TEXTURE2D_X(_Crest_WaterMaskDepthTexture, positionSS).x; +#endif #if _DEBUG_VISUALIZE_STENCIL return DebugRenderStencil(sceneColour); #endif - bool isWaterSurface; bool isUnderwater; bool hasCaustics; bool hasMeniscus; float sceneZ; float meniscusRawDepth; - GetWaterSurfaceAndUnderwaterData(input.positionCS, positionSS, rawMaskDepth, mask, rawDepth, meniscusRawDepth, isWaterSurface, isUnderwater, hasCaustics, hasMeniscus, sceneZ); - - float wt = 1.0; - - if (hasMeniscus) - { - wt = ComputeMeniscusWeight(positionSS, mask, _Crest_HorizonNormal, sceneZ); - } + bool isWaterSurface; bool isUnderwater; bool hasCaustics; float sceneZ; bool outScatterScene; bool applyLighting; + GetWaterSurfaceAndUnderwaterData(input.positionCS, positionSS, rawMaskDepth, mask, rawDepth, isWaterSurface, isUnderwater, hasCaustics, outScatterScene, applyLighting, sceneZ); #if !_DEBUG_VISUALIZE_MASK -#if d_Meniscus // Preserve alpha channel. - if (!isUnderwater && wt >= 1.0) + if (!isUnderwater) { discard; } -#endif #endif float fogDistance = sceneZ; - float meniscusDepth = 0.0; -#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN) - ApplyWaterVolumeToUnderwaterFogAndMeniscus(input.positionCS, meniscusRawDepth, fogDistance, meniscusDepth); -#endif + ApplyWaterVolumeToUnderwaterFog(input.positionCS, fogDistance); #if _DEBUG_VISUALIZE_MASK return DebugRenderWaterMask(isWaterSurface, isUnderwater, mask, sceneColour); @@ -102,15 +141,16 @@ half4 Fragment(Varyings input) if (isUnderwater) { + const float2 uv = FoveatedRemapLinearToNonUniform(positionNDC); float3 positionWS = ComputeWorldSpacePosition(uv, rawDepth, UNITY_MATRIX_I_VP); const half3 view = GetWorldSpaceNormalizeViewDir(positionWS); #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) positionWS += _WorldSpaceCameraPos; #endif - sceneColour = ApplyUnderwaterEffect(sceneColour, rawDepth, sceneZ, fogDistance, view, positionSS, positionWS, hasCaustics); + sceneColour = ApplyUnderwaterEffect(sceneColour, rawDepth, sceneZ, fogDistance, view, positionSS, positionWS, hasCaustics, outScatterScene, applyLighting, 1.0); } - return half4(wt * sceneColour, 1.0); + return half4(sceneColour, 1.0); } half4 FragmentPlanarReflections(Varyings input) @@ -118,7 +158,8 @@ half4 FragmentPlanarReflections(Varyings input) UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); const uint2 positionSS = input.positionCS.xy; - float depth = LoadCameraDepth(positionSS); + const float2 positionNDC = (positionSS + 0.5) / _ScreenSize.xy; + float depth = LoadSceneDepth(positionSS); // TODO: Do something nicer. Could zero alpha if scene depth is above threshold. if (depth == 0.0) @@ -126,12 +167,12 @@ half4 FragmentPlanarReflections(Varyings input) return half4(_Crest_Scattering.xyz, 1.0); } - half3 color = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb; + half3 color = SampleSceneColor(positionNDC).rgb; // Calculate position and account for possible NaNs discovered during testing. float3 positionWS; { - float4 positionCS = ComputeClipSpacePosition(positionSS / _ScreenSize.xy, depth); + float4 positionCS = ComputeClipSpacePosition(positionNDC, depth); float4 hpositionWS = mul(UNITY_MATRIX_I_VP, positionCS); // w is sometimes zero when using oblique projection. @@ -146,7 +187,7 @@ half4 FragmentPlanarReflections(Varyings input) const half3 view = GetWorldSpaceNormalizeViewDir(positionWS); const bool hasCaustics = depth > 0.0; - color = ApplyUnderwaterEffect(color, depth, 0.0, 0.0, view, positionSS, positionWS, hasCaustics); + color = ApplyUnderwaterEffect(color, depth, 0.0, 0.0, view, positionSS, positionWS, hasCaustics, true, true, 1.0); return half4(color, 1.0); } diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.shader b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.shader index d711715cc..ac0983410 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.shader +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.shader @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. Shader "Crest/Underwater" @@ -17,11 +17,6 @@ Shader "Crest/Underwater" _Crest_DitheringEnabled("Dithering", Integer) = 1 _Crest_DitheringIntensity("Dithering Intensity", Range(0, 10)) = 1 - [Space(10)] - - [Toggle(d_Meniscus)] - _Crest_MeniscusEnabled("Meniscus", Integer) = 1 - [Header(Advanced)] [Space(6)] @@ -68,9 +63,13 @@ Shader "Crest/Underwater" // Also on the water shader. #pragma multi_compile_local_fragment __ CREST_FLOW_ON - #pragma shader_feature_local_fragment __ d_Meniscus #pragma shader_feature_local_fragment __ d_Dithering + // NOTE: FragmentPlanarReflections do not need these. + // Whether to skip mask and/or depth sampling. + #pragma multi_compile_local_fragment __ d_Crest_NoMaskColor + #pragma multi_compile_local_fragment __ d_Crest_NoMaskDepth + #pragma multi_compile_local_fragment __ _DEBUG_VISUALIZE_MASK #pragma multi_compile_local_fragment __ _DEBUG_VISUALIZE_STENCIL ENDHLSL @@ -84,239 +83,17 @@ Shader "Crest/Underwater" Tags { "RenderPipeline"="HDRenderPipeline" } - ZWrite Off Blend Off - - Pass - { - Name "Full Screen" - Cull Off - ZTest Always - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - // Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of - // whether to skip the horizon calculation. - #pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - Name "Reflection" - Cull Off - ZTest Always - - HLSLPROGRAM - #define CREST_REFLECTION 1 - #include_with_pragmas "UnderwaterHDRP.hlsl" - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment FragmentPlanarReflections - ENDHLSL - } - - Pass - { - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (2D)" - Cull Back - ZTest LEqual - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (3D)" - Cull Back - ZTest LEqual - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (Fly-Through)" - Cull Back - ZTest LEqual - - Stencil - { - // Must match k_StencilValueVolume in: - // Portals.cs - Ref 5 - Comp Always - Pass Replace - ZFail IncrSat - } - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - // Back face will only render if view is within the volume and there is no scene in front. It will only add - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - // fog to the back face (and in effect anything behind it). No caustics. - Name "Volume: Back Face" - Cull Front - ZTest LEqual - - Stencil - { - // Must match k_StencilValueVolume in: - // Portals.cs - Ref 5 - Comp NotEqual - Pass Replace - ZFail IncrSat - } - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_BACK_FACE 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - // When inside a volume, this pass will render to the scene within the volume. - Name "Volume: Scene (Full Screen)" - Cull Back - ZTest Always - Stencil - { - // We want to render over the scene that's inside the volume, but not over already fogged areas. It will - // handle all of the scene within the geometry once the camera is within the volume. - // 0 = Outside of geometry as neither face passes have touched it. - // 1 = Only back face z failed which means scene is in front of back face but not front face. - // 2 = Both front and back face z failed which means outside geometry. - Ref 1 - Comp Equal - Pass Replace - } - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME_FULLSCREEN 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - - Pass - { - PackageRequirements - { - "com.waveharmonic.crest.portals" - } - - Name "Volume: Negative (Full Screen)" - Cull Off - ZTest Always - - HLSLPROGRAM - #include_with_pragmas "UnderwaterHDRP.hlsl" - - #define CREST_WATER_VOLUME_FULLSCREEN 1 - #define CREST_WATER_VOLUME_NEGATIVE 1 - #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" - - #pragma fragment Fragment - ENDHLSL - } - } - - Subshader - { - PackageRequirements - { - "com.unity.render-pipelines.universal" - } - - Tags { "RenderPipeline"="UniversalPipeline" } - + Cull Off + ZTest Always ZWrite Off Pass { Name "Full Screen" - Cull Off - ZTest Always HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" - - // Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of - // whether to skip the horizon calculation. - #pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT - + #include_with_pragmas "UnderwaterHDRP.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -326,14 +103,10 @@ Shader "Crest/Underwater" Pass { Name "Reflection" - Cull Off - ZTest Always HLSLPROGRAM #define CREST_REFLECTION 1 - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment FragmentPlanarReflections @@ -348,17 +121,19 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (2D)" + Name "Fog After" + Cull Back ZTest LEqual HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #pragma multi_compile_local _ d_Crest_ComputeMask + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogAfter 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -373,18 +148,18 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (3D)" + Name "Fog After To Back-Face" + Cull Back ZTest LEqual HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -399,7 +174,8 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (Fly-Through)" + Name "Fog After To Back-Face (Fly-Through)" + Cull Back ZTest LEqual @@ -414,13 +190,14 @@ Shader "Crest/Underwater" } HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #pragma multi_compile_local _ d_Crest_ComputeMask + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -436,7 +213,8 @@ Shader "Crest/Underwater" } // fog to the back face (and in effect anything behind it). No caustics. - Name "Volume: Back Face" + Name "Fog Before (Fly-Through)" + Cull Front ZTest LEqual @@ -451,12 +229,13 @@ Shader "Crest/Underwater" } HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_BACK_FACE 1 + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogBefore 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -471,9 +250,8 @@ Shader "Crest/Underwater" } // When inside a volume, this pass will render to the scene within the volume. - Name "Volume: Scene (Full Screen)" - Cull Back - ZTest Always + Name "Full Screen (Fly-Through)" + Stencil { // We want to render over the scene that's inside the volume, but not over already fogged areas. It will @@ -487,11 +265,9 @@ Shader "Crest/Underwater" } HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME_FULLSCREEN 1 + #define d_Crest_Portal 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -505,17 +281,16 @@ Shader "Crest/Underwater" "com.waveharmonic.crest.portals" } - Name "Volume: Negative (Full Screen)" - Cull Off - ZTest Always + Name "Full Screen (Negative)" HLSLPROGRAM - #include_with_pragmas "UnderwaterURP.hlsl" - #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" - #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include_with_pragmas "UnderwaterHDRP.hlsl" - #define CREST_WATER_VOLUME_FULLSCREEN 1 - #define CREST_WATER_VOLUME_NEGATIVE 1 + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_PortalNegativeVolume 1 + #define d_Crest_PortalWithBackFace 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -525,21 +300,257 @@ Shader "Crest/Underwater" SubShader { + PackageRequirements + { + "com.unity.render-pipelines.universal" + } + + Tags { "RenderPipeline"="UniversalPipeline" } + + Blend Off + Cull Off + ZTest Always ZWrite Off Pass { Name "Full Screen" - Cull Off - ZTest Always HLSLPROGRAM - #include_with_pragmas "UnderwaterBIRP.hlsl" - - // Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of - // whether to skip the horizon calculation. - #pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT - + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + Name "Reflection" + + HLSLPROGRAM + #define CREST_REFLECTION 1 + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment FragmentPlanarReflections + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + // Only adds fog to the front face and in effect anything behind it. + Name "Fog After" + + Cull Back + ZTest LEqual + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #pragma multi_compile_local _ d_Crest_ComputeMask + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogAfter 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + // Only adds fog to the front face and in effect anything behind it. + Name "Fog After To Back-Face" + + Cull Back + ZTest LEqual + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + // Only adds fog to the front face and in effect anything behind it. + Name "Fog After To Back-Face (Fly-Through)" + + Cull Back + ZTest LEqual + + Stencil + { + // Must match k_StencilValueVolume in: + // Portals.cs + Ref 5 + Comp Always + Pass Replace + ZFail IncrSat + } + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #pragma multi_compile_local _ d_Crest_ComputeMask + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + // Back face will only render if view is within the volume and there is no scene in front. It will only add + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + // fog to the back face (and in effect anything behind it). No caustics. + Name "Fog Before (Fly-Through)" + + Cull Front + ZTest LEqual + + Stencil + { + // Must match k_StencilValueVolume in: + // Portals.cs + Ref 5 + Comp NotEqual + Pass Replace + ZFail IncrSat + } + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogBefore 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + // When inside a volume, this pass will render to the scene within the volume. + Name "Full Screen (Fly-Through)" + + Stencil + { + // We want to render over the scene that's inside the volume, but not over already fogged areas. It will + // handle all of the scene within the geometry once the camera is within the volume. + // 0 = Outside of geometry as neither face passes have touched it. + // 1 = Only back face z failed which means scene is in front of back face but not front face. + // 2 = Both front and back face z failed which means outside geometry. + Ref 1 + Comp Equal + Pass Replace + } + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #define d_Crest_Portal 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + + Pass + { + PackageRequirements + { + "com.waveharmonic.crest.portals" + } + + Name "Full Screen (Negative)" + + HLSLPROGRAM + #include_with_pragmas "UnderwaterURP.hlsl" + #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" + #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl" + + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_PortalNegativeVolume 1 + #define d_Crest_PortalWithBackFace 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" + + #pragma fragment Fragment + ENDHLSL + } + } + + SubShader + { + Blend Off + Cull Off + ZTest Always + ZWrite Off + + Pass + { + Name "Full Screen" + + HLSLPROGRAM + #include_with_pragmas "UnderwaterBIRP.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -549,8 +560,6 @@ Shader "Crest/Underwater" Pass { Name "Reflection" - Cull Off - ZTest Always HLSLPROGRAM #define CREST_REFLECTION 1 @@ -569,15 +578,19 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (2D)" + Name "Fog After" + Cull Back ZTest LEqual HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #pragma multi_compile_local _ d_Crest_ComputeMask + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogAfter 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -592,16 +605,18 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (3D)" + Name "Fog After To Back-Face" + Cull Back ZTest LEqual HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -616,7 +631,8 @@ Shader "Crest/Underwater" } // Only adds fog to the front face and in effect anything behind it. - Name "Volume: Front Face (Fly-Through)" + Name "Fog After To Back-Face (Fly-Through)" + Cull Back ZTest LEqual @@ -633,9 +649,11 @@ Shader "Crest/Underwater" HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_HAS_BACKFACE 1 - #define CREST_WATER_VOLUME_FRONT_FACE 1 + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_PortalWithBackFace 1 + #define d_Crest_FogAfter 1 + #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -651,7 +669,8 @@ Shader "Crest/Underwater" } // fog to the back face (and in effect anything behind it). No caustics. - Name "Volume: Back Face" + Name "Fog Before (Fly-Through)" + Cull Front ZTest LEqual @@ -668,8 +687,14 @@ Shader "Crest/Underwater" HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME 1 - #define CREST_WATER_VOLUME_BACK_FACE 1 + #pragma multi_compile_local _ d_Crest_ComputeMask + + // For negative volumes. + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_Geometry 1 + #define d_Crest_FogBefore 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -684,9 +709,8 @@ Shader "Crest/Underwater" } // When inside a volume, this pass will render to the scene within the volume. - Name "Volume: Scene (Full Screen)" - Cull Back - ZTest Always + Name "Full Screen (Fly-Through)" + Stencil { // We want to render over the scene that's inside the volume, but not over already fogged areas. It will @@ -702,7 +726,7 @@ Shader "Crest/Underwater" HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME_FULLSCREEN 1 + #define d_Crest_Portal 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment @@ -716,15 +740,16 @@ Shader "Crest/Underwater" "com.waveharmonic.crest.portals" } - Name "Volume: Negative (Full Screen)" - Cull Off - ZTest Always + Name "Full Screen (Negative)" HLSLPROGRAM #include_with_pragmas "UnderwaterBIRP.hlsl" - #define CREST_WATER_VOLUME_FULLSCREEN 1 - #define CREST_WATER_VOLUME_NEGATIVE 1 + #define d_Crest_CustomColorTexture 1 + + #define d_Crest_Portal 1 + #define d_Crest_PortalNegativeVolume 1 + #define d_Crest_PortalWithBackFace 1 #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl" #pragma fragment Fragment diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterBIRP.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterBIRP.hlsl index 0fb106ed1..4a1951ed2 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterBIRP.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterBIRP.hlsl @@ -6,23 +6,16 @@ #define CREST_BIRP 1 #define CREST_SHADERGRAPH_CONSTANTS_H -#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Shim/Shims.hlsl" -#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Core.hlsl" +#pragma multi_compile_fragment _ DIRECTIONAL_COOKIE + +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/ShaderPass.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Defines.hlsl" + +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl" + #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/LegacySurfaceVertex.hlsl" #include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/ShaderGraphFunctions.hlsl" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl" -#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl" - -TEXTURE2D_X(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture); - -m_CrestNameSpace - -float LoadCameraDepth(uint2 pixelCoords) -{ - return LOAD_TEXTURE2D_X(_CameraDepthTexture, pixelCoords).r; -} - -m_CrestNameSpaceEnd +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareOpaqueTexture.hlsl" +#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/DeclareDepthTexture.hlsl" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterHDRP.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterHDRP.hlsl index 1ff81d1e7..ba84092d2 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterHDRP.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterHDRP.hlsl @@ -16,3 +16,4 @@ #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/HDRP/Common.hlsl" diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl index 81b022d98..f23a02f5e 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl @@ -11,8 +11,9 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Helpers.hlsl" -#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN) +#if d_Crest_Portal #include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl" #endif @@ -20,6 +21,7 @@ #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Texture.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl" +#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Shadows.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Caustics.hlsl" @@ -31,10 +33,16 @@ CBUFFER_START(CrestPerMaterial) // Surface Shared // +#ifndef d_Crest_WaterSurface + half4 _Crest_Absorption; half4 _Crest_Scattering; half _Crest_Anisotropy; +half _Crest_DirectTerm; +half _Crest_AmbientTerm; +half _Crest_ShadowsAffectsAmbientFactor; + bool _Crest_CausticsEnabled; float _Crest_CausticsTextureScale; float _Crest_CausticsScrollSpeed; @@ -48,16 +56,12 @@ half _Crest_CausticsMotionBlur; float4 _Crest_CausticsTexture_TexelSize; float4 _Crest_CausticsDistortionTexture_TexelSize; -half _Crest_DirectTerm; -half _Crest_AmbientTerm; -half _Crest_ShadowsAffectsAmbientFactor; +#endif // !d_Crest_WaterSurface // // Volume Only // -float2 _Crest_HorizonNormal; - // Out-scattering. Driven by the Water Renderer and Underwater Environmental Lighting. float _Crest_VolumeExtinctionLength; float _Crest_UnderwaterEnvironmentalLightingWeight; @@ -73,9 +77,10 @@ int _Crest_DataSliceOffset; half _Crest_DitheringIntensity; CBUFFER_END -TEXTURE2D_X(_Crest_WaterMaskTexture); TEXTURE2D_X(_Crest_WaterMaskDepthTexture); -TEXTURE2D_X(_Crest_CameraColorTexture); + +#ifndef d_Crest_WaterSurface +TEXTURE2D_X(_Crest_WaterMaskTexture); TEXTURE2D(_Crest_CausticsTexture); SAMPLER(sampler_Crest_CausticsTexture); @@ -87,118 +92,50 @@ static const m_Crest::TiledTexture _Crest_CausticsTiledTexture = m_Crest::TiledTexture::Make(_Crest_CausticsTexture, sampler_Crest_CausticsTexture, _Crest_CausticsTexture_TexelSize, _Crest_CausticsTextureScale, _Crest_CausticsScrollSpeed); static const m_Crest::TiledTexture _Crest_CausticsDistortionTiledTexture = m_Crest::TiledTexture::Make(_Crest_CausticsDistortionTexture, sampler_Crest_CausticsDistortionTexture, _Crest_CausticsDistortionTexture_TexelSize, _Crest_CausticsDistortionScale, 1.0); +#endif // !d_Crest_WaterSurface m_CrestNameSpace -float LinearToDeviceDepth(float linearDepth, float4 zBufferParam) +// Get the out-scattering term. +half3 EvaluateOutScattering +( + const half3 i_Extinction, + const float3 i_PositionWS, + const half3 i_ViewWS, + const half i_Multiplier, + const float i_RawDepth, + const float i_WaterLevel +) { - //linear = 1.0 / (zBufferParam.z * device + zBufferParam.w); - float device = (1.0 / linearDepth - zBufferParam.w) / zBufferParam.z; - return device; -} + float3 positionWS = i_PositionWS; -#if d_Dithering -// Adapted from: -// https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf -float3 ScreenSpaceDither(const float2 i_ScreenPosition) -{ - // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. - float3 dither = dot(float2(171.0, 231.0), i_ScreenPosition.xy); - dither.rgb = frac(dither.rgb / float3(103.0, 71.0, 97.0)) - float3(0.5, 0.5, 0.5); - return (dither.rgb / 255.0); -} +#if !CREST_REFLECTION + // Project point onto sphere at the extinction length. + const float3 toSphere = -i_ViewWS * _Crest_VolumeExtinctionLength * i_Multiplier * _Crest_OutScatteringExtinctionFactor; + const float3 toScene = i_PositionWS - _WorldSpaceCameraPos.xyz; + positionWS = _WorldSpaceCameraPos.xyz + toSphere; + + // Get closest position. + positionWS = dot(toScene, toScene) < dot(toSphere, toSphere) ? i_PositionWS : positionWS; #endif -float4 DebugRenderWaterMask(const bool isWaterSurface, const bool isUnderwater, const float mask, const float3 sceneColour) -{ - // Red: surface front face when above water - // Green: surface back face when below water - // Cyan: background when above water - // Magenta: background when below water - if (isWaterSurface) - { - return float4(sceneColour * float3(mask >= CREST_MASK_ABOVE_SURFACE, mask <= CREST_MASK_BELOW_SURFACE, 0.0), 1.0); - } - else - { - return float4(sceneColour * float3(isUnderwater * 0.5, (1.0 - isUnderwater) * 0.5, 1.0), 1.0); - } -} + // Account for average extinction of light as it travels down through volume. Assume flat water as anything + // else would be expensive. + float waterDepth = max(0.0, (i_WaterLevel - positionWS.y)); -float4 DebugRenderStencil(float3 sceneColour) -{ - float3 stencil = 1.0; -#if CREST_WATER_VOLUME_FRONT_FACE - stencil = float3(1.0, 0.0, 0.0); -#elif CREST_WATER_VOLUME_BACK_FACE - stencil = float3(0.0, 1.0, 0.0); -#elif CREST_WATER_VOLUME_FULLSCREEN - stencil = float3(0.0, 0.0, 1.0); -#endif - return float4(sceneColour * stencil, 1.0); -} - -float MeniscusSampleWaterMask(const float mask, const int2 positionSS, const float2 offset, const float magnitude, const float scale) -{ - float2 uv = positionSS + offset * magnitude -#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN) - * scale -#endif - ; - - float newMask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, uv).r; - -#if CREST_UNDERWATER_BEFORE_TRANSPARENT - // Normalize mask. - newMask = clamp(newMask, -1.0, 1.0); -#endif - -#if CREST_WATER_VOLUME - // No mask means no underwater effect so ignore the value. - return (newMask == CREST_MASK_NONE ? mask : newMask); -#endif - return newMask; -} - -half ComputeMeniscusWeight(const int2 positionSS, float mask, const float2 horizonNormal, const float meniscusDepth) -{ - float weight = 1.0; -#if d_Meniscus -#if !_FULL_SCREEN_EFFECT - -#if CREST_UNDERWATER_BEFORE_TRANSPARENT - // Normalize mask. - mask = clamp(mask, -1.0, 1.0); -#endif - - // Render meniscus by checking the mask along the horizon normal which is flipped using the surface normal from - // mask. Adding the mask value will flip the UV when mask is below surface. - float2 offset = (float2)-mask * horizonNormal; - float multiplier = 0.9; - -#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN) - // The meniscus at the boundary can be at a distance. We need to scale the offset as 1 pixel at a distance is much - // larger than 1 pixel up close. - const float scale = 1.0 - saturate(meniscusDepth / MENISCUS_MAXIMUM_DISTANCE); - - // Exit early. - if (scale == 0.0) - { - return 1.0; - } +#if CREST_REFLECTION + waterDepth *= 2.0; + if (i_RawDepth == 0.0) waterDepth = _Crest_VolumeExtinctionLength * i_Multiplier; #else - // Dummy value. - const float scale = 0.0; + // Full strength seems too extreme. Third strength seems reasonable. + waterDepth *= _Crest_OutScatteringFactor; #endif - // Sample three pixels along the normal. If the sample is different than the current mask, apply meniscus. - // Offset must be added to positionSS as floats. - weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 1.0, scale) != mask) ? multiplier : 1.0; - weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 2.0, scale) != mask) ? multiplier : 1.0; - weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 3.0, scale) != mask) ? multiplier : 1.0; -#endif // _FULL_SCREEN_EFFECT -#endif // d_Meniscus - return weight; + const float3 outScatteringTerm = exp(-i_Extinction * waterDepth); + + // Transition between the Underwater Environmental Lighting (if present) and this. This will give us the + // benefit of both approaches. + return lerp(outScatteringTerm, 1.0, _Crest_UnderwaterEnvironmentalLightingWeight); } void GetWaterSurfaceAndUnderwaterData @@ -208,11 +145,11 @@ void GetWaterSurfaceAndUnderwaterData const float rawMaskDepth, const float mask, inout float rawDepth, - inout float rawMeniscusDepth, inout bool isWaterSurface, inout bool isUnderwater, inout bool hasCaustics, - inout bool hasMeniscus, + inout bool io_OutScatterScene, + inout bool io_ApplyLighting, inout float sceneZ ) { @@ -220,75 +157,17 @@ void GetWaterSurfaceAndUnderwaterData hasCaustics = rawDepth != 0.0; isWaterSurface = false; isUnderwater = mask <= CREST_MASK_BELOW_SURFACE; - hasMeniscus = true; - rawMeniscusDepth = positionCS.z; + io_OutScatterScene = true; + io_ApplyLighting = true; -#if defined(CREST_WATER_VOLUME_HAS_BACKFACE) || defined(CREST_WATER_VOLUME_BACK_FACE) || defined(CREST_WATER_VOLUME_NEGATIVE) - const float rawGeometryDepth = -#if CREST_WATER_VOLUME_HAS_BACKFACE - // 3D has a back face texture for the depth. - LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, positionSS); -#elif CREST_WATER_VOLUME_NEGATIVE - LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeFrontFaceTexture, positionSS); -#else - // Volume is rendered using the back face so that is the depth. - positionCS.z; -#endif // CREST_WATER_VOLUME_HAS_BACKFACE - ; - - if ((rawMaskDepth > 0.0 && rawMaskDepth <= rawSceneDepth) || (rawGeometryDepth > 0.0 && rawGeometryDepth <= rawSceneDepth)) - { - hasMeniscus = false; - } - - // Use backface depth if closest. - if (rawDepth < rawGeometryDepth) - { - // Cancels out caustics. - hasCaustics = false; - rawDepth = rawGeometryDepth; - } - -#if CREST_WATER_VOLUME_NEGATIVE - rawMeniscusDepth = rawGeometryDepth; - if (rawGeometryDepth == 0.0) - { - const float rawBackFaceDepth = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, positionSS); - - // We are in the negative volume. Already handled by front face. - if (rawBackFaceDepth > 0.0) - { - if (rawBackFaceDepth <= rawSceneDepth) - { - hasMeniscus = false; - } - - isUnderwater = false; - } - } -#endif // CREST_WATER_VOLUME_NEGATIVE -#endif // CREST_WATER_VOLUME - -#if CREST_WATER_VOLUME_FRONT_FACE - // If negative volume, we keep the mask intact, and just mark it. - if (mask >= CREST_MASK_ABOVE_SURFACE_KEPT) - { - isUnderwater = true; - } - else if (mask <= CREST_MASK_BELOW_SURFACE_KEPT) - { - isUnderwater = false; - } +#if defined(d_Crest_PortalWithBackFace) || defined(d_Crest_FogBefore) + // Has back-face or is back-face. + Portal::EvaluateVolume(positionCS, positionSS, rawMaskDepth, rawSceneDepth, rawDepth, hasCaustics, isUnderwater, io_OutScatterScene, io_ApplyLighting); #endif // Merge water depth with scene depth. if (rawDepth < rawMaskDepth) { -#if CREST_UNDERWATER_BEFORE_TRANSPARENT - // Apply fog to culled tiles otherwise there will be no fog as water shader can only fog enabled tiles. And - // only apply fog to culled tiles otherwise it will be fogged twice (second by water shader). - isUnderwater = mask <= CREST_MASK_BELOW_SURFACE_CULLED; -#endif isWaterSurface = true; hasCaustics = false; rawDepth = rawMaskDepth; @@ -297,21 +176,19 @@ void GetWaterSurfaceAndUnderwaterData sceneZ = Utility::CrestLinearEyeDepth(rawDepth); } -void ApplyWaterVolumeToUnderwaterFogAndMeniscus(float4 positionCS, const float meniscusRawDepth, inout float fogDistance, inout float meniscusDepth) +void ApplyWaterVolumeToUnderwaterFog(float4 positionCS, inout float fogDistance) { -#if CREST_WATER_VOLUME_FRONT_FACE - float depth = Utility::CrestLinearEyeDepth(positionCS.z); - // Meniscus is rendered at the boundary so use the geometry z. - meniscusDepth = depth; - fogDistance -= depth; + // TODO: could we use min here with near plane? less optimized +#if d_Crest_FogAfter + fogDistance -= Utility::CrestLinearEyeDepth(positionCS.z); #else - float depth = Utility::CrestLinearEyeDepth(meniscusRawDepth); - // Meniscus is rendered at the boundary so use the geometry z. - meniscusDepth = depth; + // Subtract near plane. + fogDistance -= _ProjectionParams.y; #endif } -half3 ApplyUnderwaterEffect( +half3 ApplyUnderwaterEffect +( half3 sceneColour, const float rawDepth, const float sceneZ, @@ -319,8 +196,12 @@ half3 ApplyUnderwaterEffect( const half3 view, const uint2 i_positionSS, const float3 i_positionWS, - const bool hasCaustics -) { + const bool hasCaustics, + const bool i_OutScatterScene, + const bool i_ApplyLighting, + const half i_multiplier +) +{ const bool isUnderwater = true; float3 lightDirection; float3 lightColor; @@ -340,6 +221,9 @@ half3 ApplyUnderwaterEffect( if (g_Crest_SampleAbsorptionSimulation) absorption = Cascade::MakeAbsorption(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz; if (g_Crest_SampleScatteringSimulation) scattering = Cascade::MakeScattering(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz; + absorption *= _Crest_ExtinctionMultiplier; + scattering *= _Crest_ExtinctionMultiplier; + const float waterLevel = g_Crest_WaterCenter.y + Cascade::MakeAnimatedWaves(sliceIndex).Sample(_WorldSpaceCameraPos.xz).w; half shadow = 1.0; @@ -354,55 +238,35 @@ half3 ApplyUnderwaterEffect( // #endif } - half3 ambientLighting = _Crest_AmbientLighting; -#if CREST_HDRP - ApplyIndirectLightingMultiplier(ambientLighting); -#endif + half3 ambientLighting = AmbientLight(_Crest_AmbientLighting); + + const half3 extinction = VolumeExtinction(absorption, scattering); // Out-Scattering Term. { - float3 positionWS = i_positionWS; - -#if !CREST_REFLECTION - // Project point onto sphere at the extinction length. - float3 toSphere = -view * _Crest_VolumeExtinctionLength * _Crest_OutScatteringExtinctionFactor; - float3 toScene = i_positionWS - _WorldSpaceCameraPos.xyz; - positionWS = _WorldSpaceCameraPos.xyz + toSphere; - - // Get closest position. - positionWS = dot(toScene, toScene) < dot(toSphere, toSphere) ? i_positionWS : positionWS; -#endif - - // Account for average extinction of light as it travels down through volume. Assume flat water as anything - // else would be expensive. - half3 extinction = (absorption + scattering) * _Crest_ExtinctionMultiplier; - float waterDepth = max(0.0, (waterLevel - positionWS.y)); -#if CREST_REFLECTION - waterDepth *= 2.0; - if (rawDepth == 0.0) waterDepth = _Crest_VolumeExtinctionLength; -#else - // Full strength seems too extreme. Third strength seems reasonable. - waterDepth *= _Crest_OutScatteringFactor; -#endif - - float3 outScatteringTerm = exp(-extinction * waterDepth); - - // Transition between the Underwater Environmental Lighting (if present) and this. This will give us the - // benefit of both approaches. - outScatteringTerm = lerp(outScatteringTerm, 1.0, _Crest_UnderwaterEnvironmentalLightingWeight); + const half3 outScatteringTerm = EvaluateOutScattering + ( + extinction, + i_positionWS, + view, + i_multiplier, + rawDepth, + waterLevel + ); // Darken scene and light. - sceneColour *= outScatteringTerm; + sceneColour *= i_OutScatterScene ? outScatteringTerm : 1.0; #if !CREST_REFLECTION lightColor *= outScatteringTerm; ambientLighting *= outScatteringTerm; #endif } - VolumeLighting + volumeOpacity = VolumeOpacity(extinction, fogDistance); + volumeLight = VolumeLighting ( - absorption * _Crest_ExtinctionMultiplier, - scattering * _Crest_ExtinctionMultiplier, + extinction, + scattering, _Crest_Anisotropy, shadow, view, @@ -412,23 +276,15 @@ half3 ApplyUnderwaterEffect( half3(0.0, 0.0, 0.0), _Crest_AmbientTerm, _Crest_DirectTerm, - fogDistance, _Crest_SunBoost, - _Crest_ShadowsAffectsAmbientFactor, - volumeLight, - volumeOpacity + _Crest_ShadowsAffectsAmbientFactor ); } #ifndef k_DisableCaustics if (_Crest_CausticsEnabled && hasCaustics) { - float3 position = i_positionWS; -#if CREST_BIRP - position = float3(i_positionSS, 0); -#endif - - half lightOcclusion = PrimaryLightShadows(position); + half lightOcclusion = PrimaryLightShadows(i_positionWS, i_positionSS); half blur = 0.0; const uint slice0 = PositionToSliceIndex(i_positionWS.xz, 0, g_Crest_WaterScale); @@ -473,11 +329,16 @@ half3 ApplyUnderwaterEffect( #ifndef k_DisableDithering #if d_Dithering // Increasing intensity can be required for HDRP. - volumeLight += ScreenSpaceDither(i_positionSS) * _Crest_DitheringIntensity; + volumeLight += Utility::ScreenSpaceDither(i_positionSS) * _Crest_DitheringIntensity; #endif #endif - return lerp(sceneColour, volumeLight, volumeOpacity); + if (i_ApplyLighting) + { + sceneColour = lerp(sceneColour, volumeLight, volumeOpacity); + } + + return sceneColour; } m_CrestNameSpaceEnd diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterURP.hlsl b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterURP.hlsl index bd4794032..676f561f9 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterURP.hlsl +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterURP.hlsl @@ -10,17 +10,7 @@ #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" - -TEXTURE2D_X(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture); +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" #include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl" - -m_CrestNameSpace - -// Shim as HDRP uses this. -float LoadCameraDepth(uint2 pixelCoords) -{ - return LOAD_TEXTURE2D_X(_CameraDepthTexture, pixelCoords).r; -} - -m_CrestNameSpaceEnd diff --git a/Packages/com.waveharmonic.crest/Runtime/Shaders/Waves/Gerstner/Gerstner.compute b/Packages/com.waveharmonic.crest/Runtime/Shaders/Waves/Gerstner/Gerstner.compute index a04d62570..7c2f80f49 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Shaders/Waves/Gerstner/Gerstner.compute +++ b/Packages/com.waveharmonic.crest/Runtime/Shaders/Waves/Gerstner/Gerstner.compute @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. // Computes a set of patches of waves, one for each scale. diff --git a/Packages/com.waveharmonic.crest/Runtime/Textures/Caustics/Caustics.png.meta b/Packages/com.waveharmonic.crest/Runtime/Textures/Caustics/Caustics.png.meta index d7a380aad..bf84057ca 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Textures/Caustics/Caustics.png.meta +++ b/Packages/com.waveharmonic.crest/Runtime/Textures/Caustics/Caustics.png.meta @@ -93,6 +93,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Runtime/Textures/WaveNormals/WaveNormals.png.meta b/Packages/com.waveharmonic.crest/Runtime/Textures/WaveNormals/WaveNormals.png.meta index 765a2a9c8..e98679f0d 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Textures/WaveNormals/WaveNormals.png.meta +++ b/Packages/com.waveharmonic.crest/Runtime/Textures/WaveNormals/WaveNormals.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 1 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Runtime/Textures/foam.png.meta b/Packages/com.waveharmonic.crest/Runtime/Textures/foam.png.meta index 4c572f475..75ef155a3 100644 --- a/Packages/com.waveharmonic.crest/Runtime/Textures/foam.png.meta +++ b/Packages/com.waveharmonic.crest/Runtime/Textures/foam.png.meta @@ -93,6 +93,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Flare50mm.psd.meta b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Flare50mm.psd.meta index e130c3cc5..5734ec99c 100644 --- a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Flare50mm.psd.meta +++ b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Flare50mm.psd.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 512 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/PartialRing.png.meta b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/PartialRing.png.meta index 05c0dd160..e2ea276f2 100644 --- a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/PartialRing.png.meta +++ b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/PartialRing.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Ring.png.meta b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Ring.png.meta index 2491f05d2..16c464994 100644 --- a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Ring.png.meta +++ b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Ring.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Shimmer.png.meta b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Shimmer.png.meta index b58d52a77..ecd196aa3 100644 --- a/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Shimmer.png.meta +++ b/Packages/com.waveharmonic.crest/Shared/Effects/LensFlares/Textures/Shimmer.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Prefabs/Camera.prefab b/Packages/com.waveharmonic.crest/Shared/Prefabs/Camera.prefab index e4c844be0..bf46945a1 100644 --- a/Packages/com.waveharmonic.crest/Shared/Prefabs/Camera.prefab +++ b/Packages/com.waveharmonic.crest/Shared/Prefabs/Camera.prefab @@ -73,7 +73,7 @@ Camera: y: 0 width: 1 height: 1 - near clip plane: 1 + near clip plane: 0.3 far clip plane: 10000 field of view: 60 orthographic: 0 diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/AlignSceneViewToCamera.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/AlignSceneViewToCamera.cs index 0be8999af..b24fa032d 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/AlignSceneViewToCamera.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/AlignSceneViewToCamera.cs @@ -54,7 +54,8 @@ namespace WaveHarmonic.Crest.Examples void EditorUpdate() { - if (s_SceneChanged && SceneView.lastActiveSceneView != null && WaterRenderer.Instance != null && WaterRenderer.Instance.IsSceneViewActive) + var water = WaterRenderer.Instance; + if (s_SceneChanged && SceneView.lastActiveSceneView != null && water != null && water.IsSceneViewActive) { TeleportSceneCamera(transform); s_SceneChanged = false; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/CameraController.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/CameraController.cs index 248043346..3e8cbbe95 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/CameraController.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/CameraController.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. #if d_UnityInputSystem && ENABLE_INPUT_SYSTEM @@ -137,7 +137,6 @@ namespace WaveHarmonic.Crest.Examples forward = 1f; } - _TargetTransform.position += dt * forward * _LinearSpeed * _TargetTransform.forward; var speed = _LinearSpeed; #if INPUT_SYSTEM_ENABLED diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/LerpCamera.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/LerpCamera.cs index 53b78d611..e88ca29e5 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/LerpCamera.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/LerpCamera.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleDisplacementDemo.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleDisplacementDemo.cs index 9a2bb7656..94ebaf6db 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleDisplacementDemo.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleDisplacementDemo.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using System; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleHeightDemo.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleHeightDemo.cs index b432adb1c..051fac8f3 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleHeightDemo.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/Queries/SampleHeightDemo.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/RandomMotion.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/RandomMotion.cs index 6f10041b4..5a865d3af 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/RandomMotion.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/RandomMotion.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/AmbientLightPatcher.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/AmbientLightPatcher.cs index 822f5ca8c..a08db24bd 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/AmbientLightPatcher.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/AmbientLightPatcher.cs @@ -83,6 +83,10 @@ namespace WaveHarmonic.Crest.Editor UnityEditor.Lightmapping.giWorkflowMode = oldWorkflow; #endif +#if CREST_DEBUG + Debug.Log($"Crest: Baked scene lighting!"); +#endif + if (!_Baked) { Debug.LogWarning($"Crest: Could not generate scene lighting. Lighting will look incorrect."); diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/RenderPipelineTerrainPatcher.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/RenderPipelineTerrainPatcher.cs index c31298888..c70e54690 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/RenderPipelineTerrainPatcher.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/Rendering/RenderPipelineTerrainPatcher.cs @@ -44,6 +44,7 @@ namespace WaveHarmonic.Crest.Editor return; } +#if d_Unity_Terrain foreach (var terrain in GetComponentsInChildren()) { terrain.materialTemplate = RenderPipelineHelper.RenderPipeline switch @@ -54,6 +55,7 @@ namespace WaveHarmonic.Crest.Editor _ => throw new System.NotImplementedException(), }; } +#endif // d_Unity_Terrain } #endif } diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/SimpleMotion.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/SimpleMotion.cs index a7a1d6183..ec8a19bb8 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/SimpleMotion.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/SimpleMotion.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/TimedDestroy.cs b/Packages/com.waveharmonic.crest/Shared/Scripts/TimedDestroy.cs index 5f96218dc..7b064ac06 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/TimedDestroy.cs +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/TimedDestroy.cs @@ -1,4 +1,4 @@ -// Crest Water System +// Crest Water System // Copyright © 2024 Wave Harmonic. All rights reserved. using UnityEngine; diff --git a/Packages/com.waveharmonic.crest/Shared/Scripts/WaveHarmonic.Crest.Samples.asmdef b/Packages/com.waveharmonic.crest/Shared/Scripts/WaveHarmonic.Crest.Samples.asmdef index eeced06e4..73dc4c27e 100644 --- a/Packages/com.waveharmonic.crest/Shared/Scripts/WaveHarmonic.Crest.Samples.asmdef +++ b/Packages/com.waveharmonic.crest/Shared/Scripts/WaveHarmonic.Crest.Samples.asmdef @@ -20,6 +20,11 @@ "UNITY_2022_3_OR_NEWER" ], "versionDefines": [ + { + "name": "com.unity.modules.terrain", + "expression": "", + "define": "d_Unity_Terrain" + }, { "name": "com.unity.modules.vr", "expression": "", diff --git a/Packages/com.waveharmonic.crest/Shared/Shaders/Lit.shadergraph b/Packages/com.waveharmonic.crest/Shared/Shaders/Lit.shadergraph index 36400493f..4cf3119ae 100644 --- a/Packages/com.waveharmonic.crest/Shared/Shaders/Lit.shadergraph +++ b/Packages/com.waveharmonic.crest/Shared/Shaders/Lit.shadergraph @@ -315,6 +315,9 @@ }, { "m_Id": "3dc06e3c9ccb4bc8b1479d4d78855705" + }, + { + "m_Id": "3d920b053a2f4bbfaaf6ba4f8c9f137e" } ], "m_GroupDatas": [ @@ -599,6 +602,34 @@ "m_SlotId": 0 } }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3d920b053a2f4bbfaaf6ba4f8c9f137e" + }, + "m_SlotId": 1 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "bc13f29ae89348fd880b7361cff27f24" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3d920b053a2f4bbfaaf6ba4f8c9f137e" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "fca2a686d3fd4b588cde3b54823bb062" + }, + "m_SlotId": 0 + } + }, { "m_OutputSlot": { "m_Node": { @@ -650,9 +681,9 @@ }, "m_InputSlot": { "m_Node": { - "m_Id": "bc13f29ae89348fd880b7361cff27f24" + "m_Id": "3d920b053a2f4bbfaaf6ba4f8c9f137e" }, - "m_SlotId": 0 + "m_SlotId": 18569658 } }, { @@ -1000,9 +1031,9 @@ }, "m_InputSlot": { "m_Node": { - "m_Id": "fca2a686d3fd4b588cde3b54823bb062" + "m_Id": "3d920b053a2f4bbfaaf6ba4f8c9f137e" }, - "m_SlotId": 0 + "m_SlotId": -457410494 } }, { @@ -2799,6 +2830,21 @@ } } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "2f7034eaf21b4eedaf6c9dbfbc101d80", + "m_Id": -1490972, + "m_DisplayName": "Multiplier", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Vector1_0640f7e405ca4ded9cced0944e419139", + "m_StageCapability": 3, + "m_Value": 1.0, + "m_DefaultValue": 0.0, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.Rendering.BuiltIn.ShaderGraph.BuiltInLitSubTarget", @@ -3144,6 +3190,64 @@ "m_Labels": [] } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.SubGraphNode", + "m_ObjectId": "3d920b053a2f4bbfaaf6ba4f8c9f137e", + "m_Group": { + "m_Id": "" + }, + "m_Name": "Integrate Water Volume", + "m_DrawState": { + "m_Expanded": true, + "m_Position": { + "serializedVersion": "2", + "x": -494.00006103515627, + "y": 249.5000457763672, + "width": 195.00006103515626, + "height": 142.9999542236328 + } + }, + "m_Slots": [ + { + "m_Id": "620ebe491daf41b7a2a79b30e2820846" + }, + { + "m_Id": "9f92af83b5ad4eb6840f7858e51e9736" + }, + { + "m_Id": "2f7034eaf21b4eedaf6c9dbfbc101d80" + }, + { + "m_Id": "5bff6fd9b79f4cef83b76fa7991d407b" + }, + { + "m_Id": "7a6d09da26b84c7abd84a17926d857cf" + } + ], + "synonyms": [], + "m_Precision": 0, + "m_PreviewExpanded": false, + "m_DismissedVersion": 0, + "m_PreviewMode": 0, + "m_CustomColors": { + "m_SerializableColors": [] + }, + "m_SerializedSubGraph": "{\n \"subGraph\": {\n \"fileID\": -5475051401550479605,\n \"guid\": \"df63a8d198812478985b6d0a5d68a59a\",\n \"type\": 3\n }\n}", + "m_PropertyGuids": [ + "4e700f9f-71e1-44ca-82f1-a15c46d60057", + "bebcb4b2-70d3-4426-b192-1c54922e3a4a", + "33f7abbf-d481-4327-84fd-12645ebd2beb" + ], + "m_PropertyIds": [ + 18569658, + -457410494, + -1490972 + ], + "m_Dropdowns": [], + "m_DropdownSelectedEntries": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", @@ -3287,8 +3391,8 @@ "m_ObjectId": "40a7b9274eb447a48d0f1e31def6ba52", "m_Title": "Normal", "m_Position": { - "x": -2894.000244140625, - "y": 348.1286315917969 + "x": -2894.0, + "y": 348.5 } } @@ -3462,7 +3566,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 @@ -3818,7 +3922,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -4131,8 +4235,8 @@ "m_ObjectId": "5a905965f0d64818bbfb2d4f869e738b", "m_Title": "Emission", "m_Position": { - "x": -1076.6800537109375, - "y": 971.6621704101563 + "x": -1077.0, + "y": 972.5 } } @@ -4208,6 +4312,31 @@ } } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "5bff6fd9b79f4cef83b76fa7991d407b", + "m_Id": 1, + "m_DisplayName": "Color", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Color", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", @@ -4473,6 +4602,31 @@ } } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "620ebe491daf41b7a2a79b30e2820846", + "m_Id": 18569658, + "m_DisplayName": "Color", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "Color_5d923c2657794970996af7cb7159276f", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1Node", @@ -4674,7 +4828,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 @@ -4732,7 +4886,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 @@ -5150,8 +5304,8 @@ "m_ObjectId": "75ae407f7549455383d1c32d8989f303", "m_Title": "Albedo", "m_Position": { - "x": -2232.414306640625, - "y": -327.3903503417969 + "x": -2232.0, + "y": -326.5 } } @@ -5161,8 +5315,8 @@ "m_ObjectId": "7844c309071b4f42b7329805070ce54e", "m_Title": "Apply Albedo Detail", "m_Position": { - "x": -2462.000244140625, - "y": -812.8714599609375 + "x": -2462.0, + "y": -812.5 } } @@ -5272,6 +5426,29 @@ "m_Labels": [] } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "7a6d09da26b84c7abd84a17926d857cf", + "m_Id": 2, + "m_DisplayName": "Emission", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Emission", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", @@ -5298,7 +5475,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 3 @@ -5619,7 +5796,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -5634,8 +5811,8 @@ "m_ObjectId": "8c0e1cebdf4b4a90ae93ed60f9876e72", "m_Title": "Occlusion", "m_Position": { - "x": -876.0001220703125, - "y": 1328.0001220703125 + "x": -876.0, + "y": 1328.5 } } @@ -5679,8 +5856,8 @@ "m_ObjectId": "8dbd81486d314bc690d94dc6281fe289", "m_Title": "Smoothness", "m_Position": { - "x": -1159.0020751953125, - "y": 590.990234375 + "x": -1159.0, + "y": 591.5 } } @@ -6223,7 +6400,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -6287,12 +6464,35 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "9f92af83b5ad4eb6840f7858e51e9736", + "m_Id": -457410494, + "m_DisplayName": "Emission", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "_Emission", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", @@ -6341,7 +6541,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 @@ -6408,7 +6608,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -6529,7 +6729,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -6591,7 +6791,7 @@ "hlslDeclarationOverride": 2, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -6768,8 +6968,8 @@ "m_ObjectId": "adb53098703d462f9d82c495cfcb09e9", "m_Title": "Apply Normal Detail", "m_Position": { - "x": -2892.000244140625, - "y": 52.12871551513672 + "x": -2892.0, + "y": 52.5 } } @@ -6785,7 +6985,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 0 @@ -7155,8 +7355,8 @@ "m_ObjectId": "b8b5e48f3c87435c8fe78bddf85831ee", "m_Title": "Flip Normal", "m_Position": { - "x": -1531.8348388671875, - "y": -112.36843872070313 + "x": -1532.0, + "y": -111.5 } } @@ -8092,8 +8292,8 @@ "m_ObjectId": "cd446e3cb81b417a8bd2dc2ccafcd42e", "m_Title": "Detail Mask", "m_Position": { - "x": -2890.3525390625, - "y": -351.2122802734375 + "x": -2890.0, + "y": -350.5 } } @@ -8151,8 +8351,8 @@ "m_ObjectId": "cebae50b11e94e838b6e7a5a61d4f2e8", "m_Title": "Metallic", "m_Position": { - "x": -2030.0767822265625, - "y": 432.3829345703125 + "x": -2030.0, + "y": 432.5 } } @@ -8311,7 +8511,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, @@ -9185,8 +9385,8 @@ "m_ObjectId": "f0446934f1f84b8480c20f72122e30f3", "m_Title": "Alpha", "m_Position": { - "x": -1165.30859375, - "y": -460.5617370605469 + "x": -1165.0, + "y": -460.5 } } @@ -9374,7 +9574,7 @@ "m_StageCapability": 3, "m_BareResource": false, "m_Texture": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "m_DefaultType": 3 @@ -9401,7 +9601,7 @@ "hlslDeclarationOverride": 0, "m_Hidden": false, "m_Value": { - "m_SerializedTexture": "{\"texture\":{\"instanceID\":0}}", + "m_SerializedTexture": "", "m_Guid": "" }, "isMainTexture": false, diff --git a/Packages/com.waveharmonic.crest/Shared/Textures/Red.png.meta b/Packages/com.waveharmonic.crest/Shared/Textures/Red.png.meta index a367c1a52..0ac24b73e 100644 --- a/Packages/com.waveharmonic.crest/Shared/Textures/Red.png.meta +++ b/Packages/com.waveharmonic.crest/Shared/Textures/Red.png.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/Shared/Textures/Skybox.hdr.meta b/Packages/com.waveharmonic.crest/Shared/Textures/Skybox.hdr.meta index 45a821ff4..2580a22b7 100644 --- a/Packages/com.waveharmonic.crest/Shared/Textures/Skybox.hdr.meta +++ b/Packages/com.waveharmonic.crest/Shared/Textures/Skybox.hdr.meta @@ -106,6 +106,32 @@ TextureImporter: ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: iPhone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: serializedVersion: 2 sprites: [] diff --git a/Packages/com.waveharmonic.crest/package.json b/Packages/com.waveharmonic.crest/package.json index 5a809aa60..27b5a4f20 100644 --- a/Packages/com.waveharmonic.crest/package.json +++ b/Packages/com.waveharmonic.crest/package.json @@ -1,6 +1,6 @@ { "name": "com.waveharmonic.crest", - "version": "5.4.2", + "version": "5.6.6", "displayName": "Crest", "description": "An advanced water system for Unity.", "unity": "2022.3", diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index d57187619..de5671957 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -841,7 +841,7 @@ PlayerSettings: QNX: TextMeshPro;UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;ENVIRO_3;ENVIRO_URP;UNITY_POST_PROCESSING_STACK_V2;DotSpatial ReservedCFE: TextMeshPro;ENVIRO_3;ENVIRO_URP;UNITY_POST_PROCESSING_STACK_V2;DotSpatial Server: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI - Standalone: CINEMACHINE_URP;FAIRYGUI_TMPRO;OBI_ONI_SUPPORTED;TextMeshPro;UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;STEAMWORKS_NET;ENVIRO_3;ENVIRO_URP;VLB_URP;UPPipeline;__MICROSPLAT__;__MICROSPLAT_SNOW__;__MICROSPLAT_ALPHAHOLE__;__MICROSPLAT_MESH__;__MICROSPLAT_STREAMS__;__MICROSPLAT_GLOBALTEXTURE__;__MICROSPLAT_TRAX__;__MICROSPLAT_DECAL__;__MICROSPLAT_SCATTER__;__MICROSPLAT_TEXTURECLUSTERS__;__MICROSPLAT_MESHTERRAIN__;__MICROSPLAT_DETAILRESAMPLE__;__MICROSPLAT_TERRAINBLEND__;__MICROSPLAT_TESSELLATION__;__MICROSPLAT_WINDGLITTER__;__MICROSPLAT_LOWPOLY__;__MICROSPLAT_OBJECTSHADER__;__MICROSPLAT_PROCTEX__;__MICROSPLAT_TRIPLANAR__;__MICROSPLAT_MICROVERSEPREVIEW__;UNITY_POST_PROCESSING_STACK_V2;DotSpatial;FANTASY_UNITY;KWS_HD_MODULE_INSTALLED;KWS_URP;ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1;ODIN_INSPECTOR_3_2;ODIN_INSPECTOR_3_3 + Standalone: CINEMACHINE_URP;FAIRYGUI_TMPRO;OBI_ONI_SUPPORTED;TextMeshPro;UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;STEAMWORKS_NET;ENVIRO_3;ENVIRO_URP;VLB_URP;UPPipeline;__MICROSPLAT__;__MICROSPLAT_SNOW__;__MICROSPLAT_ALPHAHOLE__;__MICROSPLAT_MESH__;__MICROSPLAT_STREAMS__;__MICROSPLAT_GLOBALTEXTURE__;__MICROSPLAT_TRAX__;__MICROSPLAT_DECAL__;__MICROSPLAT_SCATTER__;__MICROSPLAT_TEXTURECLUSTERS__;__MICROSPLAT_MESHTERRAIN__;__MICROSPLAT_DETAILRESAMPLE__;__MICROSPLAT_TERRAINBLEND__;__MICROSPLAT_TESSELLATION__;__MICROSPLAT_WINDGLITTER__;__MICROSPLAT_LOWPOLY__;__MICROSPLAT_OBJECTSHADER__;__MICROSPLAT_PROCTEX__;__MICROSPLAT_TRIPLANAR__;__MICROSPLAT_MICROVERSEPREVIEW__;UNITY_POST_PROCESSING_STACK_V2;DotSpatial;FANTASY_UNITY;KWS_HD_MODULE_INSTALLED;ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1;ODIN_INSPECTOR_3_2;ODIN_INSPECTOR_3_3;KWS_URP VisionOS: TextMeshPro;UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;ENVIRO_3;ENVIRO_URP;UNITY_POST_PROCESSING_STACK_V2;DotSpatial WebGL: TextMeshPro;UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;ENVIRO_3;ENVIRO_URP;UNITY_POST_PROCESSING_STACK_V2;DotSpatial Windows Store Apps: UNITY_VISUAL_SCRIPTING;ES3_TMPRO;ES3_UGUI;DotSpatial diff --git a/UMotionData/AutoBackups/20260108_205507_player_umotion_project.bak b/UMotionData/AutoBackups/20260108_205507_player_umotion_project.bak new file mode 100644 index 000000000..96fb31c25 Binary files /dev/null and b/UMotionData/AutoBackups/20260108_205507_player_umotion_project.bak differ diff --git a/UMotionData/AutoBackups/20260108_214600_player_umotion_project.bak b/UMotionData/AutoBackups/20260108_214600_player_umotion_project.bak new file mode 100644 index 000000000..5c48be52c Binary files /dev/null and b/UMotionData/AutoBackups/20260108_214600_player_umotion_project.bak differ diff --git a/UMotionData/AutoBackups/20260108_215304_player_umotion_project.bak b/UMotionData/AutoBackups/20260108_215304_player_umotion_project.bak new file mode 100644 index 000000000..66b262058 Binary files /dev/null and b/UMotionData/AutoBackups/20260108_215304_player_umotion_project.bak differ diff --git a/UMotionData/Temp/EditorUndoStack.dat b/UMotionData/Temp/EditorUndoStack.dat index 6a38d927d..e69de29bb 100644 Binary files a/UMotionData/Temp/EditorUndoStack.dat and b/UMotionData/Temp/EditorUndoStack.dat differ diff --git a/UMotionData/Temp/EditorUndoTable.dat b/UMotionData/Temp/EditorUndoTable.dat index e1004ebdf..e69de29bb 100644 Binary files a/UMotionData/Temp/EditorUndoTable.dat and b/UMotionData/Temp/EditorUndoTable.dat differ diff --git a/UserSettings/EditorUserSettings.asset b/UserSettings/EditorUserSettings.asset index 0e74a16dc..f49612eb7 100644 --- a/UserSettings/EditorUserSettings.asset +++ b/UserSettings/EditorUserSettings.asset @@ -9,34 +9,34 @@ EditorUserSettings: value: 18134705175a055722080a3115371d4a0d55006876786860616b0471b8b3666cacb72ba5a52a362c3c0ee63201181433fe3e101bf3250b06144ca74c24f1190708e016c213c61a52f91c12cac80fd8edd298e1e4d1fde2cacddeacbcc1fee7eef0e3b6faa69af9ceaeaaec81a6d2c2c8c8c4b2e5dfd5ccd3f8cf flags: 0 RecentlyUsedSceneGuid-0: - value: 5b520400060d5a5a5b5b557641770b43424f1c28787d25612b2d196ab0b66068 - flags: 0 - RecentlyUsedSceneGuid-1: - value: 52530c5601535f020f565a2043770d1612154d2f747975692c7b4e66b5e3303b - flags: 0 - RecentlyUsedSceneGuid-2: value: 5303020755510a0f5e085c2744775a40454e1a2f282b72632f284d61e1e5673d flags: 0 - RecentlyUsedSceneGuid-3: + RecentlyUsedSceneGuid-1: value: 565700055d51590c0f56557545710744124f492b2a2976662828456ae6b03269 flags: 0 - RecentlyUsedSceneGuid-4: - value: 5309035757065a0a54575f7216265c4444151d28792e72627d2f1935bbb8673a - flags: 0 - RecentlyUsedSceneGuid-5: + RecentlyUsedSceneGuid-2: value: 0254070454505a0d55595d2113250844404f48297b7927342e281b6ab7b2676d flags: 0 - RecentlyUsedSceneGuid-6: + RecentlyUsedSceneGuid-3: value: 5301015756025c0a095d082148750c444f154e79752e2569787e4966b7b53561 flags: 0 - RecentlyUsedSceneGuid-7: + RecentlyUsedSceneGuid-4: value: 5307565150535b0b0c5a552711700644474e19297a29206379704b37e7b86368 flags: 0 + RecentlyUsedSceneGuid-5: + value: 00050c5150005f5f54560f2640270d4410161c28282b72357e7c4835e4b63760 + flags: 0 + RecentlyUsedSceneGuid-6: + value: 5b520400060d5a5a5b5b557641770b43424f1c28787d25612b2d196ab0b66068 + flags: 0 + RecentlyUsedSceneGuid-7: + value: 52530c5601535f020f565a2043770d1612154d2f747975692c7b4e66b5e3303b + flags: 0 RecentlyUsedSceneGuid-8: - value: 5505015f5c515a085f5b092149760f441716407a787d7564287b1b36e7e1366e + value: 5309035757065a0a54575f7216265c4444151d28792e72627d2f1935bbb8673a flags: 0 RecentlyUsedSceneGuid-9: - value: 00050c5150005f5f54560f2640270d4410161c28282b72357e7c4835e4b63760 + value: 5505015f5c515a085f5b092149760f441716407a787d7564287b1b36e7e1366e flags: 0 UnityEditor.ShaderGraph.Blackboard: value: 18135939215a0a5004000b0e15254b524c030a3f2964643d120d1230e9e93a3fd6e826abbd2e2d293c4ead313b08042de6030a0afa240c0d020be94c4ba75e435d8715fa32c70d15d11612dacc11fee5d3c5d1fe9ab1bf968e93e2ffcbc3e7e2f0b3ffe0e8b0be9afeffa9ffff8e85dd8390e2969e8899daa7