How to color grooves/engravings differently from their surroundings?

I’m making 3D models of weathered gravestones with photogrammetry and using the textureless model with simulated shadows to read the engravings:

Photo vs textureless 3D model

It works pretty well, but it’s much more legible if I make the engravings black and the surface white and don’t depend on shadows. For flat stones, I figured out I can do this in Blender by importing the .obj file, and making a shader that divides the world into white and black by coordinates, then very carefully rotating and shifting the model until the surface is in the white zone and the engravings are in the black zone:

Blender nodes for black/white slicing plane

This is tedious, and doesn’t work at all if the stone isn’t perfectly flat, like if it bulges out in the middle, etc. You can see how the area around “July” is darker because it’s not quite flat there:

Engravings shaded with black

How can I make only the engravings dark and the flat parts white, in a way that ignores broad curvature and doesn’t require me to rotate it manually to a specific angle? Is there some kind of “color by local depth while ignoring global depth” shader? Conceptually, something like:

  • Take the median position of the connected vertices within a certain radius and then shade based on Y depth relative to that median
  • Anything that can be touched by a 10 mm rolling ball is colored white and everything it can’t reach is black
  • Smooth the surface in a way that removes the grooves (median lowpass filter?) and then slide that back a bit to act as the “cutting plane” that separates the white/black colors?

I tried just using the pointiness output but it doesn’t work well:

Previously asked on https://blender.stackexchange.com/q/221738/106269

so you have only one mesh with all the engrave letters!

1 - you could set some material for the letter’s faces
but limited for control over edges ect…

2- you could remove the letters from your slab
then use a boolean modifier for the 2 objects
can also add a bevel modifier ect…

happy cl

Yes, that’s the problem! :slight_smile:

1 - you could set some material for the letter’s faces
but limited for control over edges ect…

How would you do this?

You could try an AO shader, you might need to crank it up a bit, but it could work.

can you upload sample file to test it
if no too big !

but you need to select the letters by hand and assign some new mat

it is tedious but the only way

as said by SterlingRoth

AO might do some weird texturing but worth to try and see results

happy bl

You could use vertex paint to add this effect to the text …

Newer version…

That doesn’t seem to do anything for me:

I can’t select the letters by hand. The whole point is that the letters are hard to read and distinguish and I’m trying to make them more visible. Shading by depth works, but I need that depth to be relative to the surroundings.

upload sample file with image so we can test it

happy bl

Try the “Ambient Occlusion” input node. It lets you configure the distance, which might be enough flexibility for engravings like this. And you can have multiple different nodes at once.

Did you follow the second tutorial? As it looks as if you set the material on the whole mesh … the process creates a mask that is used as a factor placing the dirt / grim only in the cavities… and like in the tutorial perhaps you need the color-ramp to make it show better, also you might try it and don’t set it for Dirt only. I have used it and it will work on anything with an indent.

Yes I’ve tried following it, but the Dirty Vertex Colors doesn’t do anything visible:

  1. Create New project
  2. Delete default cube
  3. Import mesh.obj
  4. Rotate it to be viewable from the default camera
  5. It has default shader image
  6. Go to Object Data
  7. Open Vertex Colors
  8. Add a new slot
  9. Name it “Dirt”
  10. Go to Texture Paint
  11. There is no map to get rid of
  12. Unlike the tutorial, the left side of my screen just shows a blank square, no shaded areas image
  13. Change right side to Vertex Paint mode
  14. Unlike the tutorial, the mesh does not already have dark cavities on it image
  15. Click Paint → Dirty Vertex Colors
  16. It processes for a long time
  17. Afterward, it becomes darker, like the tutorial, but still doesn’t have any dark cavities image
  18. Click Dirt Only
  19. Processes for a long time
  20. Makes it lighter everywhere image

Ok, that all looks ok…now have you added the Attribute node and second Principled etc etc.
It is the color ramp that will add to and make darker…
? This does have a UV correct, and the base color from the scan?

Did a quick one with a deep blue color so you can see the effect…EeVee in lookdev mode…

I don’t know what that means :confused:

No, that would make it unreadable again. I’m just using the raw mesh. I’m purely interested in making it readable, not making it look pretty

I asked about the UV as that would be why nothing showed up in the Blank Square when switching to Texture Paint…It’s not that important as it will all be mapped as a Generated texture by default…

I would still use the original texture in the first principled and add the dirt Noise to the second as in my example…and really play with the color-ramp to push up the contrast for the dirt…to might need to change the Reflection angle and/or the Dirt angle…also you might need to reverse the color-ramp it does make a difference…
Highlight at 60 degrees, dirt at 45 and color-ramp reversed…

If that don’t get it… would you be willing to share the original scan and we could see what we can do…?

Ok, do you understand the Reflection angle and/or the Dirt angle and how to set them?

Conceptually, what I would like to do:

for every vertex in the mesh:
    s = set of all vertices that are connected to this one, within a certain radius
    calculate the median x position of s
    shade vertex based on difference between its x position and the median x position (so that 0 distance is white and engraving depth is black)

Then it would shade small features while ignoring large features/warping/drifting

I’m going to throw out another option:

duplicate your scanned geometry
apply a remesh modifier to the duplicate to get the overall shape of the background stone without the engraving
UV unwrap the low poly remeshed model
bake a displacement map from the hi poly version to the low poly version

This displacement map should capture those details fairly well.

We’re all just shooting in the dark here without a mesh to test on, can you share a .blend?

Here’s one that bulges a little in the middle, with the “half white half black” shading that I’ve been using: https://we.tl/t-mUQGD6VBhr

Alright, I forgot that cycles can’t bake displacement for some reason, but I was able to play with it a little bit to try to find a way to streamline this a bit:


I used the viewport cavity shading effect:

and I used some modifiers to clean up the mesh:

First off, I went into edit mode, selected the main mesh by selecting one piece of it and pressing ctrl+L to select all linked pieces, then I inverted the selection to get all of the loose pieces left over from the photogrammetry mesh generation:

none of those pieces are helping with the process, so go ahead and delete them.

It’s a challenge to extract these fairly subtle details from some fairly noisy data, so cleanup is the key to getting better results

The best thing I’ve tried is to modify my white/black shader so that it includes a little bit of Y and Z coordinates, too, and taper it off a little in those directions so it matches the surface of the stone. It’s very tedious, though.

image