Skip to content

Commit f1e9901

Browse files
committed
feat(Locomotion): option to add skybox texture to tunnel overlay cage
The view in which the Tunnel Overlay fades out to can now have a Cubemap texture provided to display as a static skybox to provide a better point of reference. The Effect Color can also be used to tint the skybox texture if required. Thanks to @JWNJWN for the work on this!
1 parent 406f4e8 commit f1e9901

File tree

4 files changed

+74
-5
lines changed

4 files changed

+74
-5
lines changed

Assets/VRTK/Documentation/API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,7 @@ Applys a tunnel overlay effect to the active VR camera when the play area is mov
25522552
* **Minimum Speed:** Minimum movement speed for the effect to activate.
25532553
* **Maximum Speed:** Maximum movement speed where the effect will have its max settings applied.
25542554
* **Effect Color:** The color to use for the tunnel effect.
2555+
* **Effect Skybox:** An optional skybox texture to use for the tunnel effect.
25552556
* **Initial Effect Size:** The initial amount of screen coverage the tunnel to consume without any movement.
25562557
* **Maximum Effect Size:** Screen coverage at the maximum tracked values.
25572558
* **Feather Size:** Feather effect size around the cut-off as fraction of screen.

Assets/VRTK/Internal/Materials/Resources/TunnelOverlay.mat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ Material:
2222
m_Texture: {fileID: 0}
2323
m_Scale: {x: 1, y: 1}
2424
m_Offset: {x: 0, y: 0}
25+
- _SecondarySkyBox:
26+
m_Texture: {fileID: 0}
27+
m_Scale: {x: 1, y: 1}
28+
m_Offset: {x: 0, y: 0}
2529
m_Floats:
2630
- _AngularVelocity: 0
2731
- _FeatherSize: 0.1

Assets/VRTK/Source/Scripts/Internal/Shaders/VRTK_TunnelEffect.shader

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
_Color("Color Tint", Color) = (0,0,0,1)
66
_MainTex ("Texture", 2D) = "white" {}
77
_AngularVelocity ("Angular Velocity", Float) = 0
8-
_FeatherSize ("FeatherSize", Float) = 0.1
8+
_FeatherSize ("Feather Size", Float) = 0.1
9+
_SecondarySkyBox("Cage SkyBox", Cube) = "" {}
910
}
1011

1112
SubShader
@@ -46,20 +47,28 @@
4647
float _AngularVelocity;
4748
float _FeatherSize;
4849
half4 _Color;
50+
samplerCUBE _SecondarySkyBox;
51+
float4x4 _EyeProjection[2];
52+
float4x4 _EyeToWorld[2];
4953

5054
fixed4 frag (v2f i) : SV_Target
5155
{
5256
float2 uv = UnityStereoScreenSpaceUVAdjust(i.uv, _MainTex_ST);
5357
fixed4 col = tex2D(_MainTex, uv);
54-
5558
float2 coords = (i.uv - 0.5) * 2;
56-
float radius = length(coords) / 1.414214;
59+
float4 viewPos = mul(_EyeProjection[unity_StereoEyeIndex], float4(coords, 0, 1));
60+
viewPos.xyz /= viewPos.w;
61+
62+
float radius = length(viewPos.xy / (_ScreenParams.xy / 2)) / 2;
5763
float avMin = (1 - _AngularVelocity) - _FeatherSize;
5864
float avMax = (1 - _AngularVelocity) + _FeatherSize;
5965
float t = saturate((radius - avMin) / (avMax - avMin));
60-
return lerp(col, _Color, t);
61-
}
6266

67+
float3 rayDir = mul(_EyeToWorld[unity_StereoEyeIndex], viewPos).xyz;
68+
half4 skyData = texCUBE(_SecondarySkyBox, normalize(rayDir));
69+
70+
return lerp(col, skyData * _Color, t);
71+
}
6372
ENDCG
6473
}
6574
}

Assets/VRTK/Source/Scripts/Locomotion/VRTK_TunnelOverlay.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class VRTK_TunnelOverlay : MonoBehaviour
3030

3131
[Tooltip("The color to use for the tunnel effect.")]
3232
public Color effectColor = Color.black;
33+
[Tooltip("An optional skybox texture to use for the tunnel effect.")]
34+
public Texture effectSkybox;
3335
[Tooltip("The initial amount of screen coverage the tunnel to consume without any movement.")]
3436
[Range(0f, 1f)]
3537
public float initialEffectSize = 0f;
@@ -43,6 +45,7 @@ public class VRTK_TunnelOverlay : MonoBehaviour
4345
public float smoothingTime = 0.15f;
4446

4547
protected Transform headset;
48+
protected Camera headsetCamera;
4649
protected Transform playarea;
4750
protected VRTK_TunnelEffect cameraEffect;
4851
protected float angularVelocity;
@@ -53,9 +56,11 @@ public class VRTK_TunnelOverlay : MonoBehaviour
5356
protected int shaderPropertyColor;
5457
protected int shaderPropertyAV;
5558
protected int shaderPropertyFeather;
59+
protected int shaderPropertySkyboxTexture;
5660
protected Color originalColor;
5761
protected float originalAngularVelocity;
5862
protected float originalFeatherSize;
63+
protected Texture originalSkyboxTexture;
5964
protected float maximumEffectCoverage = 1.15f;
6065

6166
protected virtual void Awake()
@@ -64,17 +69,25 @@ protected virtual void Awake()
6469
shaderPropertyColor = Shader.PropertyToID("_Color");
6570
shaderPropertyAV = Shader.PropertyToID("_AngularVelocity");
6671
shaderPropertyFeather = Shader.PropertyToID("_FeatherSize");
72+
shaderPropertySkyboxTexture = Shader.PropertyToID("_SecondarySkyBox");
6773
VRTK_SDKManager.instance.AddBehaviourToToggleOnLoadedSetupChange(this);
6874
}
6975

7076
protected virtual void OnEnable()
7177
{
7278
headset = VRTK_DeviceFinder.HeadsetCamera();
79+
headsetCamera = headset.GetComponent<Camera>();
7380
playarea = VRTK_DeviceFinder.PlayAreaTransform();
7481
cameraEffect = headset.GetComponent<VRTK_TunnelEffect>();
7582
originalAngularVelocity = matCameraEffect.GetFloat(shaderPropertyAV);
7683
originalFeatherSize = matCameraEffect.GetFloat(shaderPropertyFeather);
7784
originalColor = matCameraEffect.GetColor(shaderPropertyColor);
85+
CheckSkyboxTexture();
86+
if (effectSkybox != null)
87+
{
88+
originalSkyboxTexture = matCameraEffect.GetTexture(shaderPropertySkyboxTexture);
89+
matCameraEffect.SetTexture("_SecondarySkyBox", effectSkybox);
90+
}
7891

7992
if (cameraEffect == null)
8093
{
@@ -86,10 +99,14 @@ protected virtual void OnEnable()
8699
protected virtual void OnDisable()
87100
{
88101
headset = null;
102+
headsetCamera = null;
89103
playarea = null;
90104

91105
if (cameraEffect != null)
92106
{
107+
matCameraEffect.SetTexture("_SecondarySkyBox", originalSkyboxTexture);
108+
originalSkyboxTexture = null;
109+
93110
SetShaderFeather(originalColor, originalAngularVelocity, originalFeatherSize);
94111
matCameraEffect.SetColor(shaderPropertyColor, originalColor);
95112
Destroy(cameraEffect);
@@ -130,6 +147,25 @@ protected virtual void FixedUpdate()
130147

131148
lastForward = fwd;
132149
lastPosition = pos;
150+
151+
if (effectSkybox != null)
152+
{
153+
matCameraEffect.SetMatrixArray("_EyeToWorld", new Matrix4x4[2]
154+
{
155+
headsetCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Left).inverse,
156+
headsetCamera.GetStereoViewMatrix(Camera.StereoscopicEye.Right).inverse
157+
});
158+
159+
Matrix4x4[] eyeProjection = new Matrix4x4[2];
160+
eyeProjection[0] = headsetCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
161+
eyeProjection[1] = headsetCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
162+
eyeProjection[0] = GL.GetGPUProjectionMatrix(eyeProjection[0], true).inverse;
163+
eyeProjection[1] = GL.GetGPUProjectionMatrix(eyeProjection[1], true).inverse;
164+
eyeProjection[0][1, 1] *= -1f;
165+
eyeProjection[1][1, 1] *= -1f;
166+
167+
matCameraEffect.SetMatrixArray("_EyeProjection", eyeProjection);
168+
}
133169
}
134170

135171
protected virtual void SetShaderFeather(Color givenTunnelColor, float givenAngularVelocity, float givenFeatherSize)
@@ -138,5 +174,24 @@ protected virtual void SetShaderFeather(Color givenTunnelColor, float givenAngul
138174
matCameraEffect.SetFloat(shaderPropertyAV, givenAngularVelocity);
139175
matCameraEffect.SetFloat(shaderPropertyFeather, givenFeatherSize);
140176
}
177+
178+
protected virtual void CheckSkyboxTexture()
179+
{
180+
if (effectSkybox == null)
181+
{
182+
Cubemap tempTexture = new Cubemap(1, TextureFormat.ARGB32, false);
183+
tempTexture.SetPixel(CubemapFace.NegativeX, 0, 0, Color.white);
184+
tempTexture.SetPixel(CubemapFace.NegativeY, 0, 0, Color.white);
185+
tempTexture.SetPixel(CubemapFace.NegativeZ, 0, 0, Color.white);
186+
tempTexture.SetPixel(CubemapFace.PositiveX, 0, 0, Color.white);
187+
tempTexture.SetPixel(CubemapFace.PositiveY, 0, 0, Color.white);
188+
tempTexture.SetPixel(CubemapFace.PositiveZ, 0, 0, Color.white);
189+
effectSkybox = tempTexture;
190+
}
191+
else if (effectColor.r < 0.15f && effectColor.g < 0.15 && effectColor.b < 0.15)
192+
{
193+
VRTK_Logger.Warn("`VRTK_TunnelOverlay` has an `Effect Skybox` texture but the `Effect Color` is too dark which will tint the texture so it is not visible.");
194+
}
195+
}
141196
}
142197
}

0 commit comments

Comments
 (0)