Wie kann ich einen benutzerdefinierten Charakter-Gesichtseditor in meinem Spiel optimal erstellen?

7

In vielen Spielen gibt es einen Abschnitt als benutzerdefinierten Charakter, in dem Sie Ihren eigenen Charakter erstellen können. Ich liebe es immer zu wissen, wie ich so etwas erstellen kann.

Auch altes Spiel haben diese Funktion? aber wie ?

altes Spiel

Für die Implementierung benötige ich eine genaue Trennung für die Kommunikation zwischen Werten und Größe der Gesichtsteile. Also habe ich zuerst mehrere Höhenkarten basierend auf Gesichtsteilen erstellt, um sie mit dem Vertex-Shader zu ändern und korrekt zu arbeiten, aber diese Methode ist nicht optimal. Kann ich sie nur mit einer Textur implementieren?

hat funktioniert erste Lösung

Dann habe ich versucht, eine farbenfrohe Mapping-Textur zum Erkennen von Gesichtsteilen zu verwenden, aber ich habe Probleme, Farbwerte aus der Mapping-Textur in meinem Shader-Code zu erhalten.

Mortal Kombat

Mapping-Textur:

Gesichtszuordnung

Mein Problem ist, dass mein Scheitelpunkt-Shader nicht mit meiner Mapping-Textur übereinstimmt. Wenn ich zum Beispiel _NoseLengthandere Teile ändere, ändert sich dies . Wie kann ich dem Scheitelpunkt-Shader sagen, welcher Teil Nase, Stirn, Lippe, Wange, ... ist? Kartierung.

Hier ist mein 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"
    }
Seyed Morteza Kamali
quelle

Antworten:

1

Lassen Sie es uns Schritt für Schritt implementieren:

1.Zunächst benötigen Sie eine Möglichkeit, auf Farbwerte in der Textur per Shader zuzugreifen.

2.Dann können Sie den Vertex-Shader anhand der Farbwerte in Ihrer farbenfrohen Höhenkarte ändern.

Schritt 1 : Zugriff auf Farben Im Textur-Test:

Zugriff auf Farben In Textur

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
        }
    }
}

Schritt 2 : Jetzt können Sie den Vertex-Shader einfach nach Farbwerten ändern. In Ihrer farbenfrohen Höhenkarte:

Ändern des Vertex-Shaders durch Farbwerte

    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;
    }
}
Seyed Morteza Kamali
quelle