-
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
Automatically generate a specular map when there is no specular map #1243
base: master
Are you sure you want to change the base?
Conversation
That's something I worked on in April. A naive way would be to convert color to greyscale but this is wrong in many situations. First thing that is wrong in converting color to greyscale, is that full white would be 1, while full red, full green or full blue would only be 0.3. So instead of converting RGB to grey, I convert to Second thing that is wrong is that:
but this is not completely wrong as legacy textures may have baked some glossiness and then brighter parts may be more glossy. What we should avoid is to get obviously wrong reflections, like a sand beach being glossy because being light beige. Things being wrongly matte looks far less unpleasing to the eyes than things wrongly glossy. In fact, without specular maps all surfaces are already all wrongly matte, it is still fine, and if the implemented algorithm produces something too matte than needed, at worst it just does not do better and never does wrong. So, the idea is to reach some average specularity value of concrete. Metal may be not shiny enough, but all other surfaces would not be too shiny. Also we still want full back to have no specularity at all, as full black is used as a trick for undrawn things (like the bottom of a pit). I want the emulated specularity to be very subtle: it is not meant to be noticed, it is meant to be felt better. Something I dislike a lot in early games implementing specularity, is that they made sure we noticed it, the surfaces were yelling at the player “look! look! I implemented specular mapping! look at all this shininess! loook!”, but in real life the concrete is not supposed to yell at you “look! look at my shininess, do you notice my gorgeous specular map?”. And since it's emulated and we don't want to make it obviously too shiny, focusing on being very subtle is a good idea. The targets are:
It happens that the color variations of a surface are a good data to build shininess variation: different color may be different material, different paint, with different shininess, color changes may even be dust or corrosion. That's part of why converting color to greyscale is not a bad idea per se, the shininess change follows the color change patterns. For example a white and black checkered floor will get checkered shininess with different shininess on white and black tiles but same shininess on all white tiles and same shininess on all black tiles. Assuming a darker color is less shiny isn't bad, especially since legacy textures may bake some holes filled with shadows, and some reflections, and we want such shadowed holes to be less shiny and reflections to be more shiny. So what I came up with was:
The values of |
There are currently two additional commits that are just fixes I noticed while rebasing and rewriting some code to leave the proof-of-concept state, I plan to submit those two other commits in separate PRs. |
ec5eca9
to
3c302bc
Compare
My initial factor of |
It is useful to know that the feature currently only works on maps with baked deluxemaps. So it works with legacy textures but not with legacy Tremulous maps that were never rebuilt. In the future we may use the lightgrid to emulate a deluxemap like we already do with models, this would allow us to get specularity on all maps, including legacy ones, without any texture change and map rebuild, but this is out of scope of this PR. |
I did not read the code. But I am currently looking at some maps. This looks great. |
3c302bc
to
efa5e75
Compare
src/engine/renderer/gl_shader.cpp
Outdated
@@ -949,6 +949,11 @@ static bool IsUnusedPermutation( const char *compileMacros ) | |||
see https://github.com/DaemonEngine/Daemon/issues/355 */ | |||
if ( !glConfig2.specularMapping ) return true; | |||
} | |||
else if ( strcmp( token, "USE_AUTOMATIC_SPECULARMAPPING" ) == 0 ) |
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.
The macro spelling is wrong
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.
Fixed.
vec4 material = texture2D(u_MaterialMap, texCoords); | ||
#if defined(USE_AUTOMATIC_SPECULARMAP) | ||
float mean = (diffuse.r + diffuse.g + diffuse.b) * 0.333333; | ||
mean = max(max(max(mean, diffuse.r), diffuse.g), diffuse.b); |
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.
These two lines are just the same as taking the max component, i.e. float mean = max(max(diffuse.r, diffuse.g), diffuse.b)
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.
Oh, right! 😅️ Now fixed.
efa5e75
to
1974af7
Compare
About the maximum r/g/b channel thing... what is the point of boosting the specularity of certain hues (red, green, and blue) compared to others? IIRC in chat you were saying that just using grayscale is naive or something, but at least that seems less arbitrary. In general the feature seems hit or miss. In the nexus6 scene the pipes look nice, but the gray concrete-looking parts are brightened way too much. Basically we are putting the same specularity for all surfaces, regardless of what roughness/shininess/whatever they ought to have, and only varying with a kind of random function of pixel color, which doesn't really correlate with shininess. Based on the screenshots provided I don't find it an improvement. I don't like how the feature generally increases the overall brightness of the map, as if r_gamma had been increased. (Though there is the same issue when toggling r_normalMapping.) If the mapper targets some specific level of brightness, it is impossible to achieve it both with and without automatic specular mapping enabled. |
I think the effect could be a little stronger in some cases. Here is an example of making this effect too strong: |
For comparison, I created specular maps for the atcshd materials by simply converting to grayscale. This is too complicated to link here, but you can look at it on my server. The maps are: atcshd, ptcs1, ptcs7, utcs, new-hope, pierogi, uds. I have conducted a little survey, and people seem to think that this is neither too strong nor too weak. |
4ed00b0
to
a05afd8
Compare
I rebased, the algorithm to guess a specular map can be refined later, I made sure it is not obviously wrong on things like the atcshd floor. The idea is to make it subtle so in worst case it would be too much subtle (which is not a problem). This also means reflection cubemaps will have subtle effects on legacy maps too. |
Does this still do anything? I checked out the latest version and couldn't see any difference. If I could, I would probably be annoyed at what I saw though. There is no way at all to determine what surfaces are supposed to be smooth, so it will inevitably lead to shiny dirt. |
Automatically generate a specular map when there is no specular map
Example video:
20240816-024444-001.unvanquished.webm
More video and images: