This is one of those things that started with me going in like ‘There has to be a simple way to to this!’ and just ending with ‘I guess not?’…
At this point I’m mostly writing this in the hope of someone coming around and pointing out, how wrong I am and how this is easily doable.
The problem in general seems to be that the volume shader only really cares about the generated coordinates and doesn’t really seem to respond to anything related to the mesh or surface attributes like UVs or normals.
Because of the limitations with the mapping of the coordinates, this is probably best approached by projecting a texture from the top onto it using the generated coordinates.
Another way I tried was to use a radial gradient and stretch/deform it with the RGB-curves based on it’s angle to fit your shape. You can kinda get it to work, but it’s extremely fiddly and mostly trial and error. So I think a texture is the way to go in this case.
Regarding your second screenshot:
I don’t think this is (reasonably) doable with pure texture mapping in cycles - or honestly at all at this point.
Depending on how patient and comfortable you are with the texture space you might get close by shaping the coordinate space with math nodes or RGB-Curves, but I doubt it would be a fun process and you’d have to redo it for every change in the model.
The closest I found to a repeatable and adaptable workaround is to basically create your volume from several layers and give each layer a volume material that represents a slice of your gradient.
The solidify modifier can help with this by applying it several times without a rim to create slices and one last time to give each slice a thickness. Using the material offset in the solidify modifier each slice can get it’s own material.
Personally I wasn’t too happy with the result, because the layering was more obvious than I had hoped
I admittedly didn’t put too mush effort into the gradient. So you might be able to get better results.
In case this is something you wanna look into, here’s the blend file of the setup:
layered-volume.blend (1.2 MB)