Skip to main content

Body Shape Change using Vertex Extrusion

Expected Output

UploadUser Incan Progresschange body shape using a slider. Clothing and other accessories are expected to follow the body shape.

Key Problem

When there are a lot of Clothing and Accessories, authoring every one of them to match the body shape could become tedious

Possible Solution

Using Masked Vertex Displacement to change character body shape. Displacement map can be baked from normal body shape and fat body shape.

Body displacement map can be mapped to clothing’s uv so the clothing could follow the body shape without using blendshape

Here’s a simple standard surface shader with masked vertex displacement

Shader "Custom/SurfaceShaderWithVertexDisplacement"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _DisplacementMap ("Displacement Map", 2D) = "white" {}
        _ModelScale("Model Scale", float) = 0.05
        _BodyType ("BodyType", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows vertex:vert

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _Mask;

        float _BodyType;
        float _ModelScale;

        void vert (inout appdata_full v) {
              //Get displacement amount from _DisplacementMap, 
							//substracted by 0.5 since baked netral color is grey(0.5,0.5,0.5)
              float amount = tex2Dlod (_DisplacementMap, float4(v.texcoord.xy,0,0)).a - 0.5;
              //Displace vertex by amount
              v.vertex.xyz += v.normal * _BodyType * _ModelScale * amount;
        }

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            //o.vertex.xyz += o.normal * _BodyType * 0.0005;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

And here is the result :

[freemake.com LOGO] gainingWeight.mp4

Currently there’s only two possible body shape. But it can be extended by using multiple displacement map.

Obstacle

Still need to investigate the cause of mesh gap when extruded.

Update :

The gaps happen on uv seams, this can be mitigated by ensuring the seam color matched on all sides