A colour-puzzle to solve - Visual differences between Blender, Photoshop, Substance and BabylonJS

Hello everyone !
We have been battling with this for the better of 3 weeks now, and hope to find someone that might have an answer.

The below linked screenshot is an assembly of screenshots showcasing the visual differences between the materials created in Blender, Substance Painter, Photosop, and even if just applied with a simple hexcode in the basecolor of the PBR material inside Babylon JS.

The model used is a GLB, and the maps have also been tested in various ways, coming along with the GLB export, or simply plugged into the material within the sandbox or playground. All with the same color-shifting result.

Needless to say we tried (what feels like “everything”), many things - to no avail.

Inclusive saving all texture maps in linear, untagged (RGB 8bpc) or in sRGB.
We removed / added the IBL environment, added a white omni-light.
Tried turning on / off tone-mapping. Switched between ACES and standard mapping.
Tried turning up and down exposure/ contrast.

Switched scene ambient and material ambient back and forth between black and white.

Tried adding colour and light-bakes into the ambient channel, light-map, and emission.
Tried using a completely until material.

The colour never matches up.
When colour-picked from the Babylon scene in the browser it shows a different colour as well. Despite having pushed in an exact value matching to what we tried in Photoshop, Blender and Substance.

I tried switching Substances’ colormanagement to OpenColorIO, and ACES as well. Which changes the colour a bit but still doesn’t look like it occurs in Babylon.
Changed viewing profile to linear and and to sRGB with the same result. (no match with Babylon)

Substance works in linear space, but even the change to save out maps in sRGB or back as Linear doesn’t seem to have an impact on the colour Babylon is displaying.

Same with maps baked and exported, from Blender. Neither saved as linear, nor as sRGB seems to make a difference.

Interestingly, when we convert the colour in an un-tagged document (8bpc) in Photoshop into sRGB IEC61966 we get a similar colour-shift to what Babylon seems to be doing.
(see bottom of the screenshot)

We are scratching our heads as to what we might miss here.

Any input would be much appreciated !

In short : SEND HELP ! PLEASE :smiley:

Imgur ← link to PNG on IMGUR
And here as JPG

1 Like

Have you tried to display the model with another gltf viewer (like https://gltf-viewer.donmccurdy.com/)? Does it have the right colors or not?

As an aside, are you able to share the model file or is it private?

cc @PatrickRyan in the meantime, as he knows very well all the toolset you used.

2 Likes

Just sanity check stuff. Try using Firefox browser. Back the last time I messed with this problem in 9/21, not every browser produced the same results, and you could go around in circles. From that thread, I showed a mesh in Firefox, which looked the same in Blender.

I also showed on from Chrome:

The chrome & Edge browsers, at the time, both showed like a light blue green film on them. I proved that, at least to myself, because the colors all match if you form your image from a readPixels() call.
Best to compare different browsers to ensure against this.

2 Likes

@codewarrior, I am having a hard time reproducing your issue. I took your hex color and plugged that into a material that uses a simple plastic material and ground dirt (which is what I am guessing you are using in your Painter file) do make something similar to your render. I am showing only the base color in each application so that we don’t have to worry about things like lighting or shadow making the materials look different. But I am able to reproduce the same color in all of the packages.

This pipeline is using Painter to create and export the texture set, assign them to a Principled BSDF material in Blender, and the export to a glb which is dropped into the sandbox.

What looks to be happening with the render you are showing is that the shaders is applying a gamma curve on top of the base color texture. You mentioned that the textures coming out of Painter were set to sRGB as normal. Did your materials in Blender match the color space of your textures? In the node graph, you should have your base color texture set to sRGB, but roughness, metallic, and normal set to Linear.

image

When exporting to glTF, Blender will assume an sRGB texture attached to Base Color, but setting the color space for the Base Color Texture in Blender can account for some mismatching of the renders.

If you can walk me through your export process, or share a sample asset with me (it can be your material on a sphere if you can’t share the original asset) I might be able to figure out what’s tripping you up. In particular, I am curious about if you are simply dropping your glTF into the sandbox (or loading into a Babylon scene) with all of the materials embedded in the glTF, or are you importing the textures separately and then applying them to a material made in Babylon and then assigned to the mesh? The glTF loader should not be doing anything to change the color space of the images when loading them into the scene. But if, for example, you are loading your textures into a node material and wiring them to the PBR blocks, the base color texture needs to be in Linear space when wired to the PBRRoughnessMetallic block, so toggling the convert to linear parameter on your Texture block is necessary.

4 Likes

Thank you JCPalmer for sharing, a colorshift within the browser is certainly one factor, as i have encountered it before. Just wondering about the crazy shift in colors, and i was able to get certain materials to look right, but it keeps failing in this scenario so maybe there is something more to it !
Not giving up my hope just yet >.<

sharing files the next post as reply to Patrick Ryan whom you tagged for me ! thanks for that <3

Hello Patrick
Thank you so much for the lengthy answer.
You almost nailed the material in substance as well. I just didn’t add any of the asset-shaders. Just a few simple fill layers with very little influence on roughness/metalness and plopped in some dirt - you got that right ! :slight_smile:

Regarding the workflow. I tried a few but let’s start here :slight_smile:

Substance workflow:

01 Created a material in substance (as described above)
(exported the maps with a GLTF M/R settings I had created and which combines M/R/O in one map but not using that one here anyways)
02 assign the basecolor map in blender.
03 export file from Blender with Export to GLTF - chose “GLB”, subsetting: selected objects only (to not grab the lights), inclusive basecolor map in PBSDF material
04 go to https://sandbox.babylonjs.com
05 drop the blend.glb into the sandbox
06 in scene settings - turn down IBL intensity to zero, change scene ambient color to white
07 go to material settings (material name = White) - change material ambient color to white

Already here i see the colour shifted.

If you’d want to continue, you can also:

08 Add emissive map into emissive slot , change emissive color to white
09 add lightmap into lightmap slot
10 turn on use lightmap as shadowmap

I have also tried within sandbox on the same uploaded GLB to just exchange the basecolor map to the linear version that was not exported with it. But no change here either. Also tried changing the sampling settings in the texture map settings, no change as well.

Blender-Test to cross check:
I tried baking the same hex color as simple map (diffuse color only) from blender and save as linear as well as sRGB. And payed attention to plug in the map as sRGB as I read it expects this when exporting / converting.
Pretty much the same result. >.<

Please find in the link below the:

  • BlendFile (Blender 3.3.1)
  • Basecolormap in linear, and as sRGB both PNG
  • Lightmap (linear) PNG
  • Emissive Map PNG
  • A screenshot of the material setup in BLender (in case you can’t open this version) with the basecolor plugged in as sRGB

https://drive.google.com/drive/folders/1By34Jww7G5bxXLhZTwiGQL3dRyaymeuP

2 Likes

@codewarrior, thank you for supplying your files to debug with. I did use your steps and used your glb and textures (I didn’t re-export the glb, but used the one you supplied) and I am still not able to repro what you are seeing. Here is what is happening when I set up your material in this way.

Scene albedo color is multiplied with the material albedo color and that is multiplied with the material albedo and added to the final color. This is why if you have your environment intensity set to above 0, your asset will appear brighter because the scene lighting is adding on top of the ambient color. To use PBRMaterial like this is not really the intention of the shader because it is not physically accurate. What you are doing here is basically setting PBRMaterial up to be an unlit shader. You can see in the comparison image below, I have two sandboxes open and on the left is the material from the glTF toggled to display the albedo texture (click on the wrench next to the texture name) and on the right is the scene set up as you describe to right before adding in the emissive and lightmap textures:

There isn’t a difference between the two yet. So I added in the emissive and lightmap textures as you described as well:

Again there is no color shift here. Comparing them back to the texture you send for the albedo texture:

I am not seeing a big shift here in color either. The thing I would suggest next is if you could supply a playground so we can make sure that my settings are exactly what you have authored. If you set up the playground so that you can see the shift, I should be able to see it as well and diagnose what is going on.

In the case of the pipeline you are describing, however, you may be wasting some resources here in using the PBRMaterial that is loaded with the glTF file. The reason is that you aren’t using metallic or roughness and no environment lighting. This may just be for your test. However, if this is the look that you are going for in your final render, it’s likely better to just use an unlit material. You can set up the material in Blender to use the KHR_materials_unlit extension which won’t require you to set your scene and material ambient colors.

Another option would be to create a node material that takes your albedo texture and adds in your emissive texture and multiplies your lightmap texture. This would be a much simpler shader and you wouldn’t be doing any unnecessary operations for lighting calculations that are not there. Not sure if this was your intention, but wanted to bring it up in case you were after a more unlit approach.

4 Likes

not that im an expert but the docs say to use “Non-Color”

https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html#metallic-and-roughness

says similar for the other not diffuse maps you mention. That being said they are not clear about the format of the image on disc being used in the node? Are they assuming sRGB? I wonder… anyway I do always set mine to Non-Color.

1 Like

@shaderbytes, you are correct that any lighting maps (normal, metallic, roughness, glossiness, ambient occlusion, etc) are non-color data maps. This means there is no gamma curve applied to the data and it does not need to be converted to linear color space in the shader before any operations are done. There shouldn’t be a difference between setting the color space to non-color vs linear since the color space definition here is to tell the shader if the texture is in sRGB space and needs to be converted back to linear space before any calculations are done in the shader. But if the manual says use Non-Color then you will always be safe since this is the option that Blender put in to match their shader code.

3 Likes

Hello Patrick,
thanks for testing this through.

Regarding space used on material choice, we have not 100 % nailed down yet whether or not we’d go fully unlit or add in some spec or other material outputs so testing right now with PBR or the GLTF node setup from KHR makes it a bit easier. We mainly turn down the IBL for the lightmap to have a better impact, and to get a more stylized look. But we might of course go fully unlit if the look suits with what we are trying to achieve - so thanks for the pointer :slight_smile:

I am starting to wonder, what monitor color profile do you have ?

Because for me the difference occurs when comparing 3d software viewports and image editors( blender viewport render, substance viewport, photoshop, irfan view ) to babylon in the browser.

All of these show the exact same way more saturated color, And the shift only occurs once uploaded to babylon and viewed in the browser.

If it’s just that i might just need to find a way to match my viewport look to what babylon does. I tried switching the viewport / workspace settings in Substance to srGB, played with the color-management in Blender, but i still don’t get the same look.

I am used to visual differences when putting your work into engines, such as Unreal or Unity, etc. and a bit of a shift when working in the browser. Just never had to work “that much” offset from what i am looking at when creating it.

Trying to do look-dev, when I would have to oversaturate my colors beyond eye-comfort so they appear correct in babylon would be quite a bit of a hassle.

Now I wonder if its the monitor profile. My monitor is on “14D6” which is a HDR profile, maybe that just boosts everything over the top and then when showed in sRGB space or linear space looses all color. Been wondering about that a few times now.

But then there is also still the difference of the colors in the different browsers , firefox = same look as in my viewports, chrome - not at all.

Here is a preset Playground link.

1 Like

I was following the conversation from a distance since I have been involved in colorprofiling a few years ago. I appreciate your desire for consistent color output and management and I can also see you struggling with it (like we all do :wink:) Since with @PatrickRyan at your side, you allready have the best creative and tech direction you can get :man_superhero: :grinning: I’m not gonna add to it.
Just wanted to say, “You realize this issue will affect the end users no matter how hard you try with colorprofiling”, yes?
No matter if you use color profiling, sRGB or linear, monitors and color spaces/profiles set (and sometimes set for apps) will always provide different results (not to speak about the calibration of the monitor). Even on two of the same high-end monitors (LaCie) calibrated with high-end tools, I get a tiny difference in colors. I believe important would be that you set-up a workflow that remains consistent, knowing that, in the end, the end user will still see differences in colors (and for that you should may be add some options to handle color management/display).

3 Likes

Hello @mawa ,
thanks for taking the time to chime in.
I completely am aware of this. Been working in CGI for over a decade, and struggle every day with clients reviewiewing our renders in mobile phones, on Teams, on web-backends, DAM systems and whatnot. Or even forcing us to still convert to AdobeRGB due to some legacy workflow based on photography. Our hearts bleed every time when we convert them and have to then upload these to a webplatform which can effectively not read adobe RGB and thus converting it into a flat looking sad image… brrrrrr :smiley:

And yeah the chaos of even having a perfectly calibrated monitor, which we have at work, but then having to deal with delivering the images to someone looking at them at a different monitor or device type, is just a never ending struggle.

My home PC with its out of normal 14D6 profile is a different story of course, it’s not color calibrated for CGI and could be the struggle here, so I am digging into that question.

I am used to “some colorshift” just never have encountered such a big gap / mismatch. So i really wonder where the cause lies within.

Let’s see if Patrick might have some more ideas. If he is using a monitor with RGB profile that might just be why it looks the same everywhere for him. Looking forward to the answer, as this could just nail the issue down to this being the reason.

And there is yet still the difference between the colors shown in firefox and chrome … adding to the riddle

@codewarrior, I do just use an sRGB color profile for my monitor. I am on a Cintiq 27QHD, which is not an HDR monitor. I used to be a print designer for a couple decades and when I worked in that industry, I had calibrated monitors to be able to simulate print color (which is an entirely different beast using CMYK) because the output was controlled. When we went to press, a specific ink on a specific paper always looked the same. And though lighting conditions can influence what the user sees (fluorescent light versus natural light for example) for the most part we could know how the final product would look.

Since moving to real time rendering, there are so many variables out of our control from the type of monitor or device displaying the content to always needing to target the lowest possible device, I tend to stick with a more generic calibration so that I can see what an average viewing experience will look like. Even the struggle you detail going from a highly calibrated environment to a client’s environment is a real concern and one we’ve all run into because there is no way to tell the client that their environment isn’t correct.

When we make our demos, we try to use a bunch of different configurations to test (though we aren’t exhaustive because our team is just too small and we are spread around several continents). We are always asking people with different devices and configurations to open up a demo and tell us if they see anything strange. This isn’t the best workflow as you can’t see side by side comparisons, but if you have a testing lab it’s well worth the time to detail what different devices render.

I asked our engineers and no one can come up with a reason why the monitor calibration would be doing this, but I would also loading your glTF file in another WebGL viewer like model viewer on your calibrated system to see if there is a similar issue or if it is something specific to our renderer. Unfortunately, I don’t have the hardware to be able to test that out.

I wish I could be more help in giving you a direct answer, but hopefully this gets you another step along the way to a solution.

2 Likes

Hey @PatrickRyan
thanks for taking all that time to look into it.It is really greatly appreciated.

The mornitor profile is a hint, but yeah does not seem to be the end of the “stick” that would solve this puzzle.

We tried follwoing your suggestion and did a quick run on multiple viewers on 2 different browsers.
Just mere screen colorpicking gives a difference:

Khronos Viewer:
glTF Sample Viewer (edited)

DonMcCurdy gltf viewer

BJS Sandbox
bjs sandbox

All above Left are Firefox and right is Chrome / Webkit

Note that for all viewers both look the same in FF as well as in Chrome.
The only one that goes off the rail in chrome is BabylonJS

scratches head … o.O

2 Likes

Pulling back in @Evgeni_Popov or @sebavan

2 Likes

Are you able to share the model, so that we can perform some more in-depth checks with it?

1 Like

@Evgeni_Popov I guess it is related to srgb textures ? do you remember how to disable it or enable ?

1 Like

Hello @Evgeni_Popov
Of course :slight_smile:
Let me copy in an earlier answer where i provided the files and the exact viewer settings i used
(download link on the bottom)
Thanks for looking into it !

I did the procedure you described and got the same result in both Chrome and Firefox (Windows 11):

Chrome 109.0.5414.120 (Official Build) (64-bit):

Firefox 109.0.1 (64 bits):

@sebavan Because of this bug in Chrome/Angle, sRGB buffer support is disabled by default except in the 3D commerce sandbox (see this PR). Note that the bug seems fixed, and yet it is not so clear (see last comments…).

@codewarrior Could you test your asset in https://3dcommerce.babylonjs.com/ instead of https://sandbox.babylonjs.com/? In the first case, sRGB buffer support is enabled, it would be interesting to know if this changes anything to the problem.

In fact, looking at the screenshots, it looks like you didn’t use the same environment map in Firefox and in Chrome: it looks like you used the “studio” environment map in Chrome, as the gray gradient in the background seems to indicate.

If I use this env map (all screenshots below are from Chrome):

I get something that looks a lot like the pic on the right of your screenshot:

And with the default env map, it looks like the pic on the left of your screenshot:

5 Likes