<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های احمد عرفانی</title><link>https://virgool.ir/feed/@ahmaderfani12</link><description>دانشجوی کامپیوتر، طراح و توسعه دهنده بازی، علاقه مند به گرافیک کامپیوتری</description><language>fa</language><pubDate>2026-11-12 11:07:19</pubDate><image><url>https://files.virgool.ir/upload/users/591357/avatar/VPVot8.jpeg</url><title>احمد عرفانی</title><link>https://virgool.ir/@ahmaderfani12</link></image><item><title>The Book of Shaders (بخش سوم) Uniforms</title><link>https://virgool.ir/@ahmaderfani12/the-book-of-shaders-part3-k4ehnymhjvtf</link><description>Uniformsتاکنون دیدیم که GPU چگونه تعداد زیادی ترد موازی را مدیریت می‌کند. هر کدام از آن ها وظیفه تخصیص رنگ، به جزئی(fragment) از تصویر را دارند. با اینکه هر ترد موازی نسبت به دیگران کور است، اما باید بتوانیم از CPU ورودی هایی به همه ترد ها ارسال کنیم. به دلیل معماری کارت گرافیک، این ورودی ها برای همه ترد ها یکسان هستند و فقط بصورت خواندنی(read only). به عبارتی هر ترد اطلاعات مشابهی را دریافت می‌کند که می‌تواند بخواند، اما نمی‌تواند تغییر دهد.به این ورودی ها یونیفرم(uniform) گفته می‌شود. و معمولا به صورت تایپ های مقابل استفاده می‌شوند: float, vect2, vect3, vect4, mat2, mat3, mat4, sampler2D, samplerCube. یونیفرم ها در بالای شیدر، پس از تعریف دقت نقطه شناور پیشفرض تعریف می‌شوند.#ifdef GL_ES&#xA;precision mediump float;&#xA;#endif&#xA;&#xA;uniform vec2 u_resolution;  // Canvas size (width,height)&#xA;uniform vec2 u_mouse;       // mouse position in screen pixels&#xA;uniform float u_time;       // Time in seconds since loadیونیفرم ها را می‌توان مانند پل های کوچک بین CPU و GPU تصور کرد. نام ها در محیط های مختلف ممکن از تفاوت داشته باشند، اما در این مجموعه از مثال ها همیشه این نام ها ثابتند: u_time(زمان بر حسب ثانیه از شروع شیدر)، u_resolution(اندازه کنوس، جایی که شیدر کشیده می‌شود) و u_mouse(موقعیت ماوس در داخل کنوس بر حسب پیکسل).من این قرار داد را دنبال می‌کنم که قبل یونیفرم ها u_ بگذارم، اما شکل های دیگری هم ممکن است به چشمتان بخورد، مثلا ShaderToy.com از همین یونیفرم ها اما به شکل زیر استفاده کرده است.uniform vec3 iResolution;   // viewport resolution (in pixels)&#xA;uniform vec4 iMouse;        // mouse pixel coords. xy: current, zw: click&#xA;uniform float iTime;        // shader playback time (in seconds)صحبت کردن کافیست بیایید یونیفرم ها را در عمل ببینیم. در کد زیر ما از u_time استفاده می‌کنیم. یعنی تعداد ثانیه از زمانی که شیدر شروع شده است را به همراه عملکرد سینوس برای تحریک مقدار قرمز به کار گرفتیم.تعامل در کد بالا در اینجاهمانطور که می‌بینید GLSL سورپرایز های بیشتری دارد. GPU دارای عملکرد های زاویه شتاب همچنین توابع نمایی و مثلثاتی هست. برخی ازین توابع عبارتند از: sin(), cos(), tan(), asin(), acos(), atan(), pow(), exp(), log(), sqrt(), abs(), sign(), floor(), ceil(), fract(), mod(), min(), max() and clamp().اکنون زمان آن است که دوباره با کد با بازی کنیم. فرکانس را کم کنید تا زمانی که تغییر رنگ نامحسوس شود.سرعت را آنقدر زیاد کنید که یک رنگ بدون پرش ببینید.با سه کانال RGB در فرکانس های مختلف بازی کنید تا الگو ها و رفتار های جالبی ببینید.gl_FragCoordبه همان صورت که GLSL به ما یک خروجی vec4 gl_FragColor می‌دهد، همچنین یک ورودی پیشفرض در نظر دارد. vec4 gl_FragCoord که مختصات پیکسل ها در صفحه و یا قطعه صفحه ای که ترد روی آن کار می‌کند را نگه می‌دارد، با vec4 gl_FragCoord، می‌توانیم بفهمیم یک ترد کجای بیلبورد کار می‌کند. در این مورد ما آن را یونیفرم صدا نمی‌زنیم، بلکه به gl_FragCoord یک varying می‌گوییم.#ifdef GL_ES&#xA;precision mediump float;&#xA;#endif&#xA;&#xA;uniform vec2 u_resolution;&#xA;uniform vec2 u_mouse;&#xA;uniform float u_time;&#xA;void main() {&#xA;&#x9;vec2 st = gl_FragCoord.xy/u_resolution;&#xA;&#x9;gl_FragColor = vec4(st.x,st.y,0.0,1.0);&#xA;}تعامل در کد بالا در اینجاخروجی کد بالادر مثال بالا ما با تقسیم gl_FragCoord بر u_resolution مختصات نرمالایز شده(بین 0 و 1) را در st ذخیره می‌کنیم. با این کار به راحتی میتوان مقادیر x را به قرمز و مقادیر y را به سبز مپ کرد.در شیدر نویسی ما منابع زیادی برای دیباگ کردن نداریم، خواهید فهمید که گاهی اوقات کد نویسی در GLSL مانند قراردادن کشتی در داخل بطری است. به همان اندازه سخت زیبا و خوشایند.اکنون وقت آن است درک خود را در مورد این کد به چالش بکشیم.می‌توانید بگویید مختصات (0.0،0.0) در کنوس کجاست؟در مورد (1.0, 0.0), (0.0, 1.0), (0.5, 0.5), (1.0, 1.0) چطور؟آیا می‌توانید نحوه استفاده از u_mouse را بیابید و مقدار واقعی در پیکسل نه نرمالایز شده آن را بفهمید؟ از آن برای جابه جایی رنگ ها می‌توانید استفاده کنید؟آیا می‌توانید روش جالبی برای تغییر این الگوی رنگ با استفاده از u_time و u_mouse تصور کنید؟بعد از انجام این تمرینات، ممکن است کنجکاو باشید که در کجا ها می‌توانید از توانایی شیدر نویسی خود استفاده کنید. در قسمت بعد خواهید دید که چگونه می‌توان ابزار های شیدر نویسی خود را در three.js, Processing و یا openFrameworks بسازید.</description><category>احمد عرفانی</category><author>احمد عرفانی</author><pubDate>Wed, 27 Jan 2021 17:11:26 +0330</pubDate></item><item><title>The Book of Shaders (بخش دوم) Hello World</title><link>https://virgool.ir/@ahmaderfani12/ترجمه-the-book-of-shaders-بخش-دوم-hello-world-vuoxedttlkl8</link><description>معمولا عبارت &#34;Hello World&#34; مثالی از اولین قدم برای یادگیری یک زبان جدید است.در مورد ما ارائه یک متن کار پیچیده ای برای قدم اول است، در عوض یک رنگ روشن را به عنوان شور و شوق اولین کدمان اجرا می‌کنیم!#ifdef GL_ES&#xA;precision mediump float;&#xA;#endif&#xA;uniform float u_time;&#xA;void main() {&#xA;    gl_FragColor = vec4(1.0,0.0,1.0,1.0);&#xA;}اگر این کتاب را در یک مرورگر مدرن می‌خوانید، کد بالا قابل تغییر است، تغییرات شما بلافاصله کامپایل و به شما نمایش داده می‌شوند، در مثال بالا سعی کنید خط 8 را تغییر دهید.(رجوع به صفحه اصلی برای تعامل با کد)البته این خطوط ساده به نظر نمی‌رسند، اما می‌توان مفاهیم قابل توجهی از آنها استباط کرد:برنامه نویسی شیدر یک عملکرد اصلی(main) دارد، که در انتها یک رنگ برمی‌گرداند. شبیه زبان C.رنگ نهایی پیکسل به متغیر گلوبال gl_FragColor اختصاص داده شده است.این زبان شبه C با متغیر ها و تابع های مختلف ساخته شده و استفاده می‌شود. در این مورد ما با vect4 آشنا شدیم که مخفف یک بردار 4 بعدی با دقت شناور(float) است. انواع بیشتری ازین متغیر ها مانند vect2, vect3 و bool, int, float در آینده خواهیم دید.اگر به vect4 دقت کنیم می‌یابیم این 4 آرگومان به کانال های RGBA پیکسل مورد نظر پاسخ می‌دهند. همچنین این مقادیر نرمال شده اند یعنی بین 0تا1(نه بین 0 تا 255)، بعدا خواهیم آموخت چگونه نرمال سازی مقادیر، ترسیم مقادیر بین متغیر ها را آسان می‌کند.یکی از دیگر ویژگی های مشابه C مثال بالا وجود ماکرو ها هستند. با استفاده از آنان می‌توان متغیر های جهانی را تعریف کرد و یا برخی عملیات شرطی اساسی را انجام داد(ifdef and #endif#). تمام دستورات کلان(ماکرو) با هشتگ شروع می‌شوند. ماکرو ها قبل از کامپایل اجرا می‌شوند، شرایط را بررسی می‌کند(ifdef and #endif#) و ارجاعات به defines# را کپی می‌کند. مثلا در مثال بالا ما خط 2 را در صورت تعریف GL_ES وارد می‌کنیم. که معمولا در هنگام کامپایل این کد در تلفن های همراه و مرورگر ها اتفاق می‌افتد.شناور ها(float) در شیدر ها حیاتی هستند، بنابراین سطح دقت بسیار مهم است. دقت پایین تر به معنای رندر سریع تر است، همچنین کیفیت کمتر. می‌توانید مثل خط دو مثال بالا متغیر ها را شناور با دقت متوسط درنظر بگیرید(precision mediump float)، همچنین می‌توانید متغیر شناور با دقت پایین(precision lowp float) یا بالا(precision highp float)هم در نظر بگیرید.آخرین و شاید مهمترین نکته در مثال بالا اینکه در GLSL تضمین نمی‌شود که متغیر ها به طور خودکار تغییر نوع داده(casting) رویشان اعمال شود. این به چه معناست؟ تولید کنندگان رویکرد های مختلفی برای سرعت بخشیدن روند پردازش کارت های گرافیکی دارند، و مجبورند حداقل مشخصات را تضمین کنند. کستینگ ازین رویکرد ها نیست. در مثال بالا vect4 دارای نقطه شناور است و برای آن انتظار می‌رود که به متغیر های شناور انتساب شود. اگر می‌خواهید کد سازگار خوبی ایجاد کنید و ساعت ها وقت صرف دیبگ کردن آن نکنید، عادت کنید در float ها از نقطه(.) استفاده کنید.void main() {&#xA;    gl_FragColor = vec4(1,0,0,1);   // ERROR&#xA;    gl_FragColor = vec4(1.0,0.0,1.0,1.0); //CORRECT&#xA;}اکنون که مهم ترین عناصر مثال بالا را با هم مرور کردیم، وقت آن است که روی کد کلیک کنید(اینجا) و چیز هایی که یاد گرفتیم را پیاده کنیم. توجه کنید که در صورت خطا برنامه صفحه سفید را به شما نشان می‌دهد. بعضی چیز های جالب وجود دارد که باید امتحان کنید، مثلا:شناور ها را با اعداد صحیح(int) جایگزین کنید، کارت گرافیک شما معلوم نیست بتواند این کد را اجرا کند یا خیر.سعی کنید خط 8 را کامنت کنید و هیچ مقدار پیکسلی به تابع اختصاص ندهید.سعی کنید یک تابع جداگانه ایجاد کنید که رنگ خاصی را برگرداند و از آن داخل main استفاده کنید، به عنوان یک راهنمایی در اینجا کد مربوط به تابعیست که رنگ قرمز را بر می‌گرداند.vec4 red(){&#xA;     return vec4(1.0,0.0,0.0,1.0);&#xA;}باید تابع ()red را قبل از ()main تعریف کنید.روش ها مختلفی برای ساخت vect4 وجود دارد، سعی کنید راه های دیگر را پیدا کنید، یکی از آن ها به این صورت است:vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);اگرچه این مثال خیلی هیجان انگیز نیست، اما ابتدایی ترین مثال است. ما تمام پیکسل های داخل کنوس(canvas) را به یک رنگ تغییر می‌دهیم. در فصل بعد نحوه تغییر رنگ پیکسل را با استفاده از دو نوع ورودی دیگر می‌بینیم. فضا(محل و مختصات پیکسل روی صفحه) و زمان(مقدار زمان از لحظه بارگیری صفحه بر حسب ثانیه). https://virgool.io/@ahmaderfani12/the-book-of-shaders-part3-k4ehnymhjvtf </description><category>احمد عرفانی</category><author>احمد عرفانی</author><pubDate>Wed, 27 Jan 2021 01:24:55 +0330</pubDate></item><item><title>The Book of Shaders (بخش اول) ?What is a shader</title><link>https://virgool.ir/@ahmaderfani12/the-book-of-shaders-part1-tvs61l2rm1c8</link><description>این رشته مقالات ترجمه ای از The Book of Shaders می‌باشد، که نگاهی عمیق و قدم به قدم در مورد شیدر نویسی در گرافیک کامپیوتری هست.شیدر خرد (fragment shader) چیست؟اگر تجربه نقاشی در کامپیوتر را داشته باشید می‌‌دانید که در این فرایند، دایره، مستطیل و خط هارا یکی پس از دیگری می‌کشید تا شکل مورد نظر خود را نهایی کنید، این فرایند شبیه نوشتن کتاب است، در واقع این کار ها مجموعه ای از دستور العمل ها هستند که وظایف را یکی پس از دیگری انجام می‌دهند.From Letter-by-Letter, Right: William Blades (1891). To Page-by-page, Left: Rolt-Wheeler (1920).شیدر ها هم مجموعه ای از دستور العمل ها هستند، اما دستور المل هایی که به یکباره برای هر پیکسل روی صفحه اجرا می‌شود. این بدان معناست، کدی که می‌نویسید بسته به موقعیت پیکسل روی صفحه نمایش باید رفتار متفاوتی انجام دهد. برنامه شما مانند تابعی کار می‌کند که موقعیت را دریافت می‌کند و یک رنگ را بر می‌گرداند، زمانی که کد شما کامپایل می‌شود، این عملیات بسیار سریع انجام می‌‌شود.Chinese movable typeچرا شیدر ها سریع هستند؟برای پاسخ به این سوال من شگفتی پردازش موازی را به شما معرفی می‌کنم.پردازه مرکزی(CPU) رایانه خود را به عنوان یک لوله بزرگ صنعتی در نظر بگیرید، و هر تسکی را مانند چیزی که از داخل آن عبور می‌کند بپندارید. بعضی تسک ها بزرگ تر از بقیه هستند پس زمان و انرژی بیشتری برای پردازش آن ها نیاز است. به نوعی می‌گوییم این نوع تسک ها به قدرت پردازش بالاتری نیاز دارند. به دلیل معماری رایانه ها تسک ها مجبور هستند به صورت سری اجرا شوند، تسک ها باید یک به یک تمام شوند. رایانه های مدرن معمولا دارای گروه های چهارتایی از پردازنده ها هستند، که مانند این لوله ها کار می‌کنند و وظایف را یکی پس از دیگری انجام می‌دهد تا کار ها بدون مشکل انجام شود، هر لوله را به عنوان یک ترد(thread) هم می‌شناسند.بازی های ویدئویی و سایر برنامه های گرافیکی به پردازش بیشتری نسبت به برنامه های معمول نیاز دارند. به دلیل محتویات زیاد، آن ها باید باید مقادیر زیادی عملیات پیکسل به پیکسل انجام دهند. هر یک از پیکسل ها باید محاسبه شوند، همچنین در بازی های سه بعدی باید عملیات های بیشتری مثل محاسبات هندسی و پرسپکتیو هم انجام شود.بیاید به استعاره خود در مورد لوله ها و تسک ها برگردیم، هر پیکسل رو صفحه نمایش یک تسک کوچک و ساده را نشان می‌دهد، به طور جداگانه تسک هر پیکسل برای CPU مسئله ای نیست. اما اینکه این تسک های کوچک باید برای هر پیکسل انجام شود برای CPU مشکل ساز است. این یعنی در صفحات قدیمی 800x600 باید 480,000 پیکسل در هر فریم پردازش شود که به معنی 14,400,000 محاسبه در ثانیه است! بله این مقدار به قدری بزرگ هست که یک ریزپردازنه را سرریز کند. در یک نمایشگر مدرن 2880x1800 با نرخ 60 فریم بر ثانیه، این محاسبات به 311,040,000 محاسبه در ثانیه می‌رسد. چگونه مهندسان گرافیک این مشکل را حل ‌می‌کنند؟این زمانی است که پردازش موازی به یک راه حل خوب تبدیل می‌شود، منطقی است که به جای داشتن چند ریز پردازنده بزرگ یا قدرتمند(لوله)، ریزپردازنده های کوچکتری و بیشتری به صورت موازی کار کنند. واحد پردازنده گرافیکی(GPU) همین طور عمل می‌کند.GPUریز پردازنده های کوچک را مانند جدولی از لوله ها وداده های هر پیکسل را مانند یک توپ تصور کنید، 14,400,000 توپ می‌تواند هر لوله های را مسدود کند، اما می‌توان یک جدول از 800x600 لوله کوچک را که 30 موج 480,000 تایی پیکسل در ثانیه دریافت می‌کند را به راحتی کنترل کرد. در وضوح بالاتر هم به همین صورت عمل می‌کند. هرچه سخت افزار های موازی بیشتری داشته باشید، به همان نسبت جریان بیشتری را می‌توانید مدیریت کنید.از دیگر قدرت های فوق العاده GPU عملکرد های ویژه ریاضی آن است که از طریق سخت افزار سریع تر می‌شود، یعنی این عملیات ریاضی به جای استفاده از نرم افزار مستقیما توسط میکرو تراشه حل می‌شوند، به عبارتی عملکرد های مثلثاتی و ماتریسی به سرعت الکتریسیته می‌تواندد سریع باشند. عبارت GLSL چیست؟مخفف OpenGL Shading Language است. که استانداری خاص از برنامه های شیدر هست و در فصل بعدی خواهید دید. بسته به سخت افزار و سیستم عامل ها انواع دیگر شیدر نیز وجود دارند. در اینجا ما با OpenGL  تنظیم شده توسط گروه Khronos کار خواهیم کرد. دانستن تاریخچه OpenGL می‌تواند به درک بیشتر قرار داد های عجیب و غریب آن مفید باشد، برای همین توصیه میکنیم نگاهی به این موضوع داشته باشید: openglbook.com/chapter-0-preface-what-is-opengl.htmlچرا شیدر ها به دردناک بودن معروفند؟ :)همانطور که عمو بن گفت:&#34;قدرت زیاد، با مسئولیت بزرگی همراه است&#34;، و محاسبه موازی ازین قاعده پیروی می‌کند، طراحی معماری قوی GPU محدودیت ها و خصوصیات مخصوص به خودش را دارد.برای این که به صورت موازی هر لوله یا ترد اجرا شود. باید از هر ترد دیگری مستقل باشد، ترد ها نسبت به آنچه بقیه ترد ها انجام می‌دهد نا آگاه هستند. این محدودیت نشان می‌دهد که همه داده ها باید در یک جهت جریان داشته باشند. پس بررسی نتیجه یک ترد دیگر، اصلاح داده های ورودی و یا انتقال نتیجه یک ترد به ترد دیگر غیر ممکن است. اگر به ترد ها اجازه ارتباط داده شود، یکپارچگی داده ها در معرض خطر قرار خواهد گرفت.همچنین GPU پردازنده های موازی را به طور مداوم مشغول نگه می‌دارد، به محض اینکه آزاد می‌شوند، داده های جدید برای پردازش دریافت می‌کنند. برای یک ترد غیر ممکن است که بداند که لحظه قبلی چه کاری انجام داده. عملیات قبلی آن می‌تواند کشیدن یک دکمه برای UI سیستم عامل بوده باشد یا رندر یک آسمان در بازی ویدئویی. هر ترد نه تنها کور(Blind) است(نا آگاه از عملیات ترد های دیگر) بلکه بی حافظه نیز هست.  علاوه بر دانستن مفهوم نحوه کد نویسی بر اساس موقعیت هر پیکسل، این کور بودن و بی حافظه بودن، باعث می‌شود، شیدر ها در میان برنامه نویسان تازه محبوبیت نداشته باشد.نگران نباش در فصل های بعد، گام به گام یاد خواهیم گرفت چگونه محاسبات ساده تا پیشرفته شیدر را انجام دهیم. https://virgool.io/@ahmaderfani12/%D8%AA%D8%B1%D8%AC%D9%85%D9%87-the-book-of-shaders-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-hello-world-vuoxedttlkl8 </description><category>احمد عرفانی</category><author>احمد عرفانی</author><pubDate>Tue, 26 Jan 2021 14:59:45 +0330</pubDate></item></channel></rss>