{"id":23,"date":"2020-08-10T09:48:09","date_gmt":"2020-08-10T09:48:09","guid":{"rendered":"https:\/\/noirccc.net\/blog\/?p=23"},"modified":"2023-05-18T00:28:49","modified_gmt":"2023-05-18T00:28:49","slug":"unity-vr-compatible-mirror-effects","status":"publish","type":"post","link":"https:\/\/noirccc.net\/blog\/posts\/23","title":{"rendered":"Unity VR-Compatible Mirror Effects"},"content":{"rendered":"\n<p>The following two methods are tested under environment: Unity 2019.2.14 + SteamVR SDK, Built-in RP.<\/p>\n\n\n\n<h2>Method A. Render Texture<\/h2>\n\n\n\n<p>This is a simple way to make mirros that also work in VR.<\/p>\n\n\n\n<ol>\n<li>Create render texture.<\/li>\n\n\n\n<li>Create camera \u201cMirrorCamera\u201d, set Fov=90. Set our render texture as MirrorCamera\u2019s Target Texture.<\/li>\n\n\n\n<li>Create material to pass our render texture into, assign the render texture as its texture.<\/li>\n\n\n\n<li>Create 3D object in the scene, preferrably a plane or thin cube. Set material from step 3 as its material. This acts as the mirror model.<\/li>\n<\/ol>\n\n\n\n<p>The 3D obejct should now replicate MirrorCamera\u2019s camera view on its surface. Adjust MirrorCamera rotation to face the appropriate direction.<\/p>\n\n\n\n<h2>Method B. Vive Stereo Rendering Toolkit<\/h2>\n\n\n\n<p>Vive Stereo Rendering Toolkit provides VR mirror rendering methods. We need to download it from Asset Store and make a few quick changes to make it compatible with Unity 2019.2.x. Changes are made to the following files:<\/p>\n\n\n\n<p>DeviceType.cs<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Lines 43 ~ 68\n\/\/Comment out lines 43 ~ 68;\n\n        public static IDeviceParamFactory InitParamFactory(HmdType hmdType)\n        {\n\/\/ #if (VIVE_STEREO_STEAMVR)\n\/\/             if (hmdType == HmdType.SteamVR)\n\/\/             {\n                return new SteamVRParamFactory();\n\/\/             }\n\/\/ #endif\n\n\/\/ #if (VIVE_STEREO_OVR)\n\/\/             if (hmdType == HmdType.OVR)\n\/\/             {\n\/\/                 return new OVRParamFactory();\n\/\/             }\n\/\/ #endif\n\n\/\/ #if (UNITY_ANDROID &amp;&amp; VIVE_STEREO_WAVEVR)\n\/\/             if (hmdType == HmdType.WaveVR)\n\/\/             {\n\/\/                 return new WaveVRParamFactory();\n\/\/             }\n\/\/ #endif\n\n\/\/             Debug.LogError(\"Cannot get suitable projection parameter for current HMD.\");\n\/\/             return null;\n        }<\/code><\/pre>\n\n\n\n<p>SteamVRParamFactory.cs<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/\/========= Copyright 2016-2017, HTC Corporation. All rights reserved. ===========\nusing UnityEngine;\nusing Valve.VR; \/\/ Add using Valve.VR at the beginning.\n\n\/\/ Comment out some lines as shown.\n\nnamespace HTC.UnityPlugin.StereoRendering\n{\n\/\/ #if (VIVE_STEREO_STEAMVR)\n    public class SteamVRParamFactory : IDeviceParamFactory\n    {\n        public int GetRenderWidth()\n        {\n            return (int)SteamVR.instance.sceneWidth;\n        }\n\n        public int GetRenderHeight()\n        {\n            return (int)SteamVR.instance.sceneHeight;\n        }\n\n        public Vector3 GetEyeSeperation(int eye)\n        {\n            var eyePos = SteamVR.instance.eyes&#91;eye].pos;\n            eyePos.z = 0.0f;\n            return eyePos;\n        }\n\n        public Quaternion GetEyeLocalRotation(int eye)\n        {\n            return SteamVR.instance.eyes&#91;eye].rot;\n        }\n\n        public Matrix4x4 GetProjectionMatrix(int eye, float nearPlane, float farPlane)\n        {\n            return HMDMatrix4x4ToMatrix4x4(SteamVR.instance.hmd.GetProjectionMatrix((Valve.VR.EVREye)eye, nearPlane, farPlane));\n        }\n\n        \/\/ transform a SteamVR matrix format to Unity matrix format\n        private Matrix4x4 HMDMatrix4x4ToMatrix4x4(Valve.VR.HmdMatrix44_t hmdMatrix)\n        {\n            Matrix4x4 m = Matrix4x4.identity;\n\n            m&#91;0, 0] = hmdMatrix.m0;\n            m&#91;0, 1] = hmdMatrix.m1;\n            m&#91;0, 2] = hmdMatrix.m2;\n            m&#91;0, 3] = hmdMatrix.m3;\n\n            m&#91;1, 0] = hmdMatrix.m4;\n            m&#91;1, 1] = hmdMatrix.m5;\n            m&#91;1, 2] = hmdMatrix.m6;\n            m&#91;1, 3] = hmdMatrix.m7;\n\n            m&#91;2, 0] = hmdMatrix.m8;\n            m&#91;2, 1] = hmdMatrix.m9;\n            m&#91;2, 2] = hmdMatrix.m10;\n            m&#91;2, 3] = hmdMatrix.m11;\n\n            m&#91;3, 0] = hmdMatrix.m12;\n            m&#91;3, 1] = hmdMatrix.m13;\n            m&#91;3, 2] = hmdMatrix.m14;\n            m&#91;3, 3] = hmdMatrix.m15;\n\n            return m;\n        }\n    }\n\/\/ #endif\n}<\/code><\/pre>\n\n\n\n<p>With these quick changes in place, there should be no error messages anymore. Create a 3D object Quad to act as our mirror model. Add a Stereo Renderer component to it. Within this Stereo Renderer component, enable IsMirror, set Canvas Origin World Rot and Anchor World Rot = 270.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>References:<\/p>\n\n\n\n<p>\u4e09\u65e5\u6708 \u3075\u3086\u306e. (2019, December 2). Unity 2019.2.x \u3067 VR \u7a7a\u9593\u5185\u306b\u93e1\u3092\u7f6e\u304d\u305f\u3044. Retrieved April 1, 2020, from&nbsp;<a href=\"https:\/\/mikazuki.hatenablog.jp\/entry\/2019\/12\/02\/005945\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/mikazuki.hatenablog.jp\/entry\/2019\/12\/02\/005945<\/a><br><br>&nbsp;&nbsp;&nbsp;&nbsp;Sesleria. (2019, July 13). Vive Stereo Rendering Toolkit(MirrorExample)\u3092Unity2019 SteamVR Plugin2.3.2\u3067\u52d5\u304b\u3059\u307e\u3067. Retrieved April 1, 2020, from&nbsp;<a href=\"https:\/\/qiita.com\/Sesleria\/items\/350092968d6e9b893053\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/qiita.com\/Sesleria\/items\/350092968d6e9b893053<\/a><\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;Ytomi. (2019, October 13). \u3010Unity\u3011\u30e2\u30fc\u30b7\u30e7\u30f3\u30ad\u30e3\u30d7\u30c1\u30e3\u30fc\u3092\u4f7f\u3063\u305f\u30aa\u30ea\u30b8\u30ca\u30eb\u30a2\u30cb\u30e1\u30fc\u30b7\u30e7\u30f3\u4f5c\u6210. Retrieved April 1, 2020, from&nbsp;<a href=\"https:\/\/styly.cc\/ja\/tips\/motioncapture-animation_ytomi\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/styly.cc\/ja\/tips\/motioncapture-animation_ytomi\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Methods for achieving simple VR-compatible mirror effect.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[43],"tags":[53,75],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/posts\/23"}],"collection":[{"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/comments?post=23"}],"version-history":[{"count":3,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/posts\/23\/revisions"}],"predecessor-version":[{"id":543,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/posts\/23\/revisions\/543"}],"wp:attachment":[{"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/media?parent=23"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/categories?post=23"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/noirccc.net\/blog\/wp-json\/wp\/v2\/tags?post=23"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}