FTE skyrooms for dummies

[UPDATE: 28 Sep 2021: Updating to latest TrenchBroom helped fix errors in scaling to 0.0625, and now 1/16 scale works!! This page needs a rewrite, but for now, just follow METHOD 2, and use 0.0625]

[UPDATE: 28 Sep 2021: 1/4 shrinkage works, but 1/8th, or 1/16th is still *off* (maybe due precision errors in Trenchbroom?). With scale 0.25, and g_skyscale = 4, it WORKS!!]

DISCLAIMER: This guide is still a wip.

Before we get started, here’s a great introductory video which covers all the concepts discussed here:

“Ok, so what do I actually do?”

METHOD 1 (Let FTE do it):


  1. Open trenchbroom, make the map.
  2. Make  a point entity info_null, put it at ‘0 0 0’
  3. Select it, as well as any stuff (brushes/ entities/ whatever) in the ‘playable area’, you’ll need to orient the buildings, mountains or other (distant) brushes you are going to put in the skyroom.
  4. Copy/paste them in a spot outside the ‘playable level’, lets call this collection of copied ‘stuff’ the ‘diorama’
  5. While everything is selected in the diorama, select the scale tool, and “scale objects” “by factors”  ‘0.0625 0.0625 0.0625’ (one 1/16th)
  6. Everything is much smaller, so go close into the diorama, and make your extra stuff, buildings, mountains etc etc, and for reference, use things you copied (in step 3)
  7. Make all the skyroom brushes func_detail
  8. Texture everything, scale textures in the diorama (to x and y scale 0.0625)
  9. Enclose the diorama in a 6 sided sealed cube, and give all the walls a sky texture.
  10. In the main ‘playable area’ of the map, select the worldspawn entity (ie just click a brush), and add a key called ‘_skyroom’, and give it the value of the origin of the info_null entity in your diorama, and the scale factor you chose eg: if the info_null was at ‘300 50 0’, make the value of the _skyroom key be ‘300 50 0 0.625’.Keys to add to worldspawn (copied from here)
    • _skyroom: Set to the x y z coords of the center of your skyroom. Sky surfaces will then show the skyroom in place of regular sky surfaces (sky surfaces inside the skyroom itself will render as normal).
    • _skyname / _sky: Overrides sky surfaces with an explicit skybox name (without needing to resort to shaders).
    • _skyrotate: Sets the speed at which any skybox will rotate at.
    • _skyaxis: Specifies an x/y/z direction around which the skybox will rotate, eg 0 0 1 will feel like a merry-go-round.
  11. Delete the all the info_null entities

At the FTE client console, set “allow_skybox” to “1”. No, not needed. Spoike: “allow_skybox existed because engines at the time failed to write depth values properly. setting it to 1 may provide a tiny speedup but that’s it”

I am told this method should work, but I haven’t been able to do it:

It comes close, but (even though I got it to work once!) the end result currently doesn’t align properly. The ‘SKYROOM FLOOR’ doesn’t match up with the ‘PLAYABLE AREA’ floor. Why not?

Theory 1: There’s something wrong/incorrect with one of the steps (see below)
Theory 2: There’s a missing step
Theory 3: Theres some other setting, somewhere, which is interfering
Theory 4: My test map is ‘too small’ (default settings assume a bigger ‘playable area’?)
Theory 5: It’s a map compilation issue, some setting, something Trenchbroom, or qbsp related..
Theory 6: It’s something to do with the map being ‘off centre’ (Spoike says “movement of the skyroom camera is related to the movement of the player’s position within the world relative to the origin of the map, so if your map is off-center, the skyroom will be off-center“)

If anyone has gotten this to work, please let me know:


METHOD 2:  Use extra code (ssqc and csqc) to make it work

  1. Open trenchbroom, make the map.
  2. Make a seperate (ie out in the void) 6 sided sealed cube, and give all the walls a sky texture.
  3. Make  a point entity info_null, rename it ‘sky_camera’, and put it at ‘0 0 0’.
  4. Select sky_camera, as well as any stuff (brushes/ entities/ whatever) in the ‘playable area’, you’ll need to orient the buildings, mountains or other (distant) brushes you are going to put in the skyroom.
  5. Copy them(TrenchBroom ctl+d), and move them in a spot outside the ‘playable level’, lets call this collection of copied ‘stuff’ the ‘diorama’
  6. With the diorama still elected, select the scale tool, and “scale objects” “by factors”  ‘0.0625 0.0625 0.0625’ (one 1/16th).
  7. The diorama (including the sky_camera) should still be selected, so move them into the box you made in Step 2.
  8. Go close into the diorama, and make your extra stuff, buildings, mountains etc etc. Everything is much smaller, so for reference, use things you copied (in step 4)
  9. Make all the skyroom brushes func_detail
  10. Texture everything, scale textures in the diorama (to x and y scale 0.0625)
  11. Delete the original sky_camera entity (at 0 0 0)

EXTRA CODE. Spoike tells me this code shouldn’t be needed. But without the following code, my skyroom doesnt ‘move’ when the player moves..

//Capture the sky_cameras coordinates and send them to CSQC using writebytes
var vector sky_room_position; // global
void() sky_camera =
sky_room_position = self.origin;
//at the bottom of putclientinserver

WriteFloat(MSG_MULTICAST, sky_room_position_x);
WriteFloat(MSG_MULTICAST, sky_room_position_y);
WriteFloat(MSG_MULTICAST, sky_room_position_z);
msg_entity = self;
multicast (self.origin, MULTICAST_ONE_R);

  1. CSCQ


vector sky_room; // global

void() CSQC_Parse_Event =


sky_room[0] = readfloat();
sky_room[1] = readfloat();
sky_room[2] = readfloat();

void() SkyRoom =
// g_skyscale value / trenchbroom scale factor
// 4 / 0.25
// 8 / 0.125
// 16 / 0.0625
float g_skyscale = 16;
vector realpos;
vector player_origin = getproperty(VF_ORIGIN);

realpos[0] = player_origin[0] / g_skyscale;
realpos[1] = player_origin[1] / g_skyscale;
realpos[2] = player_origin[2] / g_skyscale;
setproperty(VF_SKYROOM_CAMERA, sky_room + realpos);

/* Spoike says
(playerorigin-skyorigin)*scale + cameraorigin
that’s basically the fomula
with a scale of 0, you get no paralax effect and the skyroom doesn’t change as you walk around
otherwise with _skyroom the skyorigin term is always ‘0 0 0’
so if you want paralax then you need your map to be centered properly, or the skyroom to be offset relative to its camera



void(float width, float height, float menushown) CSQC_UpdateView =




  • After you edit, and compile, you dont have to reload the map (‘map mapname’). Just type (at the client console) ‘vid_reload’. NO, you DO. At least once I had to load a different map, then reload the map I was editing (and had just recompiled) so that you could load the latest version of the map.
  • You might need to add lights in the skyroom so it matches your ‘playable area’
  • EZQuake clients won’t be able to connect: “AllocBlock: full”

More info:
Good News: I got this working:

Making a 3D Skybox

Below is mostly compatible documentation, [copied from here], although it is for the Source Engine, using Hammer editor.

Adding a 3D skybox can be a powerful addition to the visual treatment of a level. The 3D skybox is an extra area constructed by the level designer that is outside the bounds of the gameplay portion of the map. When the map is loaded, Source enlarges the objects in the 3D skybox area and places them outside the boundaries of the current level, between the skybox and the player. This is used to give the appearance of a much wider world out side of your level, without being too expensive on the budget due to the (by default) 1:16 scale. 3D skyboxes are non-interactive – the player and other entities cannot move into the 3D skybox space.

3D skybox geometry can be indistinguishable from normal level geometry. Seamless transitions from normal level geometry and 3D skybox are very possible, and are used in many of the maps for official Source games such as Counter-Strike: Source.

Bug.png Bug: In [Portal] Portal, 3D skyboxes do not render properly when observed through portals. – see here.
 Note:A 3D skybox is not a replacement for a 2D skybox. The 2D skybox is always in the background of the 3D skybox. To edit or change the standard 2D skybox, see Skybox (2D).
 Note:In <Left 4 Dead>, the default scaling is 1:32, NOT 1:16 (But 1:16 works properly!)
 Note:to avoid lighting problems, do not use light (or any other lights without the Env_ prefix)
 Note:In [Portal 2] Portal 2 some skybox geometry won’t be visible unless you set the cvar r_skybox_draw_last to 0.


Standard skyboxes are simple 2D images, mapped onto a cube so they surround the level. 3D skyboxes are full 3D geometry, and properly parallax as the player moves through the level. Since they are rendered in real time, they scale with the video card resolution and also support real-time shader effects not possible in 2D skyboxes.

The main benefit of using a 3D skybox is that it allows the level designer to make the map look much larger than is possible with the standard world geometry. The largest map that can be made without a 3D skybox is 32768 units on each side. Using a 3D skybox, the map can be extended to 16 times that amount.

Maps of this size are possible because 3D skyboxes are created in the Hammer editor at 1/16 the scale of standard maps. At run time, the engine scales them back up to match the scale of the rest of the map. Not only does this save space in the editor views, it also is much less expensive to compile and render.

Due to their scale, 3D skyboxes have much lower lightmap and texture resolution. This makes 3D skybox geometry less expensive performance-wise than standard world geometry.

3D skyboxes can be used to overcome draw distance limitations, if a low-detail skybox identical to the main map is created. A mod team wanting to do this would have to develop code to ease the transition between map versions.

Basic characteristics

3D Skyboxes have the following characteristics:

  • Are constructed (by default) in 1/16 scale in the Hammer editor and then rendered at 16 times size in the engine to match the world geometry.
  • Support materials with shader effects such as normal mapping, water, environment mapping, proxies, etc.
  • Are non-interactive – players and other world entities cannot enter 3D skyboxes. The 3D skybox is just a visual extension of the map extents.
  • Can be constructed with brushes, displacements, static and dynamic props, lights, brush entities, and point entities (such as env_sprite).
  • Any models that are placed in the 3D skybox must be authored at 1/16 scale. Standard models (props) are not scaled properly for 3D skybox. Special 1/16 scale versions must be used. For Half-Life 2, these props can be found in the models/props_skybox directory.
  • Should not contain info_player_start, NPCs or monsters.
  • Have lower lightmap and texture resolution because of the scale at which they are created.
  • Must have their own lighting sources, although a light_environment in the non-skybox section will also be used for the 3D skybox lighting.
  • Use the sky_camera entity to control how they line up with the non-skybox world geometry.
  • 3D skyboxes have their own fog parameters, adjustable in the sky_camera entity.
  • Geometry in the 3D skybox is not occluded or culled like the rest of the level geometry. Adding lots of detailed brush geometry or models to the 3D skybox, especially with translucent materials, can severely affect performance.
  • A map must have a light_environment in it, otherwise models in the 3d skybox will be lit incorrectly. A light_environment in the non-skybox part of the map negates the need for one in the 3D skybox.

Construction of 3D skyboxes

  • A note about the sky_camera entity: point entities do not scale down.

The most efficient way of creating a 3D skybox that matches or “lines up” with the your current map is to use some of the geometry in the main part of the level. Follow these steps after you’ve created your main level geometry:

  1. Add a sky_camera entity at the world origin (coordinates 0, 0, 0), the center of the map grid. The sky_camera is a reference point used by the renderer to align the 3D skybox with the main part of the map. In other words, it acts as a marker telling the renderer how the 3D skybox’s origin and the world’s origin relate to one another. You can think of this process as being similar to selecting all the 3D skybox geometry and then aligning the sky_camera entity in that selection with the world’s origin (0,0,0). The geometry is translated back to that position in the world. This is the same concept used when the skybox is rendered in the engine.
  2. Select some distinct parts of the level that you can use a guideline for scale and position in the 3D skybox. Common elements to select for this purpose would be some of the larger structures, as well as the walls, cliffs, hills, etc. that define the edges of the map. Make sure you also have the sky_camera you created selected as well.
     Note:It is important not to select any model entities, only brushes. Models cannot be used as reference geometry, because models cannot be scaled down in the Hammer editor.
     Note:In <Counter-Strike: Global Offensive> you can manually scale down prop_static entities with the same scale, making them useable for reference.
  3. Choose Copy from the Edit menu, or hit CTRL-C.
  4. Choose Paste Special from the Edit menu. Set the Number of copies to paste to 1, and all other values to 0. Hit OK. This makes a duplicate of the geometry you had selected.
  5. Turn on Scaling Texture Lock in the toolbar, if it is not already on. Its icon resembles <tl>. This will shrink the textures along with the geometry.
  6. Leaving geometry selected, choose Transform from the Tools menu. Select the radio button next to Scale. Type in a value of .0625 for X, Y and Z. This is the decimal equivalent to 1/16 – the scale of the 3D skybox. Click OK.
     Note:If you want textures on the geometry to scale accordingly, make sure you have scaling texture lock enabled.
  7. You now have a 1/16 scale version of your reference geometry. Now drag (move) it to another part of the map where you wish build your 3D skybox. It doesn’t matter where it is as long as it’s not touching any part of the main level geometry area.
  8. Delete the sky_camera entity from the normal world map area you started from. Important: only the sky_camera entity in the 3D skybox should remain in the map. In L4D2 (and possibly other Source games), forgetting this step (having multiple sky_cameras in your map), will result in every Navigation area being blocked.
  9. Build your 3D skybox geometry around the reference geometry, using it as a guide. You can build skybox geometry that meets the reference geometry seamlessly. You can use brush and displacement geometry. Models can also be placed, but since the 3D skybox is at 1/16 scale, any models must also be at 1/16 scale. The model hl2\models\props_skybox\coast01.mdl is a sample model in 1/16 scale. Try positioning the 3D view camera near the height of the player. This will give you a good idea of how the 3D skybox will look when it’s rendered in the engine.
  10. Add a hollow cube of brushes around your reference geometry and assign the tools\toolsskybox material to it. The standard 2D cubic skybox will appear on these surfaces. The 3D skybox area must be sealed with these brushes.
  11. When you’re done, delete or hide all of the reference geometry except for the sky_camera entity. You may find that it work best to add the reference geometry to its own visgroup so that it can be toggled on and off or re-placed. Just make sure you turn it off before you save and compile the level, or it will be compiled into the 3D skybox.
  12. If you have brushes inside your 3D skybox other than the reference geometry, make all of these brushes func_detail brushes.
     Note:The only exception to this is displacements. For obvious reasons, do not tie displacements to an entity.
  13. Your original map still needs the tools\toolsskybox material wherever you want to see the sky, however it will now show the 3D skybox as well as the 2D skybox (which is what it did previously).
  14. If you want a part of your map to only show the 2D skybox and not the 3D skybox geometry, use the tools\toolsskybox2d texture, which only draws the 2D skybox. There are no restrictions for this texture and it can be used together the normal skybox texture without problems. This feature is useful when you have I.E. a window and you only want to see the sky from it, like if you are in a very tall building.


If you properly sealed your 3D skybox and your map does not have a leak, you can now compile the map and check out your new 3D skybox in the engine.


Making 3D Skybox in 3ds Max

You can also create your 3D Skybox in a much simpler way than the traditional Hammer method if you build your level inside 3ds Max with Wall Worm Model Tools. Wall Worm lets you build your 3D Skybox at the scale of the map and avoids the need to shrink down the skybox.

To do this, simply “tag” the skybox geometry with the Tag functions in the Anvil tools that come with Wall Worm.

See a demonstration and download a sample scene here.


still cant get 3d skyboxes to work
<eukara> OneManClan: if you’re using custom CSQC and want the _skyroom key to work (which only controls position) you have to manually set the VF_SKYROOM_CAMERA property to the origin of the skyroom
<OneManClan> ah.. my CSQC doesnt have VF_SKYROOM_CAMERA
<OneManClan> how new is this?
<eukara> All happened around the last year
<eukara> I was trying to get skyrooms working for my game as you know, but issues came up with being unable to not render entities in the first sky pass. That’s where the r_ignoreentpvs came from
<eukara> and CSQC now being able to give a crap about PVS
<eukara> Spoike likes adding ways for people who don’t use CSQC to use some features
<OneManClan> What version FTE client can display 3d Skyboxes?
<eukara> but it does tend to confusion, clearly – because it doesn’t apply to you in this situation
<OneManClan> I tested last Sunday and noone could see my test version, but they had old FTEs
<OneManClan> ugh lemme rephrase
<OneManClan> I tested Skyrooms Sunday and no other players could see my skyroom, but they had older versions of FTE
<eukara> Well, I can’t change that people don’t upgrade
<eukara> I can only say that I wouldn’t rely on _skyroom for reasons like this. While I agree people need to update their clients regularily there’s certain things that _belong_ in CSQC
<eukara> I know why Spoike hard-codes a bunch of features – there’s some developers unwilling to use anything but SSQC
<eukara> but you have to cut your losses at some point
<OneManClan> so how do I set VF_SKYROOM_CAMERA to the origin of the skyroom?
<OneManClan> i updated csqcsysdefs.qc
<eukara> setproperty(VF_SKYROOM_CAMERA, someorigin);
<OneManClan> yea but how to i access someorigin?
<OneManClan> ah its a key or worldspawn
<eukara> that’s entirely up to you
<OneManClan> ah its a key of worldspawn
<OneManClan> worldspawn is still entity 0 yea?
<the_shpuld> that’s not going to change either 🙂
<OneManClan> ok but to be clear: Do 3d skyboxes work with Q1?
<OneManClan> or does the map need to be q3bsp?
<eukara> map format doesn’t matter.
<OneManClan> ah, cool
<OneManClan> so.. do i use findfloat to get the value of the worldspawn’s _skyroom vector?
<OneManClan> entity w = findfloat(world, entnum, 0); //?
<OneManClan> setproperty(VF_SKYROOM_CAMERA, w._skyroom); //?
<OneManClan> In ssqc youd use infokey yea?
<OneManClan> otoh infokey is strings
<OneManClan> damn im confused (again)
* You are now known as omc-brb
<omc-brb> stof(infokey(world, “_skyroom”)); // ssqc.. and then send it to CSQC?
* You are now known as OneManClan
<OneManClan> Something like this?: https://pastebin.com/WDtThZXr
<OneManClan> vector sky_room = stov(infokey(world, “_skyroom”)); // returning ‘0 0 0’
<OneManClan> (help!)
<OneManClan> surely CSQC should put _skyroom’s values into VF_SKYROOM_CAMERA by default?
<OneManClan> in any case .. this didnt make a diff either:
<OneManClan> setproperty(VF_SKYROOM_CAMERA, ‘322 -30 -22’); // the actual values
<OneManClan> (at the top of CSQC_UpdateView(), just after clearscene();)
<eukara> You still see a scrolling Quake sky, yes?
<eukara> Change the texture of the brushes that will be used to display the skyroom in the in-game world to a material that contains this:
<eukara> surfaceParm noimpact
<eukara> surfaceParm nolightmap
<eukara> surfaceParm sky
<eukara> surfaceParm nodlight
<eukara> nomipmaps
<eukara> skyParms – 512 –
<eukara> and nothing more
<eukara> (then make sure your skyroom’s got your scrolling sky in it
<OneManClan> this is what I see: https://www.youtube.com/watch?v=heDUcgxcLMo
<OneManClan> the ‘boxes in the distance’ are supposed to be right up against the box in the main map
<eukara> so it’s a perspective thing
<OneManClan> the sky displayed *is* the skymap sky
<OneManClan> (the actual map sky is a different coloir)
<OneManClan> yea theres no parralax
<eukara> parallax only happens if you take the player position and apply it to the SKYROOM_CAMERA position in scaled down form
<eukara> that scale should be provided by individual skyroom itself (hence why I use a sperate entity and don’t abuse worldspawn keys…)
<OneManClan> I dint understand what you mean by “apply it to the SKYROOM_CAMERA position in scaled down form”
<OneManClan> Do I have to manually code the ‘3d skybox effect’ in CSQC?
<eukara> skyroompos + (playerpos * scale)
<eukara> in your case you can probably just add getproperty(VF_ORIGIN) / 16 to it or something
<eukara> just to test.
<eukara> https://youtu.be/0eX9LcCYo6k is what it’d look like
<eukara> since the 3d skybox is a miniature representation, you need to scale the player position before applying the offset
<eukara> or else it’ll translate player position in world VS in skyroom 1:1
<eukara> which is…. bad
<eukara> because the camera will most likely move outside the skyroom
<OneManClan> https://pastebin.com/j55acvCk //?
<eukara> getproperty(VF_ORIGIN / 16);
<eukara> getproperty(VF_ORIGIN) / 16;
<eukara> more like
<eukara> also
<eukara> skyroompos = skyroompos + my_origin;
<eukara> what a weird line.
<eukara> that just does ‘322 -30 -22’ + ‘322 -30 -22’ + playerpos
<OneManClan> sry man
<eukara> err, nvm tired
<eukara> just remove it and add the playerpos to the setproperty call.
<eukara> I thought it said += for a second, but my vision is all fuzzed.
<OneManClan> vector my_origin = getproperty(VF_ORIGIN) / 16; // “implicit cast from float to vector”
<eukara> setproperty(VF_SKYROOM_CAMERA, [322, -30, -22] + (getproperty(VF_ORIGIN) / 16));
<eukara> perfectly valid
<OneManClan> https://www.flickr.com/photos/60268498@N06/50613113731/in/dateposted-public/
<eukara> compiler fun
<OneManClan> sky is all HoM now
<eukara> https://sourceforge.net/p/nuclide/code/ci/master/tree/src/client/entry.c#l296
<OneManClan> (it always feels like theres a mising manual everyone but me has read!)
<OneManClan> So that line (wiuth the warnings) *should* work?
<eukara> just adopt my code, you’ll be fine
<eukara> I’ll investigate the rest
<OneManClan> the engine code?
<OneManClan> oh u mean the: setproperty(VF_SKYROOM_CAMERA, [322, -30, -22] + (getproperty(VF_ORIGIN) / 16));
<eukara> what I posted is QC
<OneManClan> the sourcefirge link?
<eukara> Yes
<OneManClan> entry.c ?
<OneManClan> ‘->’ is a qc operator now?
<the_shpuld> yes, when working with pointers
<the_shpuld> same as in C
<OneManClan> wow
<OneManClan> since when?
<the_shpuld> ever since pointer support I guess
<eukara> ^
<the_shpuld> when writing “regular” quakec you don’t really need it anywhere
<OneManClan> heres my latest *.map and *.bsp: http://www.mediafire.com/folder/l1ld4wf8quo8i/maps
<OneManClan> in case theres something i f**ked up in the map
<OneManClan> spoike suggested i add a light
<OneManClan> the box labelled ‘A’, shoud be right up against the biox labeled ‘B’
<OneManClan> latest vid: https://www.youtube.com/watch?v=-CHIY64PLmM
<OneManClan> though thats w no CSQC


Some definitions by Spoike

  • (scrolling) sky – a miptex that gets split into two and then projected spherically according to the pixel’s position relative to the camera.
    skybox – a cubemap with texture coords projected relative to the camera.
    skyroom – a separate part of the map with a second camera that is drawn instead of the normal sky (may have its own skybox though).
  1. the skyroom camera may rotate separately, and its position may be offset relative to the offset of the normal camera (relative to 0 0 0).
  2. scale is relative, thus if the skyroom is 1/64th of normal size, the camera scaled by 1/64th means the skycam will move through the skyroom at the same sort of speed as the player would, though you can disable all panning if eg its supposed to be a space scene with a load of spinning rocks or whatever
  3. you can also set up the skycam to spin constantly.

Leave a Reply




You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>