Phong materials

From Valve Developer Community
< Zh
Jump to navigation Jump to search
English (en)Español (es)中文 (zh)Translate (Translate)
Info content.png
This page needs to be translated.
This page either contains information that is only partially or incorrectly translated, or there isn't a translation yet.
If this page cannot be translated for some reason, or is left untranslated for an extended period of time after this notice is posted, the page should be requested to be deleted.
Also, please make sure the article tries to comply with the alternate languages guide.
使用《第一章》中全新光照增强效果渲染的Alyx。
关于 VMT参数, 见 $phong.

随着半衰期2:第一章 半衰期2:第一章的发布,起源 起源引擎中的光照方式进行了多项增强。这些增强主要集中在全局光照上,以便将角色更好地融入游戏世界,使他们在环境中显得更加真实。

其中一项增强是为使用“ps_2_b”或更高版本像素着色器的玩家(大约70%的《半衰期2:第一章》玩家,据玩家统计数据)添加了“Phong着色”。此新功能让材质设计师能够包含由高光遮罩和指数纹理驱动的Phong项。这些项与现有的光照系统自然结合,尤其为像艾莉克斯·万斯这样的关键角色提供了更好的细节表现。

Phong着色还可以包括Fresnel项,从而在强光下显著增强轮廓光,而不是普通的高光反射。在非常亮的光源下,光泽的轮廓高光通常会因为Source引擎的正常HDR后期处理而显得格外突出。

澄清: 光照贴图编译器使用Wikipedia icon Phong着色来平滑刷子的光照;这与由$phong实现的更高级实时Phong不同,后者还会处理漫反射高光。

简要介绍Phong着色

以下简短介绍并非使用Source Phong着色器的必备知识,但可以为某些读者提供技术见解,展示该技术的工作原理。

简单来说,Phong着色是一种在3D图形中提升高光反射分辨率的技术。它由冯武(Dr. Bui Tuong Phong)于1973年在犹他大学开发。他的原始论文将该技术的插值部分与其反射模型结合,“Phong着色”一词通常指反射模型本身或反射模型与插值方法的结合。

Phong反射公式的图示化表示。

Phong反射模型

Phong反射模型是一种简化的计算3D表面特定点阴影的方法。

  • 它未考虑光线追踪或漫射渲染中常见的二次反射。为补偿这一点,场景中增加了额外的环境光照项。
  • 它将表面的反射分为三个子部分——高光反射、漫反射和环境反射。

Phong反射是一种经验性的模型,基于非正式观察。冯博士观察到,对于非常光滑的表面,高光反射区域较小且亮度衰减迅速;而对于较为粗糙的表面,高光反射区域较大且亮度衰减较为缓慢。

Phong插值示例。
待完善: 替换;还应与Wikipedia icon Gouraud着色进行比较,这是非Phong和非光照贴图的VertexLitGeneric材质所使用的着色方式。

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 遮罩。
Note.png注意:虽然 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 遮罩和指数纹理

    • Phong 遮罩** 是存储在模型的 法线贴图(由 $bumpmap 定义)的 Alpha 通道中的灰度图像。遮罩按 texel 控制每个 texel 的 Phong 高光强度。黑色表示最低强度(无高光),而白色表示最高强度。

您也可以通过 $basemapalphaphongmask 1 参数使用基础纹理的 Alpha 通道作为 Phong 遮罩,或者通过 $basemapluminancephongmask 1 参数直接使用基础纹理的亮度值作为遮罩。

Alyx 的 Phong 遮罩纹理。
    • Phong 指数** 控制高光的“紧凑性”。指数越高,高光越小越紧凑;指数越低,高光则更宽更平。

根据材质的物理特性,不同材料会表现出不同的高光特性。例如,硬而光滑的材料(如台球)可能具有非常紧凑的高光,而柔软粗糙的材料(如橡胶轮胎)可能有更宽泛的高光。

Alyx 的 Phong 指数纹理。

Phong 指数纹理可以通过以下两种方式定义:

  • $phongexponenttexture 定义一个纹理,根据 texel 指定表面的指数值。
  • $phongexponent 覆盖指数纹理。通常用于开发阶段快速调整整体高光效果,在创建纹理后通常会被注释掉。

Phong 指数纹理的红色和绿色通道分别用于不同目的。红色通道定义 Phong 指数值,而绿色通道用于反照率(albedo)调整。然而,反照率调整目前在某些分支中并不支持,因此建议指数纹理使用灰度图。

Note.png注意:指数值通常在 0 到 150 范围内。Valve 为了避免混叠问题选择了该映射范围,这在实践中效果较好。

Phong 增强因子

Phong 增强因子会应用于 Phong 遮罩通道的过度亮化效果。值无界,甚至可以为负值,但负值通常会导致无意义的结果。

菲涅耳范围与表面和视角角度的关系。

Phong 菲涅耳范围

Alyx 的菲涅耳项:当表面更接近观察角时亮度增加。

菲涅耳范围值控制菲涅耳项,用于为模型增加“边缘光”。简单来说,这会使模型中远离玩家视角的表面更加明亮。

在 VMT 文件中,菲涅耳范围通过格式 $phongfresnelranges [φX φY φZ] 定义。X 表示视角与表面法线一致时的反射率,Z 表示视角与表面平行时的反射率,Y 表示两者之间的中间值。

尽管通常使用 0 到 1 的值,实际值无界。例如,《Day of Defeat: Source》中可见值 [1 3 8]。这种大范围值对暗纹理效果尤为有用。

Tip.png提示:如不需要边缘光,可使用菲涅耳范围 [0 0 0] 禁用此效果。

以下代码展示了菲涅耳的工作原理:

// 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 日修复该问题。

参见

外部链接