How to render Quake 3 volumetric fog

I’m currently working on a Quake 3 level viewer, and I am having trouble with the volumetric fog.

I know how to decode the fog-lump, but I am unsure how Quake 3 goes about rendering the fog.

I’d really appreciate any help on this subject.

I don’t know about Q3, but the most common way of rendering volumetric fog is to have voxels of fog (is that how Q3 does it?) and render bilboarded, alpha-blended triangles in the fog color… Dunno if that applies to you, but hopefully it’s helpful

you have to simulate fog density accumulation on the line of sight.

i would trace a ray from the eye to a vertex in the scene.
if this ray intersects the fog volume, see how long the ray traveled into the fog.

depending on values of your fog equation, try to have a outvalue wich varies from 0 to 1.

then, assign this value to the fog coordinate of opengl (GL_EXT_fog_coord extension, glFogCoord family funcions) and you have correctly fogged the vertex.

you also would have to look for bounding boxes - ray intersection… or things like this.


Guys, thanks for your replies. Maybe I should have been a bit more specific in my question.

  1. As far as I can tell, Q3 renders the fog as a number of extra passes “on top” of the existing geometry. That is, it’s not the GL fog coordinates that are being used.

  2. I know I have to trace rays to vertices inside the fog to determine the amount of fog between the eye and the vertex.

  3. The fog is specified as a brush, i.e. a number of polygons, in principle. It’s convex.

My idea is to do something along the lines of first rendering the backside of the fog, having traced rays to the fog volume vertices. In that way, I don’t have to shoot rays to anything behind the volume.
Then, I presume I have to determine what’s inside the volume by intersecting the fog’s bounding box with various 3d object’s boxes. And from there go on to shooting rays to each vertex.

My questions are:

Are there any more optimizations I can do?

Is this the way Q3 does?

Sorry Rune,no answer but a question:Where did you get infos on the q3 level format?
I assume that you talk about the *.bsp format.

Thanx in advance,XBTC!

So far, I’m only reading the .BSP-format, and not .AAS. I think the most complete BSP file format listing is Keoka Proudfoot’s.

You can find it at (the site seems to be down right now).

If you have more specific questions, feel free to ask … maybe I can help.

[This message has been edited by Rune (edited 05-28-2000).]

Thanx alot!
Is this site only currently down or will it be down forever?If so,it would be nice if you mail me the docs.

P.s.: Do you know if the q3 bsp-files are compatible with the one from q1 which would mean I could work with q3 files with my q1-bsp viewer I´m currently working on.I just heard this at an other url,so perhaps you know?

Thanx in advance,XBTC!

[This message has been edited by XBCT (edited 05-28-2000).]

I hope the site is just down for a short while. Otherwise, I’ll type up a doc describing what I know.

I’ve never looked into the Q1 format, but my guess is that the Q3 format is not the same as that one, but probably has a lot of similarity (i.e. lump-based etc.).

Sorry to disturb your nice algorithm rune, but one thing you have to understand is that elements behing the fog volume are still fogged!!

If the volume is a box, and you are looking at it perpendiculary, all the geometry behind the volume will have the same fog value, because of the fog equation. Put if your are looking at it from a corner of the box, then you have to calculate the fog for all the vertices.

This is still a two pass or more algorithm and probably uses glFogCoord or gouraud shaded polygon.

Also, I think I read somewhere( Carmack .plan?) that it’s engine uses portals. That should cut down a lot of geometry.

[This message has been edited by Gorg (edited 05-28-2000).]

Perhaps that thread from aftershock´s( ,a q3-bsp viewer) discussion board is interesting for you:

: Hiyasverdas,

: did anybody of you Volume Fog right as its seen in Quake3? I would like know where i can find the necessaries to implement the volume fog. I need to find parameters (color, denth etc.) and the fog-brush…

: And if someone did that already, could you place the necessary infos here?

: any help?

: thangs

There was a topic on 3DEL.

The guy there said that Carmack uesd a ‘trick’. He turned the fog on, then drawed the polygons in the fog, turned the fog back off and then drawed the polygons outside of the foggy area. Thus, no volumetric fog, only pseudo-volumetric. Sharp thing.

Like, peace, dudes !

well, it works the same. also is faster to implement and surely it will run faster, even though the speed difference could be unnoticeable.


Guys, thanks for your suggestions. I have spent some time going over the problem in more detail and doing some tests. I think I now have it figured out, and thought I would share my findings with you:

  1. The Q3A Shader Manual sets a number of restrictions on a fog volume, most importantly: it can only have one surface visible. I verified this by going over some fog-lumps. Five of the brushes 6 sides have normals set to (0,0,0).

  2. In the .BSP each face has a variable telling which fog volume it is inside (an index to the fog lump, or -1 if not inside a fog volume).

So, when the time to render comes, we first use the well-defined surface from the fog volume brush to determine whether we’re inside or outside the brush.

If we’re outside, we’ll “shoot rays” to the vertices of all the faces that are tagged as being inside the fog volume, and determine “fog coverage” at each vertex from how far into the fog volume the vertex is.

If we’re inside, we’ll do this as well, but also render the one well-defined surface from the fog volume brush. Once again, we find the fog coverage at the vertices of this surface and draw it as well. This surface will always represent the “far edge” of the fog volume within it, so there will be no fog behind it. Therefore, we simply draw it instead of having to fog all the surfaces outside the fog volume.

The actual rendering seems to be done as one or more extra passes (since you can define extra passes for a fog shader). The fog is drawn with a simple gradient texture instead of gouraud shading, to avoid affine stretching when moving around.

I think this is how it is done. At least, it seems to work rather well for my needs.

Hi Rune!
I have a little question concerning q3´s .bsp-Files.
How are the different var-types stored in the File?
I figured out,that an int is stored as four bytes,BUT(took me long ) in reversed order,which means that the last significant byte is stored first!!
=>int x=byte0 + byte1
2^8 + byte2 * 2^16 + byte3 * 2^32.
But what about the floats?
Or perhaps you know the c or c++ function carmack used to store the vars?
´Cause with with fscanf or fread I got wrong results so far.

Thanx in advance,XBTC!

Hey Rune!

Just wanted to say well done on the fog reverse engineering effort!!. I wrote a quake engine shortly after quake came out and a q2 engine after q2 - I know exactly the kind of mind bending involved in working backwords from a file format!!

Anyway for what it’s worth I read an interview a couple of months ago (with Tim Sweeney-Unreal coder) about the volumetric fog feature in the Unreal engine. He said they actually build a low res texture (per poly) to serve as a fog map, and render that as an extra pass. He also commented that that was how it was done in q3.

Do you have a web page where I could download a demo?


Hey Mr.Minion perhaps you could answer my question if you´ve coded two *.bsp -viewer already?

Thanx in advance,XBTC!


AFAIK, the .BSP format uses only four data types:

unsigned byte
integer (4-byte, little endian)
float (4-byte, little endian)
string (ASCII, not necessary 0-terminated)

I simply “mirror” the structures of the .BSP file in my code, then I load them as big chunks of raw data and cast a pointer to each lump. From that, I process the data as needed.


Thanks for your encouragement.

Yes, I believe that is how Unreal does the volumetric fog (from looking at the rendering code Sweeney made available), but I don’t think that is Quake 3’s approach.

I don’t have a demo available yet, but I might make a website later on.

I have my viewer running now.It displays the level geometry(only faces from poly-type) without textures,just colored faces.
But now I have a question again:
The Face-structure contains one int “vert”,which is as far as I know the index(into the huge vertex array) of the first vertex of the face.And one int “num_vert”,that´s how much vertices the current face has.
Currently I draw each face with
one “glBegin(GL_POLYGON)” and feed it the vertices from vert to vert+num_vert in a
Is this correct?
It looks right(on the screen),but this would mean that one has to break up the faces to triangles at runtime(if one wants to render triangles only,what q3 does) which looks like a waste of time to me.
And am I right that one can ignore the info:first_meshvert and num_meshverts if the face-type isn´t “mesh”?

Thanx in advance,XBTC!

[This message has been edited by XBCT (edited 06-04-2000).]


I talked to John Carmack last night and he confirmed that the algorithm I sketched here earlier (posted 05-29-2000 11:32 PM) is how Quake 3 does its volumetric fog.

He had the following additional comments:

  1. If the fog surface has visible passes, it is rendered both when you are inside and outside the fog volume. When you are inside, the fog surface will have the additional fog blending on top of it (which is the only visible part if no passes were specified by the fog shader).

  2. Note that you may run into some issues with border colors when in large fogged areas unless you use GL_NEAREST filtering and clamped texture repeat on the fog texture.


Yes, I believe Quake 3 draws (almost) all geometry as triangles, using glDrawElements.

I think all visible faces are collected and sorted based on shader and a number of other things.

Take a look at for some words on the subject from Carmack himself.