Add XR sample assets and update settings

This commit is contained in:
2026-01-21 14:18:30 +01:00
parent da213b4475
commit 0ae28bf32d
1990 changed files with 506411 additions and 76 deletions

View File

@@ -0,0 +1,23 @@
{
"name": "AndriodSurfaceSample",
"rootNamespace": "",
"references": [
"Unity.XR.CompositionLayers",
"Unity.XR.OpenXR"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.xr.openxr",
"expression": "1.12.0-exp.1",
"define": "UNITY_XR_OPENXR_COMPLAYER"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e4428ec3a4e57c9de833d0ca4f4dfea3
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
# Andriod Surface Sample
Demonstrates testing of a still imgae for Adriod Surface Layer in the Composition Layers Package using the Unity.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 76e6460a9ea9dc77aa62163df2fe1625
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 254a5f1d75674fac59d4a701260cf3d4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,552 @@
%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.44657898, g: 0.4964133, b: 0.5748178, 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: 20201, guid: 0000000000000000f000000000000000, type: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 3
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
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &18644208
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 18644210}
- component: {fileID: 18644209}
m_Layer: 0
m_Name: XRRig
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &18644209
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 18644208}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a2483b9bd782f9449a5972b61b7d51a9, type: 3}
m_Name:
m_EditorClassIdentifier:
m_CameraFloorOffsetObject: {fileID: 608631956}
m_RequestedTrackingMode: 1
m_TrackingOriginMode: 1
m_TrackingSpace: 0
m_CameraYOffset: 1.36144
--- !u!4 &18644210
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 18644208}
serializedVersion: 2
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:
- {fileID: 608631957}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &608631956
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 608631957}
m_Layer: 0
m_Name: Camera Offset
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &608631957
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 608631956}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 1.36144, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1339398921}
m_Father: {fileID: 18644210}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 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}
serializedVersion: 2
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_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &782628375
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 782628379}
- component: {fileID: 782628378}
- component: {fileID: 782628377}
- component: {fileID: 782628380}
- component: {fileID: 782628381}
m_Layer: 0
m_Name: External Surface Layer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &782628377
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 782628375}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45327f2c44c145df809bbdd9829b456d, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SourceTexture: 1
m_TargetEye: 0
m_LeftTexture: {fileID: 2800000, guid: 19ff5cd7ef8264f4499eaff2f70258ef, type: 3}
m_RightTexture: {fileID: 2800000, guid: 19ff5cd7ef8264f4499eaff2f70258ef, type: 3}
m_InEditorEmulation: 0
m_CustomRects: 0
m_Resolution: {x: 1600, y: 905}
m_LeftEyeSourceRect:
serializedVersion: 2
x: 0
y: 0
width: 0.8
height: 0.76666665
m_RightEyeSourceRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
m_LeftEyeDestinationRect:
serializedVersion: 2
x: 0.23333333
y: 0.21111111
width: 0.6333333
height: 0.50000006
m_RightEyeDestinationRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
m_CropToAspect: 1
--- !u!114 &782628378
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 782628375}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3adf0bb75a444c61bde2e7841591bf41, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UICanvas: {fileID: 0}
m_UIMirrorComponent: {fileID: 0}
m_LayerOutline: {fileID: 782628381}
m_Order: 3
m_LayerData:
rid: 1506356371474874369
m_PlatformLayerDataKeys: []
m_PlatformLayerDataTexts: []
references:
version: 2
RefIds:
- rid: 1506356371474874369
type: {class: QuadLayerData, ns: Unity.XR.CompositionLayers.Layers, asm: Unity.XR.CompositionLayers}
data:
m_BlendType: 0
m_Size: {x: 5, y: 5}
m_ApplyTransformScale: 1
--- !u!4 &782628379
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 782628375}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.19, y: 1, z: 3.2}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &782628380
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 782628375}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e1537674bf1cc874f9b390067e444367, type: 3}
m_Name:
m_EditorClassIdentifier:
ImageName: Unity-Logo.png
--- !u!114 &782628381
MonoBehaviour:
m_ObjectHideFlags: 2
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 782628375}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c239b33ee5aee77488aadc51463c91de, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1339398920
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1339398921}
- component: {fileID: 1339398924}
- component: {fileID: 1339398923}
- component: {fileID: 1339398922}
m_Layer: 0
m_Name: Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1339398921
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1339398920}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -3.54}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 608631957}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1339398922
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1339398920}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5a2a9c34df4095f47b9ca8f975175f5b, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Device: 0
m_PoseSource: 2
m_PoseProviderComponent: {fileID: 0}
m_TrackingType: 0
m_UpdateType: 0
m_UseRelativeTransform: 0
--- !u!81 &1339398923
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1339398920}
m_Enabled: 1
--- !u!20 &1339398924
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1339398920}
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_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.01
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294955007
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 705507995}
- {fileID: 18644210}
- {fileID: 782628379}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7385fe6676c536e4a86ffbbca7875df7
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3aa24913804abb85fae5d6a90d1a2e92
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using UnityEngine;
using System.Runtime.InteropServices;
/// <summary>
/// A static class that initializes a test surface on Android
/// using Java Native Interface (JNI) calls. It facilitates interaction between Unity and
/// Android native code, particularly for handling texture and surface operations.
/// </summary>
public static class AndroidTestSurface
{
private static System.IntPtr? _TestSurfaceClass;
private static System.IntPtr initTestSurfaceMethodId;
/// <summary>
/// Gets the reference to the Java class 'TestSurface'. It uses JNI to find and hold a
/// global reference to the class for future use.
/// </summary>
private static System.IntPtr TestSurfaceClass
{
get
{
if (!_TestSurfaceClass.HasValue)
{
try
{
// Find the Java class and create a global reference
System.IntPtr testSurfaceClassLocal = AndroidJNI.FindClass("com/unity/xr/compositorlayers/TestSurface");
if (testSurfaceClassLocal != System.IntPtr.Zero)
{
_TestSurfaceClass = AndroidJNI.NewGlobalRef(testSurfaceClassLocal);
AndroidJNI.DeleteLocalRef(testSurfaceClassLocal);
}
else
{
Debug.LogError("Failed to find Java class `TestSurface`");
_TestSurfaceClass = System.IntPtr.Zero;
}
}
catch (System.Exception ex)
{
Debug.LogError("Exception occurred while finding Java class `TestSurface`");
Debug.LogException(ex);
_TestSurfaceClass = System.IntPtr.Zero;
}
}
return _TestSurfaceClass.GetValueOrDefault();
}
}
/// <summary>
/// Initializes a test surface using a JNI call to the 'InitTestSurface' method of the
/// 'TestSurface' Java class. It passes a native Android object and a texture converted to
/// a Bitmap to the Java method.
/// </summary>
/// <param name="jobject">The native Android object to which the surface is attached.</param>
/// <param name="texture">The Unity Texture2D to be converted and passed as a Bitmap.</param>
public static void InitTestSurface(System.IntPtr jobject, Texture2D texture)
{
if (initTestSurfaceMethodId == System.IntPtr.Zero)
{
// Retrieve the method ID for 'InitTestSurface'
initTestSurfaceMethodId = AndroidJNI.GetStaticMethodID(TestSurfaceClass, "InitTestSurface", "(Ljava/lang/Object;Landroid/graphics/Bitmap;)V");
}
// Convert the texture to a Bitmap and call the Java method
using (AndroidJavaObject bitmap = Texture2DToBitmap(texture))
{
System.IntPtr bitmapPtr = bitmap.GetRawObject();
jvalue[] args = new jvalue[2];
args[0] = new jvalue { l = jobject };
args[1] = new jvalue { l = bitmapPtr };
AndroidJNI.CallStaticVoidMethod(TestSurfaceClass, initTestSurfaceMethodId, args);
}
}
/// <summary>
/// Converts a Unity Texture2D to an Android Bitmap object. This is used to pass textures
/// from Unity to Android native code.
/// </summary>
/// <param name="texture">The Unity Texture2D to be converted.</param>
/// <returns>An AndroidJavaObject representing the Bitmap.</returns>
private static AndroidJavaObject Texture2DToBitmap(Texture2D texture)
{
byte[] imageBytes = texture.EncodeToPNG();
sbyte[] signedImageBytes = (sbyte[])(System.Array)imageBytes;
using (AndroidJavaClass byteBufferClass = new AndroidJavaClass("java.nio.ByteBuffer"))
{
AndroidJavaObject byteBuffer = byteBufferClass.CallStatic<AndroidJavaObject>("wrap", signedImageBytes);
using (AndroidJavaClass bitmapFactory = new AndroidJavaClass("android.graphics.BitmapFactory"))
{
AndroidJavaObject bitmap = bitmapFactory.CallStatic<AndroidJavaObject>("decodeByteArray", byteBuffer.Call<sbyte[]>("array"), 0, signedImageBytes.Length);
if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.OpenGLES3)
{
using (var matrix = new AndroidJavaObject("android.graphics.Matrix"))
{
matrix.Call<bool>("preScale", 1.0f, -1.0f);
using (var bitmapClass = new AndroidJavaClass("android.graphics.Bitmap"))
{
AndroidJavaObject flippedBitmap = bitmapClass.CallStatic<AndroidJavaObject>("createBitmap",
bitmap, 0, 0, bitmap.Call<int>("getWidth"), bitmap.Call<int>("getHeight"), matrix, false);
return flippedBitmap;
}
}
}
return bitmap;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 907440e96477d434b8027232e72b4b33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac2dd0c0c645be04ba9fa58a6af05431
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
/// <summary>
/// A class that ensures that the Android minimum SDK version meets certain requirements.
/// </summary>
[InitializeOnLoad]
public class AndroidBuildSettings : IPreprocessBuildWithReport
{
/// Specifies the order in which this pre-build process should be executed.
public int callbackOrder { get { return 0; } }
/// Static constructor called on load to initially set Android build settings.
static AndroidBuildSettings()
{
SetAndroidBuildSettings();
}
/// <summary>
/// Called before the build process begins. Ensures Android build settings are correctly set.
/// </summary>
/// <param name="report">Contains information about the build, such as its target platform and output path.</param>
public void OnPreprocessBuild(BuildReport report)
{
SetAndroidBuildSettings();
}
/// <summary>
/// Sets the minimum SDK version for Android builds to a specified level if it is currently set lower.
/// This ensures compatibility with features provided in composition layers.
/// </summary>
private static void SetAndroidBuildSettings()
{
if (PlayerSettings.Android.minSdkVersion < AndroidSdkVersions.AndroidApiLevel24)
{
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel24;
Debug.Log("Android minimum SDK version has been updated to Level 24. The lowest level supported by the composition layers package.");
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66d508d62ebbcb742b8674838d4b2a11
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
#if UNITY_EDITOR && UNITY_ANDROID
using UnityEditor;
using UnityEditor.Android;
using System.IO;
using UnityEngine;
/// <summary>
/// This class primarily focuses on copying specific files
/// from a source folder to the Android project's assets directory after the Gradle project
/// has been generated.
/// </summary>
public class UploadAndroidFiles : IPostGenerateGradleAndroidProject
{
/// <summary>
/// Specifies the order in which this post-processing task should be executed.
/// </summary>
public int callbackOrder => 1;
/// <summary>
/// Called after the Gradle Android project is generated. Copies files from a specified
/// source folder to the project's assets directory.
/// </summary>
/// <param name="path">The path to the generated Gradle project.</param>
public void OnPostGenerateGradleAndroidProject(string path)
{
string sourceFolder = Path.Combine(Application.dataPath, "Samples/XR Composition Layers/2.2.0/Sample External Android Surface Project/StreamingAssets");
string destinationFolder = Path.Combine(path, "src/main/assets");
// Create the destination folder if it does not exist
if (!Directory.Exists(destinationFolder))
{
Directory.CreateDirectory(destinationFolder);
}
CopyFilesRecursively(sourceFolder, destinationFolder);
}
/// <summary>
/// Copies all files and subdirectories from a source path to a target path recursively.
/// </summary>
/// <param name="sourcePath">The source directory path.</param>
/// <param name="targetPath">The target directory path where files should be copied.</param>
private static void CopyFilesRecursively(string sourcePath, string targetPath)
{
// Copy each file in the source directory to the target directory
foreach (string filePath in Directory.GetFiles(sourcePath))
{
string fileName = Path.GetFileName(filePath);
string destFile = Path.Combine(targetPath, fileName);
File.Copy(filePath, destFile, true);
}
// Recursively copy each subdirectory
foreach (string subdirectoryPath in Directory.GetDirectories(sourcePath))
{
string subdirectoryName = Path.GetFileName(subdirectoryPath);
string destSubdirectory = Path.Combine(targetPath, subdirectoryName);
if (!Directory.Exists(destSubdirectory))
{
Directory.CreateDirectory(destSubdirectory);
}
CopyFilesRecursively(subdirectoryPath, destSubdirectory);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c6257f7aad5b4445ad10809fcc8f816
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using UnityEngine;
using System;
using System.Collections;
using System.IO;
using Unity.XR.CompositionLayers;
#if UNITY_XR_OPENXR_COMPLAYER
using UnityEngine.XR.OpenXR.CompositionLayers;
#endif
using UnityEngine.Networking;
/// <summary>
/// Class for loading and displaying an image on Android devices.
/// </summary>
public class TestAndroidImage : MonoBehaviour
{
public string ImageName;
/// <summary>
/// Coroutine started upon script activation to initiate image loading.
/// </summary>
/// <returns>IEnumerator for coroutine management.</returns>
private IEnumerator Start()
{
yield return StartCoroutine(LoadImage());
}
/// <summary>
/// Main coroutine handling the image loading process based on the platform.
/// Loads an image using specified ImageName and displays it if found.
/// </summary>
/// <returns>IEnumerator for coroutine management.</returns>
private IEnumerator LoadImage()
{
if (!string.IsNullOrEmpty(ImageName))
{
Texture2D image = null;
#if UNITY_EDITOR
// Load image for Unity Editor
image = LoadImageForEditor();
#elif UNITY_ANDROID
// Load image for Android
yield return StartCoroutine(LoadImageForAndroid(loadedImage => image = loadedImage));
#endif
if (image != null)
{
// Display the loaded image
yield return DisplayImage(image);
}
else
{
Debug.LogError("Image not found at path: " + ImageName);
}
}
}
#if UNITY_EDITOR
/// <summary>
/// Loads an image from the project's assets when running in the Unity Editor.
/// </summary>
/// <returns>Texture2D - The loaded image texture.</returns>
private Texture2D LoadImageForEditor()
{
var guids = UnityEditor.AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(ImageName));
if (guids.Length > 0)
{
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
return UnityEditor.AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
}
return null;
}
#elif UNITY_ANDROID
/// <summary>
/// Coroutine for loading an image in an Android build. Uses UnityWebRequest to fetch the image.
/// </summary>
/// <param name="onLoaded">Callback action to handle the loaded Texture2D.</param>
/// <returns>IEnumerator for coroutine management.</returns>
private IEnumerator LoadImageForAndroid(Action<Texture2D> onLoaded)
{
string filePath = Path.Combine(Application.streamingAssetsPath, ImageName);
using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(filePath))
{
yield return uwr.SendWebRequest();
if (uwr.result == UnityWebRequest.Result.ConnectionError || uwr.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Error while loading image: " + uwr.error);
onLoaded(null);
}
else
{
onLoaded(DownloadHandlerTexture.GetContent(uwr));
}
}
}
#endif
/// <summary>
/// Coroutine handling the display of a loaded image using XR composition layers.
/// Waits for the surface from OpenXRLayerUtility before displaying the image.
/// </summary>
/// <param name="image">The Texture2D image to be displayed.</param>
/// <returns>IEnumerator for coroutine management.</returns>
private IEnumerator DisplayImage(Texture2D image)
{
if (image != null)
{
CompositionLayer layer = gameObject.GetComponent<CompositionLayer>();
IntPtr surface = IntPtr.Zero;
yield return new WaitUntil(() =>
{
#if UNITY_XR_OPENXR_COMPLAYER
surface = OpenXRLayerUtility.GetLayerAndroidSurfaceObject(layer.GetInstanceID());
#endif
return (surface != IntPtr.Zero);
});
AndroidTestSurface.InitTestSurface(surface, image);
}
else
{
Debug.LogError("No image provided.");
}
}
/// <summary>
/// Event handler triggered when the application gains or loses focus.
/// Restarts image loading process when the application gains focus.
/// </summary>
/// <param name="hasFocus">Boolean indicating if the application has focus.</param>
void OnApplicationFocus(bool hasFocus)
{
if (hasFocus)
{
StartCoroutine(LoadImage());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1537674bf1cc874f9b390067e444367
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d7753b9b7af3dac3bb281ccc2565110f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,124 @@
fileFormatVersion: 2
guid: 612ae0c0d44d9604bb9cd508c26352e9
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
swizzle: 50462976
cookieLightType: 2
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3bd48574c1e7e84a08ab8d16bba84d52
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 98c63244d80671d49a23f703330f4619
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a451b52f40e21dc4d9697d025f41299d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dfad0a8f5ca2ec942a0a9a6c6ff9dc5c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed3f77cabee551f478d5073edc5ee535
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
package com.unity.xr.compositorlayers;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.view.Surface;
/**
* Provides functionality to render a Bitmap onto a Surface
* received from Unity. Primarily used for handling and displaying
* texture data passed from Unity to Android native code.
*/
public class TestSurface {
/**
* Initializes and renders a Bitmap onto a specified Surface.
*
* @param surfaceObject An object that should be an instance of android.view.Surface.
* @param bitmap The Bitmap image to be drawn on the surface.
* @throws RuntimeException if surfaceObject is not an instance of Surface or if bitmap is null.
*/
public static void InitTestSurface(Object surfaceObject, Bitmap bitmap) {
if (!(surfaceObject instanceof Surface)) {
throw new RuntimeException("TestSurface.ctor: supplied object is not an android.view.Surface!");
}
Surface surface = (Surface) surfaceObject;
Canvas canvas = surface.lockCanvas(null);
if(bitmap != null)
{
canvas.drawBitmap(bitmap, new Matrix(), new Paint());
}
else
{
throw new RuntimeException("Surface or Image is not initialized or is null.");
}
surface.unlockCanvasAndPost(canvas);
}
}

View File

@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: fffb0d3ab42fe5146a4c2bea5c690c53
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant: