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
}
}