الوحدة والخلط الشبكي

مرحباً بالجميع ، في يونيو ستطلق OTUS دورة مطوري Unity Games مرة أخرى . تحسبًا لبدء الدورة ، قمنا بإعداد ترجمة لمواد مثيرة للاهتمام حول هذا الموضوع.



سنتحدث اليوم عن كيفية مزج شبكة التضاريس (أو شبكة أخرى) في Unity. هذا الدليل متقدم جدًا ، لكنني حاولت تقسيمه إلى خطوات منفصلة. يفترض أن لديك مهارات الوحدة العامة والمعرفة الأساسية C #. تم تصميم الدليل للتضخيم ، ولكن أعتقد أنه يمكن تطبيقه أيضًا على Shader Graph. هذا هو دليلي الأول ، لذلك آمل أن يكون واضحًا بما فيه الكفاية. إذا كنت تريد إضافة شيء ما ، فأخبرني بذلك. لقد قمت بتضمين مجموعة بداية هنا ، والتي تحتوي على بعض التظليل الإضافي لهذا المشروع ، بالإضافة إلى مجموعة أساسية للبدء. جميع ملفات المشاريع من دليل اليوم متاحة للمستفيدين مقابل 5 دولارات ، ولكن في المستقبل القريب ، ستكون متاحة للجميع.

مجموعة المبتدئين
المشروع بأكمله

: , , . . , , , . ( ) unity . , , .

لذا ، لنبدأ. في البداية ، سوف أذكر المشكلة وأتعمق في النظرية التي سيبنى عليها الحل. لجعل المزج بين الأرض والشبكات الأخرى ، تحتاج إلى إخبار التظليل بطريقة أو بأخرى عن مكان حدوث التقاطع مع الأرض. القول أسهل من الفعل ، لكن هناك طريقة. وماذا يتكون؟ Render Texture سيساعدنا !

ما هو نسيج تقديم؟


Render Texture ، في الواقع ، هو موضع الكاميرا ، والذي يتم حفظه في ملف الأصول. غالبًا ما يتم استخدام Render Texture في الألعاب لأشياء مثل إنشاء شاشات المراقبة بالفيديو. يمكننا استخدام Render Texture لحفظ عرض الكاميرا في المحرر بحيث يمكن بعد ذلك استخدام هذا النسيج كظليل. هذا مفيد لأنه يمكننا خبز معلومات حول تضاريسنا ، مثل الارتفاع والمعايير والألوان ، في نسيج يمكن استخدامه بعد ذلك في وقت التشغيل للمزج بين الشبكات والتضاريس.


يتم استخدام عرض الأنسجة لعرض صور الأوزة على أجهزة التلفزيون في لعبة الأوز غير المعنونة

التخصيص


للبدء ، لنقم بإنشاء مشهد وتضاريس جديدة. حدد حجمًا مناسبًا للعمل ، على سبيل المثال ، 200x200. الآن يمكنك ترتيب التضاريس كما تريد. ثم قم بإنشاء طبقة جديدة واسمها "تضاريس" وقم بتعيين تضاريس لهذه الطبقة. يعد ذلك ضروريًا حتى يتمكن قناع الكاميرا من تسجيل التضاريس في مادة التقديم .


أرضي الرائعة الخاصة بي

تحتوي ملفات مصدر المشروع على إعداد مسبق يسمى "BlendBakingCamera" - اسحبه إلى الجزء الرئيسي. سوف تحصل على كاميرا إملائية بسيطة. على الكاميرا ، تحتاج إلى وضع قناع إعدام على طبقة جديدة من التضاريس. ضع الكاميرا في وسط الأرض أعلى قليلاً من أعلى نقطة على التضاريس. ثم اضبط مستوى المشبك البعيد بحيث ترى الكاميرا أرضية التضاريس. في النهاية ، يجب أن يبدو المشهد كالتالي:


تظليل بديل


الآن بعد أن تم إعداد الكاميرا ، تحتاج إلى إيجاد طريقة لتسجيل بيانات التضاريس. لهذا نحن بحاجة إلى تظليل الاستبدال. يبدو استبدال Shader وكأنه احتمال مشبوه ؛ أنا نفسي لم أفهم كيف يعمل لفترة طويلة. ولكن في الواقع ، كل شيء بسيط وفعال للغاية. يعني استخدام Shader البديل بشكل أساسي عرض كل كائن في مجال رؤية الكاميرا باستخدام جهاز تظليل واحد ، بغض النظر عن أي جهاز تظليل متراكب على الكائنات. نتيجة لذلك ، سيتم تقديم كل الكائنات باستخدام تظليل الاستبدال المحدد ، والذي هو في الواقع مجرد تظليل عادي.

التظليل الذي نحتاجه للمزج هو تظليل العمق. إنه يجعل عمق المشهد ومكونًا رئيسيًا في إنشاء تأثير المزج الخاص بنا ، حيث يكتب قيم عمق الكاميرا إلى النسيج حتى نتمكن من قراءتها لاحقًا. لمعرفة المزيد حول هذا التظليل و Shader البديل بشكل عام ، أوصي بقراءة هذا الدليل من Make Stuff تبدو جيدة في الوحدة .


مثال على تظليل العمق

لنبدأ الخبز


لنقم بإنشاء فئة جديدة واسمها "TerrainBlendingBaker" . لنبدأ بتطبيق قناع عمق لتضاريس القاعدة. سنعود لاحقًا إلى هذا النص البرمجي لإضافة الألوان والمعايير.

حدد عدة متغيرات.

//Shader that renders object based on distance to camera
public Shader depthShader;
//The render texture which will store the depth of our terrain
public RenderTexture depthTexture;
//The camera this script is attached to
private Camera cam;

الآن دعنا ننشئ طريقة جديدة ونطلق عليها "UpdateBakingCamera" . في هذه الطريقة ، سنحدد بيانات الكاميرا التي قد يحتاجها جهاز التظليل لتقديم المزج في المتغيرات العالمية.

private void UpdateBakingCamera()
    {
        //if the camera hasn't been assigned then assign it
        if (cam == null)
        {
            cam = GetComponent<Camera>();
        }
 
        //the total width of the bounding box of our cameras view
        Shader.SetGlobalFloat("TB_SCALE", GetComponent<Camera>().orthographicSize * 2);
        //find the bottom corner of the texture in world scale by subtracting the size of the camera from its x and z position
        Shader.SetGlobalFloat("TB_OFFSET_X", cam.transform.position.x - cam.orthographicSize);
        Shader.SetGlobalFloat("TB_OFFSET_Z", cam.transform.position.z - cam.orthographicSize);
        //we'll also need the relative y position of the camera, lets get this by subtracting the far clip plane from the camera y position
        Shader.SetGlobalFloat("TB_OFFSET_Y", cam.transform.position.y - cam.farClipPlane);
        //we'll also need the far clip plane itself to know the range of y values in the depth texture
        Shader.SetGlobalFloat("TB_FARCLIP", cam.farClipPlane);
 
        //NOTE: some of the arithmatic here could be moved to the shader but keeping it here makes the shader cleaner so ¯\_(ツ)_/¯
    }

الآن دعنا نخبز عمق الأرض في الملمس.

// The context menu tag allows us to run methods from the inspector (https://docs.unity3d.com/ScriptReference/ContextMenu.html)
[ContextMenu("Bake Depth Texture")]
public void BakeTerrainDepth()
{
    //call our update camera method 
    UpdateBakingCamera();
 
    //Make sure the shader and texture are assigned in the inspector
    if (depthShader != null && depthTexture != null)
    {
        //Set the camera replacment shader to the depth shader that we will assign in the inspector 
        cam.SetReplacementShader(depthShader, "RenderType");
        //set the target render texture of the camera to the depth texture 
        cam.targetTexture = depthTexture;
        //set the render texture we just created as a global shader texture variable
        Shader.SetGlobalTexture("TB_DEPTH", depthTexture);
    }
    else
    {
        Debug.Log("You need to assign the depth shader and depth texture in the inspector");
    }
}

ستصبح القيم أكثر وضوحًا عندما نبدأ العمل مع جهاز تظليل. هذه صورة صغيرة قد تلقي بعض الضوء:


سنقوم بنقل التضاريس إلى نسيج العمق من أجل قراءتها لاحقًا وفهم مكان مزجها.

الآن لدينا كل ما نحتاجه لإنشاء تأثير المزج الأساسي في التظليل. عند هذه النقطة ، يبدو النص كما يلي: pastebin.com/xNusLJfh

حسنًا ، بعد أن أصبح لدينا النص البرمجي ، يمكننا إضافته إلى كاميرا الخبز التي أضفناها سابقًا. تحتوي الأصول الأولية على تظليل يسمى "DepthShader" (Inresin / Shaders / DepthShader) و Render Texture يسمى "DepthTerrainRT" (Inresin / RenderTextures / DepthTextureRT) ، تحتاج إلى وضعها في الحقول المناسبة في المفتش.

بعد ذلك ، قم ببساطة بتشغيل الطريقة من خلال قائمة السياق لخبز عمق التضاريس في مادة التقديم .


شادر


دعونا في النهاية إنشاء تظليل للمزج. قم بإنشاء معيار جديد لتضليل التظليل وافتحه ، واسمه `` TerrainBlending '' أو نحو ذلك.

الآن نحن بحاجة إلى إنشاء الأشعة فوق البنفسجية لنسيج التجسيد . سيكون هذا هو الفرق بين النقطة التي يتم تقديمها وموضع كاميرا الخبز المقاسة بالنسبة إلى المساحة الإجمالية. المتغيرات العالمية الثلاثة هنا هي تلك التي أعلنا عنها للتو في الكود. قمنا أيضًا بتعيين worldY كمتغير محلي ، وسوف نحتاجه لاحقًا.



لنأخذ نسيج العمق ، الذي قمنا بتعيينه كمتغير عام (لهذه العقدة لإضافة عينة نسيج ، اجعلها عامة واسمها "TB_DEPTH") ، إذا وضعنا الإخراج في التصحيح تضخيم تظليل حقل ، يمكننا أن نرى ما يحدث. قم بإنشاء طائرة بالمواد التي سيتم تطبيق تظليلها الجديد عليها.


لذا ، في التظليل ، لدينا معلومات حول العمق ، والآن نحتاج إلى إضافة تعويض في y للحصول على المزج.



تقوم هذه الكتلة بقياس الموضع y لقناع مستوى المشبك البعيد ، وطرح هذه القيمة من الموضع العالمي على طول المحور y للنقطة التي يتم تقديمها ، ثم تقوم في النهاية بتحويلها إلى الجانب السفلي من المربع المحيط بالكاميرا (موضع y للكاميرا مطروحًا من مستوى farclip ).

شيء بالفعل! نرى كيف تندمج حواف الطائرة مع الأرض.



حسنًا ، لنجعل المزج أكثر تحكمًا.



يمكننا الآن التحكم في سمك ومساحة أرض المزج.



أعتقد أنه يمكننا حتى إضافة القليل من الضوضاء. دعونا نستخدم الموقع العالمي لتوليد ضوضاء من الملمس.



توجد مواد الضجيج في مجلد النسيج في مشروع بدء التشغيل ، ويمكن تعيينها في المفتش أو كثابت في التظليل نفسه.

أخيرا حان الوقت لإضافة بعض القوام! للبدء ، دعنا نستخدم بعض الأنسجة البسيطة ذات اللون الواحد ، أضفت نسيجين إلى المجلد بأصول نسيج. اجعل نسيج "SingleColorGrass" نسيجًا أرضيًا. ثم في التظليل ، تحتاج إلى إنشاء نسيج أرضي وعقدة نسيج كائن . سنقوم بالتبديل بينهما على القناة الحمراء للقناع الذي أنشأناه للتو.




وها هو التظليل الكامل ،



إن إضافة إضاءة تون مخصصة أو نماذج إضاءة غير مضاءة ستوفر أفضل النتائج لهذا التظليل. أنا تحولت مضاءةتيران شادر وإصدار غير مظلل من تظليل في الحزمة الكاملة المتاحة للرعاة.


Unlit Terrane and Meshes

أوصي أيضًا بإضافة تظليل ثلاثي إلى الأرض وربما شبكات أخرى. يمكنني النظر في هذه المشكلة في الدليل التالي.

حسنًا ، لقد انتهينا تقريبًا من الموضوع الرئيسي لدليل اليوم. لقد أضفت بعض الأقسام التي يمكن أن تساعد في تمديد تظليل.

تمديد شادر - عادي


أضفت تظليلًا منتظمًا إلى الملفات ، يمكنك استخدامه لكتابة عاديات على سطح الأرض وكذلك استخدام المزج. بالنسبة إلى لعبتي ، لا أحتاج إلى المزج العادي ، لذا جربت قليلاً ويبدو أن التجربة كانت ناجحة ، وفكرتي تعمل بشكل جيد مع التضاريس دون درجة عالية من تغير الارتفاع. قمت بتضمين تظليل تعيين عادي في الدليل مع تظليل مجموعة البداية. هنا يمكنك أن ترى تنفيذي الأساسي للخريطة العادية:



الرمز هو تقريبًا كما هو الحال مع خريطة العمق ، ولكن هذه المرة سنستخدم الخريطة العادية كخلايا بديلة . أضفت أيضًا مجموعة من نسيج التجسيد للتسجيل العادي (هنا قد تحتاج إلى تكوين إضافي).

لكي تعمل المعايير الطبيعية بشكل جيد ، قد يستغرق الأمر مزيدًا من الجهد المرتبط بالتوليف ، وقد يكون هناك أيضًا قيود مرتبطة بالأرض ذات المستوى المنخفض (لكنني لم أجري اختبارات كافية لتأكيد ذلك).

تمديد شادر - جميع الألوان


لن أتعمق في تفاصيل هذا الموضوع ، لأنه يتجاوز ما هو مطلوب للعبتي ، لكنني فكرت في ذلك أثناء كتابة هذا الدليل. لإضافة مزج للعديد من الألوان ، يمكننا تحديد ألوان غير مضاءة وحفظها كأنسجة. في هذه الحالة ، نحن مقيدون بدقة منخفضة إلى حد ما ، ولكن هذه الطريقة تعمل بشكل جيد عند استخدام مواد التضاريس أحادية اللون والأنسجة ذات الدقة المنخفضة ، أو عند استخدام تجاوز الهوامش . مع تعديلات طفيفة ، يمكن أيضًا تطبيقها على شبكات التضاريس.

هنا هو رمز الخيار متعدد الألوان:

[Header("The following settings are only if using the multi-color terrain shader")]
//Shader that renders the unlit terraom of an object
public Shader unlitTerrainShader;
//The render texture which will store the normals of our terrain
public RenderTexture surfaceTexture;
//An unlit terrain material used to capture the texture of our terrain without any lighting
public Material unlitTerrainMaterial;
//The terrain you want to capture the textures of
public Terrain yourTerrain;
 
[ContextMenu("Bake Surface Texture")]
public void BakeTerrainSurface()
{
    UpdateBakingCamera();
 
    //return if there is no terrain assigned
    if (yourTerrain == null)
    {
        Debug.Log("You need to assign a terrain to capture surface texture");
        return;
    }
 
    StartCoroutine(BakeColors());
}
 
IEnumerator BakeColors()
{
    Material tempTerrainMaterial = yourTerrain.materialTemplate;
 
    yourTerrain.materialTemplate = unlitTerrainMaterial;
 
    yield return 0;
 
    cam.SetReplacementShader(unlitTerrainShader, "RenderType");
    cam.targetTexture = surfaceTexture;
    Shader.SetGlobalTexture("TB_SURFACE", surfaceTexture);
 
    yield return 0;
 
    cam.targetTexture = null;
    yourTerrain.materialTemplate = tempTerrainMaterial;
 
    yield return null;
 
}

التغيير الوحيد في التظليل هو أنه بدلاً من استخدام نسيج محدد مسبقًا ، نستخدم نسيج سطح تضاريس محدد عالميًا والذي سيستخدم الموضع النسبي مثل الأشعة فوق البنفسجية. يتيح لك الامتداد الإضافي الحصول على مزيج أكثر متعة من القوام.


مزج مواد متعددة

هنا رسم بياني متعدد الألوان كامل مع تظليل مزج عادي:




استنتاج


تهانينا إذا كنت قد قرأت حتى هذه اللحظة! كما قلت ، هذا هو دليلي الأول ، لذا سأكون ممتنًا حقًا للتعليقات. إذا كنت تريد مساعدتي في إنشاء الألعاب والبرامج التعليمية ، فألق نظرة هنا أو اشترك في تويتر الخاص بي .



تعلم المزيد عن الدورة

All Articles