如何开始使用 SilverLining
本文为如何开始使用SilverLining(中文教程五):调整外观,继续查看>>
如何开始使用SilverLining(中文教程一):演示示例
如何开始使用SilverLining(中文教程二):渲染场景
如何开始使用SilverLining(中文教程三):资源内存管理
如何开始使用SilverLining(中文教程四):集成技巧
烛光射线
当太阳被云层遮挡时,SilverLining可以自动渲染来自太阳的新月形光线。这种效果也被称为 "上帝射线"、光轴和体积照明。
要启用黄昏射线,只需在SilverLining::Atmosphere::DrawObjects()中为crepuscularRays参数传递 "true"。当启用时,当摄像机面向太阳时,光线将在场景上被画出来。射线的强度将根据摄像机上方的云层覆盖情况而变化,所以如果没有云层存在,就不会绘制射线。
我们对新月形光线的实现是一个后处理效果,所以它不能访问场景中的深度信息。默认情况下,射线将在Atmosphere::DrawObjects()被调用之前绘制的任何东西前面渲染,并在云层前面渲染。SilverLining.config的设置 "crepuscular-rays-depth "可以用来调整场景中光线的深度;你可能更喜欢让它们在你的场景对象的后面渲染,在这种情况下,你可以将深度设置为1。
还要记住,SilverLining不能访问你的场景的几何图形,所以光线将只根据场景中的云层来投射。场景中其他可能遮挡太阳的物体不会影响光线。
射线的整体强度可以通过Resources/SilverLining.config中的crepuscular-rays-exposure设置来调整。
高级:使用阴影贴图
SilverLining可以很容易地将云层的阴影投射到你的地形上。只要看看SilverLining::Atmosphere::GetShadowMap()方法就知道了。
当调用GetShadowMap()时,SilverLining将从太阳或月亮的视角将云层渲染成一个纹理地图返回给你。伴随着这个纹理地图,你将得到一个矩阵,它将把世界坐标转化为阴影地图上的纹理坐标。你需要做的就是在渲染你的地形时将这个纹理乘进去,同时应用提供的矩阵来获得它的纹理坐标。这在将阴影贴图纳入片段着色器时是很直接的。
调用Atmosphere::GetShadowMap()的最佳时间是在调用Atmosphere::DrawObjects()之后。避免在渲染场景的过程中调用它,特别是在调用Atmosphere::DrawSky()和Atmosphere::DrawObjects()之间--这将要求SilverLining执行一个额外的剔除过程,并损害性能。
如果你在OpenGL或DirectX 9下使用固定函数管道渲染,下面是将阴影贴图应用到表面的例子。首先,在OpenGL中:
void *texHandle;
Matrix4 mat, shadowMatrix;
atm->GetShadowMap(texHandle, &mat, &shadowMatrix, false);
Gluint shadowMap = (GLuint)texHandle;
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, shadowMap);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGendv(GL_S, GL_EYE_PLANE, shadowMatrix.GetRow(0));
glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGendv(GL_T, GL_EYE_PLANE, shadowMatrix.GetRow(1));
glEnable(GL_TEXTURE_GEN_T);
上面的代码使用Atmosphere::GetShadowMap()提供的矩阵配置了自动纹理坐标生成,并将阴影贴图绑定到纹理单元1。你还需要配置OpenGL,让这个纹理与你在第0单元的基本纹理相乘,就像这样:
// Stage 1 = prev * shadow
glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
// Stage 0 = tex * primary color
glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
同样,如果你使用着色器,这样做会更灵活。这里是DirectX 9下的等效代码--注意,你需要在DirectX 9下乘以视图矩阵的倒数,以便进入世界空间,因为它不像OpenGL那样自动做这个。
SilverLining::Matrix4 mvp, xform;
void *texture;
if (atm->GetShadowMap(texture, &mvp, &xform, false))
{
device->SetTexture(1, (IDirect3DTexture9*)texture);
float mf[16];
int i = 0;
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
mf[i++] = (float)xform.elem[row][col];
}
}
D3DXMATRIX worldToTextureMatrix(mf);
D3DXMATRIX invView, textureMatrix;
D3DXMatrixInverse(&invView, NULL, &view);
D3DXMatrixMultiply(&textureMatrix, &invView, &worldToTextureMatrix);
device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
device->SetSamplerState(1, D3DSAMP_BORDERCOLOR, 0xFFFFFFFF);
device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device->SetTransform(D3DTS_TEXTURE1, &textureMatrix);
device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX,
D3DTSS_TCI_CAMERASPACEPOSITION | 1);
device->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED | D3DTTFF_COUNT3);
device->SetTextureStageState(1, D3DTSS_COLOROP,D3DTOP_MODULATE);
device->SetTextureStageState(1, D3DTSS_COLORARG1,D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLORARG2,D3DTA_CURRENT);
device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
device->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
}
Atmosphere::GetShadowMap()中存在一些选项来控制阴影图中包含的云量和阴影的暗度。更多细节见该方法的文档。如果你将其配置为将整个云层渲染到阴影贴图中,你也许可以避免每一帧都生成阴影贴图--但这将以低分辨率的阴影为代价。
从SilverLining创建环境地图
SilverLining提供了SilverLining::Atmosphere::GetEnvironmentMap()方法来自动生成一个立方体地图纹理,它代表了当前摄像机位置视野中的天空和云。
默认情况下,立方体贴图的每个面将是256x256。如果你需要更高的分辨率,可以在resources/silverlining.config文件的 "environment-map-size "设置下调整。
如果你的场景中有云层,你将需要在摄像机或云层移动一定量的时候重新生成立方体地图,以获得准确的反射。
像这样生成的立方体地图可以被传递到Sundog软件公司的Triton Ocean SDK中,用于从SilverLining的天空中生成水的反射。
在高动态范围应用中使用SilverLining(HDR)
在引擎盖下,SilverLining的所有照明都是物理模拟的,并以每平方米千烛光为单位--然后我们将这些原始的物理值调成可显示的范围。
这种色调映射可以通过调用Atmosphere::EnableHDR()关闭。这可以和浮点渲染目标一起使用,以获得以每平方米千烛光为单位的天空和云层渲染,而不是[0,1.0]。在这种情况下,用户要负责对整个场景进行自己的色调映射,因为浮点渲染目标被转移到可显示的表面。
当HDR被启用时,诸如Atmosphere::GetSunOrMoonColor()等返回的照明值也将不再被色调映射或夹紧。
支持HDR需要着色器模型3.0的支持(因为像素着色器的输入将被钳制。)
如果场景的其他部分不是以kCD/m^2为单位渲染的,你可以缩放HDR输出以更好地匹配场景的其他部分。在resources/silverlining.config文件中,寻找诸如sun-transmission-scale和sun-scattered-scale这样的设置,它们将把我们的内部照明值乘以给定的比例系数,从而使场景变亮或变暗。你也可以通过设置sun-luminance-scale来独立影响云层(相对于天空)的亮度,这将进一步调节应用于云层的照明值。
缩放天空本身的整体亮度可以用 hosek-wilkie-radiance-scale 来完成。
作为禁用色调映射的一部分,伽玛校正也将在HDR模式下被禁用。请确保在你自己的色调映射操作中考虑到伽马校正,以避免天空看起来太暗。
在HDR模式下,闪电的亮度可以通过lightning-hdr-boost配置设置来调整。
选择一个天空模型
SilverLining允许你在两种不同的数学模型中进行选择,以模拟给定时间和地点的天空颜色;每种模型都有各自的优点和缺点。你可以使用SilverLining::Atmosphere::SetSkyModel()方法选择你的天空模型。天空模型可以在运行时改变,使你可以并排比较我们提供的两种模型。
PREETHAM天空模型是1999年SIGGRAPH会议记录中的Preetham论文的扩展。它提供了一个简单性、速度和准确性的良好组合,而我们对它的实现有一个好处,那就是自SilverLining在2006年首次推出以来,已经得到了改进。我们使用我们自己的太阳辐射度模型,以及我们自己的黄昏和夜间亮度模型来扩展原始算法。
HOSEK_WILKIE的天空模型比较新,来自2012年的SIGGRAPH会议记录。它与Preetham的方法相似,但更复杂,能更准确地处理地平线附近的高浊度和颜色。你会发现,Hosek-Wilkie模型产生的天空颜色可能更真实,但在较低的浊度值下就不那么引人注目了。游戏开发者可能更喜欢PREETHAM模型,而模拟开发者可能更喜欢HOSEK_WILKIE。我们对Hosek-Wilkie的实现也使用了我们自己的太阳辐射度模型和色调映射。Hosek-Wilkie方法的一个限制是,它只能模拟太阳在地平线以上时的效果。因此,当太阳接近地平线时,我们将Hosek-Wilkie与我们的Preetham模型实现相融合,以保留SilverLining的暮色效果和月光的天空照明。
在一个云层中定位单个云
默认情况下,积云congestus和积云mediocris云层将用具有真实大小分布的云填充该层,以实现CloudLayer::SetDensity()所要求的云覆盖。然而,这些云的位置将是随机的。如果你试图表现诸如锋面边界或特定的云层,随机散布的云层可能无法满足你的需求。
我们提供了SilverLining::CloudLayer::AddCloudAt()方法,允许你在云层中随机分布的云之外,放置你自己的云,或者代替这些云。要使用这一功能,首先要在云层中加入你想要的任何随机分布的云的种子。即使你希望所有的云都是手工定位的,你仍然必须在放置单个云之前调用CloudLayer::SeedClouds()(你只需使用CloudLayer::SetDensity(0)来防止随机云被创建。)然后,对于每个云,调用CloudLayer::AddCloudAt(),输入每个云的位置和尺寸。传入的位置必须是相对于云层的中心,在它的底部,并代表每个云的底部中心的位置。你必须确保传入的位置在云层的范围内,如其SetBaseWidth()和SetBaseLength()调用所定义的。
下面是一个设置积云密集型云层的例子,随机散布的云覆盖率为20%,一条由2x2x1公里的云组成的直线穿过云层中心延伸。
cumulusCongestusLayer = CloudLayerFactory::Create(hasCumulusCongestusHiRes ? CUMULUS_CONGESTUS_HI_RES : CUMULUS_CONGESTUS, *atm);
cumulusCongestusLayer->SetBaseAltitude(4000);
cumulusCongestusLayer->SetThickness(500);
cumulusCongestusLayer->SetBaseLength(80000);
cumulusCongestusLayer->SetBaseWidth(80000);
cumulusCongestusLayer->SetLayerPosition(0, 0);
cumulusCongestusLayer->SetFadeTowardEdges(true);
cumulusCongestusLayer->SetIsInfinite(true);
cumulusCongestusLayer->SetCurveTowardGround(false);
if (cumulusCongestusLayer->SupportsAddCloudAt())
{
cumulusCongestusLayer->SetDensity(0.2);
cumulusCongestusLayer->SeedClouds(*atm);
for (double x = -40000; x < 40000; x += 5000)
{
Vector3 pos(x, 0, 0); // position relative to layer center
Vector3 size(2000, 1000, 2000); // each cloud is 2km across and 1km high
cumulusCongestusLayer->AddCloudAt(*atm, pos, size);
}
}
请参考SilverLining::CloudLayer::AddCloudAt()的文档以获得更多信息。
在线性色彩空间中使用SilverLining
一些应用程序在内部以线性色彩空间进行渲染,这就否定了伽马校正的效果,以改善照明和阴影。如果你的应用程序是这样做的,你可能会发现SilverLining的天空显得太亮了,因为它正在对天空应用伽马校正。
要纠正这一点,请使用Atmosphere::SetGamma(1.0) - 这将禁用SilverLining的伽玛校正,并以线性色彩空间来绘制天空。
调整SilverLining的外观
SilverLining是高度可配置的。它的默认设置试图准确地模拟所规定的条件下的天空,再加上色调映射,以考虑到人类的感知和你的眼睛如何适应低光水平。但是,如果你不喜欢特定环境下的天空、云层或降水的外观,你有可能将其调整到你喜欢的程度。SilverLining的大多数 "旋钮和转盘 "都可以在resources/SilverLining.config文件中找到。在你的开发环境中打开它,检查可用的设置;大多数在文件中都有详细的说明。
要改变一个设置,把你的改变保存到SilverLining.config文件中,然后重新启动你的应用程序。有些改变可以在运行时通过使用SilverLining::Atmosphere::SetConfigOption()来配置。
配置文件由以下主要部分组成:
常规设置 - 这些控制高层渲染策略、整体色调映射亮度和默认值。
天空设置 - 控制天空盒的外观,以及模拟太阳和月光的缩放值。
降水 - 这些设置控制降水粒子的外观和密度。
来自太空的大气 - 控制从太空观察大气时 "大气层边缘 "的大小和分辨率。
眩光设置 - 控制围绕太阳、月亮和亮星的基于物理的眩光效果。
闪电设置 - 调整积雨云的闪电的复杂性和颜色。
云设置 - 调整一般积雨云的外观。
特定云类型设置 - 调整每种云类型的模拟液滴粒子属性、云的生长模型和云的分布模型。
例如,如果你想增加云层的整体亮度,就把环境散射的设置调高。如果想让云层内的阴影更深,就把积云-照明-快速和昏暗-衰减调低。
天空和光线的整体亮度可能会受到 "亮度 "设置的影响。
为了使大气层的颜色更加丰富,可以尝试使用其他空气质量模型设置(ICQ或NREL)。你也可以直接使用空气质量乘数设置来调整空气质量;更高的空气质量会导致更多的大气散射。
日落和日出的颜色也可以直接调整,使用设置日落-X-增强、日落-Y-增强、日落-Z-增强和日落-增强-指数。要使日落更红,可以增加一点日落-X-增强值。这些设置代表了应用于XYZ色彩空间的散射阳光颜色的提升。指数控制这些提升如何随着太阳与地平线的角度变化而应用。日落-增强-指数的较高整数将限制增强的效果,使其更接近地平线;较低的数值将使增强更普遍。
为了获得更明显的雨粒,请增加rain-streak-brightness和rain-streak-width-multiplier。
层状云内雾的颜色和密度可以用stratus-fog-*设置来调整。
想要一个更大的太阳或月亮?增加太阳宽度-度或月亮宽度-度。
如果你希望将你对SilverLining.config的修改与默认的配置文件分开,你可以将你的修改放在SilverLining.override文件中,与SilverLining.config放在一起。这样,你就可以在新版本的SilverLining中更新SilverLining.config文件,而不必担心将你的修改合并回去。
许多其他的调整都是可能的;检查配置文件以获得更多的选项,如果你有任何关于这些选项的问题,请随时联系我们 https://www.dhorde.com/ 在线客服,电话 023-62585653,或邮箱 sales@dhorde.com。
本文为如何开始使用SilverLining(中文教程五):调整外观,继续查看>>
如何开始使用SilverLining(中文教程一):演示示例
如何开始使用SilverLining(中文教程二):渲染场景
如何开始使用SilverLining(中文教程三):资源内存管理
如何开始使用SilverLining(中文教程四):集成技巧
渝公网安备50010702505508