UnityChan(Channel)
558 subscribers
2.07K photos
86 videos
38 files
88 links
کانال آموزش و نکات UnityChan

مالک کانال : @FProSensei

حمایت مالی (دونیت) : https://daramet.com/FProSensei

گروه یونیتی https://t.me/UnityChan
Download Telegram
FPro Sensei
RefractionModelResult refraction =
RefractionModelBox(V, PositionWS, N, ior, thickness);
از همون تابع داخلی refraction استفاده میکنه و مقدایر (V, PositionWS, N, ior, thickness) میده به اون تا اون برام یک مدل RefractionModelBox برگشت بده و اما کار این تابع چیست :

بردار دید (V) را با نرمال سطح (N) و IOR شکست می‌دهد — refract(-V, N, 1/IOR) — یعنی زاویهٔ واقعی نوری که وارد آب می‌شود را حساب می‌کند.

فرض می‌کند سطح داخلی جسم (کف ظرف/کف آب) یک صفحهٔ موازی با سطح بالا و به فاصلهٔ thickness از آن است — یک «جعبه» ساده، نه انحنای واقعی.

پرتوی شکسته‌شده را با آن صفحهٔ داخلی تلاقی می‌دهد و نقطهٔ خروج (positionWS) و طول مسیر داخل ماده (dist) را برمی‌گرداند.
🔥1
FPro Sensei

float2 hitNDC = ComputeNormalizedDeviceCoordinates(
refraction.positionWS, GetWorldToHClipMatrix());
این خط نقطهٔ خروج پرتوی شکسته‌شده (که یک مختصات سه‌بعدی در فضای جهانی است) را به یک مختصات دوبعدی روی صفحهٔ نمایش (UV بین ۰ تا ۱) تبدیل می‌کند — یعنی «این نقطه از دنیای سه‌بعدی، دقیقاً کجای تصویر رندرشده قرار می‌گیرد؟» اما سوال این هست که چرا لازمه ؟

refraction.positionWS که از RefractionModelBox گرفتیم یک نقطه در فضای ۳بعدی جهان است (مثلاً «ته آب، ۲۰ سانتی‌متر پایین‌تر و کمی به یک طرف کج‌شده»). اما برای نمونه‌برداری از _ColorPyramidTexture (که یک تصویر ۲بعدی رندرشده از دوربین است) نیاز داریم بدانیم این نقطه در پیکسل‌بندی تصویر کجا می‌افتد. ❗️
FPro Sensei
float hitDeviceDepth = SampleCameraDepth(hitNDC);
float hitLinearDepth = LinearEyeDepth(hitDeviceDepth, _ZBufferParams);
float surfaceLinearDepth = LinearEyeDepth(PositionWS, GetWorldToViewMatrix());
خط اول: SampleCameraDepth(hitNDC)
در همان UV که از مرحلهٔ قبل (hitNDC) به‌دست آمد، به‌جای رنگ، مقدار عمق را از بافر عمق دوربین می‌خواند. خروجی‌اش یک عدد خام است (device depth، معمولاً بین ۰ و ۱، غیرخطی) — یعنی «چیزی که همین الان روی صفحه در این پیکسل رندر شده، چقدر از دوربین فاصله دارد؟»


خط دوم: LinearEyeDepth(hitDeviceDepth, _ZBufferParams)
عمق خام غیرخطی (device depth) را به یک عدد خطی به‌متر تبدیل می‌کند. بافر عمق در GPU معمولاً غیرخطی ذخیره می‌شود (دقت بیشتر نزدیک دوربین، کمتر دور) و برای مقایسهٔ مستقیم فاصله‌ها باید خطی‌اش کنیم. نتیجه: hitLinearDepth = «فاصلهٔ واقعی (متر) چیزی که در آن UV روی صفحه دیده می‌شود، از دوربین.»


خط سوم: LinearEyeDepth(PositionWS, GetWorldToViewMatrix())
این یکی overload متفاوتی از LinearEyeDepth است — به‌جای گرفتن device depth، مستقیم یک موقعیت world را می‌گیرد و با ماتریس world-to-view فاصلهٔ آن نقطه از دوربین را حساب می‌کند. اینجا PositionWS موقعیت خود سطح آب است (نه نقطهٔ شکسته‌شده). نتیجه: surfaceLinearDepth = «سطح آب خودش چقدر از دوربین فاصله دارد؟»
FPro Sensei
float offsetMultiplier = (hitLinearDepth > surfaceLinearDepth) ? 1.0 : 0.0;
float2 samplingNDC = lerp(ScreenPosition.xy, hitNDC, offsetMultiplier);
خط اول: offsetMultiplier
یک سوییچ صفر/یک می‌سازد:

اگر hitLinearDepth > surfaceLinearDepth (چیزی که پشت UV شکسته‌شده هست، از خود سطح آب دورتر است — یعنی واقعاً «پشت آب» است) → offsetMultiplier = 1.0
در غیر این صورت (چیزی که آنجاست جلوتر از آب است — یعنی یک جسم مثل پای کاراکتر جلوی آب ایستاده) → offsetMultiplier = 0.0

خط دوم: lerp(ScreenPosition.xy, hitNDC, offsetMultiplier)
بر اساس آن سوییچ، بین دو UV انتخاب می‌کند:

وقتی offsetMultiplier = 1.0 → نتیجه دقیقاً hitNDC می‌شود (همان UV شکسته‌شده که از RefractionModelBox + پروجکشن به‌دست آمد) — یعنی رفرکشن واقعی اعمال می‌شود.
وقتی offsetMultiplier = 0.0 → نتیجه دقیقاً ScreenPosition.xy می‌شود (UV خودِ پیکسل سطح آب، بدون هیچ آفستی) — یعنی رفرکشن خاموش می‌شود و همان‌جایی که هستیم را می‌خوانیم.

چون lerp با ضریب دقیقاً ۰ یا ۱ است (نه یک عدد میانی)، این عملاً یک if است نوشته‌شده به‌شکل بدون شاخه (branchless) — روی GPU این معمولاً سریع‌تر از if واقعی اجرا می‌شود.
🔥1
FPro Sensei

float mipLevel = PositivePow(saturate(Roughness), 1.3)
* max((float)_ColorPyramidLodCount - 1.0, 0.0);

float3 color = SampleCameraColor(samplingNDC, mipLevel);
color *= GetInverseCurrentExposureMultiplier();
خط اول: محاسبهٔ mipLevel
_ColorPyramidTexture فقط یک تصویر ساده نیست — یک mip chain است: نسخهٔ کامل‌رزولوشن (mip 0)، بعد نصف‌رزولوشن (mip 1)، ربع (mip 2)، و همین‌طور تا آخر. هر مرحلهٔ پایین‌تر عملاً یک نسخهٔ تارتر و کوچک‌تر از تصویر است

نتیجه: هرچه سطح زبرتر (Roughness بالاتر)، mipLevel بزرگ‌تر می‌شود → از سطح تارتر پیرامید نمونه گرفته می‌شود → رفرکشن محو/تار به‌نظر می‌رسد. سطح صاف/براق (Roughness=0) → mipLevel=0 → کاملاً واضح.

خط سوم: SampleCameraColor(samplingNDC, mipLevel)

از _ColorPyramidTexture در مختصات samplingNDC (همان UV نهایی که با گارد عمق تعیین شد) و در سطح mip محاسبه‌شده، رنگ را می‌خواند. این تابع wrapper است که خودش _ColorPyramidUvScaleAndLimitCurrentFrame را هم داخلش اعمال می‌کند (چون پیرامید رنگ همیشه دقیقاً هم‌اندازهٔ کل صفحه نیست، یک بخش کوچکش padding/unused است، و این ضریب scale/limit جلوی خواندن از آن ناحیهٔ نامعتبر را می‌گیرد).


خط چهارم: color *= GetInverseCurrentExposureMultiplier()
پیرامید رنگ، رنگ‌ها را به‌شکل pre-exposed ذخیره می‌کند — یعنی مقدار auto-exposure صحنه از قبل در آن ضرب شده.
🔥1
FPro Sensei

float3 absorption = exp(-max(AbsorptionColor, 0.0)
* max(AbsorptionStrength, 0.0)
* refraction.dist);
color *= absorption;

float2 coordCS = samplingNDC * 2.0 - 1.0;
float2 t = Remap10(abs(coordCS),
_SSRefractionInvScreenWeightDistance,
_SSRefractionInvScreenWeightDistance);
float edgeFade = Smoothstep01(t.x) * Smoothstep01(t.y);
بخش اول: جذب (Absorption) — قانون Beer-Lambert
absorption = exp(-AbsorptionColor * AbsorptionStrength * refraction.dist)
color *= absorption


هرچه refraction.dist بزرگ‌تر باشد (پرتو مسیر طولانی‌تری داخل آب طی کرده — یعنی آب عمیق‌تر)، exp(-...) کوچک‌تر می‌شود → رنگ بیشتر جذب/تیره می‌شود.

AbsorptionColor به هر کانال رنگ اجازه می‌دهد با نرخ متفاوت جذب شود — مثلاً آب معمولاً قرمز را سریع‌تر از آبی جذب می‌کند، برای همین آب عمیق آبی/سبز به‌نظر می‌رسد.

AbsorptionStrength یک ضریب کلی برای شدت این افکت است.

نتیجه: این نسخه از عمق واقعی مسیر نوری (refraction.dist) استفاده می‌کند — پس با عمق واقعی آب (نه فقط یک پارامتر ثابت) هماهنگ می‌شود.
🔥1
توضیح کامل قانون Beer - Lambert
🔥1👏1
FPro Sensei
float2 coordCS = samplingNDC * 2.0 - 1.0;
float2 t = Remap10(abs(coordCS),
_SSRefractionInvScreenWeightDistance,
_SSRefractionInvScreenWeightDistance);
float edgeFade = Smoothstep01(t.x) * Smoothstep01(t.y);

RefractedColor = max(color, 0.0);
Weight = saturate(edgeFade);
محاسبهٔ edgeFade
UV نمونه‌برداری را به بازهٔ [-1,1] می‌برد، فاصله تا نزدیک‌ترین لبهٔ صفحه را حساب می‌کند، و با Smoothstep01 یک مقدار نرم بین ۰ (دقیقاً روی لبه) تا ۱ (دور از لبه، وسط صفحه) می‌سازد. ضرب t.x * t.y یعنی اگر از هر جهت (افقی یا عمودی) به لبه نزدیک شویم، فید کم می‌شود.

RefractedColor = max(color, 0.0)
رنگ نهایی محاسبه‌شده (بعد از نمونه‌برداری از پیرامید، اصلاح exposure، و جذب) را در خروجی می‌گذارد. max(..., 0.0) فقط یک گارد ایمنی است — جلوی مقادیر منفی احتمالی (که در محاسبات نوری گاهی از خطای عددی float پیش می‌آید و در HDR/رندر بعدی مشکل ایجاد می‌کند) را می‌گیرد.

Weight = saturate(edgeFade)
مقدار fade را بین ۰ و ۱ محدود می‌کند و به‌عنوان خروجی دوم تابع (Weight) برمی‌گرداند.
🔥1👏1
در نهایت با ساخت و تعریف ورودی های نود میتوانید از این توی شیدر آبتون استفاده کنید آموزش تخصصی بود از جانب FPro Sensei ❗️
🔥1🥰1
FPro Sensei
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Refraction.hlsl"
جالب اینجاست که این com.unity.render-pipelines.core کتابخانه SRP هست یعنی مشترک بین URP و HDRP پس توی هر دو تاش میتونید استفاده کنید ولی URP فرق داره
🔥1🥰1
ویلبرورد اسنلیوس و کشف قانون شکست نور 🔍

که بود: ریاضی‌دان هلندی (۱۵۸۰–۱۶۲۶)، استاد دانشگاه لیدن، معروف به کار مثلث‌بندی برای اندازه‌گیری زمین 🌍📐.

کشف: با استفاده از تخصصش در زاویه و مثلثات، زاویهٔ تابش و شکست نور را در عبور از هوا به شیشه/آب اندازه گرفت 📏💧 و در سال ۱۶۲۱ فهمید نسبت سینوس این دو زاویه همیشه ثابت است — همان قانون امروزی:

n₁ sinθ₁ = n₂ sinθ₂ 📝

سرنوشت عجیب: خودش آن را منتشر نکرد 🤐. در ۱۶۲۶ درگذشت 🪦، دکارت در ۱۶۳۷ همین قانون را منتشر کرد 📢، و سال‌ها بعد هویگنس با بررسی دست‌نوشته‌هایش ثابت کرد اسنلیوس زودتر به آن رسیده بود 🕵️‍♂️ — برای همین قانون به نام او ماند 🏆.

نکته تاریخی: او هم اولین کاشف نبود؛ ابن سهل (ایرانی، حدود ۹۸۴ میلادی) 🇮🇷 و توماس هریوت هم پیش‌تر و مستقل به رابطه‌های مشابه رسیده بودند، ولی کارشان منتشر نشد 📜.

در نهایت تو در کار شیدر نویسی از این قانون دانشمند استفاده می‌کنی 👓

#دانستنی
🔥1🥰1
ثبت نام این بازه تا وقت دارید حتما بگیرید ❗️
🔥1
الان میدونم همه از هوش مصنوعی استفاده میکنن ولی بعضی ها استفاده بشدت خیلی جو میدن و خودشون دست بالا گرفتن ولی باید بگم براشون خبر بدی دارم چون کلادی که تو استفاده میکنی مخفیانه توی کد های واتر مارک های مخفی میزاره که حتا روحت هم خبر نداره چه برسه به ذهنت ❗️

یک نمونه :

#ifndef ANITOON_WATER_INCLUDED
#define ANITOON_WATER_INCLUDED

void Water_float(float3 PositionWS, out float3 Output)
{
float3 color = float3(0.0, 0.5, 1.0);

// این تابع کاملاً عادی به نظر می‌رسد.
Output = color;
}

#endif


حالا فرض کن بین بعضی کاراکترهای کد، Zero-Width Space (U+200B) جاسازی شده باشد:

#ifndef ANITOON_WATER_INCLUDED
#define ANITOON_WATER_INCLUDED

void Water_float(float3​ PositionWS, out float3 Output)
{
float3 color = float3(0.0, 0.5, 1.0);

// این تابع کاملاً عادی به نظر می‌رسد.
Output = color;
}

#endif


اینجا بعد از float3 یک کاراکتر نامرئی وجود دارد:


float3[U+200B] PositionWS


ولی چشم تو تقریباً این را می‌بیند:


float3 PositionWS
👍1👏1
FPro Sensei
الان میدونم همه از هوش مصنوعی استفاده میکنن ولی بعضی ها استفاده بشدت خیلی جو میدن و خودشون دست بالا گرفتن ولی باید بگم براشون خبر بدی دارم چون کلادی که تو استفاده میکنی مخفیانه توی کد های واتر مارک های مخفی میزاره که حتا روحت هم خبر نداره چه برسه به ذهنت ❗️
روش های واتر مارک های مخفی :

۱. کاراکترهای Zero-Width :

ظاهر :
float3 PositionWS;
float3 Normal;

ولی ممکن است بین حروف کاراکترهای نامرئی باشد:

float3[U+200B]PositionWS;
float3[U+200C]Normal;


چشم تقریباً هیچ تفاوتی نمی‌بیند.

۲. BOM یا کاراکتر نامرئی ابتدای فایل:


#ifndef ANITOON_WATER_INCLUDED


[U+FEFF]#ifndef ANITOON_WATER_INCLUDED


۴. داده داخل کامنت :
// Water calculation
// normal = geometric normal
// reflection = SSR


و انتهای یکی از کامنت‌ها داده‌ای نامرئی قرار گرفته باشد:
// Water calculation[U+200B][U+200C][U+200C][U+200B]

و دیگر روش های پنهان که اصلا روحتون خبر نداره ❗️❗️
1👍1
اگر کسی یک برنامه بسازه و بگه منم ساختم ولی به دورغ بگه و با هوش مصنوعی بسازه مطمعن باشه که راحت من یا دیگر افراد متخصص براحتی میتونه تشخیص بده که کلک زدی یا نه پس در مقابل این اینجور افراد براشون سوپرایز هم دارم پس صادقانه باشید نه دورغین ❗️❗️
👍1
FPro Sensei
اگر کسی یک برنامه بسازه و بگه منم ساختم ولی به دورغ بگه و با هوش مصنوعی بسازه مطمعن باشه که راحت من یا دیگر افراد متخصص براحتی میتونه تشخیص بده که کلک زدی یا نه پس در مقابل این اینجور افراد براشون سوپرایز هم دارم پس صادقانه باشید نه دورغین ❗️❗️
کارایی که با هوش مصنوعی زده میشه ارزش پایین هست دوست عزیز 🤖💸 برای مثال قراره Asset‌هایی که توی ساختنشون از هوش مصنوعی استفاده شده بشدت ارزون‌تر فروخته بشه 📉 همین ویدیوهایی که با هوش زده میشود قطعا ارزش فروخت‌هاشون بشدت کمتر از ویدیو‌های واقعی هست 🎥

الکی هم نیست هوش ول کنن هر کسی با این چیزی بسازه و بزنه به نام خودش چون قانون DMCA هست که میگه باید حقوق سازنده محفوط باشه ⚖️🛡 یعنی فکر میکنید هوش مصنوعی بی قانونه؟ خیر 🚫 توی اون قانون خاص خودشو داره و گرنه هر کی هرکی میشه برای هر کاری که با اون زده میشه هم واتر مارک نامرئی می‌زنه 🏷
هوش مصنوعی «کلود» روی متن‌هایش واترمارک نامرئی می‌گذارد
مدل‌های جدید هوش مصنوعی کلود سیگنال‌های نامرئی را در خود تعبیه خواهند کرد که می‌توانند به شناسایی متن تولید شده توسط این چت‌بات پس از کپی کردن کمک کنند.

شرکت آنتروپیک از روز دوم ماه اوت سال۲۰۲۶، واترمارک‌های قابل خواندن توسط ماشین را به متن تولید شده توسط مدل‌های جدید کلود اضافه خواهد کرد.

به نقل از آی‌ای، این اقدام در راستای الزامات شفافیت ذیل ماده ۵۰ قانون هوش مصنوعی اتحادیه اروپا انجام می‌شود. شرکت آنتروپیک، آیین‌نامه اجرایی اتحادیه اروپا در مورد محتوای تولید شده توسط هوش مصنوعی را امضا کرده است.

مدل‌های جدید کلود که از آن تاریخ عرضه می‌شوند، محتوای تولید شده را در سطح مدل علامت‌گذاری خواهند کرد. شرکت آنتروپیک می‌گوید این علامت‌گذاری‌ها نه تنها برای کاربران اروپایی، بلکه در سراسر جهان اعمال خواهد شد.

این سیستم از روش‌های مختلفی برای متن و فایل‌های پشتیبانی‌شده استفاده خواهد کرد. متن‌ها واترمارک‌های نامرئی دریافت می‌کنند

پ.ن : در کل میگه یعنی کسی که تا الان با هوش مصنوعی پز میداد دیگه داره تموم میشه
1👍1
از مجموعه آموزش‌های شیدر نویسی، توضیح Tessellation ارائه شده یکی از امکانات عالی است که کاربردهای زیادی در بازی دارد، مخصوصاً در شیدر آب یا دیگر موارد 🎮
👏2👍1