Mirrors in VR

Hi everyone,

I’ve just released an open source project for realistic mirrors in VR! No raytracing required, and you can add as many mirrors as you want. Currently there is no recursive reflections, so be careful with the placement :slight_smile: You can download the project from GitHub :GitHub - emilje/UE5_Mirrors
There are a few handy knobs you can adjust to hopefully get the performance and look you are after.

Hope someone finds this useful!

3 Likes

Thank you, this was really helpful

Thank you so much for your sharing! May I ask what kind of headset you are using? I’m using the Quest 2. I added the MetaXR plugin based on your project, but it doesn’t seem to be compatible :pensive_face:

I was using meta quest 3. I don’t think meta xr should be required to make this work? As long as you can use quest 2 within unreal engine, the code should work?

Looks useful :smiley:

What version is it compatible with?

I don’t remember which version I used when I made this. But most likely you should be able to open it with a newer ue version. I think I was using 5.2 or 5.3 when making this.

5.3 is what you have on GitHub. I tried it out today with my Quest 2 as a standalone app. It worked well visually, but it needs tuning for a Quest deployment. It can’t maintain 72fps on a Q2.

The project crashes the Editor on opening in 5.6.

[2025.10.17-17.26.39:855][ 22]LogTcpMessaging: Started Connection to '127.0.0.1:6666'
[2025.10.17-17.26.59:749][ 39]LogVulkanRHI: Error: VulkanRHI::vkWaitSemaphoresKHR(Device->GetInstanceHandle(), &WaitInfo, (uint64_t)Timeout) failed, VkResult=-4
 at D:\build\++UE5\Sync\Engine\Source\Runtime\VulkanRHI\Private\VulkanSubmission.cpp:409 
 with error VK_ERROR_DEVICE_LOST
[2025.10.17-17.26.59:749][ 39]LogVulkanRHI: Error: Shader diagnostic messages and asserts:

	Device: 0, Queue Graphics:
		No shader diagnostics found for this queue.

[2025.10.17-17.26.59:749][ 39]LogVulkanRHI: Error: 
DEVICE FAULT REPORT:
* Description: 
* Address Info: 
    - VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT : 0x0000000500A337A0 (range:0x0000000500A337A0-0x0000000500A337AF)
    - VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT : 0xFFFFFFFFF1E1F000 (range:0xFFFFFFFFF1E1F000-0xFFFFFFFFF1E1FFFF)
* Vendor Info: 
* Vendor Binary Size: 29624

[2025.10.17-17.26.59:749][ 39]LogRHI: Error: Active GPU breadcrumbs:

	Device 0, Pipeline Graphics: (In: 0x800006e8, Out: 0x800006e7)
		(ID: 0x800006c6) [     Active]	Frame 39
		(ID: 0x800006c9) [     Active]		SceneRender - ViewFamilies
		(ID: 0x80000712) [     Active]			RenderGraphExecute - /ViewFamilies
		(ID: 0x800006ce) [     Active]				Scene
		(ID: 0x800006d9) [     Active]					HZB
		(ID: 0x800006da) [     Active]						BeginOcclusionTests
		(ID: 0x80000718) [     Active]							BeginOcclusionTests
		(ID: 0x80000719) [     Active]								ViewOcclusionTests 0
		(ID: 0x8000071e) [     Active]									IndividualQueries
		(ID: 0x800006f2) [     Active]						EditorPrimitives
		(ID: 0x800006f5) [     Active]					PostRenderOpsFX
		(ID: 0x800006f6) [     Active]						FXSystemPostRenderOpaque
		(ID: 0x8000071a) [     Active]							GPUParticles_PostRenderOpaque
		(ID: 0x800006f7) [     Active]					Translucency
		(ID: 0x800006f9) [     Active]						RenderTranslucency
		(ID: 0x800006fe) [     Active]					PostProcessing
		(ID: 0x800006ff) [     Active]						EditorSelectionOutlines
		(ID: 0x80000700) [     Active]							OutlineDepth 1628x1063
		(ID: 0x80000701) [     Active]						CompositeEditorPrimitives 1628x1063 MSAA=1
		(ID: 0x80000714) [     Active]							RenderViewEditorPrimitives 1628x1063 msaa=1
		(ID: 0x8000071f) [     Active]							RenderViewEditorForegroundPrimitives 1628x1063 msaa=1
		(ID: 0x80000720) [     Active]							RenderViewEditorForegroundTranslucentPrimitives 1628x1063 msaa=1
		(ID: 0x80000721) [     Active]		RenderGraphExecute - CanvasRenderThreadScope
		(ID: 0x80000722) [     Active]		SceneRender - HitProxies
		(ID: 0x80000736) [     Active]			RenderGraphExecute - /HitProxies
		(ID: 0x80000726) [     Active]				GPUScene.UploadDynamicPrimitiveShaderDataForView
		(ID: 0x80000727) [     Active]					UpdateGPUScene NumPrimitiveDataUploads 3
		(ID: 0x80000728) [     Active]				BuildRenderingCommands(Culling=On)
		(ID: 0x80000737) [     Active]		RenderGraphExecute - CanvasRenderThreadScope

[2025.10.17-17.26.59:749][ 39]LogWindows: FPlatformMisc::RequestExit(1, FVulkanDynamicRHI.TerminateOnGPUCrash)
[2025.10.17-17.26.59:749][ 39]LogWindows: FPlatformMisc::RequestExitWithStatus(1, 0, FVulkanDynamicRHI.TerminateOnGPUCrash)
[2025.10.17-17.26.59:749][ 39]LogCore: Engine exit requested (reason: Win RequestExit)

I was able to get 72fps with a single mirror using Q3, Im not sure what the hardware difference is between 2 and 3.There should be “bIsMobileMultiView” that you can toggle which then cuts the resolution to appropriate size for mobile devices and which worked fine for my Quest 3. I will try to get it running in 5.7 soon and see if I run into the same issues.

I got it working on UE 5.7.3 standalone Quest 3. Runs at 60fps.

To prevent the crash when opening the project, open DefaultEngine.ini and replace the following:

[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_Vulkan
+VulkanTargetedShaderFormats=SF_VULKAN_SM6

with

[/Script/WindowsTargetPlatform.WindowsTargetSettings]
DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 
DefaultGraphicsRHI=DefaultGraphicsRHI_Default

In project settings, enable Mobile Multi-view and Substrate. Also, add this extra line in the .ini,
r.DistanceFields=0
Which improves performance a lot. Not sure why that is even though Generate Mesh Distance Fields is disabled.

I got it working on UE 5.8 standalone Quest 3s. Runs at 60fps.