- Home /
Doom-style billard/sprite skybox without perspective warping?
Currently if I try to use an unlit texture as my skybox shader, it still warps the edges of the skyboard:
Is there a way of displaying just a sprite or billboard image that moves left/right at a slower speed than the camera rotates, but doesn't get closer or move vertically? Every 3D game before quake used this method, but I'm uncertain of how to emulate it in Unity without a skybox.
Answer by Bunny83 · Apr 30, 2018 at 02:01 AM
It's not entirely clear what you actually want. The original Doom doesn't allow looking up or down. It uses a cylindrical projection of the skytexture. Later there where free look mods which only applied "Y-shearing". So they did not rotate the camera but simply shift / shear the projection along the up axis. That way the actual scene was still rendered completely horizonal.
There are other doom remakes which offers actual freelook. They usually use a spherical mapping of the skytexture or use an actual skybox with 6 textures.
Note that for the cylindrical or spherical mapping you do not actually render a huge quad in the background but you simply use a shader on the sky brush which does the coordinate mapping based on the camera direction. This is what a spherical mapping looks like:
There are just two quads with my DoomSky material which uses the DoomSky shader i just created:
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));
fixed4 col = tex2D(_MainTex, uv);
return col;
}
ENDCG
}
}
}
Note that the texture's wrapmode is set here to "repeat". That's why you see the same texture below the horizon. Originally it only ever reaches down to the horizon. Also note that since the textures were never meant to be used in an actual free look environment (even only considering the upper hemisphere) the pole right above you will look strange as, just like every spherical projection, the top edge of the texture will collapse to a single point. The SkyTextures where only tiling horizontally so the left end matches the right one.
I've added a "Stretch" parameter which allows you to move the horizon down a bit. It will stretch the upper hemisphere so it reaches further down. While a value of 0 means the horizon equals the bottom of the texture, a value of 0.5 means the texture will be stretched across the whole sphere. So the top edge collapses at the north pole while the bottom edge would collapse at the south pole.
Generally if you use this technique you either want to restrict the cam to only rotate around y (just like the original doom) or make sure your texture properly maps to a sphere. For example a normal equirectangular map works just fine with stretch set to 0.5. I've tried it with an earth texture and i get the earth mapped as sky sphere around and it looks great in all directions, even the poles.
I was interested in doing it without the cylindrical distortion at the edges, I think the original Rise of the Triad did this, so it just looked like a large image that moved around horizontally without any curving at the sides. I really like the stretch feature on your shader, could I add a "squash horizontal" parameter to counter the stretching slightly?
That's not really possible since the perspective distortion comes from the perspective view itself. If you want to reduce / $$anonymous$$imize the distortion you have to lower your FOV. However you can never completely get rid of it. I just started up my virtual machine and got two examples from the Doom95 version
In the first have a look at the column. When it's viewed at the edge of the screen it is stretched slightly horizontally. The same thing happens to the sky in the second example.
$$anonymous$$eep in $$anonymous$$d that the FOV you set is the vertical FOV that means the horizontal FOV depends on your aspect ratio. So on wide screen resolutions you get more distortion on the sides. There is nothing you can really do about this. Whenever you map a rectangular texture onto spherical or cylindrical "surface" there will be distortion of some kind. By using a cylindrical projection you get no vertical distortion but still horizontal. If you want free look you can't use cylindrical projection as you don't have any "top" or "bottom".
The way to use this shader is up to you. In the original game there was an actual flat surface above the level which did the sky rendering pretty similar to what i do in the shader. It's actually a "raytracing" shader. You can turn off ZWrite ("ZWrite off") in the shader. That way it will always only render behind objects. That would allow you to place this material on a "window" that leads to the outside area. Of course if it's an entire outside area you would either need to "close" your playable area with that sky material or simply render a fullscreen quad on the camera. Rendering a fullscreen quad can be more expensive as you may have a lot of overdraw. Though it depends on your level design
Ahh I see, I love your shader but I might try with the window approach to see if I can completely eradicate the distortion, I'm not sure if it's possible to adjust the FOV seperately for a skybox or not. Are you using your shader on a skybox or is it geometry fixed to the camera?
Your answer
Follow this Question
Related Questions
My shader doesn't work if I use the same material for multiple objects with the same texture. 1 Answer
Culling part of a sprite in Sprite Manager 2 1 Answer
Sprite texture incorrect 0 Answers
2D Sprite Flash Shader - unwanted outline 0 Answers
How to make Pixelstudio's skydome works on Mobile(iOS & Android)? 1 Answer