From d0deaa46b5cc3abb2a547ce8c3478f59f338f9b1 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 3 Jul 2023 13:17:17 +0200 Subject: [PATCH] Experimentation with stacked cameras; apply only viewport rect and jitter offset on first camera, perform upscaling with second camera. Sync settings between cameras. --- Assets/Scenes/SampleSceneStackedCams.unity | 651 ++++++++++++++++++ .../Scenes/SampleSceneStackedCams.unity.meta | 7 + Assets/Scripts/Fsr2CameraHelper.cs | 134 ++++ Assets/Scripts/Fsr2CameraHelper.cs.meta | 11 + Assets/Scripts/Fsr2ImageEffect.cs | 32 +- 5 files changed, 830 insertions(+), 5 deletions(-) create mode 100644 Assets/Scenes/SampleSceneStackedCams.unity create mode 100644 Assets/Scenes/SampleSceneStackedCams.unity.meta create mode 100644 Assets/Scripts/Fsr2CameraHelper.cs create mode 100644 Assets/Scripts/Fsr2CameraHelper.cs.meta diff --git a/Assets/Scenes/SampleSceneStackedCams.unity b/Assets/Scenes/SampleSceneStackedCams.unity new file mode 100644 index 0000000..55145c8 --- /dev/null +++ b/Assets/Scenes/SampleSceneStackedCams.unity @@ -0,0 +1,651 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 705507994} + m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + 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 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194231} + - component: {fileID: 963194230} + m_Layer: 0 + m_Name: Background Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 119 + m_RenderingPath: 3 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_LocalRotation: {x: 0.050175156, y: 0.8117933, z: -0.07053209, w: 0.577494} + m_LocalPosition: {x: -1.94, y: 1.24, z: 2.14} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1433420594} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 9.931, y: 109.145, z: 0} +--- !u!114 &963194230 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e3b91bb9659da8f49b7b36df73b7f70a, type: 3} + m_Name: + m_EditorClassIdentifier: + amplitude: 20 + frequency: 0.15 +--- !u!114 &963194231 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cfdc7cc809e9e7a43abebb1b3cca30be, type: 3} + m_Name: + m_EditorClassIdentifier: + qualityMode: 2 +--- !u!1001 &1313173313 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 3116520327292443000, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116565385739550694, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116566584170727252, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Name + value: Workbench + objectReference: {fileID: 0} + - target: {fileID: 3116566584170727252, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116567833673953862, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116682611370670920, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116730048973814310, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116768196857343570, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116799582357039764, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116870324568808428, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3116985835048169174, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117216213805114940, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117221827256685120, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117224094773291172, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117341701900622892, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117401556870414346, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117483529073849368, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117534041242435380, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117536992404291040, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117567356644086936, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3117614292522340306, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalPosition.x + value: 0.897 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalPosition.y + value: -0.018 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalPosition.z + value: -0.609 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3119308079644534864, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 8850d132797ff49298ba781e8e1c9bfe, type: 3} +--- !u!1 &1433420593 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1433420594} + - component: {fileID: 1433420599} + - component: {fileID: 1433420597} + - component: {fileID: 1433420600} + m_Layer: 3 + m_Name: Foreground Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1433420594 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1433420593} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 963194228} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 9.931, y: 109.145, z: 0} +--- !u!114 &1433420597 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1433420593} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 955cb66a9ecc20441a7e32934c9b4690, type: 3} + m_Name: + m_EditorClassIdentifier: + qualityMode: 2 + performSharpenPass: 1 + sharpness: 0.8 + enableFP16: 0 + enableAutoExposure: 1 + preExposure: 1 + exposure: {fileID: 0} + reactiveMask: {fileID: 0} + transparencyAndCompositionMask: {fileID: 0} + autoGenerateReactiveMask: 1 + generateReactiveParameters: + scale: 1 + cutoffThreshold: 0.2 + binaryValue: 0.9 + flags: 13 + autoGenerateTransparencyAndComposition: 0 + generateTransparencyAndCompositionParameters: + autoTcThreshold: 0.05 + autoTcScale: 1 + autoReactiveScale: 5 + autoReactiveMax: 0.9 + cameraStack: + - {fileID: 963194231} +--- !u!20 &1433420599 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1433420593} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 4 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 8 + m_RenderingPath: 3 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!114 &1433420600 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1433420593} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0211abdb066e45843a6b64af75622c97, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1001 &1724307687 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1059178161569566, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_Name + value: WorkshopSet + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_RootOrder + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4527368504392492, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: a87f0180d46fd334b9025d0314a0dc70, type: 3} diff --git a/Assets/Scenes/SampleSceneStackedCams.unity.meta b/Assets/Scenes/SampleSceneStackedCams.unity.meta new file mode 100644 index 0000000..ddca8f7 --- /dev/null +++ b/Assets/Scenes/SampleSceneStackedCams.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b07c34fe871af414780af61b80cab47e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Fsr2CameraHelper.cs b/Assets/Scripts/Fsr2CameraHelper.cs new file mode 100644 index 0000000..828709e --- /dev/null +++ b/Assets/Scripts/Fsr2CameraHelper.cs @@ -0,0 +1,134 @@ +// Copyright (c) 2023 Nico de Poel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.Experimental.Rendering; +using UnityEngine.Rendering; + +namespace FidelityFX +{ + /// + /// + /// + [RequireComponent(typeof(Camera))] + public class Fsr2CameraHelper : MonoBehaviour + { + [Tooltip("Standard scaling ratio presets.")] + public Fsr2.QualityMode qualityMode = Fsr2.QualityMode.Quality; + + private Vector2Int _maxRenderSize; + private Vector2Int _displaySize; + + private Camera _renderCamera; + private DepthTextureMode _originalDepthTextureMode; + private Rect _originalRect; + + private void OnEnable() + { + // Set up the original camera to output all of the required FSR2 input resources at the desired resolution + _renderCamera = GetComponent(); + _originalDepthTextureMode = _renderCamera.depthTextureMode; + _renderCamera.depthTextureMode = _originalDepthTextureMode | DepthTextureMode.Depth | DepthTextureMode.MotionVectors; + } + + private void OnDisable() + { + // Restore the camera's original state + _renderCamera.depthTextureMode = _originalDepthTextureMode; + } + + private void LateUpdate() + { + // Determine the desired rendering and display resolutions + _displaySize = GetDisplaySize(); + Fsr2.GetRenderResolutionFromQualityMode(out var maxRenderWidth, out var maxRenderHeight, _displaySize.x, _displaySize.y, qualityMode); + _maxRenderSize = new Vector2Int(maxRenderWidth, maxRenderHeight); + + if (_maxRenderSize.x == 0 || _maxRenderSize.y == 0) + { + Debug.LogError($"FSR2 render size is invalid: {_maxRenderSize.x}x{_maxRenderSize.y}. Please check your screen resolution and camera viewport parameters."); + enabled = false; + } + + // Remember the original camera viewport before we modify it in OnPreCull + _originalRect = _renderCamera.rect; + } + + private void OnPreCull() + { + // Render to a smaller portion of the screen by manipulating the camera's viewport rect + _renderCamera.aspect = (_displaySize.x * _originalRect.width) / (_displaySize.y * _originalRect.height); + _renderCamera.rect = new Rect(0, 0, _originalRect.width * _maxRenderSize.x / _renderCamera.pixelWidth, _originalRect.height * _maxRenderSize.y / _renderCamera.pixelHeight); + + ApplyJitter(); + } + + private void ApplyJitter() + { + var scaledRenderSize = GetScaledRenderSize(); + + // Perform custom jittering of the camera's projection matrix according to FSR2's recipe + int jitterPhaseCount = Fsr2.GetJitterPhaseCount(scaledRenderSize.x, _displaySize.x); + Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount); + + jitterX = 2.0f * jitterX / scaledRenderSize.x; + jitterY = 2.0f * jitterY / scaledRenderSize.y; + + var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0)); + _renderCamera.nonJitteredProjectionMatrix = _renderCamera.projectionMatrix; + _renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix; + _renderCamera.useJitteredProjectionMatrixForTransparentRendering = true; + } + + private void OnRenderImage(RenderTexture src, RenderTexture dest) + { + // Restore the camera's viewport rect so we can output at full resolution + _renderCamera.rect = _originalRect; + _renderCamera.ResetProjectionMatrix(); + + Graphics.Blit(src, dest); + } + + private Vector2Int GetDisplaySize() + { + var targetTexture = _renderCamera.targetTexture; + if (targetTexture != null) + return new Vector2Int(targetTexture.width, targetTexture.height); + + return new Vector2Int(_renderCamera.pixelWidth, _renderCamera.pixelHeight); + } + + private bool UsingDynamicResolution() + { + var targetTexture = _renderCamera.targetTexture; + return _renderCamera.allowDynamicResolution || (targetTexture != null && targetTexture.useDynamicScale); + } + + private Vector2Int GetScaledRenderSize() + { + if (UsingDynamicResolution()) + return new Vector2Int(Mathf.CeilToInt(_maxRenderSize.x * ScalableBufferManager.widthScaleFactor), Mathf.CeilToInt(_maxRenderSize.y * ScalableBufferManager.heightScaleFactor)); + + return _maxRenderSize; + } + } +} diff --git a/Assets/Scripts/Fsr2CameraHelper.cs.meta b/Assets/Scripts/Fsr2CameraHelper.cs.meta new file mode 100644 index 0000000..ff2390f --- /dev/null +++ b/Assets/Scripts/Fsr2CameraHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cfdc7cc809e9e7a43abebb1b3cca30be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Fsr2ImageEffect.cs b/Assets/Scripts/Fsr2ImageEffect.cs index 480d496..6e41abe 100644 --- a/Assets/Scripts/Fsr2ImageEffect.cs +++ b/Assets/Scripts/Fsr2ImageEffect.cs @@ -98,9 +98,8 @@ namespace FidelityFX [Range(0, 1)] public float autoReactiveMax = 0.9f; } - [Header("Output resources")] - [Tooltip("Optional render texture to copy motion vector data to, for additional post-processing after upscaling.")] - public RenderTexture outputMotionVectors; + [Header("Slave cameras")] + public Fsr2CameraHelper[] cameraStack; private Fsr2Context _context; private Vector2Int _maxRenderSize; @@ -161,10 +160,26 @@ namespace FidelityFX CreateFsrContext(); CreateCommandBuffers(); + + if (cameraStack != null) + { + foreach (var cameraHelper in cameraStack) + { + cameraHelper.enabled = true; + } + } } private void OnDisable() { + if (cameraStack != null) + { + foreach (var cameraHelper in cameraStack) + { + cameraHelper.enabled = false; + } + } + DestroyCommandBuffers(); DestroyFsrContext(); @@ -266,6 +281,15 @@ namespace FidelityFX OnDisable(); OnEnable(); } + + if (cameraStack != null) + { + int numCams = cameraStack.Length; + for (int i = 0; i < numCams; ++i) + { + cameraStack[i].qualityMode = qualityMode; + } + } } public void ResetHistory() @@ -424,8 +448,6 @@ namespace FidelityFX // Output to the camera target texture, passing through depth and motion vectors _dispatchCommandBuffer.SetGlobalTexture("_DepthTex", BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Depth); _dispatchCommandBuffer.Blit(Fsr2ShaderIDs.UavUpscaledOutput, _originalRenderTarget, _copyWithDepthMaterial); - if (outputMotionVectors != null) - _dispatchCommandBuffer.Blit(BuiltinRenderTextureType.MotionVectors, outputMotionVectors); } else {