Shader代码的大结构---紧接之前的部分.
小结构指的是Shader中从CGPROGRAM--ENDCG---之间代码的常用结构和常用命令的写法.
在Unity的Shader代码中,块内部使用的是HLSL(High-Level Shading Language)或GLSL(OpenGL Shading Language),这是一种用于编写着色器程序的语言。在这个块内部,指令是预处理器指令,用于指导编译器如何处理代码。以下是块内的一些常用结构和它们的含义:
#pragma vertex vert:
#pragma 是预处理器指令,用于向编译器提供额外的信息。
vertex 是固定的关键字,表示后面跟随的是顶点着色器的函数名。
vert 是自定义的函数名,它是顶点着色器的入口点。你可以将其命名为任何有效的C语言标识符,但通常使用简洁且具有描述性的名称。
#pragma fragment frag:
同样,#pragma 是预处理器指令。
fragment 是固定的关键字,表示后面跟随的是片元着色器的函数名。
frag 是自定义的函数名,它是片元着色器的入口点。
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 顶点着色器
float4 vert (appdata v) : SV_POSITION
{
// 顶点着色器代码
}
// 片元着色器
fixed4 frag (v2f i) : SV_Target
{
// 片元着色器代码
}
ENDCG fixed4 frag (v2f i) : SV_Target
fixed4: 是HLSL中的一个数据类型,表示一个四维向量,其元素是固定精度浮点数(16位)。通常用于颜色和纹理坐标等不需要高精度的值。fixed4 包含四个分量:x, y, z, 和 w。
frag:是自定义的函数名,代表片元着色器的入口点。你可以将frag替换为任何有效的C语言标识符。这个名称是约定俗成的,用于表示这是片元着色器。
v2f: 是一个结构体类型,通常在Shader中用于从顶点着色器传递数据到片元着色器。v2f是自定义的,表示“vertex to fragment”的缩写,但你可以根据需要给它起任何名字。
i: 是函数参数的名称,代表传递给片元着色器的v2f结构体实例。你可以将i替换为任何有效的变量名。
SV_Target: 是一个系统值语义,用于指示这个函数返回的值将被写入渲染目标(通常是颜色缓冲区)。SV代表“system value”,是HLSL中用于特定用途的预定义语义。
float4: 是HLSL中的一个数据类型,表示一个四维向量,其元素是单精度浮点数(32位)。通常用于顶点位置、变换矩阵等需要高精度的值。float4 也包含四个分量:x, y, z, 和 w。
vert: 是自定义的函数名,代表顶点着色器的入口点。和frag一样,你可以将vert替换为任何有效的C语言标识符。这个名称同样是约定俗成的,用于表示这是顶点着色器。
appdata: 是一个结构体类型,通常用于定义顶点着色器的输入数据。它包含了顶点位置、纹理坐标、法线等信息。appdata是自定义的,可以根据需要更改其名称。
v: 是函数参数的名称,代表传递给顶点着色器的appdata结构体实例。你可以将v替换为任何有效的变量名。
SV_POSITION: 是一个系统值语义,用于指示这个函数返回的值是裁剪空间中的顶点位置。SV代表“system value”,POSITION是HLSL中预定义的语义之一,用于特定的用途。
总结来说,这些关键字和数据类型定义了着色器函数的输入、输出以及它们在渲染管线中的角色。在编写Shader时,你需要遵循这些约定来确保着色器能够正确地与Unity的渲染管线集成。
在HLSL(High-Level Shading Language)中,预处理器指令用于在编译阶段控制代码的编译过程。以下是一些常用的预处理器指令:
#define:
用于定义一个宏,可以在代码中使用这个宏来代替一个值或表达式。#define MY_VALUE 1.0
#undef:
用于取消之前定义的宏。
#undef MY_VALUE
#if:
根据条件编译代码块。如果条件为真,则编译该代码块。
#if defined(MY_VALUE) // 编译这里的代码 #endif
#ifdef:
如果指定的宏已定义,则编译代码块。
#ifdef MY_VALUE // 编译这里的代码 #endif
#ifndef:
如果指定的宏未定义,则编译代码块。
#ifndef MY_VALUE // 编译这里的代码 #endif
#else:
与#if、#ifdef或#ifndef结合使用,用于提供替代的编译路径。
#ifdef MY_VALUE // 编译这里的代码 #else // 如果MY_VALUE未定义,则编译这里的代码 #endif
#elif:
类似于#else,但是可以提供一个新的条件测试。
#if defined(MY_VALUE) // 编译这里的代码
#elif defined(ANOTHER_VALUE)// 如果ANOTHER_VALUE定义了,则编译这里的代码
#endif
#endif:
结束#if、#ifdef、#ifndef、#elif或#else代码块。
#if def MY_VALUE
// 编译这里的代码
#endif
#pragma:
用于向编译器提供额外的信息,比如指定着色器函数名。
#pragma vertex vert
#pragma fragment frag
#error:#error "This is a custom error message"
用于生成一个编译错误消息。
#line:#line 100 "newfilename.hlsl"
用于改变预处理器报告的行号和文件名。
#region 和 #endregion:#region MyShaderCode // 代码块 #endregion这些指令在编写Shader时非常有用,可以帮助你根据不同的条件编译不同的代码路径,定义宏,以及控制编译过程的其他方面。
用于在代码编辑器中折叠代码块,不是编译指令,但有助于组织代码。
#include:#include "MyCommonCode.hlsl"
用于将另一个文件的内容包含到当前文件中,通常用于包含头文件或常用的代码段。
在 Pass 代码块中使用这些命令可为该 Pass 设置渲染状态,或者在 SubShader 代码块中使用这些命令可为该 SubShader 以及其中的所有 Pass 设置渲染状态。
AlphaToMask:设置 alpha-to-coverage 模式。
Blend:启用和配置 alpha 混合。
BlendOp:设置 Blend 命令使用的操作。
ColorMask:设置颜色通道写入掩码。
Conservative:启用和禁用保守光栅化。
Cull:设置多边形剔除模式。
Offset:设置多边形深度偏移。
Stencil:配置模板测试,以及向模板缓冲区写入的内容。
ZClip:设置深度剪辑模式。
ZTest:设置深度测试模式。
ZWrite:设置深度缓冲区写入模式。
在Unity的Shader代码中, 指令用于为Pass块指定一个名称。这个名称在Unity编辑器中显示,并且对于理解Shader的各个部分很有帮助。然而, 指令的名称并不是固定的,你可以根据你的Shader的需要和理解来命名Pass块。
命名Pass块有以下几个好处:
代码可读性:
清晰的命名有助于其他开发者或你自己理解Shader的各个部分。
Unity编辑器:
在Unity编辑器中,每个Pass都会在材质窗口中显示其名称,这有助于快速识别和选择特定的Pass。
调试和优化:
如果你在调试Shader时遇到了问题,清晰的命名可以帮助你快速定位到问题所在的Pass。
自动化:
一些Shader编写工具和框架可能依赖于Pass的名称来执行特定的操作,如生成渲染路径或优化。###
在Unity的Shader代码中,Pass块内部可以包含多种指令,用于设置渲染状态、控制渲染过程和优化性能。以下是一些常用的Pass块指令及其说明:
Stencil:
用于设置与模板测试(Stencil Test)相关的状态,如模板测试函数、操作、对比等。Stencil { CompareEqual 0, 0, 0 WriteZero FailKeep ZFailKeep ZPassKeep }
ZTest:
用于设置深度测试(Depth Test)的函数,如小于、等于、不等于等。ZTest Greater
ZWrite:
用于设置是否写入深度缓冲区(Depth Buffer)。ZWrite On
Cull:
用于设置是否进行背面剪裁(Backface Culling)。Cull Back
Blend:
用于设置混合(Blending)模式,如Alpha Blending、Additive等。Blend SrcAlpha OneMinusSrcAlpha
Name:
用于为Pass块指定一个名称,这个名称在Unity编辑器中显示。Name "MyPass"
Tag:
用于为Pass块指定标签,如RenderType、Queue等,这些标签用于Unity渲染器的设置。Tags { "RenderType"="Opaque" "Queue"="Geometry" }
LOD:
用于设置细节级别(Level of Detail),影响渲染的复杂度。LOD 200
Fog:
用于设置雾效(Fog)相关的状态,如雾效类型、颜色等。Fog { Mode Linear }
Lighting:Lighting On
用于启用或禁用光照(Lighting)计算。
AlphaTest:AlphaTest Greater 0.5
用于设置是否进行Alpha测试,以及测试的函数和值。
AlphaToMask:AlphaToMask Off
用于设置是否将Alpha值用作Mask。
ColorMaterial:ColorMaterial Diffuse
用于设置材质的颜色如何与光照混合。
CullMode:CullMode Back
用于设置背面剪裁(Culling)的模式,如Back、Front、Off等。
ZTestMode:ZTestMode Greater
用于设置深度测试(Z Test)的模式,如Less、Greater、Equal等。
ZWriteMode:ZWriteMode Always
用于设置是否写入深度缓冲区(Z Write),以及写入的模式。
BlendSrc:BlendSrc SrcAlpha
用于设置混合(Blending)的源因子。
BlendDst:BlendDst OneMinusSrcAlpha这些指令可以在Pass块内部使用,以控制渲染过程中的各个方面。根据你的Shader需求,你可以选择使用其中的一些或全部指令来定制渲染行为。
用于设置混合(Blending)的目标因子。
ZClip:
在Unity的Shader代码中,ZClip 指令用于设置深度剪裁(Depth Clipping)的状态。深度剪裁是一种技术,用于隐藏超出屏幕视锥的物体。在Unity的ShaderLab中,ZClip 指令允许你控制是否剪裁超出视锥的深度值。