Is it possible to lock the position of a skybox during a teleport to an identical environment so it’s impossible to tell the player has been teleported? Currently I have two sections of the scene that match perfectly and when the player teleports, no matter which facing angle or direction, when they arrive, it’s indistinguishable, besides the skybox. That changes unless the destination facing orientation is exactly the same, which it won’t be. Is there a way of offsetting the skybox, or locking it in place so that it doesn’t rotate when the player does?
It’s not possible to “lock the position”, but you can certainly change the rotation of the skybox when you teleport the player. Most skybox shaders have a rotation property you can set.
Thanks, I’m using this shader for a simple quad sky which doesn’t seem to have an override
Shader "FX/DoomSky"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_StretchDown ("Stretch", Range(0, 0.5)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Cull off ZWrite On ZTest Lequal
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float3 worldView : TEXCOORD1;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldView = -WorldSpaceViewDir (v.vertex);
return o;
}
sampler2D _MainTex;
float _StretchDown;
fixed4 frag (v2f i) : SV_Target
{
float3 dir = normalize(i.worldView);
float2 uv = float2(0.5+atan2(dir.z, dir.x)/(2*UNITY_PI), _StretchDown+dir.y*(1-_StretchDown));
uv.x*=3;
fixed4 col = tex2D(_MainTex, uv);
return col;
}
ENDCG
}
}
}
I’m teleporting the player when they hit a collider by setting the player’s transform:
obj.transform.position = portalB.transform.TransformPoint(portalA.transform.InverseTransformPoint(obj.transform.position));
And the player’s rotation:
obj.transform.rotation = portalB.transform.rotation * Quaternion.Inverse(portalA.transform.rotation) * obj.transform.rotation;
The position is irrelevant for the skybox, but could the rotation value be somehow applied to this skybox shader (with a multiplier of some amount, I assume) to counter the repositioning? This way, no matter which orientation the collider are and the player is rotated, the skybox would look the same after the teleportation?
Take a look at the built in shaders:
Does this allow for this flat, retro looking mapping?
fabulouspleasantguillemot
That’s the reason I used this shader, to give a Doom 1993 style skyboard that just uses a single image that doesn’t warp other than the camera’s natural FOV. I’m also not quite sure if I can take the rotation quat and use it to rotate a skybox shader, but using the Y axis might be a good start.
It should, just in your case you only need to worry about rotating the worldView, not the mesh.
For some reason, skybox-panoramic is a lot bigger than the quad shader:
The quad shader I’m using appears properly on screen:
I tried playing with the settings, but it’s still surprisingly large, is this because of the PPU size?
The panoramic skybox is assume a equirectangular image that’s a full sphere. The one you posted above appears to be setup to allow for sky textures that can be scaled so they’re not a full sphere, and your example looks like it might be only a top hemisphere with it wrapping at the horizon.
The original Doom used a texture that was mapped from the middle of the screen to the top of the screen and didn’t have to worry about you looking up or down. Later hacks & doom engine games that added looking up and down just stretched the texture to be shown as tall as the highest “up” was allowed. Also they didn’t actually allow you to look up since it wasn’t a real 3D engine, it was just skewing the camera projection up and down, so it a little different.
You’d need to modify the panoramic skybox shader to let you scale the texture UVs, or double the height of your textures and fill the bottom half in with black or a copy of the texture if you want to mimic what the original shader you had did.
Yeah, this shader does work best with y-shearing, but this looks elegant enough even with true look up/down:
madradiantcapybara
The panoramic shader not only isn’t tiled, but it’s also cubic:
palatableperiodiccougar
Is there a way of either adding rotation to the DoomSky shader, or making the panoramic one act more like the DoomSky shader? I’m not quite sure where to start
You’re using the wrong settings for your material. The shader has two “Mapping” options, and that’s using the “6 frames layout” which seems to be for cubemap texture based layouts … in which case I’m not sure why you wouldn’t use an actual cubemap but whatever. You want the “Latitude Longitude Layout”.
Yes. Look at the _Rotation
property from that shader and the RotateAroundYInDegrees
function. Those are the only things you need. Then…
Thanks, okay so now it’s spherical:
harmlessunhappyfalcon
It just needs tiling. Now, originally this was posted as part of the DoomSky shader:
So could a similar technique be used for the panoramic shader? This way it could be on parity with the DoomSky shader, and all I’d need to do is somehow offset the rotation. (PS: I am pre-beginner with shaders, I barely ever get anything working properly without explicit instruction )
So, can this:uv.x *= 4;
be added to the Panoramic shader to get the same effect as DoomSky, or will it always be a little more spherical than DoomSky? I’m not quite sure if I can just add it in the same sort of place I did in DoomSky or not.
@bgolus would adding tiling to the spherical panorama shader work the same as the DoomSky shader, or would it still be a little more spherical? (I want it to be as flat as possible, besides camera distortion) If so, how could I go about adding tiling?
I would copy the one function and add the two lines of code needed to make the DoomSky rotate rather than modify the panorama shader.
Sounds good! But I still don’t reeeeally know where to start:
Shader "FX/DoomSky"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_StretchDown ("Stretch", Range(0, 0.5)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Cull off ZWrite On ZTest Lequal
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float3 worldView : TEXCOORD1;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldView = -WorldSpaceViewDir (v.vertex);
return o;
}
sampler2D _MainTex;
float _StretchDown;
fixed4 frag (v2f i) : SV_Target
{
float3 dir = normalize(i.worldView);
float2 uv = float2(0.5+atan2(dir.z, dir.x)/(2*UNITY_PI), _StretchDown+dir.y*(1-_StretchDown));
uv.x*=3;
fixed4 col = tex2D(_MainTex, uv);
return col;
}
ENDCG
}
}
}
(I used uv.x*=3; as it looked more appropriate)
Also, I get this, but it still works, is this okay?
Also need to confirm the ‘Shader of this material does not support skybox rendering’ error isn’t a big issue? I’m not even sure why it’s saying that when it clearly works as a skybox.
I’m not sure what it’s checking to see if a shader is a “skybox” shader or not. Might be as simple as your shader isn’t set to the background queue or skybox preview. Really most of those warnings are there to make sure people are dragging a Standard shader material onto the skybox slot. If it works, it’s probably fine.
Erm, I’m trying something here, but I’m not doing a great job:
Shader "FX/DoomSkyRotate"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_StretchDown ("Stretch", Range(0, 0.5)) = 0
_Rotation ("Rotation", Range(0, 360)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
Cull off ZWrite On ZTest Lequal
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float3 worldView : TEXCOORD1;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldView = -WorldSpaceViewDir (v.vertex);
float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation);
return o;
}
sampler2D _MainTex;
float _StretchDown;
float _Rotation;
fixed4 frag (v2f i) : SV_Target
{
float3 dir = normalize(i.worldView);
float2 uv = float2(0.5+atan2(dir.z, dir.x)/(2*UNITY_PI), _StretchDown+dir.y*(1-_StretchDown));
uv.x*=3;
fixed4 col = tex2D(_MainTex, uv);
return col;
}
float3 RotateAroundYInDegrees (float3 vertex, float degrees)
{
float alpha = degrees * UNITY_PI / 180.0;
float sina, cosa;
sincos(alpha, sina, cosa);
float2x2 m = float2x2(cosa, -sina, sina, cosa);
return float3(mul(m, vertex.xz), vertex.y).xzy;
}
ENDCG
}
}
}
The float _Rotation;
uniform (a shader value defined outside of a function) needs to be defined before the first time it’s used in the shader file, so you need to move that above the vert
function.
Then I’ll quote myself again.
Look at the code you have. What are you applying the RotateAroundYInDegress
function to, and what are you doing with the output value?
I’m sorry, I’m not sure which vert function? I’m really terrible with shader language, do you mean v2f vert (appdata v)
? Whereabouts above it, I tried putting it directly above and it I got:
Shader error in 'FX/DoomSkyRotate': undeclared identifier 'RotateAroundYInDegrees' at line 40 (on d3d11)
Compiling Vertex program
Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR
I’m not sure how to apply that to this, I can barely understand what that parts actually doing, does float3 rotated = RotateAroundYInDegrees(v.vertex, _Rotation);
need changing?