How to simulate different sheens of latex paint?

Hi everyone! I am trying to simulate different paint sheen (glossy, satin, egshell, etc.) of latex architectural coatings as accurately as possible. I need to be able to simply and programmatically change the RGB and glossiness of a material independently.

I have tried experimenting with different pieces of the PBR API, of course. The simplest and most realistic combination that I’ve come up so far is to set the normalTexture, diffuseColor, specularColor, glossiness of a PBRSpecularGlossinessMaterial. The code is nice and simple, but the RGB doesn’t seem to be completely accurate. And when I change the glossiness property, it seems to change the RGB dramatically.

I just wanted to check and see if anyone has general advice about the best approach to create the following:

  • A single plane material with a normal texture image that creates shadows and highlights from its peaks and valleys.
  • That can be lit with DirectionalLights and HemisphericLights (or that’s what I’m thinking, is it my lights that are making this wrong?).
  • Whose color can be set directly as a simple hex or RGB.
  • Whose intensity/brightness of reflected light cast on the surface is directly controllable with a simple programmatic technique.

As always, my thanks to this amazing community! Sooooo excited about the release of 4.2!!!

@PatrickRyan may have some advices for you.

Also, you may have more success using a metallic/roughness workflow instead of a specular/glossiness.

Thank you, @Evgeni_Popov!

I gave the metallic/roughness workflow a try as well, though I think that I was setting the material color in order to try switching the RGB, instead of changing the color properties of my light sources. I guess that I’m also not clear on which of those I should be trying to change in order to give the impression of a different color of paint applied o the surface.

Any thoughts would be appreciated, @PatrickRyan.

Thanks again, @Evgeni_Popov, and have a great day!

@CrowAndSky, the two lighting models for PBR which are spec-gloss (PBR-SG) and metal-rough (PBR-MR) both deal with the idea of metallic materials in different ways and this is important to understand. So let me define what it means to be a metallic material:

  • Metallic materials will reflect in their specular reflections the base color of the material. So a red metallic will add red to the specular reflections as well as be influenced by the color of the light hitting it.
  • Dielectric materials (non-metallics) will reflect in their specular reflections only the color of the light hitting their surface.
  • In both cases, PBR will enforce energy conservation which means that the surface can not reflect more energy than strikes it. This means that if you have a metallic surface that adds its base color to the specular reflections and needs to also account for the color of the light, we are mixing proportions of each color to reach the amount of energy that hits the surface.

For the PBR-MR model, controlling if a surface is metallic or not is easy since you have a factor to say if it’s metallic (metalness = 1.0) or dielectric (metalness = 0.0) and the shader takes care of the reflection color for you. For PBR-SG, you don’t have any idea if a material is metallic or dielectric and it is up to the person authoring the material parameters to interpret the metallic nature of the material surface by adding the base color of the material to the specular color.

However, due to energy conservation, you need to be mindful of how much you are adding to the specular color of your material or you can break energy conservation quickly. If you are controlling your PBR-SG material by factors only (in code setting your colors) we will handle energy conservation for you and this is why you see your diffuse color changing in your PBR-SG materials. Adding color to your specular color will only result in your material looking metallic, which I am guessing is not your goal in the paint material.

To illustrate and give you something to experiment with, I put together this quick PG for you. Basically, the PBR-SG material is on the left and the PBR-MR material is on the right with some IBL light and a directional light. You can see that I have dialed these in to render in the same way:

Note that the specular color for the PBR-SG material is (0.05, 0.05, 0.05) due to energy conservation. This is just enough color to retain the diffuse color without starting to pull away diffuse color from the material as the surface becomes metallic. Note that if you are going to use a brighter specular color, meaning your material is metallic, you need to keep your specular color in line with your diffuse color or the results will be jarring. This is the sample rendered as metallic for both:

Note in this case, I am using a specular color of (1.0, 0.0, 0.0) which will completely override the diffuse color due to energy conservation so it doesn’t matter what the diffuse color is at this point. Just to prove the point, when I made the above render I had also changed the diffuse color to (0.0, 0.0, 1.0) to show you that energy conservation had completely taken over the diffuse color.

It really doesn’t matter if you go the PBR-SG route or the PBR-MR route to your materials so long as you keep in mind that the two models work very differently. Once you have your specular color dialed in to your preferred metal/dielectric values, you can then just use roughness or glossiness to change the luster of your paint. The render below shows a 0.5 glossiness and a 0.5 roughness on the two materials. They will act the same by controlling only glossiness or roughness inverted from one another, of course.

There are other things you can engage like surface normal to also enhance your materials, but you would want to pass that as a texture rather than in code due to the ease of obtaining a normal texture versus writing a convincing one. You could also employ things like clear coat (best with a normal texture) so that you can render light hitting the surface normals of a material embedded in a coating like you would see with coated carbon fiber.

I hope this is enough to get you started with your materials, but please feed free to ping me again if you have other questions.


Enough? @PatrickRyan your forum posts are more like awesome, comprehensive documentation pages … and always appreciated.


Wow! Just, wow!

As you can tell, I’m a front-end web dev and completely new to 3D and to WebGL. I initially chose to work with BJS over three.js because of tech advantages in BJS at the time (and your support for WebXR and WebGPU continues to make the platform compelling in that regard). Turns out that the amazing community is a huge advantage to working with BJS. Ever noob question that I ever posted has been answered so quickly and completely. It truly amazes me, and I have raved about it many times to my colleagues.

You went even above and beyond that degree of support here, @PatrickRyan. As @inteja said, you made me my own incredible, personal documentation page. Frankly it would be a great addition to the documentation. I am certainly much more informed than I was before, and have plenty more to dig into. I thank you so much, Patrick, and will pay that kindness forward when I can.

Thanks one final time, and have a fantastic week!

Warmest regards,


Thanks for your kind words, @CrowAndSky! We are here to make sure that everyone has the support they need while developing for Babylon.js and truly recognize that people are coming to the engine with vastly different experience. We are seeing front-end web devs like you, game devs, tech artists, 3D artists, e-commerce companies, educators, and more.

The one thread that ties them all together is the need to produce real-time graphics (and not necessarily in 3D) and for many of those groups this is a new pipeline. Things like energy conservation in PBR are not unique to Babylon.js but are also not the easiest to understand unless you’ve been working in game engines as PBR was becoming the mainstay lighting model. So for us we have a difficult line to draw for our documentation. We want to cover what our engine does and how to use it, but defining how far to go in explaining topics outside of our engine is not obvious.

In that case, we do rely on the forum to see where questions are popping up and what we can do to enhance our documentation while staying on point for how to use the engine. We are in the midst of a documentation overhaul for our 4.2 release and we will continue to enhance our docs to keep them current. Thanks for adopting Babylon.js for your projects and don’t hesitate to reach out if you ever have questions. Those questions help us as well!