رحلة استكشاف الرمال تظليل

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

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


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

تحليل الرمال في رحلة


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


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

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

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

يعرض الرسم البياني أدناه جميع الآثار التي سنتعلمها في هذا البرنامج التعليمي. من الناحية الفنية ، يتم إجراء الحسابات العادية قبل معالجة الإضاءة. لسهولة الدراسة ، سيتم وصف الآثار في ترتيب مختلف.


لون منتشر

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



قبل وبعد تطبيق المعادلة

الرمال طبيعية

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



إضاءة الحافة

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



انعكاس مرآة المحيط

أحد أكثر جوانب لعبة Journey متعة هي القدرة على "تصفح" الكثبان الرملية. ربما هذا هو السبب في أن تلك اللعبة أرادت أن تشعر الرمال بأنها سائلة أكثر من كونها صلبة. لهذا ، تم استخدام انعكاس قوي ، والذي يمكن العثور عليه في كثير من الأحيان في تظليل المياه. يطلق جون إدواردز على هذا التأثير المحيطي ، وفي البرنامج التعليمي نطبقه باستخدام انعكاس Blinn-Fong .



انعكاس الوهج

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



أمواج الرمال

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



رحلة الرمال شادر التشريح


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

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

وظيفة السطح


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

 void surf (Input IN, inout SurfaceOutput o) { o.Albedo = _SandColor; o.Alpha = 1; float3 N = float3(0, 0, 1); N = RipplesNormal(N); N = SandNormal (N); o.Normal = N; } 

عند كتابة الأمور الطبيعية على o.Normal يجب التعبير عنها في مساحة الظل . هذا يعني أنه تم تحديد المتجه بالنسبة لسطح النموذج الثلاثي الأبعاد. وهذا يعني أن float3(0, 0, 1) يعني في الواقع أنه لا توجد تغييرات بالفعل على النموذج الثلاثي الأبعاد العادي.

كلتا الدالتين ، RipplesNormal ، و SandNormal المتجه العادي وتعديله. في وقت لاحق سوف نرى كيف يمكن القيام بذلك.

وظيفة الإضاءة


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

 #pragma surface surf Journey fullforwardshadows float4 LightingJourney (SurfaceOutput s, fixed3 viewDir, UnityGI gi) { float3 diffuseColor = DiffuseColor (); float3 rimColor = RimLighting (); float3 oceanColor = OceanSpecular (); float3 glitterColor = GlitterSpecular (); float3 specularColor = saturate(max(rimColor, oceanColor)); float3 color = diffuseColor + specularColor + glitterColor; return float4(color * s.Albedo, 1); } 

طريقة الجمع بين المكونات تعسفية للغاية وتسمح لنا بتغييرها لدراسة الاحتمالات الفنية.

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

الجزء 2. منتشر اللون


في الجزء الثاني من المنشور ، سنركز على نموذج الإضاءة المستخدم في اللعبة وعلى ذلك. كيفية إعادة إنشائها في الوحدة.

في الجزء السابق ، وضعنا الأساس لما سيتحول تدريجياً إلى نسختنا من تظليل الرمال Journey. كما ذكرنا سابقًا ، يتم استخدام وظيفة الإضاءة في تظليل السطح لحساب تأثير الإضاءة ، بحيث تظهر الظلال والإبرازات على السطح. لقد اكتشفنا أن Journey لها العديد من الآثار التي تندرج في هذه الفئة. سنبدأ بالتأثير الأساسي (والأبسط) الموجود في لب هذا التظليل: الإضاءة المنتشرة ( الإضاءة المنتشرة / المنتشرة).


في الوقت الحالي ، نحذف جميع الآثار والمكونات الأخرى ، مع التركيز على إضاءة الرمال .

وظيفة الإضاءة التي DiffuseColor في الجزء السابق من DiffuseColor يطلق عليه LightingJourney تفوض ببساطة حساب لون الرمال المنتشر إلى وظيفة تسمى DiffuseColor .

 float4 LightingJourney (SurfaceOutput s, fixed3 viewDir, UnityGI gi) { // Lighting properties float3 L = gi.light.dir; float3 N = s.Normal; // Lighting calculation float3 diffuseColor = DiffuseColor(N, L); // Final color return float4(diffuseColor, 1); } 

نظرًا لحقيقة أن كل تأثير قائم بذاته وتخزينه في وظيفته الخاصة ، سيكون كودنا أكثر نمطيًا ونظيفة.

لامبرت التفكير


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

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


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

قيمة N و L
عادي على السطح Nهو ناقل وحدة موجهة بعيدا عن السطح نفسه.

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

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

انعكاس لامبرت في الوحدة
قبل Unity 5 Standard Shader ، كان انعكاس Lambert هو النموذج القياسي لتظليل الأسطح المضيئة.

لا يزال بإمكانك الوصول إليه في Material Inspector: في تظليل Legacy ، يطلق عليه Diffuse .

إذا كتبت تظليل السطح الخاص بك ، فإن انعكاس لامبرت متاح كدالة إضاءة تسمى Lambert :

 #pragma surface surf Lambert fullforwardshadows 

يمكن العثور على تطبيقه في وظيفة LightingLambert المحددة في الملف CGIncludes\Lighting.cginc .

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

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


من الواضح ، الزاوية بين Nو Lحرجة للتفكير وفقا لامبرت. وعلاوة على ذلك ، فإن السطوع هو الحد الأقصى ويساوي 100 دولار \ ٪ دولار عندما تكون الزاوية 0والحد الأدنى ( 0) عندما تميل الزاوية 90 circ. إذا كنت معتادًا على الجبر المتجه ، فيمكنك أن تفهم أن الكمية تمثل انعكاس لامبرت Iيساوي N cdotLاين المشغل  cdotدعا منتج العددية .

(1)

عرض $$ $$ \ تبدأ {المعادلة *} I = N \ cdot L \ end {equation *} $$ عرض $$


منتج العددية هو مقياس لـ "المصادفة" بين متجهين بالنسبة لبعضهما البعض ، ويختلف في الفاصل الزمني من +1دولا(لاثنين من متجهات متطابقة) ل 1دولا(لاثنين من ناقلات العكس). المنتج القياسي هو أساس التظليل ، الذي درسته بالتفصيل في البرنامج التعليمي " نماذج العرض والإضاءة المادي" .

تطبيق


و الى Nو إلى Lيمكنك بسهولة الوصول إلى ميزات إضاءة تظليل السطح من خلال s.Normal و gi.light.dirin . للبساطة ، سنقوم بإعادة تسميتها في رمز التظليل إلى N و L

 float3 DiffuseColor(float3 N, float3 L) { float NdotL = saturate( dot(N, L) ); return NdotL; } 

وظيفة saturate يحد من قيمة 0إلى 1. ومع ذلك ، لأن المنتج القياسي في النطاق من 1دولاإلى +1دولاسنحتاج للعمل فقط بقيمها السلبية. وهذا هو السبب وراء تنفيذ انعكاس لامبرت في الغالب على النحو التالي:

 float NdotL = max(0, dot(N, L) ); 

انعكاس التباين للضوء المحيط


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

أحد هذه النماذج هو نموذج انعكاس Oren-Nayyar ، الذي تم تحديده في الأصل في مقال تعميم نموذج الانعكاس لامبرت ، الذي نشره عام 1994 مايكل أورين و Sri C. Nayyar. نموذج Oren-Nayyar هو تعميم لامبرت الانعكاس ومصمم خصيصا للأسطح الخشنة. في البداية ، أراد مطورو Journey استخدام انعكاس Oren-Nayyar كأساس لتظليل الرمال. ومع ذلك ، تم التخلي عن هذه الفكرة بسبب ارتفاع تكاليف الحوسبة.

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

ووفقا له ، فإن نموذج التظليل الناتج يتوافق مع هذه المعادلة:

(2)

عرض $$ $ \ تبدأ {المعادلة *} I = 4 * \ اليسار (\ اليسار (N \ odot \ left [1 ، 0.3 ، 1 \ right] \ right) \ cdot L \ right) \ end {equation *} عرض $$ $


حيث  odot- عنصر - المنتج الحكيم لاثنين من المتجهات.

 float3 DiffuseColor(float3 N, float3 L) { Ny *= 0.3; float NdotL = saturate(4 * dot(N, L)); return NdotL; } 

نموذج الانعكاس (2) يطلق John Edwards تباينًا منتشرًا ، لذلك سوف نستخدم هذا الاسم خلال البرنامج التعليمي.

توضح الرسوم المتحركة أدناه الفرق في تظليل لامبرت (يسار) والتباين المنتشر من Journey (يمين).



ما معنى 4 و 0.3؟
على الرغم من أن التباين المنتشر لم يتم تصميمه ليكون دقيقًا من الناحية البدنية ، إلا أنه لا يزال بإمكاننا محاولة فهم ما يفعله.

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

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

ملاحظة: يقيس المنتج القياسي مباشرة الزاوية بين متجهين فقط إذا كان لكل منهما طول 1. التغيير المحرز يقلل من الطول الطبيعي Nالذي لم يعد متجه وحدة.

من ظلال رمادية إلى اللون


جميع الرسوم المتحركة الموضحة أعلاه لها ظلال رمادية ، لأنها تظهر قيم نموذج الانعكاس ، متفاوتة في الفاصل الزمني من 0إلى 1". يمكننا بسهولة إضافة ألوان باستخدام NdotL استيفاء بين لونين: أحدهما مظلل بالكامل والآخر للرمل مضاء بالكامل.

 float3 _TerrainColor; float3 _ShadowColor; float3 DiffuseColor(float3 N, float3 L) { Ny *= 0.3; float NdotL = saturate(4 * dot(N, L)); float3 color = lerp(_ShadowColor, _TerrainColor, NdotL); return color; } 

الجزء 3. الرمال العادية


في الجزء الثالث ، سنركز على إنشاء خرائط طبيعية تحول نماذج ثلاثية الأبعاد ناعمة إلى كثبان رملية.

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


أحد أكثر الآثار إثارة للاهتمام في Journey هو نعومة الرمال. عند النظر إلى أي لقطة شاشة ، يبدو لنا أن الكثبان الرملية ليست سلسة ومتجانسة ، ولكن تم إنشاؤها من ملايين الحبوب المجهرية من الرمال.


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



يمكن ملاحظة الاختلافات الصغيرة مع زيادة:



نحن نتعامل مع الخرائط العادية


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

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


ويمكن القيام بذلك بطرق لا حصر لها. الأبسط هو إنشاء نسيج يغير اتجاه القواعد الطبيعية الأصلية لنموذج الكثبان الرملية.

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

يعد تغيير الحالات الطبيعية مهمة بسيطة إلى حد ما يمكن القيام بها في وظيفة surf تظليل السطح . تأخذ هذه الوظيفة معلمتين ، واحدة منها عبارة عن struct تسمى SurfaceOutput . أنه يحتوي على جميع الخصائص اللازمة لتقديم جزء من نموذج ثلاثي الأبعاد ، من لونه ( o.Albedo ) إلى الشفافية ( o.Alpha ). المعلمة الأخرى التي يحتوي عليها هي الاتجاه العادي ( o.Normal ) ، والذي يمكن إعادة كتابته لتغيير طريقة انعكاس الضوء على النموذج.

وفقًا لوثائق الوحدة على تظليل السطح ، يجب التعبير عن جميع o.Normal الطبيعية المكتوبة على هيكل o.Normal في مساحة الظل :

 struct SurfaceOutput { fixed3 Albedo; // diffuse color fixed3 Normal; // tangent space normal, if written fixed3 Emission; half Specular; // specular power in 0..1 range fixed Gloss; // specular intensity fixed Alpha; // alpha for transparencies }; 

وبالتالي ، يمكننا الإبلاغ عن وجوب التعبير عن متجهات الوحدة في نظام الإحداثيات بالنسبة للشبكة العادية. على سبيل المثال ، عند الكتابة إلى o.Normal قيم float3(0, 0, 1) عادية كما هي.

 void surf (Input IN, inout SurfaceOutput o) { o.Albedo = _SandColor; o.Alpha = 1; o.Normal = float3(0, 0, 1); } 

هذا لأن المتجه float3(0, 0, 1) هو في الواقع متجه طبيعي معبر عنه بالنسبة لهندسة النموذج الثلاثي الأبعاد.

لذلك ، لتغيير الطبيعي إلى السطح في تظليل السطح ، نحتاج فقط إلى كتابة متجه جديد في وظيفة السطح في o.Normal :

 void surf (Input IN, inout SurfaceOutput o) { o.Albedo = _SandColor; o.Alpha = 1; o.Normal = ... // change the normal here } 

في بقية المنشور ، سننشئ تقريبًا أوليًا ، والذي سنعقده في الجزء السادس من البرنامج التعليمي.

الرمال طبيعية


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

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

يمكن اختيار عينات عشوائية باستخدام نسيج مملوء بألوان عشوائية. تستخدم المكونات R و G و B لكل بكسل كمكونات X و Y و Z للمتجه العادي. مكونات اللون في النطاق  left[0،1 right]، لذلك تحتاج إلى تحويلها إلى فاصل  left[1،+1 right]. ثم يتم تطبيع المتجه الناتج بحيث يكون طوله مساوياً 1.


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

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

خلال حديث GDC ، أوضح جون إدواردز أن النسيج العشوائي المستخدم للرمال في رحلة تم توليده من توزيع غوسي. هذا يضمن أن الاتجاه السائد يتزامن مع العادي إلى السطح.

هل تحتاج النواقل العشوائية إلى التطبيع؟
تم إنشاء الصورة التي استخدمتها لأخذ عينات من المتجهات العشوائية باستخدام عملية عشوائية تمامًا. ليس فقط يتم إنشاء كل بكسل بشكل فردي: المكونات R و G و B من بكسل واحد هي أيضا مستقلة عن بعضها البعض. وهذا هو ، في الحالة العامة ، لن يتم ضمان أن يكون للمتجهات التي تم أخذ عينات منها من هذا الملمس أن يكون طولها مساويًا 1.

بالطبع ، يمكنك إنشاء نسيج فيه كل بكسل عند التحويل منه  left[0،1 right]في  left[1،+1 right]وفي الواقع سوف يكون لها طول 1. ومع ذلك ، مشكلتين تنشأ هنا.

, . -, mip-, .

, .

تطبيق


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

 void surf (Input IN, inout SurfaceOutput o) { o.Albedo = _SandColor; o.Alpha = 1; float3 N = float3(0, 0, 1); N = RipplesNormal(N); // Covered in Journey Sand Shader #6 N = SandNormal (N); // Covered in this article o.Normal = N; } 

في القسم السابق ، قدمنا ​​مفهوم تعيين نتوء ، والذي أظهر لنا أن جزءًا من التأثير سيتطلب أخذ عينات من الملمس (يطلق عليه في الكود uv_SandTex).

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

 N = WavesNormal(IN.uv_SandTex.xy, N); N = SandNormal (IN.uv_SandTex.xy, N); 

أو يمكنك أيضًا استخدام الموضع في العالم ( IN.worldPos) من النقطة المقدمة.

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

 sampler2D_float _SandTex; float3 SandNormal (float2 uv, float3 N) { // Random vector float3 random = tex2D(_SandTex, uv).rgb; // Random direction // [0,1]->[-1,+1] float3 S = normalize(random * 2 - 1); return S; } 

كيفية تكبير نسيج عشوائي؟
UV- 3D- , . , .

, Unity . , _SandText_ST . Unity ( ) _SandTex .

_SandText_ST : . , Tiling Offset :


, TRANSFORM_TEX :

 sampler2D_float _SandTex; float4 _SandTex_ST; float3 SandNormal (float2 uv, float3 N) { // Random vector float3 random = tex2D(_SandTex, TRANSFORM_TEX(uv, _SandTex)).rgb; // Random direction // [0,1]->[-1,+1] float3 S = normalize(random * 2 - 1); return S; } 

إمالة الحالات الطبيعية


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

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



كلا الحلول لا تناسبنا. نحن بحاجة إلى شيء بينهما. يجب استخدام اتجاه عشوائي تم أخذ عينات من نسيج لإمالة الوضع العادي بمقدار معين ، كما هو موضح أدناه:


العملية الموصوفة في الرسم البياني تسمى slerp ، والتي تعني الاستيفاء الخطي الكروي (الاستيفاء الخطي الكروي). تعمل Slerp تمامًا مثل lerp ، مع استثناء واحد - يمكن استخدامه للتحريف بأمان بين متجهات الوحدة ، وستكون نتيجة العملية متجهات وحدة أخرى.

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

أرني المعادلة slerp
, p0و p1, . ثم slerp:

(1)

slerp(p0,p1,t)=sin[(1t)Ω]sin(Ω)p0+sin(tΩ)sin(Ω)p1


Ωp0و p1, :

(2)

Ω=cos1(p0p1)



من المهم أن نلاحظ أنه إذا استخدمنا الاستيفاء الخطي التقليدي ، سيبدو المتجه الناتج مختلفًا تمامًا:


لا تؤدي عملية Lerp بين متجهين منفصلين للوحدة دائمًا إلى إنشاء متجهات أخرى للوحدة. في الواقع ، هذا لا يحدث أبدًا ، ما لم يكن المعامل أو10 .

على الرغم من ذلك ، عند تطبيع نتيجة lerp ، نحصل فعليًا على وحدة متجه ، والتي تكون قريبة بشكل مدهش من النتيجة الناتجة عن slerp:

 float3 nlerp(float3 n1, float3 n2, float t) { return normalize(lerp(n1, n2, t)); } 

توفر هذه التقنية ، المسماة nlerp ، تقريبًا دقيقًا لل slerp. شاع استخدامه من قبل كيسي موراتوري ، أحد مطوري The Witness . إذا كنت مهتمًا بمعرفة المزيد حول هذا الموضوع ، فإنني أوصي بفهم مقالات Slerp. ثم عدم استخدامه جوناثان بلو و الرياضيات الساحر - Lerp، Slerp، وNlerp .

بفضل nlerp ، يمكننا الآن إمالة ناقلات طبيعية بكفاءة إلى جانب عشوائي ، عينات من _SandTex:

 sampler2D_float _SandTex; float _SandStrength; float3 SandNormal (float2 uv, float3 N) { // Random vector float3 random = tex2D(_SandTex, uv).rgb; // Random direction // [0,1]->[-1,+1] float3 S = normalize(random * 2 - 1); // Rotates N towards Ns based on _SandStrength float3 Ns = nlerp(N, S, _SandStrength); return Ns; } 

النتيجة مبينة أدناه:



ما التالي


في الجزء التالي ، سننظر في الانعكاسات الوامضة ، وبفضلها ستشبه الكثبان الرملية المحيط.

شكر


تم تطوير لعبة فيديو Journey بواسطة Thatgamecompany ونشرتها Sony Computer Entertainment . وهي متوفرة لأجهزة الكمبيوتر الشخصية ( Epic Store ) و PS4 ( متجر PS ).

يتم إنشاء نماذج ثلاثية الأبعاد لخلفيات الكثبان الرملية وخيارات الإضاءة بواسطة Jiadi Deng .

تم العثور على نموذج ثلاثي الأبعاد لشخصية Journey في منتدى FacePunch (مغلق الآن).

حزمة الوحدة


إذا كنت ترغب في إعادة إنشاء هذا التأثير ، فيمكنك تنزيل حزمة Unity الكاملة من Patreon . ويشمل كل ما تحتاجه ، من التظليل إلى النماذج ثلاثية الأبعاد.

Source: https://habr.com/ru/post/ar476448/


All Articles