سؤال

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

هل هناك طريقة بشكل صحيح مزيج محتويات الملمس مع البيانات الجديدة القادمة ؟

تحرير:المزيد من المعلومات requsted, سأحاول أن أشرح أكثر من ذلك بوضوح ؛

على blendmode أستخدمه هو GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.(أعتقد أن هذا هو عادة القياسية blendmode)

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

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

إذا كنت رسم خطوط الدائرة في نفس الإطار إلا أنها مزيج بشكل صحيح.تخميني هو أن نسيج فقط لا تنسجم مع انها محتوياتها السابقة.انها فقط مزج مع glclearcolor.(وهو في هذه الحالة هو <1.0 f 1.0 f 1.0 f 1.0 f>)

هل كانت مفيدة؟

المحلول

أعتقد أن هناك نوعان من المشاكل المحتملة هنا.

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

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

وهناك مشكلة أخرى تتعلق:عند مزج سطر واحد على آخر في "المعيار" وضع مزيج (src ألفا 1 - src ألفا) في FBO, قناة ألفا من "المخلوطة" جزء تحتوي على مزيج من أشعة الفا من اثنين تراكب العناصر.قد لا يكون هذا هو ما تريد.

على سبيل المثال ، إذا كنت رسم اثنين من 50% ألفا خطوط فوق بعضها البعض في تراكب ، للحصول على الأثر المماثل عند blit المنظمات القائمة على العقيدة ، تحتاج FBO ألفا أن يكون... 75%.(وهذا هو ، 1 - (1-.5) * (1-0.5) الذي هو ماذا سيحدث إذا كنت مجرد لفت اثنين 50% ألفا خطوط على المشهد الخاص بك.ولكن عند رسم اثنين من 50% خطوط, سوف تحصل على 50% ألفا في FBO (مزيج من 50 ٪ مع...50%.

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

مزيج(مزيج(مزيج(لون الخلفية ، نموذج) السطر الأول) ، السطر الثاني);

الآن سيكون لديك

مزيج(مزيج(السطر الأول, الثاني), مزيج(لون الخلفية ، نموذج)).

وبعبارة أخرى ، قبل خلط تراكب خطوط في FBO من مزج وبالتالي تغيير نظرة النهائي بطريقة قد لا تريد.

أولا طريقة بسيطة للحصول على حول هذا:لا تستخدم FBO.وأنا أدرك أن هذا هو "الذهاب إعادة تصميم التطبيق الخاص بك" نوع من الإجابة ، ولكن باستخدام FBO ليست أرخص شيء و الحديث GL بطاقات جيدة جدا في رسم خطوط.لذلك سيكون أحد الخيارات:بدلا من مزج الخطوط في FBO ، كتابة الخط الهندسة في قمة العازلة كائن (VBO).ببساطة تمديد VBO قليلا في كل مرة.إذا كنت ترسم أقل من 40,000 خطوط في وقت واحد ، وهذا يكاد يكون من المؤكد سوف يكون بأسرع ما كنت تفعل من قبل.

(طرف واحد إذا كنت السير في هذا الطريق:استخدام glBufferSubData كتابة الخطوط, لا glMapBuffer رسم الخرائط يمكن أن تكون مكلفة و لا يعمل على الفرعية النطاقات على العديد من السائقين...من الأفضل أن مجرد السماح للسائق نسخ بعض القمم.)

إذا كان هذا ليس خيارا (على سبيل المثال ، إذا كنت رسم مزيج من أنواع الشكل أو استخدام مزيج من GL الدولة ، مثل أن "تذكر" ما فعلته هو الكثير أكثر تعقيدا من مجرد تراكم القمم) ثم قد تحتاج إلى تغيير كيفية رسم في VBO.

أساسا ما عليك القيام به هو تمكين منفصلة مزج;تهيئة تراكب السوداء + 0% ألفا (0,0,0,0) ومزيج من قبل "ستاندرد مزج" RGB ولكن المضافة مزج قنوات ألفا.هذا ليس صحيحا تماما عن قناة ألفا لكنه عموما أقرب كثيرا - دون هذا ، على مدى مرسومة المناطق تكون شفافة جدا.

ثم عند رسم FBO ، استخدم "قبل ضرب" ألفا ، وهذا هو (واحد ناقص-src-alph).

هنا هو السبب في أن الخطوة الأخيرة هي المطلوبة:عند رسم في FBO ، لديك بالفعل ضرب كل رسم دعوة قناة ألفا (إذا مزج على).منذ كنت ترسم على أسود, أخضر (0,1,0,0.5) الخط هو الآن الأخضر الداكن (0,0.5,0,0.5).إذا كان ألفا على مزيج بشكل طبيعي مرة أخرى ، ألفا هو تطبيق و ليل قد 0,0.25,0,0.5.).ببساطة عن طريق استخدام FBO اللون كما هو تجنب الثانية ألفا الضرب.

وهذا ما يسمى أحيانا "قبل ضرب" ألفا لأن ألفا وقد تم بالفعل ضرب في الألوان RGB.في هذه الحالة كنت تريد أن تحصل على النتائج الصحيحة, ولكن في حالات أخرى ، المبرمجين استخدام السرعة.(قبل ضرب ، فإنه يزيل mult لكل بكسل عندما تمتزج op بها.)

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

نصائح أخرى

امسح FBO بالأسود الشفاف (0 ، 0 ، 0 ، 0) ، ارسم فيه إلى الوراء مع

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

ورسم FBO مع

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

للحصول على النتيجة الدقيقة.

كما كتب Ben Supnik ، يحتوي FBO على لون مضروب بالفعل مع قناة Alpha ، لذا بدلاً من القيام بذلك مرة أخرى مع GL_SRC_ALPHA ، يتم رسمه باستخدام GL_ONE. يتم تخفيف لون الوجهة بشكل طبيعي مع gl_one_minus_src_alpha.

سبب مزج قناة ألفا في المخزن المؤقت بهذه الطريقة يختلف:

الصيغة لجمع الشفافية

resultTr = sTr * dTr

(أستخدم S و D بسبب التوازي مع مصدر ووجهة OpenGL ، ولكن كما ترون لا يهم الترتيب.)

مكتوبة مع عتامات (قيم ألفا) يصبح هذا

    1 - rA = (1 - sA) * (1 - dA)
<=> rA = 1 - (1 - sA) * (1 - dA)
       = 1 - 1 + sA + dA - sA * dA
       =         sA + (1 - sA) * dA

وهو نفس وظيفة المزيج (عوامل المصدر والوجهة) (GL_ONE ، GL_ONE_MINUS_SRC_ALPHA) مع الافتراضي مزج المعادلة gl_func_add.


جانبا:

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

    glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_ONE);

وإلا استخدم نفس الطريقة.

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

كما قال بن سوبنيك ، فإن أفضل طريقة للقيام بذلك هي تقديم المشهد بأكمله مع وظائف مزيج منفصلة للألوان وألفا. إذا كنت تستخدم وظيفة المزيج الكلاسيكية غير الممتازة ، فحاول glblendfuncseparateoes (gl_src_alpha ، gl_one_minus_src_alpha ، gl_one ، gl_one) لتقديم المشهد الخاص بك إلى fbo. و glblendfuncseparateoes (GL_ONE ، GL_ONE_MINUS_SRC_ALPHA) لتقديم FBO إلى الشاشة.

إنها ليست دقيقة بنسبة 100 ٪ ، ولكن في معظم الحالات التي لن تخلق أي شفافية غير متوقعة.

ضع في اعتبارك أن الأجهزة القديمة وبعض الأجهزة المحمولة (معظمها من الأجهزة OpenGL ES 1.X ، مثل iPhone الأصلي و 3G) لا تدعم وظائف المزيج المنفصلة. :(

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top