Hi everyone, Does anyone know how I can rotate a skybox so it matches the position of my directional light? I don't want to animate it just rotate it into the correct position. It's important that it matches the directional light rather than the other way around. I'm using the included "DawnDusk Skybox" Thanks in advance, Max
+1 This is something that I wonder since long time why no engine allows a parameter of skybox rotation. It should be so easy to do, I think, and so useful! I place the light with the right direction only to find then that I have to rerender the skybox or make another one entirely because I can't adjust the original one. I found myself again recently in the same condition. Luckily I have my solution to create skyboxes in Max very easily so it wasn't a problem but I guess not everybody has the knowledge or time to do this so an option to rotate the skybox would be definitely useful.
Maybe I'm missing something but since the skybox is composed of separate images right left etc. why don't you just copy the images into the orientation you want and rotate the overhead one?
Probably because he (like me) needs finer tuning than 90 degrees After all, the skybox, for what I know, is really a geometry box so why not allow to draw it rotated respect to the cam?
Why not fake a skybox instead? - Create an empty GameObject. - Add 6 Unity plane objects. Form them into a cube with the normals pointing inward. Parent planes to GameObject (preferably with GameObject in the center of the cube). - Make six Unlit materials, one for each face of the cube. Make materials for the six textures that make up the skybox. - Apply the materials to the skybox in such a way that, when looking at it from the inside, it looks like a skybox. - Make a new layer called "Skybox". Add your fake skybox to that layer. - Make a new camera. Set it to only render the Skybox layer. Set its depth below the depth of your main camera. - Make sure your main Camera does not render the Skybox layer. - Position the new camera in the center of your fake skybox. - Write a script to make the new camera copy the rotation of your main camera. You should now have a fake Skybox. If you want to rotate the skybox by itself, you can just rotate the GameObject.
Yeah that's the first solution I thought of, Screenhog, thank you anyway, but the best solution, seeing that we already have a skybox built-in Unity, would be from them to add this option, right?
This was my solution to the problem. I make my skybox Unity way. then make an GameObject to put all my components in the scene in including my cam. Now I can rotate that object and the skybox background changes but the game setup is still the same. you may have to change the scrips to handle this rotation.
Hang on, there is a much simpler solution than this. It's always best to use the built in stuff if you can, and in this case it's not too hard. Heres what you can do: Add a second camera named "SkyboxCamera" to whatever game object your "main camera" is attached to. Set the clear flags of your Main camera to "don't clear" in the inspector Set the clear flags of "SkyboxCamera" to be "skybox", and set the depth of "SkyboxCamera" to be 1 less than the depth of "MainCamera in the inspector, and the culling mask of "SkyboxCamera" to be "nothing" add a script like below (or your own customized version) to your game object set the MainCamera and SkyCamera variables of the script in the inspector create your Unity Skybox and attach it to the "SkyboxCamera" in the inspector set the rotation of the script in the inspector if you need to rotate your skybox only intially, otherwise you set it in an update function if you want the skybox to rotate while running Good luck! Code (csharp): public class SkyboxCamera : MonoBehaviour { // set the main camera in the inspector public Camera MainCamera; // set the sky box camera in the inspector public Camera SkyCamera; // the additional rotation to add to the skybox // can be set during game play or in the inspector public Vector3 SkyBoxRotation; // Use this for initialization void Start() { if (SkyCamera.depth >= MainCamera.depth) { Debug.Log("Set skybox camera depth lower "+ " than main camera depth in inspector"); } if (MainCamera.clearFlags != CameraClearFlags.Nothing) { Debug.Log("Main camera needs to be set to dont clear" + "in the inspector"); } } // if you need to rotate the skybox during gameplay // rotate the skybox independently of the main camera public void SetSkyBoxRotation(Vector3 rotation) { this.SkyBoxRotation = rotation; } // Update is called once per frame void Update() { SkyCamera.transform.position = MainCamera.transform.position; SkyCamera.transform.rotation = MainCamera.transform.rotation; SkyCamera.transform.Rotate(SkyBoxRotation); } }
With some modifications to his script, scottm361's solution worked for me, thanks to the detailed guide. Thanks.
scottm361's solution worked for me after commenting a few lines. Code (CSharp): // Update is called once per frame void Update () { SkyCamera.transform.Rotate (SkyBoxRotation); }
I had to make a update function like this to make it work (Space.World) Code (JavaScript): public function LateUpdate() : void { transform.position = parentTransform.position; transform.rotation = parentTransform.rotation; transform.Rotate ( 0.00, skyRotation, 0.00, Space.World); } also some tips; I replaced transform with rTransform and added in awake rTransform = transform; I renamed lateupdate() and call it from my actual camera script that provides the position and rotation to the function.
When using Deferred lighting, this does not seem to work, the skybox won't render, and if i change the camera witch has the depth only from deferred to forward it works. Bug? Also the skybox only cam can be set to vertex lit for performance or does this not matter?
You could create a skybox shader for this purpose Skybox.shader Code (CSharp): Shader "World/Skybox" { Properties { _Brightness("Brightness", Range(0,1)) = .5 _MainTex("Stars", Cube) = "white" {} } SubShader { Tags { "Queue" = "Background" } Pass { ZWrite Off Cull Off CGPROGRAM #pragma vertex vert #pragma fragment frag float _Brightness; float4x4 _SkyboxRotation; #include "UnityCG.cginc" struct vertexInput { float4 vertex : POSITION; float3 texcoord : TEXCOORD0; }; struct vertexOutput { float4 vertex : SV_POSITION; float4 vertexWorld : POSITION1; float3 texcoord : TEXCOORD0; }; vertexOutput vert(vertexInput _input) { vertexOutput output; output.vertex = mul(UNITY_MATRIX_MVP, mul(_SkyboxRotation,-_input.vertex)); output.texcoord = -_input.texcoord; output.vertexWorld = mul(_Object2World, -_input.vertex); return output; } fixed4 frag(vertexOutput _input) : COLOR { return texCUBE(_StarsText, _input.texcoord); } ENDCG } } }
This code rotate an skybox, but only from Y axis: void Update () { RenderSettings.skybox.SetFloat("_Rotation", Time.time * adjustment); }
This shader will let you rotate a skybox in any direction. It will rotate with Light0. Code (CSharp): Shader "Custom/MovingSkyboxUpload" { Properties { _CubeMap ("Skybox Cube Map", Cube) = "" {} } SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag uniform samplerCUBE _CubeMap; struct vertexInput{ float4 vertex: POSITION; }; struct vertexOutput{ float4 pos : SV_POSITION; float4 posWorld : TEXCOORD1; fixed3x3 R : TEXCOORD4; }; vertexOutput vert(vertexInput v){ vertexOutput o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.posWorld = mul(_Object2World, v.vertex); fixed3 new_up = normalize(_WorldSpaceLightPos0.xyz); // folowing code from http://stackoverflow.com/questions/32257338/vertex-position-relative-to-normal float3 up = float3(0,1,0); float3 w = cross(up, new_up); float s = length(w); // Sine of the angle float c = dot(up, new_up); // Cosine of the angle float3x3 VX = float3x3 ( 0, -1 * w.z, w.y, w.z, 0, -1 * w.x, -1 * w.y, w.x, 0 ); // This is the skew-symmetric cross-product matrix of v float3x3 I = float3x3 ( 1, 0, 0, 0, 1, 0, 0, 0, 1 ); // The identity matrix o.R = I + VX + mul(VX , VX) * (1 - c)/(s*s); // The rotation matrix! YAY! // previous code from http://stackoverflow.com/questions/32257338/vertex-position-relative-to-normal return o; } float4 frag(vertexOutput i) : COLOR{ float3 viewDirection = normalize( _WorldSpaceCameraPos.xyz - i.posWorld.xyz ); viewDirection = mul (viewDirection , i.R); return texCUBE(_CubeMap, viewDirection); } ENDCG } } } Built in Unity5.2.1
I know this thread's been running for a while, but here's a real simple way to do it: Do the double camera set-up as scottm 361 explained above, but then put this simple script on the SkyboxCam : void FixedUpdate (){ transform.Rotate (0, rotation speed, 0); } Works great and hardly any typing at all.
Nic, Your shader works well but it only seems to rotate the skybox about 2 axes. "Z" has no effect. Strangely, the main camera y and z rotation have exactly the same effect. Help please.
Hey all. I stumbled upon this recently, and came up with a modified version of the Unity 5 Skybox (6-sided) shader that allows rotation in the 3 axes. I'm not good at shaders so I don't know how efficient this is. Just move the sliders on the material and it will rotate. Cheers.
@NicRule In Unity 5.4 it compiles but shows the HDRI wrong. Can you kindly have a look and repost the shader code? Thank you very much.
https://docs.unity3d.com/Manual/class-Skybox.html In 5.4 rotation is included in the skybox class, it's only in one axis but seems like using custom shaders is doing it the hard way?
Yes true i am aware of this. Unfortunately you need to brake the HDRI to 6 pieces. Will see if i can find a soft that can do this easily. Thank you for the support @catfink
I use this tool http://ggnome.com/pano2vr for converting panoramas into 6 face cube output. I think the trial version will let you experiment. Basically input the panorama image and then specify transformation as what you want to do and select cube map type output.
Great work! It worked pretty well for me. While profiling, I couldn't see any impact on the performance at all.
Thanks, works nicely with default unity skybox (atleast 2019)! this is the simplest and best solution in this thread. what you can do with it is: 1. rotate your sky dynamically while the game is running (careful: if your skybox contains a sun, then this can complicate things) 2. you can also use a value "public float myrotation" in a monobehaviour script, attach that to your camera or wherever you want, and then you can in editor rotate your skybox. public float Skybox_Rotation_Y = 0.0f; // OnValidate is called when value is changed in editor AND on "game startup" private void OnValidate() { RenderSettings.skybox.SetFloat("_Rotation", Skybox_Rotation_Y); }
If you still are still looking and just want to rotate skybox once go to your skybox material settings and there is a Rotation slider. Please, don't create unnecessary scripts for that.
Optimized version of code with reseting rotation on disable Code (CSharp): using UnityEngine; public class SkyBoxRotation : MonoBehaviour { public float speed = 0.2f; private int RotationProperty; private float initRot; private Material skyMat; private void OnDisable () => skyMat.SetFloat (RotationProperty, initRot); void Start() { RotationProperty = Shader.PropertyToID ("_Rotation"); skyMat = RenderSettings.skybox; initRot = skyMat.GetFloat (RotationProperty); } void Update () => skyMat.SetFloat (RotationProperty, Time.time * speed); }