Zh/Phong materials

随着的发布，引擎中的光照方式进行了多项增强。这些增强主要集中在全局光照上，以便将角色更好地融入游戏世界，使他们在环境中显得更加真实。
其中一项增强是为使用“ps_2_b”或更高版本像素着色器的玩家（大约70%的《半衰期2：第一章》玩家，据玩家统计数据）添加了“Phong着色”。此新功能让材质设计师能够包含由高光遮罩和指数纹理驱动的Phong项。这些项与现有的光照系统自然结合，尤其为像艾莉克斯·万斯这样的关键角色提供了更好的细节表现。
Phong着色还可以包括Fresnel项，从而在强光下显著增强轮廓光，而不是普通的高光反射。在非常亮的光源下，光泽的轮廓高光通常会因为Source引擎的正常HDR后期处理而显得格外突出。
==简要介绍Phong着色==
以下简短介绍并非使用Source Phong着色器的必备知识，但可以为某些读者提供技术见解，展示该技术的工作原理。
简单来说，Phong着色是一种在3D图形中提升高光反射分辨率的技术。它由冯武（Dr. Bui Tuong Phong）于1973年在犹他大学开发。他的原始论文将该技术的插值部分与其反射模型结合，“Phong着色”一词通常指反射模型本身或反射模型与插值方法的结合。
===Phong反射模型===
Phong反射模型是一种简化的计算3D表面特定点阴影的方法。
* 它未考虑光线追踪或漫射渲染中常见的二次反射。为补偿这一点，场景中增加了额外的环境光照项。
* 它将表面的反射分为三个子部分——高光反射、漫反射和环境反射。
Phong反射是一种经验性的模型，基于非正式观察。冯博士观察到，对于非常光滑的表面，高光反射区域较小且亮度衰减迅速；而对于较为粗糙的表面，高光反射区域较大且亮度衰减较为缓慢。
===Phong插值===
Phong着色通过假设表面法向量平滑变化，为每像素应用基础反射模型提供了更好的近似。Phong插值方法在应用于Phong反射模型或任何具有小高光反射的反射模型时效果尤为显著。
在一些现代硬件中，插值算法的变体被称为“像素着色”（不要与“像素着色器”混淆）。通常这意味着可以在每个像素上进行光照计算，并包括其他光照变量，例如从法线贴图插值得出的表面法线，这些法线被跨多边形插值。
==Source引擎中的Phong==
虽然上面对Phong着色的概念做了较为基础的解释，但您在《第一章》中看到的效果实际上是多个光照效果结合在一起的结果。有关这些效果以及它们如何结合的概述可以在着色器树的图表中看到。
在模型光照中，Source引擎使用结合了从光能传递解决方案中得出的空间变化方向辐照度样本、局部光源和环境映射的方法。在支持2.0及以下像素着色器的显卡上，Source引擎从最多两个局部光源计算漫反射光照，这些计算可以在每像素或每顶点上进行。而在具有更长像素着色器的新显卡上，Source引擎包括具有Fresnel项的高光贡献以及更多自定义效果。
Phong着色是这些扩展效果的一部分，可以在着色器树的左下路径中看到。Phong指数、遮罩和Fresnel项结合起来形成高光项，并与漫反射解决方案在最终输出中结合。
本文档的其余部分将重点解释着色树中Phong部分的组成及其创建方法。
== 使用 Phong 着色器 ==
要在模型中使用 Phong 着色，您需要在材质的 VMT 文件中添加指令 $phong 1。此指令告知着色器在执行代码时包括 Phong 渲染阶段。接下来，您需要在法线贴图的 Alpha 通道中定义一个 Phong 遮罩，指定一个作为纹理或常量的 Phong 指数值，以及用于重新映射菲涅耳输出的参数。
=== Phong 着色器参数 ===
以下是启用 Phong 效果所需的 VMT 参数列表：
; $phong <bool>
: 启用/禁用该材质的 Phong 渲染阶段。
; $phongexponenttexture path/to/vtf
: 定义每个 texel 的 Phong 指数的纹理文件路径。
; $phongexponent 0..255
: 本地镜面光的 Phong 指数值。如果定义了此常量值，它会覆盖 $phongexponenttexture，并在整个纹理上应用此值。默认值为 5.0。
; $phongboost <float>
: Phong 增强因子。Phong 遮罩通道应根据此因子进行调整。默认值为 1.0。
; $phongfresnelranges "[n n n]"
: 用于重新映射菲涅耳输出的参数，默认值为 [0 0.5 1]。
; $basemapalphaphongmask <bool>
: 使用 $basetexture 的 Alpha 通道作为 Phong 遮罩。
; $basemapluminancephongmask <bool>
: 使用 $basetexture 的亮度值作为 Phong 遮罩。
=== Phong 的 VMT 示例 ===
以下简化示例来自《半衰期2：第一章》的文件 materials/models/Alyx/alyx_faceandhair.vmt，控制 Alyx 面部的纹理：
VertexLitGeneric
{
	$basetexture models/Alyx/alyx_faceandhair
	$bumpmap models/alyx/alyx_head_normal
	$halflambert 1
	$nodecal 1
	$model 1
	$phong 1
//	$phongexponent 33
	$phongexponenttexture models/Alyx/alyx_head_exponent
	$phongboost	6
	$phongfresnelranges	"[0.05 0.5 1]"
}
== Phong 的组成部分和参数详解 ==
=== Phong 遮罩和指数纹理 ===
**Phong 遮罩** 是存储在模型的 法线贴图（由 $bumpmap 定义）的 Alpha 通道中的灰度图像。遮罩按 texel 控制每个 texel 的 Phong 高光强度。黑色表示最低强度（无高光），而白色表示最高强度。
您也可以通过 $basemapalphaphongmask 1 参数使用基础纹理的 Alpha 通道作为 Phong 遮罩，或者通过 $basemapluminancephongmask 1 参数直接使用基础纹理的亮度值作为遮罩。
**Phong 指数** 控制高光的“紧凑性”。指数越高，高光越小越紧凑；指数越低，高光则更宽更平。
根据材质的物理特性，不同材料会表现出不同的高光特性。例如，硬而光滑的材料（如台球）可能具有非常紧凑的高光，而柔软粗糙的材料（如橡胶轮胎）可能有更宽泛的高光。
Phong 指数纹理可以通过以下两种方式定义：
* $phongexponenttexture 定义一个纹理，根据 texel 指定表面的指数值。
* $phongexponent 覆盖指数纹理。通常用于开发阶段快速调整整体高光效果，在创建纹理后通常会被注释掉。
Phong 指数纹理的红色和绿色通道分别用于不同目的。红色通道定义 Phong 指数值，而绿色通道用于反照率（albedo）调整。然而，反照率调整目前在某些分支中并不支持，因此建议指数纹理使用灰度图。
=== Phong 增强因子 ===
Phong 增强因子会应用于 Phong 遮罩通道的过度亮化效果。值无界，甚至可以为负值，但负值通常会导致无意义的结果。
=== Phong 菲涅耳范围 ===
菲涅耳范围值控制菲涅耳项，用于为模型增加“边缘光”。简单来说，这会使模型中远离玩家视角的表面更加明亮。
在 VMT 文件中，菲涅耳范围通过格式 $phongfresnelranges [φX φY φZ] 定义。X 表示视角与表面法线一致时的反射率，Z 表示视角与表面平行时的反射率，Y 表示两者之间的中间值。
尽管通常使用 0 到 1 的值，实际值无界。例如，《Day of Defeat: Source》中可见值 [1 3 8]。这种大范围值对暗纹理效果尤为有用。
以下代码展示了菲涅耳的工作原理：
// Source 引擎菲涅耳范围计算
float Fresnel2( vec3 vNormal, vec3 vEyeDir )
{
	float fresnel = 1-saturate( dot( vNormal, vEyeDir ) );				// 菲涅耳项: 1-(N.V)
	return fresnel * fresnel;											// 平方计算增强效果
}
float Fresnel(vec3 vNormal, vec3 vEyeDir, vec3 vRanges)
{
	float result, f = Fresnel2( vNormal, vEyeDir );			// 传统菲涅耳项计算
	if ( f > 0.5f )
		result = mix( vRanges.y, vRanges.z, (2*f)-1 );		// 在中高值间混合
	else
 result = mix( vRanges.x, vRanges.y, 2*f );			// 在低中值间混合
	return result;
}
== 注意事项 ==
感谢 Valve 的 Jason Mitchell 协助准备本文，并提供其 SIGGRAPH 2006 演讲中的图片。
过去，Orange Box 引擎中的 Phong 指数纹理曾显示过度光亮的问题（显著于 DOD:S 和 TF2 的 HWM 模型），Valve 已于 2011 年 5 月 25 日修复该问题。
== 参见 ==
* $phong
* $envmap（镜面反射）
* $rimlight
* $lightwarptexture
== 外部链接 ==
*Jason Mitchell, Gary McTaggart 和 Chris Green (Valve) 的演讲，Shading in Valve's Source Engine。SIGGRAPH 2006: 第7章内容。
*Source Engine Phong Shader 用于 Substance Painter 的着色器插件
Category:Technical
Category:Source
Category:Material System
Category:Half-Life 2: Episode One
Category:Language/zh-cn