UnityChan(Channel)
402 subscribers
1.79K photos
59 videos
13 files
40 links
کانال آموزش و نکات UnityChan

گروه یونیتی https://t.me/UnityChan
Download Telegram
FPro Sensei
خب داشتم کد نویسی HLSL شیدر استلایزد بازی رو انجام میدادم ولی خیلی بهم درخواست دادید نمونه از کد را براتون بزارم و توضیح بدم که اینکارو میکنم : قبل از این کار بدونید که سه تا پایپ لاین توی یونیتی داریم که کد نویسی انها تفاوته یعنی شما نمی توانید شیدر urp…
قبل از کد نویسی و توضیح دادن باید بگم که hlsl یک زبان شیدر نویسی بر اساسc++ که کمی به c# شبیه ولی دونستن c# هیچ کمکی به کد نویسی اش نمی کنه پس میخواهید شیدر نویسی کنید HLSL یاد بگیرید

بخش اول :

Shader "Custom/StylizedURPShader_FProSensei"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_HeightMap ("Height Map", 2D) = "white" {}
_TranslucencyColor ("Translucency Color", Color) = (1,1,1,1)
_TranslucencyIntensity ("Translucency Intensity", Range(0, 1)) = 0.5
_RimColor ("Rim Color", Color) = (1,1,1,1)
_RimPower ("Rim Power", Range(1, 10)) = 3
_EmissionColor ("Emission Color", Color) = (1,1,1,1)
_EmissionIntensity ("Emission Intensity", Range(0, 10)) = 1
_Alpha ("Alpha", Range(0, 1)) = 1
_SpecularColor ("Specular Color", Color) = (1,1,1,1)
_SpecularIntensity ("Specular Intensity", Range(0, 1)) = 0.5
_Metallic ("Metallic", Range(0, 1)) = 0.0
_Smoothness ("Smoothness", Range(0, 1)) = 0.5
_TransmissionColor ("Transmission Color", Color) = (1, 1, 1, 1)
_TransmissionIntensity ("Transmission Intensity", Range(0, 1)) = 0.5
_OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)
_OutlineThickness ("Outline Thickness", Range(0.01, 0.1)) = 0.05
_StylizedColor ("Stylized Color", Color) = (1, 0.5, 0.5, 1)
_StylizedIntensity ("Stylized Intensity", Range(0, 2)) = 1.0
}

SubShader
{
Tags { "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite On
ZTest LEqual

Pass
{
Name "Forward"
Tags { "LightMode"="UniversalForward" }

HLSLPROGRAM
#pragma target 4.5
#include "UnityShaderVariables.hlsl"
#include "UnityLighting.hlsl"
#include "CoreRP/ShaderLibrary/Core.hlsl"
#include "CoreRP/ShaderLibrary/Lighting.hlsl"

struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
};

struct Varyings
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float4 positionCS : SV_POSITION;
float3 tangentWS : TEXCOORD3;
};

struct FragmentInput
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS : TEXCOORD3;
};

sampler2D _MainTex;
sampler2D _NormalMap;
sampler2D _HeightMap;
fixed4 _TranslucencyColor;
float _TranslucencyIntensity;
fixed4 _RimColor;
float _RimPower;
fixed4 _EmissionColor;
float _EmissionIntensity;
float _Alpha;
fixed4 _SpecularColor;
float _SpecularIntensity;
float _Metallic;
float _Smoothness;
fixed4 _TransmissionColor;
float _TransmissionIntensity;
fixed4 _OutlineColor;
float _OutlineThickness;
fixed4 _StylizedColor;
float _StylizedIntensity;

Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToClip(input.positionOS);
output.uv0 = input.uv0;
output.uv1 = input.uv1;
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
👏2
FPro Sensei
قبل از کد نویسی و توضیح دادن باید بگم که hlsl یک زبان شیدر نویسی بر اساسc++ که کمی به c# شبیه ولی دونستن c# هیچ کمکی به کد نویسی اش نمی کنه پس میخواهید شیدر نویسی کنید HLSL یاد بگیرید بخش اول : Shader "Custom/StylizedURPShader_FProSensei" { Properties…
بخش اخر کد :

                output.tangentWS = TransformObjectToWorldTangent(input.normalOS); 
return output;
}

half4 frag(FragmentInput input) : SV_Target
{
half4 baseColor = tex2D(_MainTex, input.uv0);

// Normal mapping
half3 normalMapValue = tex2D(_NormalMap, input.uv0).rgb * 2.0 - 1.0;
normalMapValue.xy *= half3(0.5, 0.5);
half3 normalWS = normalize(input.normalWS + normalMapValue);

half3 translucency = _TranslucencyColor.rgb * _TranslucencyIntensity;

half rim = pow(1.0 - saturate(dot(normalWS, -_WorldSpaceCameraPos)), _RimPower);
half4 rimColor = rim * _RimColor;

half3 finalLighting = half3(0, 0, 0);

for (int i = 0; i < MAX_LIGHT_COUNT; i++)
{
half3 lightDir = normalize(_WorldSpaceLightPos[i].xyz);
half3 viewDir = normalize(-_WorldSpaceCameraPos);
half3 reflectionDir = reflect(-lightDir, normalWS);
float specAngle = max(0.0, dot(reflectionDir, viewDir));
float specularTerm = pow(specAngle, 16 * _Smoothness);

float diffTerm = max(dot(normalWS, lightDir), 0.0);
diffTerm *= (diffTerm * (1 - diffTerm) * _StylizedIntensity);

finalLighting += diffTerm * _LightColor[i].rgb + (_SpecularColor.rgb * specularTerm * _SpecularIntensity);
}

half4 finalColor = baseColor + translucency + rimColor + finalLighting;

// Add transmission effect
finalColor.rgb += (_TransmissionColor.rgb * _TransmissionIntensity);

finalColor.a *= _Alpha;

// Add emission
finalColor += _EmissionColor * _EmissionIntensity;

// Apply stylized color tinting
finalColor.rgb *= lerp(half3(1.0), _StylizedColor.rgb, _StylizedIntensity);

return finalColor;
}

ENDHLSL
}

Pass
{
Name "Outline"
Tags { "LightMode"="UniversalForward" }

Cull Front
ZWrite Off
Blend One One

HLSLPROGRAM
#pragma target 4.5

struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};

struct Varyings
{
float4 positionCS : SV_POSITION;
};

Varyings vert(Attributes input)
{
Varyings output;

float3 offset = normalize(input.normalOS) * _OutlineThickness;
output.positionCS = TransformObjectToClip(input.positionOS + float4(offset, 0));

return output;
}

half4 frag() : SV_Target
{
return _OutlineColor;
}

ENDHLSL
}
}
FallBack "Diffuse"
}
👍4
توضیح کد و نحوه کارکرد آن :

در این شما شیدر و ویژگی آن را تعریف میکنید که در این مسیر میتوانید شیدر خود را بروی متریال انتخاب کنید


Shader "Custom/StylizedURPShader_FProSensei"


ویژگی‌ها: این بخش شامل ویژگی‌های قابل تنظیم شیدر است که در ادیتور یونیتی قابل مشاهده‌ هست. هر ویژگی یک نام، نوع و مقدار پیش‌فرض داره (دقیقا مثل ورودی میمومه مثل این که شما داری public int تعریف میکین که مقدارشو توی ادیتور یونیتی تنظیم کنی)


Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_HeightMap ("Height Map", 2D) = "white" {}
_TranslucencyColor ("Translucency Color", Color) = (1,1,1,1)
_TranslucencyIntensity ("Translucency Intensity", Range(0, 1)) = 0.5
_RimColor ("Rim Color", Color) = (1,1,1,1)
_RimPower ("Rim Power", Range(1, 10)) = 3
_EmissionColor ("Emission Color", Color) = (1,1,1,1)
_EmissionIntensity ("Emission Intensity", Range(0, 10)) = 1
_Alpha ("Alpha", Range(0, 1)) = 1
_SpecularColor ("Specular Color", Color) = (1,1,1,1)
_SpecularIntensity ("Specular Intensity", Range(0, 1)) = 0.5
_Metallic ("Metallic", Range(0, 1)) = 0.0
_Smoothness ("Smoothness", Range(0, 1)) = 0.5
_TransmissionColor ("Transmission Color", Color) = (1, 1, 1, 1)
_TransmissionIntensity ("Transmission Intensity", Range(0, 1)) = 0.5
_OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)
_OutlineThickness ("Outline Thickness", Range(0.01, 0.1)) = 0.05
_StylizedColor ("Stylized Color", Color) = (1, 0.5, 0.5, 1)
_StylizedIntensity ("Stylized Intensity", Range(0, 2)) = 1.0
}


SubShader: این بخش شامل مراحل رندرینگ است یعنی کل pass ها در این بخش قرار میگیره.
Tags: نوع رندرینگ را مشخص می‌کند (در اینجا چون از ترنسپرنت استفاده کردم شفاف).
Blend: نحوه ترکیب رنگ‌ها را در حالت شفافیت مشخص می‌کند.
ZWrite: تعیین می‌کند که آیا باید عمق پیکسل‌ها نوشته شود یا نه.
ZTest: نوع تست عمق را مشخص می‌کند.


SubShader
{
Tags { "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ZWrite On
ZTest LEqual


Pass: یک مرحله رندرینگ را تعریف می کنیم مثلا اوت لاین خودش یک pass داره.
Name: نام مرحله رندرینگ.
Tags: نوع نورپردازی را مشخص می‌کند.


Pass
{
Name "Forward"
Tags { "LightMode"="UniversalForward" }

HLSLPROGRAM: شروع برنامه‌نویسی HLSL.
#pragma target: نسخه هدف HLSL را مشخص می‌کند.
#include: فایل‌های کتابخانه‌ای مربوط به متغیرها و نورپردازی را وارد می‌کند.


HLSLPROGRAM
#pragma target 4.5
#include "UnityShaderVariables.hlsl"
#include "UnityLighting.hlsl"
#include "CoreRP/ShaderLibrary/Core.hlsl"
#include "CoreRP/ShaderLibrary/Lighting.hlsl"


Attributes: ساختاری برای ورودی‌های وکتورهای هندسی که شامل موقعیت، نرمال و UVها است.


struct Attributes
{
float4 positionOS :
float3 normalOS :
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
};


Varyings: ساختاری برای نگهداری مقادیر بین مرحله vertex و fragment.


struct Varyings
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float4 positionCS : SV_POSITION;
float3 tangentWS : TEXCOORD3;
};


FragmentInput: ساختاری برای ورودی‌های مرحله fragment.


struct FragmentInput
{
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float3 normalWS : TEXCOORD2;
float3 tangentWS : TEXCOORD3;
};


متغیرهای نمونه‌برداری: این متغیرها برای نگهداری بافت‌ها و ویژگی‌های مختلف مانند رنگ، شدت و غیره استفاده می‌شوند.


sampler2D _MainTex;
sampler2D _NormalMap;
sampler2D _HeightMap;
fixed4 _TranslucencyColor;
float _TranslucencyIntensity;
fixed4 _RimColor;
float _RimPower;
fixed4 _EmissionColor;
float _EmissionIntensity;
float _Alpha;
fixed4 _SpecularColor;
float _SpecularIntensity;
float _Metallic;
float _Smoothness;
fixed4 _TransmissionColor;
float _TransmissionIntensity;
fixed4 _OutlineColor;
float _OutlineThickness;
fixed4 _StylizedColor;
float _StylizedIntensity;
🔥2👍1
FPro Sensei
توضیح کد و نحوه کارکرد آن : در این شما شیدر و ویژگی آن را تعریف میکنید که در این مسیر میتوانید شیدر خود را بروی متریال انتخاب کنید Shader "Custom/StylizedURPShader_FProSensei" ویژگی‌ها: این بخش شامل ویژگی‌های قابل تنظیم شیدر است که در ادیتور یونیتی قابل…
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = TransformObjectToClip(input.positionOS);
output.uv0 = input.uv0; // UV0
output.uv1 = input.uv1; // UV1
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
output.tangentWS = TransformObjectToWorldTangent(input.normalOS);
return output;
}

vert: تابع vertex که ورودی‌ها را از ساختار Attributes دریافت کرده و خروجی‌ها را به ساختار Varyings تبدیل می‌کند.
TransformObjectToClip: موقعیت شیء را به فضای کلیپ تبدیل می‌کند.
TransformObjectToWorldNormal: نرمال شیء را به فضای جهانی تبدیل می‌کند.
TransformObjectToWorldTangent: تانژانت شیء را به فضای جهانی تبدیل می‌کند.



half4 frag(FragmentInput input) : SV_Target
{
half4 baseColor = tex2D(_MainTex, input.uv0);

// Normal mapping
half3 normalMapValue = tex2D(_NormalMap, input.uv0).rgb * 2.0 - 1.0;
normalMapValue.xy *= half3(0.5, 0.5); // Scale the normal map
half3 normalWS = normalize(input.normalWS + normalMapValue);

frag: تابع fragment که رنگ نهایی پیکسل را محاسبه می‌کند.
tex2D: بافت اصلی را بر اساس UVها دریافت می‌کند.
نرمال مپینگ: نرمال مپ را دریافت کرده و آن را به دامنه [-1, 1] تبدیل می‌کند و سپس به نرمال شیء اضافه می‌کند.


half3 translucency = _TranslucencyColor.rgb * _TranslucencyIntensity;

half rim = pow(1.0 - saturate(dot(normalWS, -_WorldSpaceCameraPos)), _RimPower);
half4 rimColor = rim * _RimColor;

half3 finalLighting = half3(0, 0, 0);

Translucency effect: تأثیر شفافیت را محاسبه می‌کند.
Rim lighting effect: نور حاشیه‌ای را محاسبه کرده و رنگ آن را تعیین می‌کند.
finalLighting: متغیری برای ذخیره نور نهایی.


for (int i = 0; i < MAX_LIGHT_COUNT; i++)
{
half3 lightDir = normalize(_WorldSpaceLightPos[i].xyz);
half3 viewDir = normalize(-_WorldSpaceCameraPos);
half3 reflectionDir = reflect(-lightDir, normalWS);
float specAngle = max(0.0, dot(reflectionDir, viewDir));
float specularTerm = pow(specAngle, 16 * _Smoothness);

// Basic Lambertian diffuse shading with stylization effect
float diffTerm = max(dot(normalWS, lightDir), 0.0);
diffTerm *= (diffTerm * (1 - diffTerm) * _StylizedIntensity);

finalLighting += diffTerm * _LightColor[i].rgb + (_SpecularColor.rgb * specularTerm * _SpecularIntensity);
}

این حلقه برای هر منبع نوری موجود در صحنه اجرا می‌شود.
نورپردازی پایه: با استفاده از فرمول لامبرتین نورپردازی انجام می‌شود و سپس تأثیر استایلایز به آن اضافه می‌شود.



half4 finalColor = baseColor + translucency + rimColor + finalLighting;

finalColor.rgb += (_TransmissionColor.rgb * _TransmissionIntensity);

finalColor.a *= _Alpha;


finalColor += _EmissionColor * _EmissionIntensity;


finalColor.rgb *= lerp(half3(1.0), _StylizedColor.rgb, _StylizedIntensity);

return finalColor;

finalColor: رنگ نهایی ترکیب شده با تأثیرات مختلف محاسبه می‌شود.
لکه‌گذاری رنگ استایلایز: رنگ نهایی با رنگ استایلایز شده ترکیب می‌شود


Pass
{
Name "Outline"
Tags { "LightMode"="UniversalForward" }

Cull Front
ZWrite Off
Blend One One

HLSLPROGRAM

این بخش برای ایجاد یک پاس جدید برای رسم حاشیه (Outline) تعریف شده است.
در اینجا، نوع رندرینگ و تنظیمات مربوط به حاشیه مشخص می‌شود.

تابع vert برای Outline

Varyings vert(Attributes input)
{
Varyings output;

float3 offset = normalize(input.normalOS) * _OutlineThickness;



    output.positionCS = TransformObjectToClip(input.positionOS + float4(offset, 0));

return output;
}

در اینجا موقعیت اشیاء به سمت خارج جابجا می‌شود تا حاشیه ایجاد شود.


half4 frag() : SV_Target
{
return _OutlineColor;
}

رنگ حاشیه را به عنوان خروجی تعیین می‌کند.



ENDHLSL

• پایان برنامه HLSL.



FallBack "Diffuse"

• اگر شیدر نتواند بارگذاری شود، از شیدر پیش‌فرض دیفیوز استفاده خواهد کرد.
🔥2
+ آموزش باندل :
اگر یک شیدر نویس حرفه ای باشید باید خوب دقت کرده باشید که هر شیدری که در یونیتی پکیج میشه و فروخته میشه همشون UI دارن که با استفاده از C# میان اون شیدر که به زبان HLSL نوشتن رو کنترل میکنن ولی چطوری :
1
FPro Sensei
+ آموزش باندل : اگر یک شیدر نویس حرفه ای باشید باید خوب دقت کرده باشید که هر شیدری که در یونیتی پکیج میشه و فروخته میشه همشون UI دارن که با استفاده از C# میان اون شیدر که به زبان HLSL نوشتن رو کنترل میکنن ولی چطوری :
Custom Shader GUI (تغییر ظاهر Inspector)

این اسکریپت را با نام ShaderUI در یک پوشه به نام Editor (حتماً نام پوشه Editor باشد) ذخیره کنید:

using UnityEngine;
using UnityEditor;

public class ShaderUI : ShaderGUI
{
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
{
Material targetMat = materialEditor.target as Material;

// تیتر اصلی
GUILayout.Label("Arknights Style PBR Settings", EditorStyles.boldLabel);
EditorGUILayout.Space();

// بخش تنظیمات بافت و رنگ
EditorGUILayout.BeginVertical("HelpBox");
GUILayout.Label("Base Maps", EditorStyles.miniBoldLabel);
materialEditor.ShaderProperty(FindProperty("_MainTex", properties), "Albedo (RGB)");
materialEditor.ShaderProperty(FindProperty("_BaseColor", properties), "Color Tint");
materialEditor.ShaderProperty(FindProperty("_NormalMap", properties), "Normal Map");
EditorGUILayout.EndVertical();

// بخش PBR
EditorGUILayout.BeginVertical("HelpBox");
GUILayout.Label("Physical Properties", EditorStyles.miniBoldLabel);
materialEditor.ShaderProperty(FindProperty("_Metallic", properties), "Metallic");
materialEditor.ShaderProperty(FindProperty("_Smoothness", properties), "Smoothness");
EditorGUILayout.EndVertical();

// بخش Stylized (Cel Shading)
EditorGUILayout.BeginVertical("HelpBox");
GUILayout.Label("Stylized Rendering (Cel Shading)", EditorStyles.miniBoldLabel);
materialEditor.ShaderProperty(FindProperty("_StepThreshold", properties), "Shadow Threshold");
materialEditor.ShaderProperty(FindProperty("_StepFeather", properties), "Shadow Softness (Feather)");
materialEditor.ShaderProperty(FindProperty("_RimColor", properties), "Rim Color");
materialEditor.ShaderProperty(FindProperty("_RimPower", properties), "Rim Power");
EditorGUILayout.EndVertical();

// بخش Outline
EditorGUILayout.BeginVertical("HelpBox");
GUILayout.Label("Outline Settings", EditorStyles.miniBoldLabel);
materialEditor.ShaderProperty(FindProperty("_OutlineColor", properties), "Outline Color");
materialEditor.ShaderProperty(FindProperty("_OutlineWidth", properties), "Outline Thickness");
EditorGUILayout.EndVertical();

EditorGUILayout.Space();
materialEditor.RenderQueueField(); // تنظیم ترتیب رندر
}

// متد کمکی برای پیدا کردن پراپرتی‌ها
private MaterialProperty FindProperty(string name, MaterialProperty[] props)
{
return ShaderGUI.FindProperty(name, props);
}
}

نکته مهم: برای اینکه شیدر از این اسکریپت استفاده کند، باید خط آخر شیدر خود را (قبل از بستن آخرین آکوالاد) به این صورت تغییر دهید:
CustomEditor "shaderUI"
2
FPro Sensei
GUILayout.Label("Arknights Style PBR Settings", EditorStyles.boldLabel);
نکته مهم :
اگر بتوانید از این شیدر که نوشتم درست استفاده کنید و اصول نور پردازی pbr هم بلد باشید دقیقا به گرافیک رندر بازی Arknight خواهید رسید ولی نحوه استفاده از شیدر و اصول کامپوزیت به سبک arknight رو به عهده شما میزارم 😏
1
نحوه ساخت شیدر به کدام روش برای شما خفن تر و جذاب تر محسوب میشود ؟ (هر کدوم بگید براش آموزش میاد) :
من که بطور (مداوم انیمه دیدم)بطور کلی به 3 حالت تقسیم کردم :

1 - ابرو و مژه و چشم بطور کامل دیده میشه

2 - ابرو و مژه و چشم بصورت نیمه شفاف دیده میشه

3 - ابرو و مژه و چشم فقط بصورت خط دیده میشه
2
FProSensei (Reverse)
من که بطور (مداوم انیمه دیدم)بطور کلی به 3 حالت تقسیم کردم : 1 - ابرو و مژه و چشم بطور کامل دیده میشه 2 - ابرو و مژه و چشم بصورت نیمه شفاف دیده میشه 3 - ابرو و مژه و چشم فقط بصورت خط دیده میشه
در مورد نحوه رندر ابرو انیمه قراه یک آموزش کوچیک هم برای بلندر و هم یونیتی بسازم که خیلی مهم و واجبه ولی قبل از آموزش این سبک ها رو مد نظر داشته باشید 🙏
3👍2
FPro Sensei
کدوم ؟
مهم....
1