Page MenuHomeWildfire Games

(1) AO factors = 1.0 for all materials, (2) skyward bias for ambient light in shaders; (3) temporary fix for excessively bright colors in terrain textures.
Needs ReviewPublic

Authored by DanW58 on Feb 10 2021, 10:58 PM.


NOTE: Nothing in this patch involves C++ code; only XML material files and GLSL shaders are affected; no need to build; just apply and run. NOTE: Diffed from /binaries/data/mods/public folder.

(1) AO factors set to 1.0 in materials: There is no reason why AO should have arbitrary gains set by people based on taste. Gain of AO should be 1.0. In the fragment shaders, AO was arbitrarily multiplied by 2.0, making it invisible, pretty much.
(2) Skyward bias for ambient light in shaders: The traditional OpenGL pipeline models ambient light as light coming from all directions equally. This works well for scenes taking place deep inside the Sun. Anywhere else, ambient light shows directional biases. The best way to deal with this is by using the same cube or sphere used for environment mapping, and the surface normal; but the environment map has to be sufficiently blurred to match the diffuse reflection pattern (cos of the angle), which implies using an environment cube box with full range of LOD's included, rather than an arbitrarily set Environment Color. Failing that, a cheap and dirty approximation that works for open sky environments is a simple computed bias that increases the light coming from above for the blue channel, biases the green channel half as much, and keeps the red channel more or less untouched. It is despicable, yet orders of magnitude better than the OGL model.
(3) Some terrains, particularly the Acropolis Bay, are too white. So white, in fact, that they saturate. Upon working on a shader that would fix them on the fly, I discovered that the floor was tiled; I never knew this; it always seemed pure white. What this shader mod does is it computes S and V as if converting to HSV, and computes a darkening factor based on intensity and saturation. For pure white, the factor output is minimal. For less bright, or more saturated colors, the factor rapidly moves towards 1.0. The color from the terrain texture is then mixed between the original color and the original color squared times 0.75 (darkened and given more contrast). This patch also gets rid of any specular computations and ignores a specular texture if such an atrocity is specified. Specularity is of two types: metallic or dielectric (Fresnel). Ground specularity can come from sand crystals (Fresnel), or from polished marble floors (Fresnel) or from pools of water (Fresnel). Fresnel needs to be computed; it cannot come from a texture.
(4) Since some of the assets lack AO's, defaulting their ambient brightness to 1.0 would make them look much brighter than assets that do have AO's, so in the shader, where an AO texture is not present, the default AO value is 0.5 (50% shadowed). The terrain has no AO, and cannot have, since it cannot know beforehand where shadowing entities will be. Even trees can be there one moment, gone the next. I have a proposal for ambient shadowing onto the terrain for A25 below. For now, I followed the same philosophy, and made the ground 50% ambient shadowed by default. This should be removed if/when the ambient shadowing below (or some other ambient shadowing solution) is implemented.

This patch is suggested for A24. Further work is suggested below for A25.


  1. Many AO bakes have a range from 0.0 to 0.63 or whereabouts. This is incorrect, and the way to deal with it is NOT by manually tweaking materials. If re-baking the AO's for most assets is unrealistic to expect, a temporary solution would be for software to take a thousand random samples upon loading an ao to determine range, and therefor how much the shader should scale up the AO value from the texture.
  2. A better AO algorithm is included in some tools, such as X-normal: The more standard AO accumulates all unblocked rays from a point on the surface of a model, counting them all equally. The better algorithm multiplies each ray by ray dot normal, which makes rays normal to the surface count more, and rays parallel to the surface not count at all. Effectively, this is a post-diffuse-reflectance ao, which is a lot more useful than a pre-reflectance ao, and in fact looks far more realistic and natural. We should strive to get this better type of ao in-game.
  3. Having environmental cube-maps with LOD's is an invaluable asset. The blurriest level of the LOD can be used to fetch ambient light from the surface normal, for one example. For another, the shininess power of a material can be used to bias the LOD level when environment mapping, making the blurring of highlights agree with blurring of the environment map, avoiding the environment mapping's looking ridiculously sharp on otherwise visibly rough surfaces. For realistic metal looks, nothing compares to the simplicity of sprinkling randomly some shininess power variations. As you turn the metal piece, the blurry spots look like watermarks. But this does not work if only lights are affected by shininess power; it must be the environment mapping LOD bias as well. In any case, using the deepest LOD of the environment map to fetch ambient light is an extremely realistic ambient lighting algorithm, and it puts a final nail on the arbitrarily set Ambient Light hateful parameter.
  4. With (now) more realistic looking lights and shadows (with this patch) it becomes more painfully obvious how badly ambient shadowing onto the ground is needed. I have an idea for how to solve this problem for A25. For a quick preview: Create a disc (e.g. do-decagon), and write code that can create instances of it that keep forever hovering a few centimeters above the ground. That is, they govern their own Y position. Programmatically attach one of these to every moving entity upon creation, such that the entity writes its own X and Z to this contraption, but has no control of Y. These contraptions do not need a texture. The shader programmatically computes their ambient light blocking strength as a function of distance from the XZ center. At the center they'd block say 30% of ambient light, decreasing quadratic-ally towards the periphery. The size of the contraption would be based on the owner entity's height, and they would not participate in collisions or anything of the sort. Trees should get these shadow discs, also, albeit with some mechanism to make the shade block green light less than blue or red. Plant leaves partly reflect green light, but partly allow it to pass through, so the shade under trees is biased towards green.
Test Plan

Visual assessment:
(1) AO should be subtle but noticeable if you know what to look for.
(2) In a terrain that includes ambient light as well as sunlight, such as Belgian Bog, direct light shadows should look slightly bluish, as the ambient light they get comes mostly from blue sky scatter, which favors blue (and green to a lesser extent). This can now be visually verified.
(3) Looking at the saturated white terrain where Acropolis Bay begins (original civic center placement), now you will see a ground covered with white stone tiles which wasn't even visible before due to saturation. Other terrains with near white stone tile paths are now much easier to appreciate, and less blinding, such as Belgian Bog and Alpine Valley. The problem with this approach, however, is that the problem with the art is likely to remain if the shader deals with it. The art should be fixed, and these changes removed; which is why I call it "temporary" in the title.

The diff includes a fix of the Ptol civic centre. This change can be removed; it is not too important; I changed the model to hide two graphics problems that it triggered, namely flickering shadows on the terraces, and light leaking under the shadow casting walls.

Diff Detail

Lint Skipped
Unit Tests Skipped

Event Timeline

DanW58 created this revision.Feb 10 2021, 10:58 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build:

Build failure - The Moirai have given mortals hearts that can endure.

Link to build:

DanW58 edited the summary of this revision. (Show Details)Feb 10 2021, 11:53 PM
DanW58 edited the summary of this revision. (Show Details)Feb 11 2021, 12:06 AM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build:

No need to build; only XML and GLSL files are changed.

DanW58 edited the summary of this revision. (Show Details)Feb 11 2021, 12:09 AM
DanW58 edited the summary of this revision. (Show Details)Feb 11 2021, 12:41 AM
DanW58 edited the summary of this revision. (Show Details)Feb 11 2021, 12:54 AM
DanW58 edited the test plan for this revision. (Show Details)
Freagarach added a subscriber: Freagarach.

"Build failure" is actually the whole pipeline, you can click the provide link to see what is going wrong. There one can notice the patch doesn't get applied. A solution is to create patches from the root folder (next to the e.g. .svn, binaries and source folders).
But I guess you found that out already ^^

Freagarach edited projects, added Contributors; removed Restricted Project.Feb 11 2021, 7:03 AM

"Build failure" is actually the whole pipeline, you can click the provide link to see what is going wrong. There one can notice the patch doesn't get applied. A solution is to create patches from the root folder (next to the e.g. .svn, binaries and source folders).
But I guess you found that out already ^^

I'm not sure I'm understanding. This "vulcan" is not a person, but an automatic process, and it is stalled by the fact that I diff'd from a sub-folder? Before, I submitted my first, c++ patch and was told I shouldn't have diffed it from the root folder. Are you saying I should diff at either the /binaries or at the /source folders? Should I then diff from /binaries and update the diff?, or is it taken care of already? Another question is, my shader modifications now include a metal detection and improved depiction hack; namely I do a probabilistic analysis by looking at diffuse and specular to guess if the artist meant to depict shiny metal (braceletts, headbands, shields), and if the answer is yes, I improve the diffuse and specular colors to more accurately represent metallic speculiarities. Should I add that to this patch?

DanW58 updated this revision to Diff 15994.Feb 17 2021, 11:22 PM

See this forum thread for development history:
The model_common.fs and model_common.vs shaders are updated; the first extensively.
The shader is now organized into subroutines, and is designed to maximize eye-candy from existing art assets. It includes two ad-hoc detection algorithms that identify metallic materials and human skin respectively. It incorporates science based Fresnel reflectivity and refraction coefficients, to be able to represent paint, varnishes, etc.
Where the shader decides that a metallic material was intended, it adjusts diffuse and specular colors to better represent metallic reflectivity.
Where the shader decides that human skin is being drawn, it changes the index of refraction from the 1.0 default to 1.5, that of skin; and sets specular power to 17.0, making the arms and legs of human models glow in the sun the way human skin naturally reflects sunlight.
The shader also implements a pseudo environment mapping (using ambient light with skywards anisotropy) as well as a very rudimentary specular occlusion and ground reflection, based on AO value; making the reflections on objects inside patios look like bubbles of light always facing the camera. The sharpness of occlusion boundaries is controlled by the material's specular power, as it should be.
Another attribute of this shader is that it corrects the intensity of specular highlights (sun reflection) on the basis of specular power; --i.e, the smaller the light spots, the brighter, all rigorously math based.
This shader is NOT intended as a shader to target new art to, which is why the patch is called "prohibited_shader.patch". New art, as discussed in the tread linked above, is to target the next version of this shader, which will have detections removed, and instead will interface with a new texture stack able to communicate artistic intent clearly.

DanW58 requested review of this revision.Feb 17 2021, 11:22 PM
Stan added a subscriber: Stan.Feb 17 2021, 11:44 PM

Okay so here comes the frustrating and tough part :/ So bear with me cause we're in for a ride. Just know that it's not against you :)

First thing first, all patches should be generated from the root (eg the folder where binaries/ source/ and data/ lies) This is to make sure we can run detection scripts :)
Secondly if you don't need something don't comment it out remove it. In general we avoid commented code as much as possible.

30 ↗(On Diff #15994)

I need vladislav's input on this. Cause from what I can see animated meshes don't support AO maps (it crashes the game)

36 ↗(On Diff #15994)

Comments start with space, caps, ends with dots :)

58 ↗(On Diff #15994)

Can you add newlines between functions?

328 ↗(On Diff #15994)

Looks like debug code :)

DanW58 updated this revision to Diff 15997.Feb 18 2021, 4:29 AM

Updated the patch again after fixing style 'mistakes' at Stan's request. What I was not able to do is diff from the root folder, as then svn diff wants to include all the stuff from sources, which amounts to more than two megabytes. I'm sure there must be a command to skip a folder, but I was a Tortoise user for many years; never learned the command line.

DanW58 updated this revision to Diff 15998.Feb 18 2021, 5:18 AM

Figured out how to diff from root while skipping /sources.

DanW58 updated this revision to Diff 15999.Feb 18 2021, 5:44 AM

Carried on style fixes to the other shaders.

DanW58 updated this revision to Diff 16002.Feb 18 2021, 12:52 PM

More cosmetic fixes.

DanW58 updated this revision to Diff 16003.Feb 18 2021, 1:03 PM

Removed leftover code from attempting to use skybox as enviromap.

DanW58 updated this revision to Diff 16005.Feb 18 2021, 1:18 PM

Change name of function "get_white_dimming_factor(tex)" to "get_needed_white_dimming_factor(tex)", in terrain_common.fs.
Fixed a few more comments not capitalized, or not ending with a period.

DanW58 updated this revision to Diff 16007.Feb 18 2021, 1:24 PM

Minor code optimization in model_common.fs; saved one sqrt() call.

DanW58 updated this revision to Diff 16012.Feb 18 2021, 9:09 PM

Took the exporting of the half-vector out of any conditional switches in model_common.vs.

DanW58 updated this revision to Diff 16014.Feb 18 2021, 11:49 PM

Moved declaration of half vector out of conditional compile switch in model_common.vs; also swizzled lines 133 to 137 to correct dependencies.