شروع کار/بافت

ساخت وبلاگ

ما آموخته ایم که برای اضافه کردن جزئیات بیشتر به اشیاء خود می توانیم از رنگ ها برای هر راس استفاده کنیم تا تصاویر جالب ایجاد کنیم. با این حال ، برای به دست آوردن کمی از واقع گرایی ، باید رئوس های زیادی داشته باشیم تا بتوانیم رنگ های زیادی را مشخص کنیم. این مقدار قابل توجهی از سربار اضافی را به خود اختصاص می دهد ، زیرا هر مدل به راس های بسیار بیشتری نیاز دارد و برای هر راس یک ویژگی رنگی نیز دارد.

آنچه به طور کلی هنرمندان و برنامه نویسان ترجیح می دهند استفاده از یک بافت باشد. بافت یک تصویر 2D است (حتی بافت های 1D و سه بعدی وجود دارد) که برای افزودن جزئیات به یک شی استفاده می شود. به عنوان یک تکه کاغذ با یک تصویر آجری خوب (به عنوان مثال) روی آن فکر کنید که بر روی خانه سه بعدی خود مرتب شده است ، بنابراین به نظر می رسد خانه شما دارای نمای بیرونی سنگی است. از آنجا که می توانیم جزئیات زیادی را در یک تصویر واحد وارد کنیم ، می توانیم به این توهم بدهیم که شیء بدون نیاز به مشخص کردن رئوس های اضافی بسیار دقیق است.

در کنار تصاویر ، از بافت ها نیز می توان برای ذخیره مجموعه بزرگی از داده های دلخواه برای ارسال به سایه بان ها استفاده کرد ، اما ما آن را برای یک موضوع متفاوت ترک خواهیم کرد.

در زیر یک تصویر بافتی از یک دیوار آجری که از فصل قبل به مثلث نقشه برداری شده است ، مشاهده خواهید کرد.

به منظور نقشه برداری یک بافت به مثلث ، باید به هر راس مثلث بگوییم که بخشی از بافت آن با کدام قسمت مطابقت دارد. بنابراین هر راس باید یک مختصات بافتی در ارتباط با آنها داشته باشد که مشخص می کند چه بخشی از تصویر بافت به نمونه را از آن استفاده می کند. درون یابی قطعه سپس بقیه را برای سایر قطعات انجام می دهد.

مختصات بافت از 0 تا 1 در محور x و y (به یاد داشته باشید که ما از تصاویر بافت 2D استفاده می کنیم). بازیابی رنگ بافت با استفاده از مختصات بافت نمونه برداری نامیده می شود. مختصات بافت از (0/0) برای گوشه سمت چپ پایین یک تصویر بافت به (1،1) برای گوشه بالا سمت راست یک تصویر بافت شروع می شود. تصویر زیر نشان می دهد که چگونه مختصات بافت را به مثلث نقشه می کنیم:

ما 3 نقطه مختصات بافت را برای مثلث مشخص می کنیم. ما می خواهیم قسمت پایین سمت چپ مثلث با قسمت پایین سمت چپ بافت مطابقت داشته باشد ، بنابراین از مختصات (0/0) بافت برای راس چپ چپ مثلث استفاده می کنیم. همین مورد در مورد سمت راست راست با یک مختصات (1،0) بافت نیز صدق می کند. بالای مثلث باید با مرکز بالای تصویر بافت مطابقت داشته باشد ، بنابراین ما (0. 5،1. 0) را به عنوان مختصات بافت آن می گیریم. ما فقط باید 3 مختصات بافت را به سایه بان راس منتقل کنیم ، که سپس آنهایی را به سایه قطعه قطعه منتقل می کنیم که به طور مرتب تمام مختصات بافت را برای هر قطعه درون یابی می کند.

مختصات بافت حاصل مانند این به نظر می رسد:

نمونه برداری از بافت دارای تفسیر سست است و می توان از جهات مختلفی انجام داد. بنابراین وظیفه ما این است که به OpenGL بگوییم که چگونه باید از بافت های آن نمونه برداری کند.

بسته بندی بافت

مختصات بافت معمولاً از (0/0) تا (1،1) متغیر است اما اگر مختصات خارج از این محدوده را مشخص کنیم چه اتفاقی می افتد؟رفتار پیش فرض OpenGL تکرار تصاویر بافت است (ما اساساً قسمت عدد صحیح مختصات بافت نقطه شناور را نادیده می گیریم) ، اما گزینه های بیشتری وجود دارد که پیشنهادات OpenGL را ارائه می دهد:

  • gl_repeat: رفتار پیش فرض برای بافت. تصویر بافت را تکرار می کند.
  • GL_MIRRORED_REPEAT: همان GL_REPEAT اما تصویر را با هر تکرار آینه می کند.
  • GL_CLAMP_TO_EDGE: مختصات بین 0 تا 1 را گیره می کند. نتیجه این است که مختصات بالاتر به لبه بسته می شوند و در نتیجه الگوی لبه کشیده ای حاصل می شوند.
  • GL_CLAMP_TO_BORDER: مختصات خارج از محدوده اکنون به رنگ مرزی مشخص شده توسط کاربر داده می شود.

هر یک از گزینه ها هنگام استفاده از مختصات بافت خارج از محدوده پیش فرض ، خروجی بصری متفاوتی دارند. بیایید ببینیم که اینها در یک تصویر نمونه از بافت (تصویر اصلی توسط Hólger Rezende) به نظر می رسد:

هر یک از گزینه های فوق را می توان در هر محور مختصات (S ، T (و R در صورت استفاده از بافت های سه بعدی) معادل x ، y ، z) با عملکرد gltexparameter * تنظیم کرد:

اولین آرگومان هدف بافت را مشخص می کند. ما در حال کار با بافت های 2D هستیم تا هدف بافت GL_TEXTURE_2D باشد. استدلال دوم ما را ملزم می کند تا بگوییم چه گزینه ای را می خواهیم تنظیم کنیم و برای کدام محور بافت. ما می خواهیم آن را برای محور S و T پیکربندی کنیم. آخرین استدلال ما را ملزم می کند تا در حالت بسته بندی بافت مورد نظر خود عبور کنیم و در این حالت OpenGL گزینه بسته بندی بافت خود را بر روی بافت فعال در حال حاضر با GL_MIRRORED_REPEAT تنظیم می کند.

اگر گزینه GL_CLAMP_TO_BORDER را انتخاب کنیم ، باید یک رنگ مرزی را نیز مشخص کنیم. این کار با استفاده از معادل FV از عملکرد GltexParameter با GL_TEXTURE_BORDER_COLOR به عنوان گزینه آن انجام می شود و در آنجا در یک آرایه شناور از مقدار رنگ مرز عبور می کنیم:

فیلتر کردن بافت

مختصات بافت به وضوح بستگی ندارد اما می تواند هر مقدار نقطه شناور باشد ، بنابراین OpenGL باید بفهمد کدام پیکسل بافت (همچنین به عنوان یک Texel شناخته می شود) برای ترسیم مختصات بافت. این امر به ویژه در صورتی که یک شی بسیار بزرگ و یک بافت با وضوح پایین داشته باشید بسیار مهم می شود. احتمالاً در حال حاضر حدس زده اید که OpenGL گزینه هایی برای این فیلتر بافت نیز دارد. گزینه های مختلفی در دسترس است اما در حال حاضر ما در مورد مهمترین گزینه ها بحث خواهیم کرد: GL_NEAREST و GL_LINEAR.

GL_NEAREST (همچنین به عنوان نزدیکترین همسایه یا فیلتر نقطه شناخته می شود) روش پیش فرض فیلتر سازی بافت OpenGL است. هنگامی که روی GL_NEAREST تنظیم شد ، OpenGL Texel را انتخاب می کند که مرکز نزدیک به مختصات بافت است. در زیر می توانید 4 پیکسل را مشاهده کنید که در آن صلیب مختصات دقیق بافت را نشان می دهد. Texel سمت چپ بالا مرکز خود را نزدیک به مختصات بافت دارد و بنابراین به عنوان رنگ نمونه برداری شده است:

GL_LINEAR (همچنین به عنوان فیلتر خطی (BI) شناخته می شود) مقدار درون یابی را از Texels همسایگی مختصات بافت می گیرد و یک رنگ بین Texels را تقریب می دهد. هرچه فاصله از مختصات بافت تا مرکز Texel کوچکتر باشد ، بیشتر رنگ Texel به رنگ نمونه برداری کمک می کند. در زیر می بینیم که یک رنگ مختلط پیکسل های همسایه بازگردانده می شود:

اما تأثیر بصری چنین روش فیلتر بافت چیست؟بیایید ببینیم که چگونه این روش ها هنگام استفاده از بافت با وضوح پایین روی یک شیء بزرگ کار می کنند (بنابراین بافت به سمت بالا مقیاس بندی می شود و تکگرهای جداگانه قابل توجه هستند):

GL_NEAREST در الگوهای مسدود شده نتیجه می گیرد که در آن می توانیم پیکسل هایی را که بافت را تشکیل می دهند ، به وضوح ببینیم در حالی که GL_LINEAR یک الگوی نرم تر تولید می کند که در آن پیکسل های فردی کمتر قابل مشاهده هستند. GL_LINEAR خروجی واقع بینانه تری تولید می کند ، اما برخی از توسعه دهندگان ظاهری 8 بیتی تر را ترجیح می دهند و در نتیجه گزینه GL_NEAREST را انتخاب می کنند.

فیلتر بافت را می توان برای بزرگنمایی و کوچک سازی عملیات (هنگام مقیاس بالا یا پایین) تنظیم کرد ، بنابراین می توانید به عنوان مثال از نزدیکترین فیلتر همسایه استفاده کنید که بافت ها به سمت پایین و فیلتر خطی برای بافت های بالایی مقیاس می شوند. بنابراین ما باید روش فیلتر را برای هر دو گزینه از طریق GltexParameter * مشخص کنیم. کد باید شبیه به تنظیم روش بسته بندی باشد:

مگسهای

تصور کنید که ما یک اتاق بزرگ با هزاران شیء داشتیم که هر کدام دارای یک بافت متصل بودند. اشیاء بسیار دور وجود خواهند داشت که دارای همان بافت با وضوح بالا هستند که به عنوان اشیاء نزدیک به بیننده وصل شده اند. از آنجا که اشیاء بسیار دور هستند و احتمالاً فقط چند قطعه تولید می کنند ، OpenGL در بازیابی مقدار رنگ مناسب برای قطعه خود از بافت با وضوح بالا مشکل دارد ، زیرا باید یک رنگ بافت را برای قطعه ای انتخاب کند که بخش بزرگی از بافت را شامل می شودبشراین امر آثار باستانی قابل مشاهده را در اشیاء کوچک ایجاد می کند ، و به ذکر هدر رفتن پهنای باند حافظه با استفاده از بافت های با وضوح بالا بر روی اشیاء کوچک نیست.

برای حل این مسئله ، OpenGL از مفهومی به نام MIPMAPS استفاده می کند که اساساً مجموعه ای از تصاویر بافت است که در آن هر بافت بعدی دو برابر با نمونه قبلی است. ایده در پشت mipmaps باید به راحتی درک شود: پس از یک آستانه فاصله مشخص از بیننده ، OpenGL از یک بافت mipmap متفاوت استفاده می کند که به بهترین وجه مناسب با شیء است. از آنجا که شی بسیار دور است ، وضوح کوچکتر برای کاربر قابل توجه نخواهد بود. OpenGL سپس قادر به نمونه گیری از Texels صحیح است ، و هنگام نمونه برداری از آن قسمت از MIPMAPS ، حافظه حافظه پنهان کمتری در آن وجود دارد. بیایید نگاهی دقیق تر به آنچه یک بافت mipmapped به نظر می رسد:

ایجاد مجموعه ای از بافت های پیچیده شده برای هر تصویر بافت برای انجام دستی دست و پا گیر است ، اما خوشبختانه OpenGL پس از ایجاد یک بافت ، قادر به انجام همه کارها برای ما با یک تماس واحد به glgeneratemipmap است.

هنگام جابجایی بین سطح MIPMAPS در هنگام ارائه OpenGL ممکن است برخی از مصنوعات مانند لبه های تیز بین دو لایه MiPmap را نشان دهد. درست مانند فیلتر کردن بافت معمولی ، می توان با استفاده از نزدیکترین و فیلتر خطی برای جابجایی بین سطح MIPMAP ، بین سطح MIPMAP فیلتر کرد. برای مشخص کردن روش فیلتر بین سطح MIPMAP می توانیم روشهای اصلی فیلتر را با یکی از چهار گزینه زیر جایگزین کنیم:

  • GL_NEAREST_MIPMAP_NEAREST: نزدیکترین MIPMAP را برای مطابقت با اندازه پیکسل می گیرد و از نزدیکترین درون یابی همسایه برای نمونه گیری بافت استفاده می کند.
  • GL_LINEAR_MIPMAP_NEAREST: نزدیکترین سطح MIPMAP و نمونه هایی را که با استفاده از درون یابی خطی سطح می گیرد ، می گیرد.
  • GL_NEAREST_MIPMAP_LINEAR: به طور خطی بین دو مپ نقشه که از نزدیک با اندازه یک پیکسل مطابقت دارند ، درون یابی می کند و از طریق نزدیکترین همسایه سطح درون یابی را نشان می دهد.
  • GL_LINEAR_MIPMAP_LINEAR: به صورت خطی بین دو نزدیکترین MIPMAPS و نمونه از سطح درون یابی از طریق درون یابی خطی وجود دارد.

درست مانند فیلتر کردن بافت ، می توانیم روش فیلتر را با استفاده از GltexParameter I یکی از 4 روش فوق الذکر تنظیم کنیم:

یک اشتباه رایج تنظیم یکی از گزینه های فیلتر MIPMAP به عنوان فیلتر بزرگنمایی است. این هیچ تاثیری ندارد زیرا MIPMAP ها در درجه اول برای کاهش بافت استفاده می شوند: بزرگنمایی بافت از MIPMAPS استفاده نمی کند و به آن گزینه فیلتر MIPMAP می دهد ، کد خطای OpenGL GL_INVALID_ENUM را ایجاد می کند.

بارگیری و ایجاد بافت

اولین کاری که برای استفاده در واقع از بافت ها باید انجام دهیم ، بارگذاری آنها در برنامه ماست. تصاویر بافتی را می توان در ده ها قالب فایل ذخیره کرد که هر کدام دارای ساختار خاص خود و سفارش داده ها هستند ، بنابراین چگونه می توانیم آن تصاویر را در برنامه خود بدست آوریم؟یک راه حل انتخاب یک قالب پرونده ای است که می خواهیم از آن استفاده کنیم ، مثلاً . png و لودر تصویر خودمان را بنویسیم تا قالب تصویر را به آرایه بزرگی از بایت تبدیل کنیم. در حالی که نوشتن لودر تصویر خود خیلی سخت نیست ، اما اگر می خواهید از قالب های فایل بیشتری پشتیبانی کنید ، هنوز دست و پا گیر است؟سپس باید برای هر فرمی که می خواهید از آن پشتیبانی کنید ، یک لودر تصویر بنویسید.

راه حل دیگر ، و احتمالاً خوب ، استفاده از یک کتابخانه بارگیری تصویر است که از چندین قالب محبوب پشتیبانی می کند و تمام کارهای سخت را برای ما انجام می دهد. کتابخانه ای مانند STB_IMAGE. H.

stb_image. h

STB_IMAGE. H یک کتابخانه بارگیری تصویر تک آهنگ بسیار محبوب توسط شان بارت است که قادر به بارگذاری محبوب ترین قالب های فایل است و به راحتی در پروژه (های) شما ادغام می شود. STB_IMAGE. H را می توان از اینجا بارگیری کرد. به سادگی فایل هدر را بارگیری کنید ، آن را به عنوان stb_image. h به پروژه خود اضافه کنید و یک پرونده C ++ اضافی را با کد زیر ایجاد کنید:

پیش پردازنده با تعریف STB_IMAGE_IMPLEMENTATION ، پرونده هدر را به گونه ای اصلاح می کند که فقط حاوی کد منبع تعریف مربوطه باشد ، به طور موثری پرونده هدر را به یک پرونده . cpp تبدیل می کند ، و این در مورد آن است. اکنون به سادگی STB_IMAGE. h را در جایی در برنامه خود قرار دهید و کامپایل کنید.

برای بخش های بافت زیر می خواهیم از تصویری از یک ظرف چوبی استفاده کنیم. برای بارگیری یک تصویر با استفاده از stb_image. h ما از عملکرد STBI_LOAD آن استفاده می کنیم:

The function first takes as input the location of an image file. It then expects you to give three ints as its second, third and fourth argument that stb_image.h will fill with the resulting image's width , height and number of color channels. We need the image's width and height for generating textures later on. 3 . >

ایجاد بافت

مانند هر یک از اشیاء قبلی در OpenGL ، بافت ها با شناسه ارجاع می شوند. بیایید یکی را ایجاد کنیم:

تابع GlgentExtures ابتدا به عنوان ورودی چند بافت می خواهیم تولید کنیم و آنها را در یک آرایه Int بدون امضا به عنوان استدلال دوم خود ذخیره می کنیم (در مورد ما فقط یک Int بدون امضا). درست مانند سایر اشیاء ، ما باید آن را به هم وصل کنیم تا هر دستور بافت بعدی ، بافت محدود در حال حاضر را پیکربندی کند:

اکنون که بافت محدود است ، می توانیم با استفاده از داده های تصویر قبلی که قبلاً بارگذاری شده اند ، تولید بافت را شروع کنیم. بافت ها با glteximage2d تولید می شوند:

  • اولین آرگومان هدف بافت را مشخص می کند. تنظیم این کار در GL_TEXTURE_2D به این معنی است که این عمل یک بافت را در شیء بافت محدود در همان هدف ایجاد می کند (بنابراین هر بافت محدود به اهداف GL_TEXTURE_1D یا GL_TEXTURE_3D تحت تأثیر قرار نمی گیرد).
  • آرگومان دوم سطح MIPMAP را مشخص می کند که می خواهیم یک بافت ایجاد کنیم اگر می خواهید هر سطح MIPMAP را به صورت دستی تنظیم کنید ، اما ما آن را در سطح پایه قرار خواهیم داد که 0 است.
  • استدلال سوم به OpenGL در چه نوع فرمی می خواهیم بافت را ذخیره کنیم. تصویر ما فقط مقادیر RGB دارد ، بنابراین ما بافت را با مقادیر RGB نیز ذخیره خواهیم کرد.
  • آرگومان 4 و 5 عرض و ارتفاع بافت حاصل را تعیین می کند. ما قبلاً هنگام بارگیری تصویر ، آنها را ذخیره کردیم تا از متغیرهای مربوطه استفاده کنیم.
  • استدلال بعدی همیشه باید 0 باشد (برخی از میراث).
  • آرگومان هفتم و هشتم قالب و داده تصویر منبع را مشخص می کند. ما تصویر را با مقادیر RGB بارگذاری کردیم و آنها را به عنوان کاراکتر (بایت) ذخیره کردیم ، بنابراین مقادیر مربوطه را منتقل می کنیم.
  • آخرین آرگومان داده های واقعی تصویر است.

هنگامی که GLTEXIMAGE2D خوانده می شود ، شیء بافت در حال حاضر در حال حاضر دارای تصویر بافت به آن است. با این حال ، در حال حاضر فقط سطح پایه تصویر بافت بارگذاری شده است و اگر می خواهیم از mipmaps استفاده کنیم ، باید تمام تصاویر مختلف را به صورت دستی مشخص کنیم (با افزایش مداوم آرگومان دوم) یا می توانیم پس از تولید بافت ، gleneratemipmap را صدا کنیم. این به طور خودکار تمام MIPMAP های مورد نیاز را برای بافت محدود در حال حاضر ایجاد می کند.

بعد از اتمام کار در تولید بافت و MIPMAP های مربوطه ، این کار خوب است که حافظه تصویر را آزاد کنیم:

کل فرآیند تولید یک بافت به این ترتیب چیزی شبیه به این است:

استفاده از بافت

برای بخش های آینده ما از شکل مستطیل کشیده شده با GLDrawElements از قسمت آخر فصل Hello Triangle استفاده خواهیم کرد. ما باید از OpenGL نحوه نمونه برداری از بافت مطلع شویم ، بنابراین باید داده های راس را با مختصات بافت به روز کنیم:

از آنجا که ما یک ویژگی vertex اضافی اضافه کرده ایم ، مجدداً باید OpenGL را از قالب جدید راس اطلاع دهیم:

Image of VBO with interleaved position, color and texture data with strides and offsets shown for configuring vertex attribute pointers.

توجه داشته باشید که ما باید پارامتر قدم دو ویژگی قبلی راس را به 8 * اندازه (شناور) نیز تنظیم کنیم.

در مرحله بعد ، ما باید سایه بان راس را تغییر دهیم تا مختصات بافت را به عنوان یک ویژگی راس بپذیریم و سپس مختصات را به سایه بان قطعه منتقل کنیم:

سایه بان قطعه باید متغیر خروجی TexCoord را به عنوان یک متغیر ورودی بپذیرد.

سایه بان قطعه نیز باید به شیء بافت دسترسی داشته باشد ، اما چگونه می توانیم شیء بافت را به سایه بان قطعه منتقل کنیم؟GLSL دارای یک نوع داده داخلی برای اشیاء بافت به نام یک نمونه است که به عنوان یک نوع پس از آن نوع بافت مورد نظر ما را می خواهد. Sampler1d ، sampler3d یا در مورد ما sampler2d. سپس می توانیم با اعلام یک نمونه یکنواخت نمونه 2D که بعداً بافت خود را به آن اختصاص می دهیم ، یک بافت به سایه بان قطعه اضافه کنیم.

برای نمونه برداری از رنگ یک بافت ، از عملکرد بافت داخلی GLSL استفاده می کنیم که به عنوان اولین آرگومان آن یک نمونه از بافت و به عنوان آرگومان دوم آن ، مختصات بافت مربوطه است. عملکرد بافت سپس با استفاده از پارامترهای بافتی که قبلاً تنظیم کردیم ، مقدار رنگ مربوطه را نمونه می کند. خروجی این سایه بان قطعه سپس رنگ (فیلتر شده) بافت در مختصات بافت (درون یابی) است.

تمام کاری که اکنون باید انجام شود این است که قبل از فراخوانی GLDrawElements ، بافت را به هم متصل کنید و سپس به طور خودکار بافت را به نمونه Shader Fragment اختصاص می دهد:

اگر همه کارها را درست انجام دادید ، باید تصویر زیر را ببینید:

اگر مستطیل شما کاملاً سفید یا سیاه است ، احتمالاً در این مسیر خطایی ایجاد کرده اید. سیاهههای مربوط به سایه بان خود را بررسی کنید و سعی کنید کد خود را با کد منبع برنامه مقایسه کنید.

اگر کد بافت شما کار نمی کند یا کاملاً سیاه نشان داده نمی شود ، به خواندن ادامه دهید و راه خود را به آخرین مثال که باید کار کند ، ادامه دهید. در بعضی از درایورها لازم است یک واحد بافت را به هر لباس نمونه اختصاص دهید ، این چیزی است که در این فصل بیشتر مورد بحث قرار خواهیم گرفت.

برای به دست آوردن کمی بد بو ، می توانیم رنگ بافت حاصل را با رنگ های راس مخلوط کنیم. ما به سادگی رنگ بافت حاصل را با رنگ راس در سایه قطعه قطعه ضرب می کنیم تا هر دو رنگ را مخلوط کنیم:

نتیجه باید ترکیبی از رنگ راس و رنگ بافت باشد:

من حدس می زنم شما می توانید بگویید ظرف ما دوست دارد دیسکو را دوست داشته باشد.

واحدهای بافتی

احتمالاً تعجب کرده اید که چرا متغیر Sampler2d یکنواخت است اگر حتی مقداری آن را با Gluniform اختصاص ندادیم. با استفاده از Gluniform 1i ما در واقع می توانیم یک مقدار مکان را به Sampler Texture اختصاص دهیم تا بتوانیم چندین بافت را به طور همزمان در یک سایه بان قطعه تنظیم کنیم. این مکان از یک بافت بیشتر به عنوان یک واحد بافت شناخته می شود. واحد بافت پیش فرض برای یک بافت 0 است که واحد پیش فرض فعال بافت است ، بنابراین ما نیازی به اختصاص مکانی در بخش قبلی نداریم. توجه داشته باشید که همه درایورهای گرافیکی یک واحد بافت پیش فرض اختصاص نمی دهند تا بخش قبلی برای شما ارائه نشده باشد.

هدف اصلی واحدهای بافت این است که به ما امکان استفاده از بیش از 1 بافت در سایه بان های خود را بدهیم. با اختصاص واحدهای بافت به نمونه ها ، می توانیم تا زمانی که ابتدا واحد بافت مربوطه را فعال کنیم ، به چندین بافت متصل شویم. درست مانند GlbindTexture ما می توانیم واحدهای بافت را با استفاده از Glactivetexture در واحد بافت که می خواهیم از آن استفاده کنیم فعال کنیم:

پس از فعال کردن یک واحد بافت ، یک تماس بعدی GlbindTexture آن بافت را به واحد بافت فعال در حال حاضر متصل می کند. واحد بافت GL_TEXTURE0 همیشه به طور پیش فرض فعال است ، بنابراین ما مجبور نیستیم در هنگام استفاده از GLBINDTEXTURE ، هیچ واحد بافتی را در مثال قبلی فعال کنیم.

OpenGL باید حداقل 16 واحد بافت را برای استفاده از شما داشته باشد که می توانید با استفاده از GL_TEXTURE0 به GL_TEXTURE15 فعال کنید. آنها به ترتیب تعریف شده اند ، بنابراین ما می توانیم GL_TEXTURE8 را از طریق GL_TEXTURE0 + 8 نیز بدست آوریم ، که این مفید است که ما مجبور شویم بیش از چندین واحد بافت حلقه کنیم.

با این حال ، ما هنوز باید سایه بان قطعه را برای پذیرش نمونه دیگری ویرایش کنیم. این باید اکنون نسبتاً ساده باشد:

رنگ خروجی نهایی اکنون ترکیبی از دو جستجوی بافت است. تابع مخلوط داخلی GLSL دو مقدار را به عنوان ورودی و خطی بین آنها بر اساس آرگومان سوم خود وارد می کند. اگر مقدار سوم 0. 0 باشد ، اولین ورودی را برمی گرداند. اگر 1. 0 باشد ، مقدار ورودی دوم را برمی گرداند. مقدار 0. 2 80 ٪ از رنگ ورودی اول و 20 ٪ از رنگ ورودی دوم را برمی گرداند و در نتیجه ترکیبی از هر دو بافت ما به دست می آید.

اکنون می خواهیم بار دیگر بارگیری و ایجاد کنیم. اکنون باید با مراحل آشنا باشید. حتماً یک شیء بافت دیگر ایجاد کنید ، تصویر را بارگذاری کرده و بافت نهایی را با استفاده از GltEximage2d ایجاد کنید. برای بافت دوم ما هنگام یادگیری OpenGL از تصویری از بیان صورت شما استفاده خواهیم کرد:

توجه داشته باشید که اکنون یک تصویر . png را بارگیری می کنیم که شامل یک کانال آلفا (شفافیت) است. این بدان معناست که اکنون باید مشخص کنیم که داده های تصویر شامل یک کانال آلفا و همچنین با استفاده از GL_RGBA است. در غیر این صورت OpenGL به اشتباه داده های تصویر را تفسیر می کند.

برای استفاده از بافت دوم (و اولین بافت) ما باید با اتصال هر دو بافت به واحد بافت مربوطه ، روش رندر را کمی تغییر دهیم:

ما همچنین باید به OpenGL بگوییم که واحد بافت هر نمونه سایه دار با تنظیم هر نمونه با استفاده از Gluniform 1i متعلق به کدام واحد است. ما فقط باید این کار را یک بار تنظیم کنیم ، بنابراین می توانیم این کار را قبل از ورود به حلقه رندر انجام دهیم:

با تنظیم نمونه ها از طریق Gluniform 1i اطمینان حاصل می کنیم که هر نمونه یکنواخت با واحد بافت مناسب مطابقت دارد. شما باید نتیجه زیر را بدست آورید:

احتمالاً متوجه شده اید که این بافت وارونه است! این اتفاق می افتد زیرا OpenGL انتظار دارد که 0. 0 مختصات موجود در محور y در قسمت پایین تصویر باشد ، اما تصاویر معمولاً در بالای محور Y 0. 0 دارند. خوشبختانه برای ما ، STB_IMAGE. H می تواند با اضافه کردن بیانیه زیر قبل از بارگیری هر تصویر ، محور y را در حین بارگذاری تصویر بچرخانید:

بعد از گفتن STB_IMAGE. H برای بارگیری محور y هنگام بارگیری تصاویر ، باید نتیجه زیر را بدست آورید:

اگر یک ظرف شاد را می بینید ، کارها را درست انجام دادید. می توانید آن را با کد منبع مقایسه کنید.

کتاب آموزش بورس...
ما را در سایت کتاب آموزش بورس دنبال می کنید

برچسب : نویسنده : محسن زنجانچی بازدید : 59 تاريخ : پنجشنبه 10 فروردين 1402 ساعت: 1:15