Hello community,
I'm currently working on a customizable avatar system that is built at runtime from a collection of separate loose textures at runtime. It's was based heavily on MixAndMatch example.
The next feature I'm trying to implement is supporting color variations of each avatar part. So for example we could have a base grayscale shirt and use something like a Spine/Skeleton Gradient shader that takes the original grayscale texture and a gradient ramp texture and UV to determine the final shirt color.
I'm a complete shader noob, so I was hoping someone might have done this already and would be willing to share or is a shader pro and would know what to do.
At a high level I think the flow would be something like
Sprite shirtSprite = Resources.Load<Sprite>("avatar/shirt1");
RegionAttachment newShirt = shirtSprite.ToRegionAttachmentPMAClone(Shader.Find("Spine/Skeleton Gradient"));
// 1) Somehow associate gradient ramp with shader
// 2) Somehow choose the gradient ramp UV
Here's some pics of our avatar, as well as how each part is created at runtime.
18 Jul 2017, 12:35
After doing more research and experimenting, I figured out a working solution, though there are caveats.
Since custom color avatar parts use a different Shader than my normal Spine/Skeleton one, the Spine's repacking system can't be used since it only supports a single material and shader applied to everything contained in it. That means there are more draw calls and materials being used which is a trade off.
First off, I created a new SkeletonGradient shader based on the one that I found which replaces the colors on the primary texture with the ones on the ColorRamp - https://forum.unity3d.com/threads/color-replacement-shader.83582/ I used the suggested modification to preserve the primary texture alpha.
After that I switched to the SkeletonGradient shader when necessary while I'm building the custom avatar piece by piece.
...
if (spriteWithoutExtension.Contains("eyes"))
{
skeletonShader = Shader.Find("GRS/SkeletonGradient");
setup = new Material(skeletonShader);
Texture rampTexture = Resources.Load("Test/YellowRamp") as Texture;
setup.SetTexture("_ColorRamp", rampTexture);
}
AtlasRegion newRegion = avatarSprite.ToAtlasRegionPMAClone(skeletonShader, TextureFormat.RGBA32, false, setup);
newAttachment.SetRegion(newRegion);
newSkin.AddAttachment(slotIndex, attachmentName, newAttachment);
skeleton.SetAttachment(componentSlot, attachmentName);
slotVisibility[componentSlot] = true;
...