-
Notifications
You must be signed in to change notification settings - Fork 60
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
Simplify overbright implementation #1406
Conversation
Screenies? |
Vertex lighting seems to use inverse light factor the same way. |
I'm all in favor of a simpler implementation. In the past I first tried what you did there, but I got bugs. Maybe they were mistakes I did? My main concern was about surfaces where the lightmap is applied more than once (and then multiplied more than once), basically terrain blended surfaces. Fortunately with your branch those terrain blended surfaces look fine (thunder outdoor and station15 garden): On the station15 garden, plant leaves are wrongly lit, maybe they are vertex lit. So, here are the light sources that should be multiplied:
|
Doing this properly is one of the fix from #1404 (the starchart issue) and it should be done in all implementations. |
On my end when I first tried your approach, I was having such places reproducing the same clamping as we get whih the legacy clamped overbright: But as you see in this screenshot, your branch doesn't reproduce the clamping. That clamping in GLSL was also what prompted me to follow a more complex route to avoid that clamping. I don't know why I got any clamping in the past even when doing overbright in GLSL that way. The GLSL code received heavy rewrites, maybe we fixed some bugs in the meantime? |
Lightmap and grid light are what is implemented in the initial draft of this PR. I don't think the last case exists for the simplified approach; it sounds like a problem of canceling. Vertex light is a tiny bit more complex than the other cases since everything has the vertex color attributes, not only things with precomputed lighting. Maybe I can check |
Probably not, the fullbright light mode is to just apply a white lightmap, so it's just using the lightmap code. Maybe there is nothing to do. Though, for vertex lighting, we must make sure the (multiplied) vertex light doesn't multiply with the (multiplied) white lightmap fallback, to not multiply twice. |
I reproduce the clamped overbright with that GLSL implementation, now I remember when it's happening. The clamped overbright happens with such GLSL implementation when the lightmap is blended as a separate stage (i.e. no collapsing is doable), when the engine processes a lightmap stage over a colormap stage (or the colormap stage over a lightmap stage), instead of a singe diffusemap stage: This:
Or this:
Instead of:
Here is an example with a build of the pulse map attached (the one hosted on sweet folder has broken lightstyles so it doesn't reproduce the light clamping bug): The This branch: File: map-pulse_0-20230207-114641-e9a0a5e.dpk.zip viewpos: I guess I don't reproduce the bug with plat23 anymore because I improved the collapse code and we now collapse more materials, getting them processed as a single diffusemap stage instead of separate colormap + lightmap stages. |
So I actually reproduce the clamping bug with a released Tremulous map that is the original map build by the original author (only repackaged, not rebuilt): Map: https://users.unvanquished.net/~sweet/pkg/map-metro-b1-2_0%2B0.dpk viewpos: With With this branch: |
Interestingly, your branch fixes the (what is assumed to be a) floating light shader that should not be visible: Map: https://users.unvanquished.net/~sweet/pkg/map-metro-b1-2_0%2B0.dpk viewpos: branch branch The metro map is the only map known to reproduce this floating transparent surface bug, so it's low priority, but anything helping to pinpoint what is happening is welcome. |
So basically, I'm all in favor of investing this more and if we can make it handle light styles properly, let's do it. But for the 0.55.1 release we better merge my fixes, we'll have all the time to investigate a different implementation after that. |
I looked at the Metro light style shaders. So apparently it builds a composite lightmap in the color buffer from 4 additive stages, then does a standard multiplicative blend with the diffusemap in the final stage. I guess we could keep the cancellation approach for light styles only. There is already detection and special handling for light styles anyway. |
If that's doable that would be awesome! I dislike the cancelling-everywhere approach a lot (it's very fragile because of the very large amounts of uses case…). |
Vertex lighting is multiplied with the diffuse colours, so multiplying it by 4 again would be wrong. Although on master vertex lighting is also somewhat broken with overbright: e. g. on map |
Probably the same bug as the procyon hologram? |
I doubt it, the procyon one has a lightmap. |
Besides canceling, another possible approach to light styles would be using multiple collapse lightmap stages with additive blending, and disable dynamic lights in all but one. |
I guess it is already the case, at least with the tiled renderer: light styles light map are expected to be rendered with |
Actually I don't see how that would works? to collapse lightmaps with what? |
I mean the kind of stage that does diffusemap * lightmap. Like the ones notated |
This may be theoretical, but we may not exclude that some non-lightstyle lightmaps rendered with the lightMapping stage get blended like the light style ones and reproduce the bugs that happens with light styles. It's just that the collapsing has been well improved so standalone non-light-style lightmap stages are more rare nowadays, but it is not guaranteed we collapse all of them or that we even can collapse all of them. |
@slipher do you have any understanding about how the light style lightmap blending is working and then how we may workaround the related bugs? Actually we may workaround some wrongness by normalizing to |
I added a commit to multiply the light factor instead of dividing the inverse light factor, that also cleaned-up code, so it helps to have a better look at things. |
I'm guessing it's the weird square on the wall that is the issue, right? |
I'll test this after sleeping. 🙂️ |
I'd like to avoid adding u_LightFactor to the generic shader at all. I think we can do it via u_Color instead. We can add a flag to make Tess_ComputeColor scale by the light factor. I'll try this later. |
596c674
to
25a5873
Compare
77a478d
to
b593d73
Compare
It's because the vertex colour attribute is disabled. I'll look at why that happens. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Since I only did a small change here, and the pool of people who can review this isn't much larger than this pr's contributors, I took the liberty of reviewing it, especially as I reviewed most of it earlier anyway. |
1a4f01b
to
990a80e
Compare
I squashed the “fixup” commits. This looks ready to me. There are some improvements that may be doable:
But that can be done in the future in subsequent PRs. |
990a80e
to
4d63f4d
Compare
I moved the fix for the metro lanterns here: |
I also renamed the PR to fit what it does, as it is now in good shape for merging and we will going to do things that way. |
Please remember that according to our PR etiquette, no one should merge another person's PR :) |
4d63f4d
to
eba7c4b
Compare
I've now reimplemented the three special cases treated by illwieckz in way that avoids adding Let us call BASE the source tree obtained from merging #1426, #1431 and #1434 into master. Let us call SIMPLE this PR's tree, the Some bugs fixed by these overbright changesNon-lightmapped vertex-lit surface not overbright scaled (station15
|
eba7c4b
to
94ce0a5
Compare
// u_ColorModulate | ||
colorGen_t rgbGen = SetRgbGen( pStage ); | ||
alphaGen_t alphaGen = SetAlphaGen( pStage ); | ||
|
||
gl_genericShaderMaterial->SetUniform_ColorModulate( rgbGen, alphaGen ); | ||
bool mayUseVertexOverbright = pStage->type == stageType_t::ST_COLORMAP && drawSurf->bspSurface; | ||
gl_genericShaderMaterial->SetUniform_ColorModulate( rgbGen, alphaGen, mayUseVertexOverbright ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is preventing to multiply tess.svars.color
in Tess_ComputeColor
?
Why is the material variant calling Tess_ComputeColor
but not the non-material one? Is that a dormant bug we missed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-material code does Tess_ComputeColor()
in Tess_StageIteratorColor()
. Material system does not have that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah so in non-material code, Tess_ComputeColor()
is done before calling Render_generic3D()
. Is it too early to multiply the light factor? Because both tess
and pStage
are known as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we can merge this as it is. Possible optimizations can be done later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah so in non-material code,
Tess_ComputeColor()
is done before callingRender_generic3D()
. Is it too early to multiply the light factor? Because bothtess
andpStage
are known as well.
I suppose that was just to avoid having to add it to all relevant stage renderers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is preventing to multiply
tess.svars.color
inTess_ComputeColor
?
u_Color is not the same thing as u_ColorModulate. The formula for the "lighting" color (which will be multiplied by the diffuse) is u_ColorModulate * (vertex color) + u_Color
. For vertex lighting, u_ColorModulate is 1, or 4 with overbright without lightmap, and u_Color is 0. Otherwise, u_ColorModulate is 0, so it's u_Color that needs to be scaled for light styles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
This allows us to use values greater than 1 in the color buffer and as the color output of a fragment shader, so we don't have to worry so much about values getting clamped in multi-stage shaders. Co-authored-by: Thomas Debesse <dev@illwieckz.net>
Multiply lightmaps and light grid by the light factor right when they are used, instead of the elaborate canceling system. Vertex light multiplication in lightmapped stages is handled by the scaling of the white image lightmap (treated as 4.0). Various bugs will be fixed, since the canceling approach relied on detecting an enormous amount of special cases and not all of them were handled. In a few places there can be issues with intermediate color buffer values exceeding 1.0, but this is worked around (on reasonably good hardware) by the previous commit setting up an RGBA16F framebuffer. When limited to RGBA8 framebuffers, as can be tried with r_highPrecisionRendering 0, this rewrite is a mixed bag. In some places it leads to clamping in the color buffer (example: Pulse viewpos 4822 -1312 -1314 98 13), while in others it improves results due to the effective 2 extra bits of precision in the framebuffer (example: Procyon viewpos -955 3443 276 94 7). There are a few cases where lightmap/lightgrid scaling doesn't apply that required special handling: - For intermediate stages of light styles, the already-existing detection of STYLELIGHTMAP and STYLECOLORMAP is used. For these stage types u_Color is scaled by the light factor. Example: metro-b1-2 viewpos -1172 627 107 94 -21. - For non-lightmapped vertex-lit surfaces, u_ColorModulate is scaled by the light factor. Example: station15 small plants. - For fullbright lightmapped stages, the light factor is set to 1. Example: Procyon star chart. Some bugs (in non-clamped overbright mode) that are fixed by this commit: - Non-lightmapped vertex-lit surfaces (like the station15 plants) are now scaled by the light factor as they should be. - Procyon star chart is no longer too dark with material system. - Glowmap-like stage implemented with q3 syntax in a control panel shader are no longer wrongly overbright-scaled, causing visual noise. zittrig-arena viewpos 1201 -301 -338 87 0 Co-authored-by: Thomas Debesse <dev@illwieckz.net>
94ce0a5
to
344932f
Compare
AIUI overbright simply means that the lightmaps and light grid should be scaled from 0 to 4, instead of 0 to 1, so we can represent a larger range of brightness. But image colors are only allowed to go from 0 to 1. This is a big problem... if we are using GL 1 (hence, perhaps, the mysterious "hardware implementations"). But we have shaders, so all we have to do is multiply by 4 whenever we read one of those special light textures. Problem solved?
I tried this approach and it looks the same to me, consistent with the complex cancellng system that we had before. Also fixes the Perseus glass and Procyon star chart issues addressed in #1404.
An explanation for the canceling approach is given in #1050:
But this is not an accurate representation of how shaders work. Each stage acts independently and directly on the color and depth buffers. There is no scratch area where shader stages are blended before going into the color buffer.
I would expect this to ameliorate the color banding problems with low-precision color buffers since now we don't give up 2 bits of precision to make room for canceling.
I haven't tried vertex lighting yet. Not sure how it's supposed to work with overbright.