7
\$\begingroup\$

In many games there Is section as customize character that you can make your own character.I always love to know how can I make something like It.

Even old game have this feature? but how ?

old game

For Implementing It I need accurate separation for communating between values and facial parts size. So first I made multiple height-map based on facial parts for modifying by vertex shader and work correctly but this method Isn't optimal.can I Implement It just by one texture?

worked first solution

then I tried by using colorful mapping texture for detecting facial parts, but I have problem for getting color values from mapping texture In my shader code.

Mortal Kombat

mapping texture:

face mapping

My problem Is that my vertex shader Isn't match with my mapping texture.for example If I change _NoseLength other parts will changes.how can I tell to vertex shader which part is nose,forehead,lip,cheek,... In my colorful mapping.

Here Is my Shader Code:

Shader "Custom/Extrude" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _ModTex ("Vertex Modify", 2D) = "white" {}
            _NoseLength ("NoseLength ", Range(-0.05,0.01)) = 1.0
            _LipSize ("LipSize ",  Range(-0.05,0.01)) = 1.0
            _CheekBones ("CheekBones ", Range(-0.05,0.01)) = 1.0
            _ForeHead ("ForeHead ", Range(-0.05,0.01)) = 1.0
            _EyeSize("EyeSize", Range(-0.05,0.01)) = 1.0

        }
        SubShader {
            Tags { "RenderType"="Opaque" "Queue" = "Transparent"}
            Cull off
            CGPROGRAM
            #pragma surface surf Lambert vertex:vert
            #pragma target 3.0

            sampler2D _MainTex;
            sampler2D _ModTex;

            uniform fixed _NoseLength;
            uniform fixed _LipSize;
            uniform fixed _CheekBones;
            uniform fixed _ForeHead;
            uniform fixed _EyeSize;

            struct Input {
                float2 uv_MainTex;
            };

            void vert(inout appdata_full v) {
                float4 lipSize = tex2Dlod(_ModTex, float4(v.texcoord.xy, 0, 0)).g;//Green
                float4 nose = tex2Dlod(_ModTex, float4(v.texcoord.xy, 0, 0)).b; //Blue
                float4 eye = tex2Dlod(_ModTex, float4(v.texcoord.xy, 0, 0)).r; // Red
                float2 cheek = tex2Dlod(_ModTex, float4(v.texcoord.xy, 0, 0)).rg; // Yellow
                float2 forehead = tex2Dlod(_ModTex, float4(v.texcoord.xy, 0, 0)).rb; // Purple
                v.vertex.y += _LipSize * lipSize;
                v.vertex.y += _NoseLength * nose;
                v.vertex.y += _EyeSize * eye;
                v.vertex.y += _CheekBones * cheek;
                v.vertex.y += _ForeHead * forehead ;

            }

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex);
                o.Albedo = c.rgb;
                o.Alpha = c.a;
            }
            ENDCG
        } 
        FallBack "Diffuse"
    }
\$\endgroup\$
1
\$\begingroup\$

let's Implement It step by step:

1.First you need a way for accessing to color values In texture by shader.

2.Then you can modify vertex shader by color values In your colorful Height map.

Step 1 : Accessing to colors In the texture test:

accessing to colors In texture

Shader "SmkGames/ColorReplacement"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TH("Threshold value",Range(0,1)) = 0.5

        [HideInInspector]_Red("Filter Color 1", Color) = (1.0,0,0,1.0) //Red
        [HideInInspector]_Green("Filter Color 2", Color) = (0,1.0,0,1.0) //Green
        [HideInInspector]_Blue("Filter Color 3", Color) = (0,0,1.0,1.0) //Blue
        [HideInInspector]_Yellow("Filter Color 4", Color) = (1.0,1.0,0,1.0) //Yellow
        [HideInInspector]_Purple("Filter Color 5", Color) = (1.0,0,1.0,1.0) //Purple
        [HideInInspector]_Cyan("Filter Color 6", Color) = (0,1.0,1.0,1.0) //Cyan
        [HideInInspector]_White("Filter Color 7", Color) = (1.0,1.0,1.0,1.0) //Cyan

        _ColorReplacement1("Red", Color) = (1.0,0,0,1.0) //Red
        _ColorReplacement2("Green", Color) = (0,1.0,0,1.0) //Green
        _ColorReplacement3("Blue", Color) = (0,0,1.0,1.0) //Blue
        _ColorReplacement4("Yellow", Color) = (1.0,1.0,0,1.0) //Yellow
        _ColorReplacement5("Purple", Color) = (1.0,0,1.0,1.0) //Purple
        _ColorReplacement6("Cyan", Color) = (0,1.0,1.0,1.0) //Cyan
        _ColorReplacement7("White", Color) = (1.0,1.0,1.0,1.0) //White


    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            uniform sampler2D _MainTex;
            uniform float4 _MainTex_ST;

            uniform float _TH; //Threshold value

            //MainColors
            uniform float4 _Red;
            uniform float4 _Green;
            uniform float4 _Blue;
            uniform float4 _Yellow;
            uniform float4 _Purple;
            uniform float4 _Cyan;
            uniform float4 _White;

            //Colors Replacement
            uniform float4 _ColorReplacement1;
            uniform float4 _ColorReplacement2;
            uniform float4 _ColorReplacement3;
            uniform float4 _ColorReplacement4;
            uniform float4 _ColorReplacement5;
            uniform float4 _ColorReplacement6;
            uniform float4 _ColorReplacement7;


            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };



            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : Color
            {
                fixed4 color = tex2D(_MainTex, i.uv);
                if(distance(color,_Red)<=_TH){
                    return  _ColorReplacement1;
                }
                if(distance(color,_Green)<=_TH){
                    return  _ColorReplacement2;
                }
                if(distance(color,_Blue)<=_TH){
                    return _ColorReplacement3;
                }
                if(distance(color,_Yellow)<=_TH){
                    return  _ColorReplacement4;
                }
                if(distance(color,_Purple)<=_TH){
                    return _ColorReplacement5;
                }
                if(distance(color,_Cyan)<=_TH){
                    return _ColorReplacement6;
                }
                if(distance(color,_White)<=_TH){
                    return _ColorReplacement7;
                }
                return  float4(color.rgb,1);
            }
            ENDCG
        }
    }
}

Step 2: now you can easily modify vertex shader by color values In your colorful Height map:

modifying vertex shader by color values

    void vert(inout appdata_full v) {
    float4 FacialParts = tex2Dlod(_Mask, float4(v.texcoord.xy, 0, 0));

    if(distance(FacialParts,_FilterColor1)<=_TH){
    v.vertex.xyz += v.normal * _Width; // Extruding
    v.vertex.z +=  _Height * Intensity;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.