Shader - 编写 Shader Superfície

Se você não entendeu o laboratório Shader recomendo que você olhar Shader Lab conteúdo relacionado: interfaces de salto .

E LED DO preparar cada shader é muito complicado, existem diferentes tipos de iluminação, sombreamento diferentes opções, diferente caminho de processamento, corantes precisa lidar com alguma forma toda a complexidade.
Superfície Shader Unidade de um método de geração de código, faz muito mais fácil escrever do que a cor vértice / fragmento de shader, superfície Shader gerar todos, mas necessidade repetitiva para escrever código manualmente, ainda precisa shaders HLSL gravação .

Superfície princípio de funcionamento Shader:
a definição de uma "função de superfície" (função de tratamento de superfície), ele precisa colocar a nossa estrutura de dados de entrada, então o método de encher a estrutura de saída "SurfaceOutput" estrutura. Superfície Shader, em seguida, calcula a entrada desejada, produção ou similares, é enchido,E gerar o vértice / sombreamentos reais fragmentoE o processo de criação Foward Rending e Diferido caminho prestação shadering tornar passes (Pass).
Por exemplo:

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

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

Superfície Shader directiva do compilador:
Superfície Shader CGPROGRAM necessidade de escrever no bloco e ENDCGE a necessidade de prestar atenção ao seguinte:

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

#pragma formato de Instrução de superfície:

#pragma surface surfaceFunction lightModel [optionalparams]
tipo de instrução instrução descrição
parâmetro deve surfaceFunction CG é uma função de, e inclui um código de superfície sombreador, formato: ressaca vazio (na introdução, inout SurfaceOutput o), a entrada de uma definição de estrutura deve incluir qualquer função desejada coordenadas de textura de superfície e variável adicional automáticas
- lightModel Iluminação modelo para uso, não são built-in e com base física StandardSpecular Padrão, e não com base em simples modelo de Lambert, BlinnPhong e iluminação personalizada física
-
- StandardSpecular: estrutura de saída Use SurfaceOutputStandardSpecular, e correspondente na Unidade Padrão (configuração Specular) shader
- Lamber BlinnPhong e modelo com base na física não é iluminado, mas usá-los na coloração pode rapidamente processado no hardware low-end
parâmetros opcionais teste de transparência ou opacidade Opacidade, a transparência pode geralmente ter duas: mistura alfa (um objecto de desbotamento) mais racional "híbrido premultiplied" e fisicamente (mistura premultiplied, translúcido superfícies executar correctamente retido reflexão especular).
- alfa ou alfa: auto O método de escolha simplesmente desvanecer iluminado transparente (com alpha: desvanece-se mesmo), selecione um método físico de iluminação deve ser multiplicado com base na transparência (alfa: mesmo premul).
- alfa: mistura Permitir que a mistura alfa.
- alfa: desvaneça Tradicionalmente alcançar desvanecimento
- alfa: premul Permitir a transparência alfa pré-multiplicado
- AlphaTest teste de transparência, de cisalhamento permitir alfa transparência. VariableName fora de usar variáveis ​​de ponto flutuante também pode ser usado para gerar as sombras instrução addshadow corretas.
- alfa keep Por padrão, a superfície colorida opaca vai escrever 1,0 canal alfa, independentemente da estrutura de saída valor alfa é, ou o que a função de iluminação retornos. Esta opção pode ser mantido iluminação valor alfa função, mesmo para um shader superfície opaca bem.
- decalque: add Add decalques sombreamentos (por exemplo topográfico addpass). Aplicável a outros objectos localizados na parte superior da superfície, e usando o adicionados e misturados.
- decalque: mistura Translúcido sombreamentos apliques para objectos localizados sobre a superfície de topo do outro, e utilizando a mistura alfa.
- modificador função personalizada Ele é utilizado para alterar os dados de entrada ou de vértice calculados, ou alterar a cor dos fragmentos finais calculados
- vértice: VertexFunction função modificação vértice costume, esta função é chamada, no início do vértice shader gerado, e pode ser modificado ou calculada para cada dado de vértice
- finalcolor: ColorFunction A cor edição personalizada finais
- finalgbuffer: ColorFunction Gbuffer usado para alterar o conteúdo de um atraso de caminho personalizado
- finalprepass: ColorFunction caminho pré-base do canal personalizado
- Sombras e tessellation podem ser proporcionados outras instruções para controlar o modo e o processo de tecelagem
- addshadow Gerando um passo de renderização projeção de sombra (Pass), normalmente usado para modificar o vértice personalizado, de modo que qualquer projeção de sombra podem ser obtidas programa de animação de vértice. Normalmente nenhum processo de sombreamento shader especial porque eles podem ser usados ​​para sombras especificar fallback
- sombra para a frente cheia Atacante Rendering suporta todos os tipos de caminho de luz e sombra. Por padrão, o shader Atacante Rendering suporta apenas uma luz paralela sombreada (save variáveis ​​de sombreamento internos contam). Se ponto desejado ponto de luz ou sombra Atacante Rendering pode usar este comando
- tessellate: TessFunction segmentos de uso DX11 GPU. A função calcula o factor de pavimentação.
- opções de geração de código Por padrão, o código de shader superfície gerada tenta lidar com todos os possíveis luz / sombra / mapas de luz, mas em alguns casos, alguns dos quais não são necessários, e pode ajustar o código gerado para ignorá-los, a fim de produzir menor sombreador elevador velocidade de carregamento.
- exclude_path: adiada, exclude_path: para a frente, exclude_path: prepass Não gerado por um passe dado renderização renderização caminho (Pass) (shading diferido, e tornando a demora iluminação convencional)
- noshadow Desactivar todos sombra desta shader para receber apoio.
- noambient Não usar qualquer iluminação ambiente ou sonda óptica.
- novertexlights Não use qualquer luz no detector frente tornando o ou cada vértice fonte.
- nolightmap Desativar todos os lightmaps apoiar este shader.
- nodynlightmap Nesta operação de apoio iluminação shader global e dinâmica está desativado.
- nodirlightmap Desactivação do suporte neste sentido shader lightmaps.
- 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万+

Acho que você gosta

Origin blog.csdn.net/qq_18192161/article/details/90548647
Recomendado
Clasificación