مزج الفا المتأخر

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



هناك طريقة أخرى أبسط وأكثر أناقة لحل هذه المشاكل. يمكننا رسم المشهد في الاتجاه المعاكس!

انحراف صغير لتذكيرك بكيفية عمل طريقة العرض الكلاسيكية
- Alpha Blending , , , . 4 RGBA, RGB — A(Alpha) — ( ). . :


ColorSrc — RGB , ( , ), ColorDst — , , Color_Result — , , , . Variable1 Variable2, ? , ( , ). , : , ... 

:


AlphaSrc — - (), OneMinusAlphaSrc, , 1.0 — AlphaSrc. : 1 * + 2 * (1 — ). alpha (). = 1, , = 0, . OpenGL .

OpenGL ES 2.0 — .

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





ما هي الحيلة؟ 


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

كيف تعمل؟


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

(تقريبًا AlphaSaturate = min (AlphaSrc، 1 - AlphaDst))

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

للتوضيح ، يبدو مخطط العرض العكسي كما يلي: 

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


كيف نستطتيع ان نستعمل هذا؟


سأصف العديد من المهام التي تم حلها بهذه الطريقة ، باستخدام مشروعنا كمثال:

  1. قطع الكائنات بالقناع مع الشفافية. لقطة سلسة لغرفة اللعبة:


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


    يغير شكله أثناء تحرك الكاميرا بين الغرف. صيغة الخلط للتنظيف هي كما يلي:

    ColorSrc = GL_ZERO,
    ColorDst = GL_ONE_MINUS_SRC_ALPHA,
    AlphaSrc = GL_ZERO,
    AlphaDst = GL_ONE_MINUS_SRC_ALPHA

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

  2. يتم الاختفاء السلس للحقل بالمثل. سعر الإصدار هو DrawCall واحد.
  3. :


    , UI, . , «» , , « », . , : , . :

    ColorSrc = GL_SRC_ALPHA,
    ColorDst = GL_ONE_MINUS_SRC_ALPHA,
    AlphaSrc = GL_ZERO,
    AlphaDst = GL_ONE
  4. , :


  5. «»:



    . , . — 2 DrawCalls.



Ambient occlusion





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

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


يمكن التغلب على ذلك عن طريق تعديل المزج الإضافي من حيث خلط قناة ألفا:

AlphaSrc = GL_ONE_MINUS_DST_ALPHA
AlphaDst = GL_ONE

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

إذا كانت هناك مواد من النموذج: 


ثم تحتاج إلى القيام بأحدها:


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

RGB_old = Texel_in.rgb
A_old = Texel_in.a
A_middle = 1.0 / ((RGB_old) / 3.0) * A_old // linear color space
RGB_new = RGB_old * A_middle;
A_shift = minimum( 1.0 / RGB_new.r, 1.0)
A_shift = minimum( 1.0 / RGB_new.g, A_shift)
A_shift = minimum( 1.0 / RGB_new.b, A_shift)
RGB_result = RGB_new * A_shift; 
A_result = (RGB_result) / 3.0)
Texel_out = Vector4(RGB_result, A_result)



هنا سوف أتناول خطوات تقديم مشهد مشروعنا
 
  1. . , -.

  2. , , , «» :


  3. UI:

  4. , , , :

  5. :

  6. :

  7. , .




استنتاج


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

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


All Articles