Jump to content
The Dark Mod Forums

Light frustums different in DR and TDM


Recommended Posts

13 hours ago, stgatilov said:

Yeah, it is natural to assume (target, up, right) is orthogonal basis, like axes of coordinate system.
Somehow, it reminds me the story of rotation hack: everyone assumed orthogonality but nobody restricted it.

I wonder what would happen if we orthogonalize (target, up, right) spawnargs with Gram-Schmidt in game engine when parsing light spawnargs. How much stuff would stop working?

OTOH if we want to support "asymmetric" (off center) projections then would require exactly that - non-orthogonal basis?

Like glm::frustum (btw maybe just use that?)

 

Link to comment
Share on other sites

10 minutes ago, duzenko said:

OTOH if we want to support "asymmetric" (off center) projections then would require exactly that - non-orthogonal basis?

Do you think skewed/asymmetric frustums are important?
I think you can always replace it with orthogonal/symmetric frustum without much problem...

Link to comment
Share on other sites

4 hours ago, stgatilov said:

Do you think skewed/asymmetric frustums are important?
I think you can always replace it with orthogonal/symmetric frustum without much problem...

That's what I've been asking for a while but no one seems to care\know

It seems asymmetric frustums have been the "norm" in D3/DR/TDM - of course projected lights in general were taken for granted and people just used them as is without any second thoughts

If you create a projected light in DR and start dragging the anchor points around you're bound to lose symmetry soon enough

Technically it would be easier to handle if left=right and up=down but there's an issue of compatibility. Expect some angry mappers when they find out their asymmetric lights have stopped working. It can also be used for optimization if the symmetric frustum spans too much.

Link to comment
Share on other sites

4 hours ago, stgatilov said:

Where is it located, by the way?

tr_lightRun.cpp in TDM

R_DeriveLightData/R_ComputeSpotLightProjectionMatrix/R_SetLightProject

Light.cpp in DR

Light::updateProjection

Quote

But if we find that D3 math related to such light frustums makes no sense, then what?

The math in D3 was okay, I suppose. The problem is that something changed in BFG and it's not consistent any more. The end point no longer projects to the far plane. I want to understand if it was a bug in BFG, or something changed in the logic behind the anchor points. And if it did change, then it should have been reflected in whatever editor they used for BFG maps?

Link to comment
Share on other sites

5 hours ago, duzenko said:

tr_lightRun.cpp in TDM

R_DeriveLightData/R_ComputeSpotLightProjectionMatrix/R_SetLightProject

Light.cpp in DR

Light::updateProjection

The math in D3 was okay, I suppose. The problem is that something changed in BFG and it's not consistent any more. The end point no longer projects to the far plane. I want to understand if it was a bug in BFG, or something changed in the logic behind the anchor points. And if it did change, then it should have been reflected in whatever editor they used for BFG maps?

I wish I was so good at math as you guys, so I could help but alas. I can just say they used idStudio (their new editor) to do BFG maps and If you have Rage 1, it comes with idStudio, you can see if the lights still work the same there, even thou is a new editor still works mostly like Doom 3 Radiant so should be familiar.

Here someone did some tutorials for it.  https://www.moddb.com/mods/ehrlia-summerwheel/tutorials/rage-toolkit-tutorials-and-updates 

Link to comment
Share on other sites

15 minutes ago, HMart said:

I wish I was so good at math as you guys, so I could help but alas. I can just say they used idStudio (their new editor) to do BFG maps and If you have Rage 1, it comes with idStudio, you can see if the lights still work the same there, even thou is a new editor still works mostly like Doom 3 Radiant so should be familiar.

Here someone did some tutorials for it.  https://www.moddb.com/mods/ehrlia-summerwheel/tutorials/rage-toolkit-tutorials-and-updates 

Did it ever go opensource like radiant?

Link to comment
Share on other sites

4 hours ago, HMart said:

I can just say they used idStudio (their new editor) to do BFG maps and If you have Rage 1, it comes with idStudio

Wow!

I think idStudio from Rage deserves its own discussion. I was always wondering whether e.g they still use brushes today... But if we start discussing it here, the thread will be hopelessly stolen 😥

Link to comment
Share on other sites

1 hour ago, duzenko said:

Once again, we need to decide if we want to switch back to the D3 matrix in TDM or switch to BFG matrix in DR

I don't think I'm qualified to make that choice despite all the time I spent on this

I think the answer to this comes from answering these questions:

1) Is there more work to make shadow rendering efficient that can benefit from BFG code migration?

2) If so, will retaining the BFG matrix make porting BFG code easier?

3) Likewise, will the BFG matrix design make it easier to port GPU skinning code?

4) Likewise, is any portal \ light culling done in BFG more efficient and would it be easier to port?

If the BFG matrix does not assist with any code porting efforts, does not assist with any rendering efficiency designs, and causes problems with Dark Radiant compatibility then it should be reverted.

  • Like 1

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

9 hours ago, duzenko said:

Did it ever go opensource like radiant?

I don't think so, because idTech 5 source, was never (fully) released but I'm not 100% sure.

I never worked with Rage SDK and perhaps the tools source, could be in there somewhere, but imo is very unlikely.

Link to comment
Share on other sites

NOTE: This analysis assumes W as perspective divisor, which is wrong!

Spoiler

Analyzed the matrix in the BFG code.
See all the formulas in PDF.

Some notes:

  1. I explicitly extracted lengths from all three vectors: R, U, T are unit vectors from spawnargs, and W, H, D (aka width, height, and depth) are the lengths of spawnargs.
  2. I decomposed the matrix into three transforms: rotation (similar to modelview), projection, and some additional shift to put target point at center in output. It is easier to understand this way.
  3. While projection matrix in OpenGL (e.g. of gluPerspective) produces all coords in [-1..1] range, this matrix produces all coordinates in [0..1] range after division. The matrix also inverts Y coordinate.
  4. Standard convention is used: w is divisor, range of z after division is normalized.
  5. "start"/"end" spawnargs define near and far clipping plane of frustum, similar to OpenGL. However, only their component along "target" vector matters, the two other components don't affect anything.
  6. Let n = dot(target, start), f = dot(target, end). The near clipping plane is at distance n, and far clipping plane is at distance (f + n). Quite surprisingly, "end" vector does not define far distance, it defines (far - near) difference instead.
  7. Frustum half-angles are: length(right) / length(target) and length(up) / length(target). Multiplying all three vectors by same coefficient does not change anything, only their length ratios matter.
  8. If R/U/T triple is not orthogonal, then the matrix which I called "rotation" is no longer orthogonal. Strictly speaking, it maps a parallelepiped with face normals R, U, T respectively into axis-aligned box. The vectors are not axes of the local coordinate system (I guess they are called "cobasis"), they are not normals of frustum planes.

Judging from point 8, I don't think non-orthogonal R/U/T were ever intended.
However, if there is no special tools, drawing/specifying three exactly orthogonal vectors is very hard. If mapper sets almost orthogonal vectors, then the transformation will work almost as if they were orthogonal...

I'd say the spawnargs should be set as follows:

  1. Set frustum direction into "target" vector, choose length arbitrarily.
  2. Specify X/Y coordinates on frustum "screen" by choosing orthogonal "right" and "up" vectors.
  3. Set lengths of "right" and "up" in such way that (target +/- up +/- right) vectors look through frustum corners.
  4. Choose "start" and "end" so that "start" lies on near frustum plane, and "start" + "end" lies on far frustum plane.

DeriveLightData_Spot_BFG.pdf

 

  • Thanks 2
Link to comment
Share on other sites

1 hour ago, stgatilov said:

Analyzed the matrix in the current code (which I guess came from BFG).
See all the formulas in PDF.

Some notes:

  1. I explicitly extracted lengths from all three vectors: R, U, T are unit vectors from spawnargs, and W, H, D (aka width, height, and depth) are the lengths of spawnargs.
  2. I decomposed the matrix into three transforms: rotation (similar to modelview), projection, and some additional shift to put target point at center in output. It is easier to understand this way.
  3. While projection matrix in OpenGL (e.g. of gluPerspective) produces all coords in [-1..1] range, this matrix produces all coordinates in [0..1] range after division. The matrix also inverts Y coordinate.
  4. Standard convention is used: w is divisor, range of z after division is normalized.
  5. "start"/"end" spawnargs define near and far clipping plane of frustum, similar to OpenGL. However, only their component along "target" vector matters, the two other components don't affect anything.
  6. Let n = dot(target, start), f = dot(target, end). The near clipping plane is at distance n, and far clipping plane is at distance (f + n). Quite surprisingly, "end" vector does not define far distance, it defines (far - near) difference instead.
  7. Frustum half-angles are: length(right) / length(target) and length(up) / length(target). Multiplying all three vectors by same coefficient does not change anything, only their length ratios matter.
  8. If R/U/T triple is not orthogonal, then the matrix which I called "rotation" is no longer orthogonal. Strictly speaking, it maps a parallelepiped with face normals R, U, T respectively into axis-aligned box. The vectors are not axes of the local coordinate system (I guess they are called "cobasis"), they are not normals of frustum planes.

Judging from point 8, I don't think non-orthogonal R/U/T were ever intended.
However, if there is no special tools, drawing/specifying three exactly orthogonal vectors is very hard. If mapper sets almost orthogonal vectors, then the transformation will work almost as if they were orthogonal...

I'd say the spawnargs should be set as follows:

  1. Set frustum direction into "target" vector, choose length arbitrarily.
  2. Specify X/Y coordinates on frustum "screen" by choosing orthogonal "right" and "up" vectors.
  3. Set lengths of "right" and "up" in such way that (target +/- up +/- right) vectors look through frustum corners.
  4. Choose "start" and "end" so that "start" lies on near frustum plane, and "start" + "end" lies on far frustum plane.

 

DeriveLightData_Spot_BFG.pdf 320.6 kB · 3 downloads

Thanks

I don't think we should not try to modify either of the two projection matrices, just pick one of them and use in both TDM and DR.

Do you have any idea what they tried to achieve with this change and why?

Link to comment
Share on other sites

18 hours ago, nbohr1more said:

I think the answer to this comes from answering these questions:

1) Is there more work to make shadow rendering efficient that can benefit from BFG code migration?

2) If so, will retaining the BFG matrix make porting BFG code easier?

3) Likewise, will the BFG matrix design make it easier to port GPU skinning code?

4) Likewise, is any portal \ light culling done in BFG more efficient and would it be easier to port?

If the BFG matrix does not assist with any code porting efforts, does not assist with any rendering efficiency designs, and causes problems with Dark Radiant compatibility then it should be reverted.

Well, I kinda like some of the functionality the render matrix offers, like easy transformation of Vec3 to Vec4

Link to comment
Share on other sites

37 minutes ago, duzenko said:

I don't think we should not try to modify either of the two projection matrices, just pick one of them and use in both TDM and DR.

I need to do the same analysis for the old matrix, then see what is different between the old and the current one.

  • Like 1
Link to comment
Share on other sites

Well here's a surprising result. I did a test of Z falloff in DR and in game, by duplicating a projected light (with the default shader) and shifting each copy vertically. The DR renderer does indeed not match the game, but not quite in the way I expected: the game appears to have no falloff whatsoever!

projected.png.ebc0cbdc93e8e57300790937373657b5.png

On the plus side, this would be really easy to fix in DR (just ignore the Z component entirely). But surely this behaviour is not correct? Are projected lights really expected to have full brightness all the way along the target vector, then cut to black immediately? I wonder if this was always the behaviour with Doom 3 or if something has changed in our/BFG's code.

If this is the correct behaviour, I guess in maths terms this means that the Z coordinate must always end up as 0.5, since this is the brightest part of most falloff textures (including the default light shader).

Link to comment
Share on other sites

10 minutes ago, OrbWeaver said:

Well here's a surprising result. I did a test of Z falloff in DR and in game, by duplicating a projected light (with the default shader) and shifting each copy vertically. The DR renderer does indeed not match the game, but not quite in the way I expected: the game appears to have no falloff whatsoever!

projected.png.ebc0cbdc93e8e57300790937373657b5.png

On the plus side, this would be really easy to fix in DR (just ignore the Z component entirely). But surely this behaviour is not correct? Are projected lights really expected to have full brightness all the way along the target vector, then cut to black immediately? I wonder if this was always the behaviour with Doom 3 or if something has changed in our/BFG's code.

Ouch. I think we broke something:

https://bugs.thedarkmod.com/view.php?id=5529

  • Thanks 1

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

2 hours ago, duzenko said:

Before you get too excited, think about the fact that people don't use projected lights like that

While I concede that very few if any mappers use falloff images in projected lights...

...and also will offer that the idea of a falloff image itself ( instead of mathematical falloff ) is rather silly...

If anyone from a Doom 3 mapping background is currently toiling away on an old TDM version or Doom 3 to create a TDM mission then suddenly find that this feature no longer exists ( and they will need to relight their mission... ) there will be considerable frustration.

If we at least had a falloff <value> keyword then it might be easier to convert the light materials.

Also, we may have accidentally broken a few maps where the falloff image was used to grant the player a little more shadow (etc).

@stgatilov @cabalistic ?

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

Ok, here is the analysis of the old R_SetLightProject code before @anonreclaimer 's commit broke it in rev 6684.

Some notes:

  1. The inputs are the same as in the previous analysis: R, U, T are unit vectors from spawnargs, and W, H, D (aka width, height, and depth) are the lengths of spawnargs.
  2. It looks like "z" is the perspective divisor here, but it is applied only to "x" and "y". The falloff coordinate "w" should not undergo perspective division.
  3. You can see decomposition of matrix into three transforms, which produce homogeneous coordinates for "x" and "y" in range [0..1] both. Computation of the falloff coordinate "w" is totally independent of this transformation.
  4. Falloff parameter at a point is determined by its projection to "start"-"end" line segment: it is 0 at start, 1 at end, 0.5 in the middle, etc. In fact, falloff parameter changes linearly from 0 to 1 while going from S to E. Note that it does not depend on the frustum at all: you can e.g. have frustum direction and falloff direction different.
  5. Frustum half-angles are same as in BFG case: length(right) / length(target) and length(up) / length(target).
  6. If R/U/T triple is not orthogonal, then things go equally uncertain as in BFG case. Except that here T is made orthogonal to R/U plane, and becomes N. At the same time, size D is adjusted too: we take length of "target"'s projection along N instead of full length of "target". This perhaps gives some sense to the whole stuff when R and U are orthogonal but T is not.

According to p.6, this code supports T not being orthogonal to R/U plane in some sense. In fact, only the component of "target" orthogonal to R/U plane matters, the component along R/U plane is dropped away. Note that you cannot create a non-orthogonal light frustum, so this "support" does not offer any additional flexibility.

The case of non-orthogonal R and U still looks like unsupported/unintended.

Here is how this light can be set up:

  1. Specify X/Y coordinates on frustum "screen" by choosing orthogonal "right" and "up" vectors.
  2. Specify direction of light frustum by setting "target" vector. Only the orientation (which side of the plane "target" looks into) matters. If you set non-orthogonal "target", then it is automatically replaced by its projection onto X/Y plane normal in the engine.
  3. Set lengths of "right" and "up" in such way that (target +/- up +/- right) vectors look through frustum corners. Here "target" is the orthogonal vector already "fixed" by the engine if you set it non-orthogonal.
  4. Choose "start" and "end" points completely independent of all the previous parameters. Falloff parameter ranges from 0.0 to 1.0 as you move point from "start" to "end". Gradient of "falloff" parameter goes along "end" - "start" everywhere.

 

DeriveLightData_Spot_D3.pdf

  • Thanks 1
Link to comment
Share on other sites

Looking at tdm_interaction.*.glsl, I see:

// (VS) light projection texgen
var_TexLight = ( attr_Position * u_lightProjectionFalloff ).xywz;

// (FS: lightColor)
vec3 lightProjection = textureProj(u_lightProjectionTexture, var_TexLight.xyw).rgb;
vec3 lightFalloff = texture(u_lightFalloffTexture, vec2(var_TexLight.z, 0.5)).rgb;
lightColor = lightProjection * lightFalloff;

I guess these equations come from D3 shaders, and probably confirm my theory that W parameter is not divided by perspective divisor in D3. It would be great if someone could find the original shader from Doom 3 and check it.

However, I have some doubts now about BFG: perhaps Z is not divided by W there too.
Could someone please check it?

Link to comment
Share on other sites

14 minutes ago, stgatilov said:

Looking at tdm_interaction.*.glsl, I see:

// (VS) light projection texgen
var_TexLight = ( attr_Position * u_lightProjectionFalloff ).xywz;

// (FS: lightColor)
vec3 lightProjection = textureProj(u_lightProjectionTexture, var_TexLight.xyw).rgb;
vec3 lightFalloff = texture(u_lightFalloffTexture, vec2(var_TexLight.z, 0.5)).rgb;
lightColor = lightProjection * lightFalloff;

I guess these equations come from D3 shaders, and probably confirm my theory that W parameter is not divided by perspective divisor in D3. It would be great if someone could find the original shader from Doom 3 and check it.

However, I have some doubts now about BFG: perhaps Z is not divided by W there too.
Could someone please check it?

We still use the D3-style matrix in shaders, nothing has changed in that regard

It does not matter really which matrix style the BFG shaders use, they are equivalent, because one is built from the other

The question is about the first "original" matrix in R_DeriveLightData and which building function we want to stick with

Link to comment
Share on other sites

15 hours ago, duzenko said:

Before you get too excited, think about the fact that people don't use projected lights like that

Like what? I really have no idea what you're saying here.

13 hours ago, nbohr1more said:

...and also will offer that the idea of a falloff image itself ( instead of mathematical falloff ) is rather silly...

If we at least had a falloff <value> keyword then it might be easier to convert the light materials.

I'm not sure why you think a single numerical value is somehow better than a falloff image. A falloff image can represent any falloff pattern (linear, quadratic, full brightness, whatever), not just whatever hard-coded formula is programmed in by the developers.

I suppose there would be no harm in also offering a math-based falloff as an option for mappers, e.g where "falloff <power>" represents a power of Z: 0 for no falloff, 1 for linear, 2 for quadratic, 3 for cubic etc. But this is a separate issue from making the existing approach work correctly.

5 hours ago, duzenko said:

There's a good reason that falloff does not make sense with perspective projection
The z component is crammed to have most of its range near the front plane. You won't be able to apply texture to it in a meaningful way.

Only if you divide the Z component by W, which DarkRadiant certainly doesn't and from @stgatilov's analysis it seems the game doesn't either (or at least shouldn't).

4 hours ago, stgatilov said:
  1. Falloff parameter at a point is determined by its projection to "start"-"end" line segment: it is 0 at start, 1 at end, 0.5 in the middle, etc. In fact, falloff parameter changes linearly from 0 to 1 while going from S to E. Note that it does not depend on the frustum at all: you can e.g. have frustum direction and falloff direction different.

That does at least suggest that the DR code isn't broken with regard to Z falloff.

3 hours ago, stgatilov said:

I guess these equations come from D3 shaders, and probably confirm my theory that W parameter is not divided by perspective divisor in D3. It would be great if someone could find the original shader from Doom 3 and check it.

Although DR's code is hardly an authority on the correct way to render lights, as an additional data point we definitely do not divide the Z coordinate by W — only X and Y are divided.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recent Status Updates

    • Petike the Taffer

      I've finally managed to log in to The Dark Mod Wiki. I'm back in the saddle and before the holidays start in full, I'll be adding a few new FM articles and doing other updates. Written in Stone is already done.
      · 4 replies
    • nbohr1more

      TDM 15th Anniversary Contest is now active! Please declare your participation: https://forums.thedarkmod.com/index.php?/topic/22413-the-dark-mod-15th-anniversary-contest-entry-thread/
       
      · 0 replies
    • JackFarmer

      @TheUnbeholden
      You cannot receive PMs. Could you please be so kind and check your mailbox if it is full (or maybe you switched off the function)?
      · 1 reply
    • OrbWeaver

      I like the new frob highlight but it would nice if it was less "flickery" while moving over objects (especially barred metal doors).
      · 4 replies
    • nbohr1more

      Please vote in the 15th Anniversary Contest Theme Poll
       
      · 0 replies
×
×
  • Create New...