Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specular lighting fixes #2079

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Conversation

abaire
Copy link
Contributor

@abaire abaire commented Mar 31, 2025

@abaire
Copy link
Contributor Author

abaire commented Mar 31, 2025

@Triticum0 any chance you could spot check this against games with known lighting issues? I am hopeful that it'll improve highlights in games using the fixed function pipeline.

@re4thewin
Copy link

this pr fixes 838

@abaire
Copy link
Contributor Author

abaire commented Mar 31, 2025

this pr fixes 838

Cool, thanks for testing!

@abaire abaire marked this pull request as ready for review March 31, 2025 19:44
@Triticum0
Copy link
Collaborator

Not got at my computer for a while sorry. Will do some testing once I get back to my pc in few days

@ko81e24wy
Copy link

ko81e24wy commented Apr 1, 2025

Also fixes #784, hard to say its same as XBOX,but much better than before.

@abaire
Copy link
Contributor Author

abaire commented Apr 1, 2025

Cool, thanks for testing!

The reconstruction of the specular power factor isn't perfect and there are still some issues with ambient/emissive handling in certain cases so I expect that there will be some delta vs HW with this fix.

@mborgerson

This comment was marked as resolved.

@ko81e24wy

This comment was marked as resolved.

@abaire abaire force-pushed the feat_spec_params branch 2 times, most recently from bd6b911 to 39fef7e Compare April 2, 2025 02:11
@ko81e24wy

This comment was marked as resolved.

@mborgerson

This comment was marked as resolved.

@ko81e24wy
Copy link

I test NGB and DOA,this PR has stutter in game when master is smooth.

}

c3 -= SPECULAR_POWER_CONSTANT_COEFFICIENT;
float ret = SPECULAR_POWER_LOG_CONSTANT / log2(c3 / SPECULAR_POWER_COEFFICIENT_A);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Cross checked against this implementation. The power estimated by this function appears to have very high error for pow<1.0. Can you confirm?
  2. It would be nice to determine the actual specular power formula hardware uses based on these parameters, but we can save it for future work.
  3. It's also possible to calculate the exact input value given the observed original lookup table, but this curve fit approach is probably fine if accuracy is within a few percent given (2) anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, given that it's disjoint in the LUT func I'm not surprised. It may not be possible to do a trivial curve fit, will look into it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up segmenting the curve and using a couple functions to keep percent error < 3. Things get wacky around power 2500 as params start moving in the opposite direction, but I would assume in practice power is typically < 1000 (and the same wackiness can be observed on HW).

The end results are still not quite correct; it looks like the localeye variants are quite close but the infinite ones are a bit overbright. I'm inclined to look into it in a followup since this PR adds a bunch of other functionality.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up fixing the overbrightness from the point light -it seems that localeye off does not modify the VP vector in the way I'd assumed from the GL spec.

int slot = (method - NV097_SET_SPECULAR_PARAMS) / 4;
NV2A_DPRINTF("NV097_SET_SPECULAR_PARAMS[%d] 0x%X\n", slot, parameter);
if (slot == 3) {
pg->specular_power = reconstruct_specular_power_from_c3(parameter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to find where this is actually stored in device state

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it's not stored anywhere; presumably the 6 coefficients are stored since it wouldn't make sense to pass them only to have the HW reconstruct the original power value from DX/GL.

If someone reverses the actual implementation (the values look suspiciously similar to the ones used for NV097_SET_LIGHT_SPOT_FALLOFF which is also unimplemented) we could work out the registers with that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presumably the 6 coefficients are stored

This is what I'm referring to

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately it doesn't seem to be a straightforward one. Unless the values are being transformed before storage (I'm asuming this is unlikely since they're floats rather than bitvectors) there doesn't seem to be any viable sets in the diff.

This is particularly annoying since it looks like the power can't be inferred from c3 alone; for vals < 1 c2 is pretty close on its own, but c2 rolls over around 1561.

I may just stash the values in PGRAPHState for now (since I need to accumulate them for curve fitting) and leave finding the correct locations to a future PR, if that's OK.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may just stash the values in PGRAPHState for now (since I need to accumulate them for curve fitting) and leave finding the correct locations to a future PR, if that's OK.

No problem. We can iterate on it as we learn more. But as we discussed in your other comment, the new fields should be saved in the VMStateDescription

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, let's not bother saving the new field in the VMStateDescription in this PR. Other fields are not saved right now, and we'll have to come up with a better solution for them. Games likely refreshes them anyway, so it's not a huge issue.

@abaire abaire force-pushed the feat_spec_params branch from 39fef7e to 51fdaca Compare April 10, 2025 05:20
@ko81e24wy
Copy link

ko81e24wy commented Apr 10, 2025

I test the latest build of this PR,crash when loading in game.
log file
xemu.zip

@abaire abaire force-pushed the feat_spec_params branch from 51fdaca to c9c970e Compare April 10, 2025 15:06
@abaire
Copy link
Contributor Author

abaire commented Apr 10, 2025

@ko81e24wy oops! I was setting up the uniform in the infinite light handler and that game has 3 infinite lights. Should be fixed now.

@@ -197,6 +197,11 @@ typedef struct PGRAPHState {
float light_local_position[NV2A_MAX_LIGHTS][3];
float light_local_attenuation[NV2A_MAX_LIGHTS][3];

float specular_params[6];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mborgerson should these be added to VMStateDescription?

It might be useful to document the decision factor for adding pgraph state to snapshots (maybe with CI enforcement/reminders at some point, if it's easy to automate)

Copy link
Member

@mborgerson mborgerson Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one reason to prefer PGRAPHState.regs over new fields in PGRAPHState. If they are stored in regs, they are already being stored in VMStateDescription. If not, then they need to be added specifically to the VMStateDescription.

The decision factor to include it in VMStateDescription is basically this: if the data are part of device state that cannot be calculated, then they must be in VMStateDescription for faithful state loading. Imagine if the game sets specular params once on startup and never does so again. If a snapshot is saved, then loaded later in a new instance of xemu, the restored state won't have correct specular params.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one reason to prefer PGRAPHState.regs over new fields in PGRAPHState.

Agreed on preferring regs, in this case I'm just not seeing any change in an obvious way.

... if the data are part of device state that cannot be calculated, then they must be in VMStateDescription

In that case I think there are a bunch of fields missing. E.g., light_infinite_half_vector and the other constants (likely more, I just happened to have an editor open looking at that line).

Would it make sense to either adopt a naming convention for vals that should (not?) be saved in vmstate or otherwise differentiate between recalculable and non fields? Then in theory we could have a check to make sure new fields update the state.

Or is the intent more nuanced since it's likely that many of the pgraph state fields will be set very frequently and it's acceptable to have a bad frame or two after a load?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there are other fields missing. I mentioned in my comment above but I'll repeat here, I'm okay with deferring storing these new (and existing) fields VMStateDescription for now. Apologies for the misdirection.

@ko81e24wy
Copy link

@ko81e24wy oops! I was setting up the uniform in the infinite light handler and that game has 3 infinite lights. Should be fixed now.

It works now.

@abaire abaire force-pushed the feat_spec_params branch from c9c970e to 0e8fdba Compare April 10, 2025 15:51
@ko81e24wy
Copy link

Performance is better,the cutsecne after boss fight stage1 in chapter 15 has no more frame drops like before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants