By Ron Haimov ## First, Why do Lighting artists care about albedo values so much? It's important to understand that the colors we see are highly subjective and humans are incapable of giving even remotely realistic estimations of the percentage of green, blue, or red an object reflects. This is because the eye is adapting to the lighting around us, just like exposure and white balance. We also don't linearly see the world. Our brain compresses brightness into more of a curve that we perceive as natural (what we think is bright is actually a lot brighter). All of this means that we are inherently bad at guessing colors with our eyes, which often manifests in unrealistic renderings. We need to define materials in terms of the percentage of light that material reflects or absorbs. This property is always the same, no matter how bright or dark or bluishly lit our environment is. We can't use what we perceive as a "bright" or "dark" material. The interior of a house looks a lot darker when viewed from the outside on a sunny day than in the middle of the night. Let's look at a few examples of a room where everything is supposed to have a typical "white wall paint" material. (All images have been tone mapped the same way) ![No alt text provided for this image](https://media.licdn.com/dms/image/v2/C4E12AQGTa3TBoVJ2cQ/article-inline_image-shrink_400_744/article-inline_image-shrink_400_744/0/1651152492391?e=2147483647&v=beta&t=wh_fwpq2il5SCCYgQIFbGREVRtysi1pZ5ShQ9Ty-FEM) No alt text provided for this image Albedo brightness of 0.1 \- only 10% of the light bounces around, meaning we are losing 90% of the light bounce (which makes it hard for the renderer and therefore noise is being more visible) Albedo brightness of 0.3 \- means that light loses 70% of its energy with each bounce. The shadows look a bit dark and dirty. Albedo brightness of 0.7 \- This is what is generally considered a "safe" value for white walls (8bit RGB value of 180 180 180) The material reflects 70% of the light it receives. So each time a photon bounces off the surface it will lose 30% of its energy. We can see moderate shadows and the scene looks and feels like what we would expect a white room to look like. (this is what we should use as a white albedo) Albedo brightness of 1 \- This is what our scene looks like with a material that reflects 100% of the incoming light. Each photon will be reflected with 100% of the energy it had when it reached the object, basically bouncing around forever, never losing any brightness. The only reason why our render engine can complete the rendering is that the amount of bounces is capped at some level. We can also see that there are no shadows, everything looks washed out and flat. Unfortunately, some artists still use materials with such an albedo ( 8bit RGB of 255 255 255) believing that this is what a "white" material looks like. Light can be said to go through one of three processes when it hits a surface: it either gets absorbed in, reflected from, or transmitted through it. With darker colors absorbing more light and lighter colors reflecting more. Here is another example to understand why we can't trust our eyes alone, and how our sight perceives the darker values of albedos: This is a linear gradient of pure white to pure black. If you sample the middle of this range, you will see it closely matches true 50% grey, around a value of 188 in Photoshop. This gradient may look a bit "off" to you though, it " feels " too light, and the dark values transition too quickly. If you were to average all naturally occurring materials, you would see that the average amount of light reflected off of surfaces is not 50%, but 18%. This is the value that our eyes have adapted around and what we perceive as halfway between black and white. (It also just happens to be the exact value that photographers use as mid gray for calibrating exposure.) Now let's take that same gradient from above, and bias it so that the midpoint is roughly what we perceptually see as middle grey. In order to adjust the original gradient, I raised the value of every pixel to the power of 2.2. For instance, 0.5^2.2=0.21. 0.21 is exactly the mid-gray that Photoshop uses. 2.2 is the power that the sRGB color space uses to adjust the linear values of images stored on the disk to display them to the user. This is why sRGB is the de facto color space used in Photoshop and on most web pages. It very accurately represents the range of values that we perceive in the natural world. ## Colors are way more than RGB Colors are way more complex than just three numbers. To understand colors, the first concept that we need to understand is spectral power distribution - The light we see every day is composed of lighting signals of different spectrums. Human beings can only see lights with specific wavelengths, which are in a very conservative range. Rays beyond the range exist, but it is not directly visible to us so we usually don’t care about them in rendering. It is rare to attempt rendering with a full spectrum in real-time rendering because it is very expensive for interactive rendering. To make things easier for us, scientists have figured out a way to represent color in a very convenient way without too much loss of precision - and that's where Color Space comes in. ## So what is a color space? Color spaces are mathematical models describing the way colors can be represented. The easiest way of visualizing them is to think of a 3d box containing all the possible colors that can be produced by mixing the three primary colors of light: red, green, and blue. We call this a Color Space because it is a 3D space. X, Y, and Z, therefore, represent each color that can be defined. A color space relates numbers to actual colors and is a three-dimensional object which contains all realizable color combinations. Color Space mainly defines: - What RGB color model is being used - How do we define pure red, pure green, pure blue, and white - What is the gamma correction being used When we want to show color space we usually use two-dimensional diagrams that show the cross-section of the 3D color space, containing all colors which are at 50% luminance (a horizontal slice at the vertical midpoint for the color space shown above). ### CIE1931 You have probably seen this image in the past: CIE 1931 is an international standard model of human color vision that is used all around you. Do you see any color prints around you? Are you reading this on a color display? All of that is made possible by CIE 1931. CIE 1931 is a Color Matching System. Color matching tells us how to numerically specify a measured color, and then later accurately reproduce that measured color (e.g. in print or digital displays). To reiterate that point, Color Matching Systems are not focused on describing color with qualities like hue or saturation, they just tell us what combinations of light appear to be the same color to most people (they “match”). You can think of CIE 1931 like you would Newtonian physics. It’s a mathematical generalization of human color vision, that allows us to define, and accurately reproduce colors in most situations. To be an absolute Color Space, apart from the exact locations of the primary colors (RGB), we also need a definition of what we call white. And this is where the Gamma comes in - Contrary to what you might expect, people do not perceive luminance levels one-to-one with their eyes, as it is actually emitted in real life. The actual luminance of light is not observed by us linearly (linear is a straight line), but with a curve. You can see that clearly in this graph: At a light intensity of 20% (so still fairly dark), we do not see 20% - but about 40% light! That is about twice as bright as the actual luminance! (This probably has to do with us being able to survive in the dark) The greater the light intensity, the smaller the difference between perception and actual luminance. This means that we see more information in the dark and less in bright light regions. ## What is a "Linear" color workflow? If you are working with textures, I'm sure you have heard that phrase before. In the real world, light is linearly additive. This simply means that, if you use two light sources, the total luminance is the direct sum of the contribution from each light. The algorithms used by almost every 3D renderer work in the same way. Linear workflows acknowledge this fact by ensuring that all color values used in the rendering process are directly proportional to the luminance in the scene. One of the issues in a linear workflow is that images that have been prepared for display, such as .png or.jpg files used as textures, are not linear. In other words, the numeric color values are not proportional to luminance - Which means that they must be converted, or transformed, before being used in a linear workflow. Conversely, the rendered result of a linear workflow is not suitable for display directly on your screen. It needs to be transformed before it looks correct on our monitor. With old monitors (CRT) the ratio between incoming voltage and light output was non-linear, in the form of a curve. The shape of that curve can be caught by a single number: gamma. with modern flat-screen monitors, the conversion between the input voltage and output luminance is linear. If you offer more voltage, more light is emitted linearly. However, to remain compatible with old CRT screens (and other reasons) modern monitors such as flat screens now emulate the gamma curve of old CRT monitors using electronics. So that gamma-correction is also required for flat screens. The remarkable thing is that the shape of this curve is almost the opposite of the curve of the human perception of light as we saw earlier. That is pure coincidence! that correction of this curve to a straight line; we call that gamma correction. Now that we know the gamma value of a screen (often 2.2) we can make the curve linear by simply said adding an inverse curve to it. We call this procedure: the gamma transfer function. In most game engines we use linear workflow. This means that images for textures that already have a gamma correction applied, must first be converted to linear and then the entire internal 3D environment passes all signals linearly. The reason we do this is that we want all virtual lights, shaders, colors, and post-processing are then treated linearly in the software the same. Only at the rendering stage gamma correction will be applied. The advantage of this is that all virtual lights work much more like their effects in real nature. ## Why do some textures use Linear and some use sRGB The simple answer to this is that textures that are fed into a shader as raw data should use Linear, while textures that are meant to visually represent the final result should use sRGB. Diffuse and emissive textures should use sRGB since they represent what we see, whereas textures like Normal maps, AO, metalness, roughness, specular, etc. are all data that the shader runs math on once it is fed into the shader. These textures are abstractions of ideas that we use to approximate the final result of a material, and none of these textures look directly like how an actual object or material looks in real life. rule of thumb can be If it's a color that you see then it's sRGB. Everything else is linear. Think of these textures not as visual representations of their materials, but as raw data. It is important that any math functions done on textures are performed linearly and that they don't have a curve applied to their data. For this reason, unreal NRM and MSK textures should not have the "sRGB" flag toggled on in their textures. ## Metallic workflow vs Specular workflow Before we jump into the workflows, we should understand first what makes a metal → metal. Any Material can be either: Dielectric or Conductive: Dielectric materials are insulators. meaning a material that does not allow heat and/or electricity to pass through it. Examples of dielectric materials include glass, plastic, wood, ceramic, leather, and so on. these are considered non-metallic. Conductive materials as their name indicate conduct electricity. They are characterized by their high reflectivity and conduction of heat and electricity. Examples of conductive materials include steel, copper, and gold - in other words: metals. When we want to create a metal material we can use either of two shader workflows. This depends on performance and the software we are working on. Unreal uses Metallic & Roughness (unity for example uses Specular & Glossiness, and blender uses both). ### Metallic & Roughness This workflow is defined by three components: Color, Metalness, and Microsurface. Color: For Dielectric materials (non-metal) - the base color outputs only the albedo color. The reflectivity is being assigned automatically by the shader with a value of 4% to non-metals. (when Metalness is set to 0) This reflectivity of non-metals cannot normally be controlled in this workflow, but the average estimate of 4% is correct for the vast majority of them. (An exception is gemstones that have a reflectivity of around 8%) In unreal (or any other Metallic workflows software) the shader represents the range of 0-0.08% as shown in the image below for non-metallic materials. This range is remapped in the shader to 0-1.0, where 0.5 means 4% reflection. when the metallic shader is enabled (value to 1), specular will have no effect. Since metals do not have an observable diffuse color in real life, what we perceive as color is the specular reflections. (Gold for example will have yellowish reflections). Therefore, for Conductive (Metal) materials, the base color controls the specular reflections only. Metalness: It's important here to understand that when you enable metal (value of 1), you change the shader behind the scenes to expect different inputs. Therefore using values that are not 0 or 1, would be not PBR values. (but can be still used in some edge cases) This input only defines what is metal and what is non-metal, functioning as a mask. Where it's black, it's non-metal (Dielectric) Where it's white, it's metal (Conductive) Microsurface (Roughness): Most materials have microscopic irregularities on the surface that cause incident light rays to be reflected in different directions. More polished surfaces reflect the rays in the same direction and result in sharper reflections. Creating these micro-irregularities on a 3D mesh is impractical and would require several million polygons. Instead, we use the Roughness Map. The Roughness Map is the map that controls these micro-irregularities in the metallic workflow. Both are grayscale maps and are just the reverse of each other, namely: Roughness Map: Darker tones = smoother parts. Lighter tones = rougher parts. We can try to set apart Roughness and Reflectivity when Roughness controls how blurry the reflection is, and Reflectivity controls how much light is being reflected. ### Specular & Glossiness The main difference is that specular maps have colors in the areas that are metal. This means that the Specular colors stores Reflectivity as well as metal/non-metal mask. This workflow is defined by three components: Color, Microsurface, and Specularity. Color: In the Specular workflow, we remove the colors of the metals from it since we already store them in the specular texture. Microsurface (Gloss): They are exactly the same just inverted. Specularity: Here, unlike roughness, we use color in the Specular map and it controls both Reflectivities as well as metal/non-metal mask. There are a few differences between the two, but the results are the same. It's important to understand which workflow is needed for which texture: - Albedo \- Base colors with no lighting/shading data. Most albedo values exist within the mid-tones. (sRGB) - Normal \- High-res surface detail used for faking the lighting of bumps and dents. (RG) - Roughness \- Defines reflective surface properties. (Grayscale) - Ambient Occlusion (AO) \- is used to calculate how exposed each point in a scene is to ambient lighting. (Grayscale) - Opacity \- Transparency. (Grayscale) ## Simple case study of dark albedos \*Important note - all images share the same manual exposure and tone mapper (no auto-adjusting of the exposure) Here is an example of a render in UE5, of a scene using only one texture from megascans that was too dark compared to how bright it should be. looking at the base color of that texture we can see that texture is dark. but to understand how dark it really is, we need to convert it back to RGB. Remember, while unreal previews the render in sRGB on our screens, behind the scenes it uses RGB values to calculate the lighting! This is what unreal uses behind the scenes and how it calculates all lights and GI: (\*we can view this by typing " r.TonemapperGamma 1" in the Cmd line in unreal. To return to default type " r.TonemapperGamma 2.2") We can see that this texture is almost black! This megascan's texture actual luminance values averaged at 12.5 (or 0.05 RGB), which means they only bounce 5% of light! Looking back in our "Lit" mode render, our initial thought might be "This is too dark - Let's add more light" - Let's try that: Let's increase the sunlight from 2.5 to 10 (x4 times stronger). Remember that we set the exposure to be fixed, so the tone mapper isn't compensating for it anymore. While the overall image does seem less dark and you can see some light bouncing on the walls, you can also see that we have far more contrast in the scene (note how the chairs and table are being over-exposed). Let's try a different approach, fixing the albedo's luminance to be correct to their physical correct value. Here I have changed the average luminance from 12.5 to 104 (or from 0.05 to 0.4) (adding x8 times brightness to the megascan texture). This is how it looks now: Looking at the base color view, it might look bright to our eyes, but remember that we are looking at sRGB colors. Here you can see the same albedo on both color spaces: We can see how much the albedo affects the lights and GI in the scene and why Albedo is so important. ## TL;DR - If its a value of 0-255 its sRGB, if its a value between 0-1 its RGB (or linear) - If you want to create a white room, the base color luminance should be 0.7 (not 1) - If it's a color that you see in the render - then it should be sRGB. Everything else is RGB (linear). - When creating a metal material (in a metallic workflow such as in unreal), try to always use only 0 or 1. - Metals do not have an albedo base color (it's black), however, we use that same input for reflectivity, and this only works for metals. (value of 1 on the metalness) - Specular input only works for non-metals. - When you are handling the transition between metal and non-metal (such as dust or rust) you can use layers or middle values, as long as you are aware that this is a forced hack. ## Sources: - https://docs.unrealengine.com/udk/Three/TexturingGuidelines.html - https://en.wikipedia.org/wiki/CIE\_1931\_color\_space - https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/Maya/files/GUID-F7A7FC66-4D36-4544-9DBD-24FA35C66C2C-htm.html - https://substance3d.adobe.com/tutorials/courses/the-pbr-guide-part-2#:~:text=Bright%20values%20should%20not%20be,map%20to%20180%2D255%20sRGB - https://medium.com/hipster-color-science/a-beginners-guide-to-colorimetry-401f1830b65a - https://www.chaos.com/blog/understanding-metalness - https://www.racoon-artworks.de/cgbasics/albedoandphotorealism.php - https://chrisbrejon.com/cg-cinematography/chapter-1-color-management/ \* Thanks to Jiri Bicik for helping me create this doc.