Shader - Shader 编写 Surface

Si vous ne comprenez pas le laboratoire Shader recommande que vous regardez Shader contenu lié Lab: interfaces Jump .

Et la lumière ne préparent chaque shader est très complexe, il existe différents types d'éclairage, ombrage différentes options, chemin différent de rendu, les colorants doivent gérer une certaine façon toute la complexité.
Surface Shader Unité d'une méthode de génération de code, il est beaucoup plus facile d'écrire que le sommet de couleur / fragment shaders, surface Shader générer tous , mais besoin répétitif à écrire du code manuellement, toujours besoin d'écrire des shaders HLSL .

Surface Shader principe de fonctionnement:
la définition d'une « fonction de surface » (traitement de surface de fonction), il aurait besoin de mettre notre structure de données d'entrée, la méthode de remplissage de la structure de sortie de la structure « SurfaceOutput ». Shader de surface calcule ensuite l'entrée désirée, la sortie ou analogue est rempli,Et générer les sommets réels / Shaders fragmentEt le processus de création et Foward Rending différé chemin de rendu de shadering passes de rendu (Pass).
Par exemple:

//...
#pragma surface surf Lambert
struct Input
{
	//...
}
void surf(Input i,inout SurfaceOutput o)
{
	o.Albedo =1;
	//...
}
//...

上面就用#pragma surface 定义了一个surf表面函数,并且使用Lambert光照模型,定义了Input结构体,并在surf 方法中对输出结构体SurfaceOutput进行了填充

Surface Shader directive du compilateur:
Surface Shader CGPROGRAM besoin d'écrire dans le bloc et ENDCGEt la nécessité de prêter attention à ce qui suit:

1.必须放在SubShder块内(注意不是Pass内,表面着色器本身将编译为多个通道)
2.使用#pragma surface ...指令来指示当前shader为Surface Shader。

surface #pragma format d'instruction:

#pragma surface surfaceFunction lightModel [optionalparams]
Type d'instruction instruction description
paramètre doit surfaceFunction CG est une fonction, et comprend un code de nuanceur de surface, format: Surf void (Entrée IN, inout SurfaceOutput o), l'entrée à partir d'une définition de structure comportant toutes les coordonnées de texture de surface désirée de fonction et variable supplémentaire automatiques
- lightModel modèle d'éclairage à utiliser, il y a intégré et standard basé sur la physique StandardSpecular, et non basée sur Lambert physique simple, BlinnPhong et modèle éclairage personnalisé
-
- StandardSpecular: utiliser la structure de sortie SurfaceOutputStandardSpecular, et correspondant à la norme Unity (configuration spéculaire) nuanceur
- Lamber BlinnPhong et un modèle basé sur la physique ne sont pas éclairés, mais leur utilisation dans la coloration peuvent rapidement rendus sur le matériel bas de gamme
paramètres optionnels Test de transparence ou d'opacité Opacité, la transparence peut généralement avoir deux: le mélange alpha (un objet à la décoloration) plus rationnelle « hybride prémultipliée » et physiquement (mélange prémultipliée, translucide surfaces de fonctionner correctement retenu réflexion spéculaire).
- alpha ou alpha: auto La méthode de choix sera tout simplement fondu illuminé transparent (alpha: Fade même), de sélectionner un procédé physique d'illumination doit être multiplié sur la base de la transparence (alpha: même premul).
- alpha: mélange Activer alpha mélange.
- alpha: évanouissement Traditionnellement obtenir fondu
- alpha: premul Activer alpha transparence pré-multipliée
- alphatest Test de transparence, de cisaillement permettent la transparence alpha. VariableName de l'utilisation de variables à virgule flottante peut également être utilisé pour générer les ombres addshadow d'instructions correctes.
- keep alpha Par défaut, la surface colorée opaque va écrire 1,0 canal alpha, indépendamment du fait que la structure de sortie de la valeur alpha est, ou ce que la fonction retourne d'éclairage. Cette option peut être maintenue fonction d'éclairage valeur alpha, même pour un puits de nuanceur de surface opaque.
- autocollant: add autocollants Ajouter des shaders (par exemple topographique addpass). Applicable à d'autres objets situés au-dessus de la surface, et en utilisant le ajoutés et mélangés.
- décalcomanie: mélange Translucide shaders appliques pour des objets situés sur la surface de dessus de l'autre, et en utilisant le mélange alpha.
- modificateur de fonction personnalisée Il est utilisé pour modifier les données de sommets entrants ou calculées, ou changer la couleur des fragments finaux calculés
- sommet: VertexFunction Fonction de modification du sommet sur mesure, cette fonction est appelée au début du vertex shader généré et peut être modifiée ou calculée pour chaque donnée de sommet
- finalcolor: ColorFunction La couleur personnalisée d'édition finale
- finalgbuffer: ColorFunction Gbuffer utilisé pour modifier le contenu d'un retard de chemin personnalisé
- finalprepass: ColorFunction canal personnalisé chemin pré-basique
- Ombres et tessellation D'autres instructions peuvent être fournies pour contrôler la manière et le processus de tessellation
- addshadow Génération d'une passe de rendu de coulée d'ombre (Pass), généralement utilisé pour modifier le sommet personnalisé, de sorte que toute coulée d'ombre peut être obtenue programme d'animation de sommet. En règle générale pas de processus d'ombrage de shaders spécial car ils peuvent être utilisés pour spécifier des ombres fallback
- pleine ombre avant Forward rendu prend en charge tous les types de chemin de lumière et d'ombre. Par défaut, le shader avant de rendu ne supporte que la lumière parallèle ombrée (sauvegarde des variables de shaders internes comptent). Si le point désiré spot lumineux ou ombre avant de rendu peut utiliser cette commande
- paver: TessFunction Utilisez les segments GPU DX11. La fonction calcule le facteur de tessellation.
- Options de code de génération Par défaut, le code de shaders de surface générée tente de gérer toute la lumière / ombre / lumière cartes, mais dans certains cas, dont certains ne sont pas nécessaires et peuvent ajuster le code généré pour les ignorer, afin de produire plus petit ascenseur shader vitesse de chargement.
- exclude_path: différé, exclude_path: avant, exclude_path: prepass Pas généré pour une passe de rendu de trajet de rendu donné (Pass) (ombrage différé, et rendant l'éclairage conventionnel retard avant)
- noshadow Désactiver toute ombre de ce shader pour recevoir un soutien.
- noambient Ne pas utiliser de l'éclairage ambiant ou de la sonde optique.
- novertexlights Ne pas utiliser de lumière dans le détecteur avant de rendre le ou chaque sommet source.
- nolightmap Désactivez tous les lightmaps prennent en charge ce shader.
- nodynlightmap Dans cette opération de support de shader illumination globale dynamique est désactivée.
- nodirlightmap La désactivation de l'appui de cette direction shader.
- nofog 禁用所有内置的雾支持。
nometa 不生成"meta“通道(由光照贴图和动态全局照明用于提取表面信息)。
moforwardadd 禁用Forward add 渲染通道,这使得着色支持一个全方向光,所有其他的光源按照顶点/SH的方式计算,可以使着色器更小
其他
softvegetation 仅在启用”Soft Vegetation“时才渲染表面着色器
interpolateview 在顶点着色器中计算视图方向并进行插值,而不是在像素着色器中计算。这样可以使像素着色器更快,但需要消耗一个纹理插值器
halfasview 将半向方向矢量传递到光照函数而不是试图方向,每个顶点将计算并归一化半方向。这样会更快,但不完全正确
dualforward 在forward rendering中使用双光照贴图

InputStruct(输入结构)
输入结构通常具有着色器所需要的任何纹理坐标。纹理坐标必须命名为"uv",后跟纹理名称(或”uv2“开头,使用第二个纹理坐标)(例如:uv_MainTex 或 uv2_MainTex);
其他可以放入输入结构的值有:

指令 描述
float3 viewDir 包含视角方向,可用于计算边缘光照等效果
float4 变量名:Color 包含差值后逐顶点颜色
float4 screenPos 包含了屏幕空间的坐标,可用于反射或屏幕特效。注意,这不适合GrabPass;需要使用ComputeGrabScreenPos函数自己计算定义UV。
float3 worldPos 包含世界空间位置。
float3 worldRefl 如果没有修改o.Normal,则包含世界空间下的反射向量。
float3 worldNormal 如果修改o.Normal,则包含世界空间下的法线向量。
float3 worldRefl;INTERNAL_DATA 如果修改了o.Normal,需要使用该变量告诉Unity要基于修改后的法线计算世界空间下的反射向量。可以使用WorldReflectionVector(IN,o.Normal)来得到世界空间下的反射方向。
float3 worldNormal;INTERNAL_DATA 如果修改了o.normal,需要使用该变量告诉Unity要基于修改后的法线计算世界空间下的法线方向。可以使用WorldNormalVector(IN,o.Normal)来得到世界空间下的法线方向

SurfaceOutput结构
SurfaceOutput基本上描述了平面的属性(如albedo、normal、emission、specularity等)
标准输出结构如下:

struct SurfaceOutput
{
	fixed3 Albedo;					//漫反射
	fixed3 Normal; 					//正切空间法线
	fixed3 Emission;				//自发光
	half Specular;					//高光率 0-1
	fixed Gloss;						//	高光强度
	fixed Alpha;						// 透明度
};

在Unity中还可以使用基于物理的照明模型,内置Standard和StandardSpecular模型分别使用下面这些输出结构:

struct SurfaceOutputStandard
{
    fixed3 Albedo;      //漫反射颜色
    fixed3 Normal;      // 切线空间法线
    half3 Emission;	//自发光颜色
    half Metallic;      // 金属 0 - 1
    half Smoothness;    // 平滑度0-1
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // 透明度
};
struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;      // 漫反射颜色
    fixed3 Specular;    // 高光颜色
    fixed3 Normal;      // 切线空间法线
    half3 Emission; //自发光颜色
    half Smoothness;    //平滑度0-1
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // 透明度
};

实例:
1.简单的着色器:

Shader "Example/DiffuseSimple"
{
	SubShader
	{
		Tags{"RenderType" = "Opaque"}
		CGPROGRAM
		#pragma surface surf Lambert
		struct Input
		{
			fixed4 color : COLOR;
		};
		void surf(Input IN, inout SurfaceOutput o)
		{
			o.Albedo = 1;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

//在上述着色器中,声明找色器为表面找色器(#pragma surface) ,定义了表面函数(surf)以及指定基本光照为Lambert。
//声明输入结构(Input) 包含顶点颜色。
//在表面方法(surf)中,设置输出函数的漫反射颜色为1(o.Albedo = 1;)
//如果此着色器在硬件上没法使用的话会使用Diffuse着色器进行替换

2.Texture(纹理):

Shader "Example/Texture"
{
	Properties
	{
		_MainTex("MainTex",2D) = ""{}
	}
	SubShader
	{
		Tags{"RenderType" = "Opaque"}
		CGPROGRAM
		#pragma surface surf Lambert
		struct Input //获取_MainTex的第一套纹理坐标
		{
			float2 uv_MainTex;
		};
		//注意 在Properties中声明的属性,需要在CGPROGRAM块内声明一个同样名称且类型匹配的变量来进行关联
		sampler2D _MainTex;
		void surf(Input IN, inout SurfaceOutput o)
		{
			//根据Input中纹理坐标匹配_MainTex的纹理设置漫反射颜色
			o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
		}
		ENDCG
	}
	FallBack "Diffuse"
}

3.Normal(法线):

Shader "Example/DiffuseBump"
{
	Properties
	{
		_MainTex("MainTex",2D) = ""{}
		//	定义法线贴图
		_BumpTex("BumpTex",2D) = ""{}
	}

	SubShader
	{
		Tags{"RenderType"="Opaque"}
		CGPROGRAM
		#pragma surface surf Lambert
		struct Input
		{
			float2 uv_MainTex;
			//法线贴图纹理坐标
			float2 uv_BumpTex;
		};

		sampler2D _MainTex;
		sampler2D _BumpTex;

		void surf(Input IN, inout SurfaceOutput o)
		{
			o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
			//设置法线
			o.Normal = UnpackNormal(tex2D(_BumpTex, IN.uv_BumpTex));
		}
		ENDCG
	}
	FallBack "Diffuse"
}

4.Rim Light(边缘照明):

Shader "Example/RimLight"
{
	Properties
	{
		_MainTex("MainTex",2D) = ""{}
		_BumpTex("BumpTex",2D) = ""{}
		_RimColor("Rim Color",Color) = (1,1,1,1)
		_RimPower("Rim Power",Range(0,8)) = 0
	}

	SubShader
	{
		Tags{"RenderType" = "Opaque"}
		CGPROGRAM
		#pragma surface surf Lambert
		sampler2D _MainTex;
		sampler2D _BumpTex;
		float4 _RimColor;
		float _RimPower;
		struct Input
		{
			float2 uv_MainTex;
			float2 uv_BumpTex;
			float3 viewDir;//视角方向
		};
		void surf(Input IN, inout SurfaceOutput o)
		{
			o.Albedo = tex2D(_MainTex, IN.uv_MainTex);
			o.Normal = UnpackNormal(tex2D(_BumpTex, IN.uv_BumpTex));
			half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
			o.Emission = _RimColor.rgb*pow(rim, _RimPower);
		}
		ENDCG
	}
}
发布了32 篇原创文章 · 获赞 18 · 访问量 2万+

Je suppose que tu aimes

Origine blog.csdn.net/qq_18192161/article/details/90548647
conseillé
Classement