Doom 3, lighting/shadows, and BSPs

To get back to the original topic they will have a bsp as you can read on http://www.gamespy.com/e32002/pc/id/
GameSpy: It sounds like the BSP process has radically changed for DOOM III, possibly even being gone altogether …

Robert Duffy: It’s not gone. The BSP process used to be three things - it used to be a BSP, then it would be visibility and lighting calculations. Now we just do a BSP, and the lighting and visibility are all calculated in real-time.

[This message has been edited by Pentagram (edited 05-26-2002).]

so i wander what they need it for, i guess for the beam trees, i think there is a connection.

i want to raise an issue not discussed here so far, transperency. i saw a floor with a hole in it, and fire coming out of the hole.
i wander how they shadow such objects like the floor. i think it is dine regularly, and is being avoided as much as possible.

one more thing, in the legacy movie there is a scence of monster going in a hallway with big columns on each side, and a light rotating in a circle from above. the column’s sahdows are jagged, like they were generated using shadow maps, and we know they are not. so what is it?

if you reject pixels with the alpha func then they never get written to the z-buffer so things like holes in walls receive shadows correctly. They don’t transmit them though, unless mess about projecting a rendering of the hole in the wall from the light’s frustum, and switching off stencil bits which fail the alpha test.

if you’re using cubemaps you can clamp your lights, for example to match the shape of a lamp shade, doesn’t that mean you need a lightmap for the inside of the lamp shade?

Carmack did say binary formats have gone, so the BSP must be calculated as the level is loaded?

I’d like to know how general the shader scripts are, do they just have TGAs for bump, ambient, diffuse, and specular textures? Or is it more complex, like a Quake3 shader script for each term, or maybe even something like the Render Tree in Softimage XSI.

Does anyone have any ideas how the can fly without offline-calculated PVS?

Bsp’s are certainly needed for the Beam-Tree since you must insert polygons front to back in them (so the "nearer"polygons can hide the further ones) and that’s very easy with a bsp.
And mabye for collision testing.

Charles

Hey there!

Starting at post 20 by dorbie, he has a very valid, on topic, and IMO intresting rant about the use of different res. meshes for selfshadowing.

He also goes on a bit about all the soft-shadows, and possible ways they coul’d be created.

Now here comes the scary part:
People turn against dorbie as if they were offended by his thoughts, saying “there are no softshadows”.

The strange thing is that so many (3? :slight_smile: people go at it, without even looking at the facts.
I mean, come on, you all saw the soft shadows in the old Macworld demo even.

I was shocked, cuz of some of you that were in “denial” :), were people I have read lots of intelligent post from before.

Q:s

  1. Whats wrong with discussing the use of different res. models for shadowing?
  2. If you haven’t seen any vids from D3, how can you be confident that there are no soft-shadows (No offence, but you cant possibly have seen any videos when claiming that)?

Thanks
/Fredrik Olsson

edit: removed smilies

[This message has been edited by FXO (edited 05-27-2002).]

Nobody is in denial. You can call whatever you want a soft shadow, but that doesnt make it a soft shadow. You can call whatever you want a lightmap, but that doesnt make it a lightmap. Saying that you see these things in the image may be fine and dandy to a layperson, but in here we need to be more technical and more precise in how we describe these things.

Oooooooooooooooooooooo!

jwatte is right:

“I think this is incorrect. I don’t think there’s any modulation nor replacement. I think the scene starts out as all shadowed, and all the light that’s painted is ADDED, not modulated. I think the shadow volumes serve as gates for whether the light gets added or not, but there’s no modulation going on.”

I’m really shure DOOMIII uses rendering loop like this ( a) assume newest Radeon b) don’t blame me for stencil modes/operations - it’s for example only).

Clear All Black.

[Draw scene using ambient light(s)] - optional if there is no ambient light(s) in scene

for(EACH light in scene) {
set stencil to ‘0’
disable drawing to video buffer
enable drawing to stencil buffer

for(EACH shadow-caster object in the light’s scope) {
generate/draw object’s stencil shadow volume, marking stencil pixels where light is with ‘1’.
}

// now we have stencil pixels in light marked with ‘1’, pixels in shadow - ‘0’
disable drawing to stencil buffer
enable drawing to video buffer (“only where stencil is ‘1’”)
set blending mode to “additive”
enable light’s “projective light texture” if any (it used in per-pixel light computations)

for(EACH geom object in light’s scope ) {
draw the object using diffuse texture, specular texture, bump texture, projective light texture // single pass on newest Radeon?
}

} // for: lights

At first look, there is too many passes, but don’t forget: light sources usually are limited in range, so only part of scene’s geometry required to be redrawn in each pass.

Probably I left something important out (or, I left nothing out, but You don’t think so ). Tell me about it, I will answer here.

Any comments?

edit: typos etc.

[This message has been edited by peterpan (edited 05-27-2002).]

This kind-of solves the ‘is there any ambient’ problem; if you have to render the scene before any kind of shadow-dependent passes to get the depth buffer for stencil shadows, then why not do ambient lighting then?

Carmack said expect 3x fill rate hit per realtime light. So rather than adding more lights for a scene a la Quake3 lighting, you get your ambient lighting right first, then set the mood with other lights.

> you all saw the soft shadows in the old
> Macworld demo even

Nope. All I saw was projected light textures (a la “spot lights”). I could see no diffuse shadows, and nothing that has been made public about the engine indicates that there are soft shadows, so I think anyone claiming the game does soft shadows is on very shaky ground.

> [Draw scene using ambient light(s)] -
> optional if there is no ambient light(s)
> in scene

This is not optional. You need to draw this so that you get the Z buffer right, for the stencil test to actually have anything to work with. As you need to clear the color buffer, too, you might as well clear to ambient instead of clearing to black.

The problem with doing diffuse color & specular per light is that if you need to multi-pass, your previous data will most probably get in the way, because the successive passes don’t know how much is contribution from the current light, and how much is contribution from previous passes. Thus, I’d think you’d want to paint bump mapped light first, assuming a diffuse white on everything, and only modulate color at the end. The problem THEN becomes one of how to apply specular without re-doing the stencil volumes.

Perhaps with destination alpha?

Originally posted by jwatte:
[b]> you all saw the soft shadows in the old
> Macworld demo even

Nope. All I saw was projected light textures (a la “spot lights”). I could see no diffuse shadows, and nothing that has been made public about the engine indicates that there are soft shadows, so I think anyone claiming the game does soft shadows is on very shaky ground.
[/b]

It’s dictionary problem again . People say “you all saw the soft shadows”, but they saw “projected light textures”. It’s [projected] texture which is used in per-pixel lighting calculation. Of course, it’s not a “soft shadow”.

[b]
> [Draw scene using ambient light(s)] -
> optional if there is no ambient light(s)
> in scene

This is not optional. You need to draw this so that you get the Z buffer right, for the stencil test to actually have anything to work with. As you need to clear the color buffer, too, you might as well clear to ambient instead of clearing to black.
[/b]

Yes, I’m wrong (about word “optional”), and you’re right. It’s “must be” rendering pass.


The problem with doing diffuse color & specular per light is that if you need to multi-pass, your previous data will most probably get in the way, because the successive passes don’t know how much is contribution from the current light, and how much is contribution from previous passes. Thus, I’d think you’d want to paint bump mapped light first, assuming a diffuse white on everything, and only modulate color at the end. The problem THEN becomes one of how to apply specular without re-doing the stencil volumes.

Sorry, English is hard to me (i’m Russian), but I think something is wrong with your conclusions.

Hm… “…if you need to multi-pass, your previous data will most probably get in the way…”? No way.

Each pass ADDS values to framebuffer. No any ‘MODULATE’. Never. (By saying ‘modulation’ you mean fragment – colorbufer operation?). I don’t need to know what is stored in color buffer, bacause I use ADD operation only.

Below is a colorbuffer pixel’s changings history (I assume ambient is 0, for clarity):

  1. cbuffer = Zero (black)
  2. cbuffer += Light0Based.DiffuseLightValue * TexturePixelFromObject0
  3. cbuffer += Light0Based.SpecularLightValue
  4. cbuffer += Light0Based.DiffuseLightValue * TexturePixelFromObject1
  5. cbuffer += Light0Based.SpecularLightValue
  6. cbuffer += Light0Based.DiffuseLightValue * TexturePixelFromObject2
  7. cbuffer += Light5Based.DiffuseLightValue * TexturePixelFromObject0
  8. cbuffer += Light5Based.SpecularLightValue
  9. cbuffer += Light5Based.DiffuseLightValue * TexturePixelFromObject1
  10. cbuffer += Light5Based.SpecularLightValue

Note1: LightXBased.DiffuseLightValue is per-pixel diffuse value computed by using projected light texture, bump map, surface’s normal.

Note2: LightXBased.SpecularLightValue is per-pixel specular value computed by using projected light texture, bump map, surface’s normal.

Note3: If you have troubles with SINGLE pass computing LightXBased.DiffuseLightValue (or specular), then you can split it to two or more passes: no problem, because we use ‘+=’ operation only.

Note4: You can use ANY order of computings of diffuse, specular, objects while you use SAME light. No lost of stencil buffer, so, do drawings in any order. For example:

for(objects) {
draw diffuse
draw specular
}

or

for(objects) {
draw diffusePartOfComplexComputings
draw specular
draw diffuseOtherPartOfComplexComputings
}

or

for(objects) {
draw diffuse
}
for(objects) {
draw specular
}

or

for(objects) {
draw specular
}
for(objects) {
draw diffuse
}

As you wish.

Perhaps with destination alpha?

No.
Don’t invent complicated methods. Use simplest methods. Cramack always does so.

edit: added Note3, Note4

[This message has been edited by peterpan (edited 05-27-2002).]

Originally posted by jwatte:
EDIT: Of course, there has to be at least one modulation pass, which happens when you have decided on the lighting for a specific frame buffer pixel, and then go to apply the “base color” map/shader to the pixel. However, I don’t believe this form of modulation should be mentioned while discussing the lighting solution, as it’s not part of the lighting calculation, but instead of tinting happening after “full albedo” lighting and shadow is already calculated.

jwatte, to avoid problem like this:

“All lights are mixed (with specular and diffuse) in color buffer, how can I extract lighting components to compute correctly lighted pixel? (specular needs ADD, diffuse needs MUL operation with texture pixel)”

we need to use base texture EACH TIME when we compute diffuse/specular things.

It differs from QuakeIII (IMHO) “draw all lights, then multiply my texture by color(light) which is already in colorbuffer”.
Doom3 is:
“[Many times] add lighted pixels (lighted pixels, not light) to the color buffer”.

If you mean same thing, sorry.

Edit: some info

[This message has been edited by peterpan (edited 05-27-2002).]

Well, heres my two pence: Carmack hasn’t got a clue how to implement all this. He just threw the ball up in the air and you guys have run with it. He’ll be reading this later

Originally posted by peterpan:
Hm… “…if you need to multi-pass, your previous data will most probably get in the way…”? No way.

I think you misinterpretted what jwatte was saying. He was saying that if you need to do multiple passes PER LIGHT, then previous data will get in the way. This is correct (to a certain degree). Say each light you draw is lit with diffuse light using both a bump map and distance attenuation, and you are doing this on a dual textured card. For each light you need

A) bump map (normal map) texture
B) light vector normalization cubemap
C) distance attenuation texture
D) diffuse color map

You need to calculate (A dot B)CD, and since the card is dual texture, you have to do this using multiple passes. So, the first pass you calculate (A dot B) and store it to the frame buffer. Second pass you calculate CD and multiply it into the framebuffer. Now when the second light comes along, you have a problem on the second pass (when you need to multiply (A dot B)(C*D) for the second light). The data from the first light gets in your way here.

The typical way to solve this is to (as jwatte speculated) store the temporary value to the alpha buffer instead of the color buffer. You can also do other things such as rendering the partial results to a p-buffer, but alpha is usually the most optimal.

He appears to just be using projective textures for all light sources (I think he even says this in an interview).

The projective texture could be anything the artist wants it to be. They could even paint in fake shadows in the texture to be projected (which they appear to be doing), or they could just make it a normal spot light attenuation map. Heck, they could project a smiley face if they wanted. Then when finally projected, the stencil pass will stop the texture from being projected onto geometry that is occluded from the light source.

I’d guess it all revolves around projective textures.

John

see here http://www.doom-3.net/E3/36.jpg
this shows a shadow on the dudes left arm, this is what we’re discussing right?
now ppl have mentioned this as a ‘projected light texture’ whereas i say its a ‘projected shadow texture’. ideally u would want to use ‘projected light textures’ (as with lighting generally u begin with black + then add the light sources) but from my experience this just aint practical. i believe u begin with a white screen + the shadows (stencil+projected) are modulated in. im ignoring the problems with ‘projected shadow textures’ but looking at the screenshots all the geometry (pipes grill fan etc) that appears to cast these softshadows wont suffer from those.
on a personal note im still investing my time in a ‘grand unified lighting system very similar to radiosity’ where each surface is treated equally (though im still a ways off having this in a doom3 level hell ild be happy having it in a quake1 level at 30fps)

No, its generally more practical to start with black and add the light. Trying to remove light is just a pain in the neck, and you can never get it to work properly without tons of effort. Here are a few reasons:

1)Shadowing everything: If you start with white and then remove light, this means you have to mask off every area of the scene that is not hit by light. To be sure you catch everything, you have to “path trace” the light everywhere visible and make sure to draw the shadow wherever the light can’t reach. If the visible portion of your scene consists of a hallway divided into 10 segments, and the light can only reach one of those segments, then you need to trace the shadow throught the other 9 segments and draw all the shadows. Not a pretty thing to do. With additive lighting, you only need to be concerned with the areas that the light can reach, which is a much smaller subset.

2)Light saturation. What happens when you have 2 lights together that saturate to white. For instance lets assume you have 2 white lights each with an intensity 0.6(to make things simple for this example, lets assume no attenuation of any kind). If these 2 lights hit the same area, you have a potential total luminocity of 1.2 (which saturates to 1.0). Now, if we start with a luminocity of 1.0 and subtract 0.6 for each light that doesnt hit a surface, we end up with a problem, because we get:
1.0 for anyplace illuminated by both lights (this is fine)
0.4 for anywhere that only gets hit by 1 light (this should be 0.6)
-0.2 (saturates to 0.0) for any surface that gets hit by no lights (this is correct)

To get things correct, we either need to start with an intensity of 1.2 (not possible in the frame buffer) or we need keep track of where lights overlap and special case it (gets to be a real mess).

Originally posted by John Pollard:
[b]He appears to just be using projective textures for all light sources (I think he even says this in an interview).

The projective texture could be anything the artist wants it to be. They could even paint in fake shadows in the texture to be projected (which they appear to be doing), or they could just make it a normal spot light attenuation map. Heck, they could project a smiley face if they wanted. Then when finally projected, the stencil pass will stop the texture from being projected onto geometry that is occluded from the light source.

I’d guess it all revolves around projective textures.

John[/b]

gotta laugh if in fact it sounds as if he is using the techinque i ditched last year (though his is prolly better optimized + solid), the reason i ditched it was because it required lots + lots of passes over the geometry (killed my vanta) and it wasnt ‘a unified approach + required a lot of hacking’ i might have to dig out the old files on my harddisk + see how they perform on my gf2mx

u dont believe me when i say i was doing this (uotes from june2001)
>>but now single pass meshes are rare. most of the stuff im drawing now uses 3-4
passes (perhaps ill even go to double figures passes in the future) which
basically means its worthless to sort meshes by state<< http://groups.yahoo.com/group/opengl-gamedev-l/message/18594

from the followup post
>> perhaps ill take the easy way out and just use method B (im using A at the moment) + ppl without hardware t+l can
choose to have dynamic shadows (+ the single digit
fps) or not<<

i guess theres something in that saying 'great minds think alike;

thinking about it more i realise im talking out my ass, sorry folks, i failed to notice that gotterdammerung is predominately outdoors + doom3 is indoors doh!, big difference! with outdoors shadowed pixels are usually far a lesser area on the screen than non shadowed things this is the opposite to indoor stuff where as LordKronos saiz are corridoors and such where light is confined to a certain area a LOT more of the screen is in shadow. the reason this is important is with this lighting/shadowing technique u end up doing heaps of passes over certain geometry which u want to keep to a minimum (perhaps with todays cards this is not so important) but at the time it was. btw in practice theres no difference between the 2 methods (adding light or removing light except the stencil part) adding light though is by far the better method (mainly cause thats how the world works )

btw i remember another reason why i gave up on this technique ‘i believe there was a bug in the nvidia drivers on my vanta using multitexture which basically meant of being able to use both texture units i could only use 1 (which is very important to this techniue ie u want to compact those passes into as few as possible)’

LordKronos,

You eloquently described the problem I was talking about; specifically when you only have 2 textures. Thanks for bringing clarity. I believe a Radeon with 3 texture units can be coaxed into doing (diffuse*color+specular)*min((bump.light),0) in a single pass; there’s a demo of it on the ATI developer site. That would make PeterPan’s method work on all cards with 3 or more texture units. But still not those ubiquitous GeForce 2s :frowning:

zed,

When you are outdoors, shadow volumes are typically small, assuming the sun is reasonably high in the sky. That should lead to fewer pixels being in shadow. That, in turn, should cause LESS fill rate hit when drawing the stencil. Also, when you’re outdoors, there are probably fewer lights that actually affect a scene (as you can cull out any far/soft lights which sunlight will drench out).

There may be cases where outdoors doesn’t obey these “well behaved” assumptions – if you’ve seen them, can you go into a little more detail about what they are?

Last, I’ve been going back and forth between stencil shadows vs. shadow buffers for my own use. Stencil shadows pays potentially a lot of fill rate per element per light. Shadow buffers pay only a fixed amount per element per light. On the other hand, shadow buffers may need more on-card memory to look OK, unless we get some new extensions that average the tested result and lerp (which is different from lerping the in-buffer values).

Here’s where everybody flame me because I mentioned shadow buffers, where Doom III is clearly stated to use shadow volumes :slight_smile: