إنشاء ماين كرافت الخاص بك: توليد مستويات 3D من مكعبات


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

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

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

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

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

 terraintree =
 {
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1}
 } 

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

في حالة ثنائي الأبعاد ، تستقبل وظيفة التدرج اللوني قطعة مستقيمة في النموذج (x1 ، x2 ، y1 ، y2) ، وفي حالة 3D ، يتم توسيع التنسيق إلى (x1 ، x2 ، y1 ، y2 ، z1 ، z2). تشير النقطة التي تم تشكيلها بواسطة (x1 ، y1) إلى بداية مقطع الخط المرتبط بـ 0. والنقطة التي تم تشكيلها (x2 ، y2) هي نهاية المقطع المرتبط بـ 1. وهذا هو ، حيث نقوم بتعيين مقطع الخط (0،1) -> ( 0،0) مع التدرج. لذلك ، سيكون التدرج بين مناطق الوظيفة Y = 1 و Y = 0. وهذا يعني أن هذا الشريط يمثل أبعاد العالم في Y. أي جزء من العالم سيكون في هذا الشريط. يمكننا التقاط أي منطقة على طول X (تقريبًا الإعلان اللانهائي ، ولكن الدقة double تحدنا) ، لكن كل شيء مثير للاهتمام ، على سبيل المثال سطح الأرض سيكون ضمن هذه الفرقة. يمكن تغيير هذا السلوك ، ولكن في داخلنا لدينا قدر كبير من المرونة. لا تنسَ أن أي قيم أعلى أو أقل من هذا النطاق من المرجح أن تكون غير مهمة ، لأن القيم المذكورة أعلاه من المرجح أن تكون الهواء ، والقيم أدناه هي أرض. (كما سترى قريبًا ، قد يكون هذا البيان خاطئًا.) بالنسبة لمعظم الصور في هذه السلسلة ، سأطابق المنطقة المربعة المعطاة في المربع (0،1) -> (1،0) في مساحة ثنائية الأبعاد. لذلك ، في البداية يبدو عالمنا كما يلي:


لا شيء مثير للاهتمام حتى الآن ؛ علاوة على ذلك ، لا تجيب هذه الصورة على السؤال "هل النقطة المعطاة صلبة أم مجوفة؟". للإجابة على هذا السؤال ، نحتاج إلى تطبيق Step Function ( دالة محددة قطعة). بدلاً من التدرج السلس ، نحتاج إلى فصل واضح ، تكون فيه جميع المواقع على جانب واحد مجوفة ، وجميع المواقع على الجانب الآخر صلبة. في ANL ، يمكن تنفيذ ذلك باستخدام وظيفة التحديد . تستقبل الدالة Select وظيفتين أو قيمتين (في هذه الحالة ، ستكون مساوية لـ "صلب" و "مجوف" (مفتوح)) ، وتختارهما استنادًا إلى قيمة وظيفة التحكم (في هذه الحالة ، التدرج). تحتوي الوحدة النمطية Select على معلمتين إضافيتين ، العتبة والهبوط ، والتي تؤثر على هذه العملية. في هذه المرحلة ، يكون السقوط غير مرغوب فيه ، لذلك سنجعله يساوي 0. تحدد المعلمة الحد الفاصل أين سيذهب خط الفاصل بين Solid و Open. كل شيء سيكون أكبر من هذه القيمة في وظيفة التدرج اللوني سوف يتحول إلى صلب ، وكل شيء أقل من العتبة سيصبح مفتوحًا. بما أن التدرج اللوني يقارن الفاصل الزمني بالقيم من 0 و 1 ، فسيكون من المنطقي وضع العتبة عند 0.5. لذلك نقسم المساحة تمامًا إلى النصف. ستكون القيمة 1 موقعًا قويًا ، وستكون القيمة 0 جوفاء. وهذا هو ، نحدد وظيفة الطائرة الأرضية على النحو التالي:

 terraintree =
 {
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	 {name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "ground_gradient"}
 }

بمقارنة نفس منطقة الوظيفة كما كان من قبل ، نحصل على شيء مماثل:


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

"الاضطراب" هو تسمية معقدة لمفهوم إضافة القيم إلى الإحداثيات الواردة للوظيفة. تخيل أننا نسمي الوظيفة المذكورة أعلاه للأرض بالتنسيق (0،1). تقع فوق المستوى الأرضي ، لأن التدرج في Y = 1 له قيمة 0 ، أي أقل من العتبة = 0.5. وهذا هو ، سيتم احتساب هذه النقطة على أنها فتح. ولكن ماذا لو ، قبل التذرع بوظيفة الأرض ، قمنا بتغيير هذه النقطة بطريقة أو بأخرى؟ افترض أننا نطرح قيمة عشوائية من الإحداثي ص ، على سبيل المثال ، 3. نطرح 3 ونحصل على الإحداثي (0 ، -2). إذا قمنا الآن باستدعاء الوظيفة الأرضية لهذه النقطة ، فستكون النقطة صلبة ، لأن Y = -2 تقع أسفل شريحة التدرج المقابلة لـ 1. فجأة ، تتحول النقطة المجوفة (0،1) إلى مادة صلبة. سوف نحصل على كتلة من الحجر الصلب معلقة في الهواء. يمكن القيام بذلك مع أي نقطة في الوظيفة عن طريق إضافة أو طرح رقم عشوائي من الإحداثي ص الخاص بالنقطة الواردة قبل استدعاء الدالة ground_select. في ما يلي صورة لوظيفة ground_select التي توضح ذلك. قبل استدعاء دالة ground_select ، تتم إضافة القيمة في الفاصل الزمني (-0.25 ، 0.25) إلى الإحداثي Y لكل نقطة.


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

 terraintree =
 {
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	 {name = "ground_shape_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 2}،
	 {name = "ground_scale"، type = "scaleoffset"، scale = 0.5، offset = 0، source = "ground_shape_fractal"}،
	 {name = "ground_perturb"، type = "translomain"، source = "ground_gradient"، ty = "ground_scale"}،
	
	 {name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "ground_perturb"}
 }

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


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


في الصورة أعلاه ، جميع النقاط السوداء لها قيمة -0.25 ، وجميع النقاط البيضاء لها قيمة 0.25. وهذا هو ، عندما يكون اللون النمطي هندسي متكرر ، سيتم تحويل النقطة المقابلة لوظيفة الأرض إلى "أسفل" بمقدار 0.25. (0.25 تعني 1/4 من الشاشة.) نظرًا لأنه يمكن إزاحة نقطة واحدة قليلاً ، والنقطة الأخرى فوقها في الفضاء يمكن إزاحتها أكثر ، فهناك احتمال نتوءات من الصخور والجزر الطائرة. النتوءات في الطبيعة طبيعية تمامًا ، على عكس الجزر الطائرة. (ما لم نكن في فيلم "Avatar".) إذا كانت لعبتك تحتاج إلى مثل هذا المشهد الرائع ، فهي رائعة ، ولكن إذا كنت بحاجة إلى نموذج أكثر واقعية ، فنحن بحاجة إلى ضبط الوظيفة الكسورية قليلاً. لحسن الحظ ، يمكن أن وظيفة ScaleDomain القيام بذلك .

نريد أن نجعل الوظيفة تتصرف مثل وظيفة خريطة الارتفاع. تخيل خريطة ارتفاع ثنائية الأبعاد حيث تمثل كل نقطة على الخريطة ارتفاع نقطة في شبكة نقاط الشبكة التي يتم رفعها لأعلى أو لأسفل. تشير القيم البيضاء للخريطة إلى التلال العالية ، والوديان المنخفضة السوداء. نحن بحاجة إلى سلوك مماثل ، ولكن من أجل تحقيق ذلك ، نحتاج إلى التخلص من أحد الأبعاد. في حالة خريطة الارتفاع ، نقوم بإنشاء ارتفاع ثلاثي الأبعاد من خريطة ارتفاع ثنائية الأبعاد. وبالمثل ، في حالة التضاريس ثنائية الأبعاد ، نحتاج إلى خريطة ارتفاع 1D. بعد أن أوضحت أن جميع نقاط كسورية مع نفس إحداثي Y لها نفس القيمة ، يمكننا تحويل كل النقاط بنفس إحداثي X بنفس المقدار ، وبالتالي تختفي الجزر الطائرة. للقيام بذلك ، يمكنك استخدام ScaleDomain ، وإعادة ضبط معامل التدرج. وهذا هو ، قبل استدعاء دالة ground_shape_fractal ، ندعو ground_scale_y لتعيين إحداثي y إلى 0. وهذا يضمن أن القيمة Y لا تؤثر على إخراج الفراكتل ، وبالتالي تحويلها إلى وظيفة ضوضاء 1D. للقيام بذلك ، سنقوم بإجراء التغييرات التالية:

 terraintree =
 {
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	 {name = "ground_shape_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 2}،
	 {name = "ground_scale"، type = "scaleoffset"، scale = 0.5، offset = 0، source = "ground_shape_fractal"}،
	 {name = "ground_scale_y"، type = "scaledomain"، source = "ground_scale"، scaley = 0}،
	 {name = "ground_perturb"، type = "translomain"، source = "ground_gradient"، ty = "ground_scale_y"}،
	
	 {name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "ground_perturb"}
 }

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


الآن إذا ألقينا نظرة على المخرجات ، فسنحصل على النتيجة:


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

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

 terraintree =
 {
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	 {name = "ground_shape_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 2}،
	 {name = "ground_scale"، type = "scaleoffset"، scale = 0.5، offset = 0، source = "ground_shape_fractal"}،
	 {name = "ground_scale_y"، type = "scaledomain"، source = "ground_scale"، scaley = 0}،
	 {name = "ground_perturb"، type = "translomain"، source = "ground_gradient"، ty = "ground_scale_y"}،
	 {name = "ground_overhang_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 2}،
	 {name = "ground_overhang_scale" ، اكتب = "scaleoffset" ، source = "ground_overhang_fractal" ، المقياس = 0.2 ، الإزاحة = 0} ،
	 {name = "ground_overhang_perturb"، type = "translomain"، source = "ground_perturb"، tx = "ground_overhang_scale"}،
	
	 {name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "ground_overhang_perturb"}
 }

وهنا النتيجة:


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


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

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

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

سفوح:

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

 {name = "lowland_shape_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 2، frequency = 1}،
 {name = "lowland_autocorrect"، type = "autocorrect"، source = "lowland_shape_fractal"، low = 0، high = 1}،
 {name = "lowland_scale"، type = "scaleoffset"، source = "lowland_autocorrect"، scale = 0.2، offset = -0.25}،
 {name = "lowland_y_scale"، type = "scaledomain"، source = "lowland_scale"، scaley = 0}،
 {name = "lowland_terrain"، type = "translomain"، source = "ground_gradient"، ty = "lowland_y_scale"}،

الهضبة:

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

 {name = "highland_shape_fractal"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 2}،
 {name = "highland_autocorrect"، type = "autocorrect"، source = "highland_shape_fractal"، low = 0، high = 1}،
 {name = "highland_scale"، type = "scaleoffset"، source = "highland_autocorrect"، scale = 0.45، offset = 0}،
 {name = "highland_y_scale"، type = "scaledomain"، source = "highland_scale"، scaley = 0}،
 {name = "highland_terrain"، type = "translomain"، source = "ground_gradient"، ty = "highland_y_scale"}،

الجبل:

 {name = "mountain_shape_fractal"، type = "fractal"، fractaltype = anl.BILLOW، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 4، frequency = 1}،
 {name = "mountain_autocorrect"، type = "autocorrect"، source = "mountain_shape_fractal"، low = 0، high = 1}،
 {name = "mountain_scale"، type = "scaleoffset"، source = "mountain_autocorrect"، scale = 0.75، offset = 0.25}،
 {name = "mountain_y_scale"، type = "scaledomain"، source = "mountain_scale"، scaley = 0.1}،
 {name = "mountain_terrain"، type = "translomain"، source = "ground_gradient"، ty = "mountain_y_scale"}،

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

 {name = "terrain_type_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 3، frequency = 0.5}،
 {name = "terrain_autocorrect"، type = "autocorrect"، source = "terrain_type_fractal"، low = 0، high = 1}،
 {name = "terrain_type_cache" ، اكتب = "cache" ، source = "terrain_autocorrect"} ،
 {name = "highland_mountain_select"، type = "select"، low = "highland_terrain"، high = "mountain_terrain"، control = "terrain_type_cache"، العتبة = 0.55، falloff = 0.15}،
 {name = "highland_lowland_select"، type = "select"، low = "lowland_terrain"، high = "highland_mountain_select"، control = "terrain_type_cache"، عتبة = 0.25، falloff = 0.15}،

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

 terraintree =
 {
	 {name = "lowland_shape_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 2، frequency = 1}،
	 {name = "lowland_autocorrect"، type = "autocorrect"، source = "lowland_shape_fractal"، low = 0، high = 1}،
	 {name = "lowland_scale"، type = "scaleoffset"، source = "lowland_autocorrect"، scale = 0.2، offset = -0.25}،
	 {name = "lowland_y_scale"، type = "scaledomain"، source = "lowland_scale"، scaley = 0}،
	 {name = "lowland_terrain"، type = "translomain"، source = "ground_gradient"، ty = "lowland_y_scale"}،
	 {name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	 {name = "highland_shape_fractal"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 2}،
	 {name = "highland_autocorrect"، type = "autocorrect"، source = "highland_shape_fractal"، low = 0، high = 1}،
	 {name = "highland_scale"، type = "scaleoffset"، source = "highland_autocorrect"، scale = 0.45، offset = 0}،
	 {name = "highland_y_scale"، type = "scaledomain"، source = "highland_scale"، scaley = 0}،
	 {name = "highland_terrain"، type = "translomain"، source = "ground_gradient"، ty = "highland_y_scale"}،

	 {name = "mountain_shape_fractal"، type = "fractal"، fractaltype = anl.BILLOW، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 4، frequency = 1}،
	 {name = "mountain_autocorrect"، type = "autocorrect"، source = "mountain_shape_fractal"، low = 0، high = 1}،
	 {name = "mountain_scale"، type = "scaleoffset"، source = "mountain_autocorrect"، scale = 0.75، offset = 0.25}،
	 {name = "mountain_y_scale"، type = "scaledomain"، source = "mountain_scale"، scaley = 0.1}،
	 {name = "mountain_terrain"، type = "translomain"، source = "ground_gradient"، ty = "mountain_y_scale"}،

	 {name = "terrain_type_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 3، frequency = 0.5}،
	 {name = "terrain_autocorrect"، type = "autocorrect"، source = "terrain_type_fractal"، low = 0، high = 1}،
	 {name = "terrain_type_cache" ، اكتب = "cache" ، source = "terrain_autocorrect"} ،
	 {name = "highland_mountain_select"، type = "select"، low = "highland_terrain"، high = "mountain_terrain"، control = "terrain_type_cache"، العتبة = 0.55، falloff = 0.15}،
	 {name = "highland_lowland_select"، type = "select"، low = "lowland_terrain"، high = "highland_mountain_select"، control = "terrain_type_cache"، عتبة = 0.25، falloff = 0.15}،
	 {name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "highland_lowland_select"}
 }

فيما يلي بعض الأمثلة على النقوش الناتجة:




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

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

 {name = "cave_shape"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 1، frequency = 2}،

والنتيجة هي شيء مثل هذا:


إذا طبقنا وظيفة Select كدالة محددة بالقطع ، كما فعلنا مع التدرج الأرضي ، ننفذها بحيث يكون الجزء السفلي من الحد المحدد 1 (لا يوجد كهف) ، والجزء العلوي هو 0 (هناك كهف) ، ستبدو النتيجة كما يلي :

 {name = "cave_shape"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 1، frequency = 2}،
 {name = "cave_select" ، اكتب = "select" ، منخفض = 1 ، مرتفع = 0 ، تحكم = "cave_shape" ، عتبة = 0.8 ، سقوط = 0} ،

النتيجة:


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

 {name = "cave_shape"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 1، frequency = 2}،
 {name = "cave_select" ، اكتب = "select" ، منخفض = 1 ، مرتفع = 0 ، تحكم = "cave_shape" ، عتبة = 0.8 ، سقوط = 0} ،
 {name = "cave_perturb_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 3}،
 {name = "cave_perturb_scale"، type = "scaleoffset"، source = "cave_perturb_fractal"، scale = 0.25، offset = 0}،
{name = "cave_perturb"، type = "translomain"، source = "cave_select"، tx = "cave_perturb_scale"}،

النتيجة:


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


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

{name = "highland_lowland_select"، type = "select"، low = "lowland_terrain"، high = "highland_mountain_select"، control = "terrain_type_cache"، عتبة = 0.25، falloff = 0.15}،
{name = "highland_lowland_select_cache" ، اكتب = "cache" ، source = "highland_lowland_select"} ،
{name = "ground_select" ، اكتب = "select" ، منخفض = 0 ، مرتفع = 1 ، عتبة = 0.5 ، تحكم = "highland_lowland_select_cache"} ،

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

{name = "cave_shape"، type = "fractal"، fractaltype = anl.RIDGEDMULTI، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 1، frequency = 4}،
{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape", source_1="cave_attenuate_bias"},
{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},

بادئ ذي بدء ، أضفنا وظيفة التحيز . هذا للراحة ، لأنه يسمح لنا بضبط الفاصل الزمني لوظيفة التوهين المتدرج. ثم يتم إضافة وظيفة cave_shape_attenuate ، والتي هي Combined من النوع anl :: MULT . انها تتكاثر التدرج بواسطة cave_shape . ثم يتم تمرير نتيجة هذه العملية إلى وظيفة cave_perturb . النتيجة تبدو شيء مثل هذا:


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

terraintree =
 {
	{name = "ground_gradient" ، type = "gradient" ، x1 = 0 ، x2 = 0 ، y1 = 0 ، y2 = 1} ،
	
	{name = "lowland_shape_fractal"، type = "fractal"، fractaltype = anl.BILLOW، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 2، frequency = 0.25}،
	{name="lowland_autocorrect", type="autocorrect", source="lowland_shape_fractal", low=0, high=1},
	{name="lowland_scale", type="scaleoffset", source="lowland_autocorrect", scale=0.125, offset=-0.45},
	{name="lowland_y_scale", type="scaledomain", source="lowland_scale", scaley=0},
	{name="lowland_terrain", type="translatedomain", source="ground_gradient", ty="lowland_y_scale"},
	
	{name="highland_shape_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=4, frequency=2},
	{name="highland_autocorrect", type="autocorrect", source="highland_shape_fractal", low=-1, high=1},
	{name="highland_scale", type="scaleoffset", source="highland_autocorrect", scale=0.25, offset=0},
	{name="highland_y_scale", type="scaledomain", source="highland_scale", scaley=0},
	{name="highland_terrain", type="translatedomain", source="ground_gradient", ty="highland_y_scale"},

	{name="mountain_shape_fractal", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=8, frequency=1},
	{name="mountain_autocorrect", type="autocorrect", source="mountain_shape_fractal", low=-1, high=1},
	{name="mountain_scale", type="scaleoffset", source="mountain_autocorrect", scale=0.45, offset=0.15},
	{name="mountain_y_scale", type="scaledomain", source="mountain_scale", scaley=0.25},
	{name="mountain_terrain", type="translatedomain", source="ground_gradient", ty="mountain_y_scale"},

	{name="terrain_type_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=3, frequency=0.125},
	{name="terrain_autocorrect", type="autocorrect", source="terrain_type_fractal", low=0, high=1},
	{name="terrain_type_y_scale", type="scaledomain", source="terrain_autocorrect", scaley=0},
	{name="terrain_type_cache", type="cache", source="terrain_type_y_scale"},
	{name="highland_mountain_select", type="select", low="highland_terrain", high="mountain_terrain", control="terrain_type_cache", threshold=0.55, falloff=0.2},
	{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
	{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
	{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},
	
	{name="cave_shape", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
	{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape", source_1="cave_attenuate_bias"},
	{name="cave_perturb_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=6, frequency=3},
	{name="cave_perturb_scale", type="scaleoffset", source="cave_perturb_fractal", scale=0.5, offset=0},
	{name="cave_perturb", type="translatedomain", source="cave_shape_attenuate", tx="cave_perturb_scale"},
	{name="cave_select", type="select", low=1, high=0, control="cave_perturb", threshold=0.48, falloff=0},
	
	{name = "ground_cave_multiply"، type = "combiner"، operation = anl.MULT، source_0 = "cave_select"، source_1 = "ground_select"}
 }

فيما يلي أمثلة على بطاقات عشوائية مشتقة من هذه الوظيفة:




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

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

القصور


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

الذهاب إلى 3D


كل هذا رائع إذا قمت بإنشاء لعبة مثل Terraria أو King Arthur's Gold ، ولكن ماذا لو كنت بحاجة إلى شيء مثل Minecraft أو Infiniminer؟ ما هي التغييرات التي سنحتاج إلى إجرائها في سلسلة الوظائف؟ في الواقع ، ليس هناك الكثير. ستعمل الوظيفة الموضحة أعلاه بدون تعديل للإغاثة ثلاثية الأبعاد. سيكون كافياً بالنسبة لك مقارنة مستوى الصوت ثلاثي الأبعاد باستخدام الأشكال ثلاثية الأبعاد للمولد ، وكذلك لمقارنة المحور Y بالمحور الرأسي للحجم ، وليس بالمنطقة ثنائية الأبعاد. ومع ذلك ، سيكون هناك حاجة لتغيير واحد ، وهو طريقة لتحقيق الكهوف. كما رأيت ، يعد Ridged Multifractal رائعًا لنظام الكهوف ثنائي الأبعاد ، ولكنه في الأبعاد الثلاثية يقطع الكثير من الأصداف المنحنية ، وليس الأنفاق ، ويظهر تأثيره خطأ. أي أنه من الضروري في ثلاثي الأبعاد تحديد شكلين كسريين من الكهوف ، كلاهما عبارة عن ضجيج متعدد الأضلاع ذو أوكتاف واحد ، ولكن مع بذور مختلفة. باستخدام تحديد ، اضبطهم على 1 أو 0 ، واضربهم. وهكذا ، عند تقاطع الفركتلات ، سوف يظهر كهف ،وكل شيء آخر سيبقى صلبًا ، وسيصبح مظهر الأنفاق طبيعيًا أكثر من استخدام كسورية واحدة.

terraintree3d=
 {
	{name="ground_gradient", type="gradient", x1=0, x2=0, y1=0, y2=1},
	
	{name="lowland_shape_fractal", type="fractal", fractaltype=anl.BILLOW, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=2, frequency=0.25},
	{name="lowland_autocorrect", type="autocorrect", source="lowland_shape_fractal", low=0, high=1},
	{name="lowland_scale", type="scaleoffset", source="lowland_autocorrect", scale=0.125, offset=-0.45},
	{name="lowland_y_scale", type="scaledomain", source="lowland_scale", scaley=0},
	{name="lowland_terrain", type="translatedomain", source="ground_gradient", ty="lowland_y_scale"},
	
	{name="highland_shape_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=4, frequency=2},
	{name="highland_autocorrect", type="autocorrect", source="highland_shape_fractal", low=-1, high=1},
	{name="highland_scale", type="scaleoffset", source="highland_autocorrect", scale=0.25, offset=0},
	{name="highland_y_scale", type="scaledomain", source="highland_scale", scaley=0},
	{name="highland_terrain", type="translatedomain", source="ground_gradient", ty="highland_y_scale"},

	{name="mountain_shape_fractal", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=8, frequency=1},
	{name="mountain_autocorrect", type="autocorrect", source="mountain_shape_fractal", low=-1, high=1},
	{name="mountain_scale", type="scaleoffset", source="mountain_autocorrect", scale=0.45, offset=0.15},
	{name="mountain_y_scale", type="scaledomain", source="mountain_scale", scaley=0.25},
	{name="mountain_terrain", type="translatedomain", source="ground_gradient", ty="mountain_y_scale"},

	{name="terrain_type_fractal", type="fractal", fractaltype=anl.FBM, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=3, frequency=0.125},
	{name="terrain_autocorrect", type="autocorrect", source="terrain_type_fractal", low=0, high=1},
	{name="terrain_type_y_scale", type="scaledomain", source="terrain_autocorrect", scaley=0},
	{name="terrain_type_cache", type="cache", source="terrain_type_y_scale"},
	{name="highland_mountain_select", type="select", low="highland_terrain", high="mountain_terrain", control="terrain_type_cache", threshold=0.55, falloff=0.2},
	{name="highland_lowland_select", type="select", low="lowland_terrain", high="highland_mountain_select", control="terrain_type_cache", threshold=0.25, falloff=0.15},
	{name="highland_lowland_select_cache", type="cache", source="highland_lowland_select"},
	{name="ground_select", type="select", low=0, high=1, threshold=0.5, control="highland_lowland_select_cache"},
	
	{name="cave_attenuate_bias", type="bias", source="highland_lowland_select_cache", bias=0.45},
	{name="cave_shape1", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_shape2", type="fractal", fractaltype=anl.RIDGEDMULTI, basistype=anl.GRADIENT, interptype=anl.QUINTIC, octaves=1, frequency=4},
	{name="cave_shape_attenuate", type="combiner", operation=anl.MULT, source_0="cave_shape1", source_1="cave_attenuate_bias", source_2="cave_shape2"},             
	{name = "cave_perturb_fractal"، type = "fractal"، fractaltype = anl.FBM، basistype = anl.GRADIENT، interptype = anl.QUINTIC، octaves = 6، frequency = 3}،
	{name = "cave_perturb_scale"، type = "scaleoffset"، source = "cave_perturb_fractal"، scale = 0.5، offset = 0}،
	{name = "cave_perturb"، type = "translomain"، source = "cave_shape_attenuate"، tx = "cave_perturb_scale"}،
	{name = "cave_select" ، اكتب = "select" ، low = 1 ، high = 0 ، control = "cave_perturb" ، العتبة = 0.48 ، falloff = 0} ،
	
	{name = "ground_cave_multiply"، type = "combiner"، operation = anl.MULT، source_0 = "cave_select"، source_1 = "ground_select"}
 }

أمثلة للنتائج:



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

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


All Articles