GPU Gems1 - 19 基于图像的光照(Image-Based Lighting)

这篇文章打破了当时立方体贴图环境(Cube-Map Environment)用法的桎梏,深入研究了更多可能的逼真光照效果。文章主要研究了基于图像的光照(Image-Based Lighting,IBL),包括局部化的立方体映射,类似于使用基于图像的局部光照(Localizing Image-Based Lighting),然后介绍了如何把哪些重要的技巧用于着色模型,包括逼真的反射、阴影和漫反射/环境项。

cube map反射总是使它好像在无限远处,只与观察角度有关(想象一下skybox),这限制了它对小的封闭环境的应用.

                                                  

传统cube map反射贴图

 

  在室内环境移动模型时,环境最好是近距离的cube map,距离的大小与当前的房间类似。当模型移动式,根据模型在房间中的位置进行反射。只要加很少的shader代码就能将反射局部化。这种方法得到的模拟效果使人感到更为可靠和逼真。尤其在包含窗户,屏幕和其他可识别光源的环境中。而只要加入很少的Shader数学就能将反射局部化。具体可以看原文贴出的Shader源码。

 

     局部化的反射

 

不同位置上的局部反射

 

顶点shader:由cpu传入世界空间和光照空间的矩阵等信息,在顶点shader中将点和矢量转换两次,先由模型空间转换到世界空间,然后从世界空间转换到光照空间。具体代码如下:

Example 19-1. Vertex Shader to Generate World-Space and Lighting-Space Coordinates

vertexOutput reflectVS(appdata IN,
                       uniform float4x4 WorldViewProjXf,
                       uniform float4x4 WorldITXf,
                       uniform float4x4 WorldXf,
                       uniform float4x4 ViewITXf,
                       uniform float4x4 LightingXf,
                       uniform float4x4 LightingITXf)
{
  vertexOutput OUT;
  OUT.TexCoord = IN.UV;
  float4 Po = float4(IN.Position.xyz,1.0); // pad to "float4"
  OUT.HPosition = mul(WorldViewProjXf, Po);
  float4 Pw = mul(WorldXf, Po); // world coordinates
  
   float3 WorldEyePos = ViewITXf [3].xyz;
  float4 LightingEyePos = mul(LightingXf, float4(WorldEyePos, 1.0));
  float4 Pu = mul(LightingXf, Pw);
  float4 Nw = mul(WorldITXf, IN.Normal);
  float4 Tw = mul(WorldITXf, IN.Tangent);
  float4 Bw = mul(WorldITXf, IN.Binormal);
  OUT.LightingEyeVec = (LightingEyePos - Pu).xyz;
  OUT.LightingNormal = mul(LightingITXf, Nw).xyz;
  OUT.LightingTangent = mul(LightingITXf, Tw).xyz;
  OUT.LightingBinorm = mul(LightingITXf, Bw).xyz;
  OUT.LightingPos = mul(LightingXf, Pw).xyz;
  return OUT;
}

片元shader:给定待着色点的位置和矢量,在光照空间计算反射矢量,它的起点是光照空间的表面,通过解球的二次方程,让矢量与那个球面相交,球面中心在照明空间的原点,半径=1.0。得到反射矢量后就可以采样从cube map采样。该shader还提供了几个另外的选项,以增加shader的逼真性,如表面颜色,Fresnel反射衰减等。

Example 19-2. Localized-Reflection Pixel Shader

float4 reflectPS(vertexOutput IN,
                 uniform samplerCUBE EnvMap,
                 uniform sampler2D NormalMap,
                 uniform float4 SurfColor,
                 uniform float Kr, // intensity of reflection
                 
   uniform float KrMin, // typical: 0.05 * Kr
                 
   uniform float FresExp, // typical: 5.0
                 
   uniform float Bumpiness // amount of bump
                 ) : COLOR
{
  float3 Nu = normalize(IN.LightingNormal);
  // for bump mapping, we will alter "Nu" to get "Nb"
  
   float3 Tu = normalize(IN.LightingTangent);
  float3 Bu = normalize(IN.LightingBinorm);
  float3 bumps = Bumpiness *
                   (tex2D(NormalMap, IN.TexCoord.xy).xyz - (0.5).xxx);
  float3 Nb = Nu + (bumps.x * Tu + bumps.y * Bu);
  Nb = normalize(Nb); // expressed in user-coord space
  
   float3 Vu = normalize(IN.LightingEyeVec);
  float vdn = dot(Vu, Nb); // or "Nu" if unbumped - see text
  
   // "fres" attenuates the strength of the reflection
  
   // according to Fresnel's law
  
   float fres = KrMin + (Kr - KrMin) * pow((1.0 - abs(vdn)), FresExp);
  float3 reflVect = normalize(reflect(Vu, Nb)); // yes, normalize
  
   // now we intersect "reflVect" with a sphere of radius 1.0
  
   float b = -2.0 * dot(reflVect, IN.LightingPos);
  float c = dot(IN.LightingPos, IN.LightingPos) - 1.0;
  float discrim = b * b - 4.0 * c;
  bool hasIntersects = false;
  float4 reflColor = float4(1, 0, 0, 0);
  if (discrim > 0) {
    // pick a small error value very close to zero as "epsilon"
    hasIntersects = ((abs(sqrt(discrim) - b) / 2.0) > 0.00001);
  }
  if (hasIntersects) {
    // determine where on the unit sphere reflVect intersects
    reflVect = nearT * reflVect - IN.LightingPos;
    // reflVect.y = -reflVect.y; // optional - see text
    
   // now use the new intersection location as the 3D direction
    reflColor = fres * texCUBE(EnvMap, reflVect);
  }
  float4 result = SurfColor * reflColor;
  return result;
}

另外,我们可以将3D几何体做成立方体贴图,并且在正常地渲染环境的时候,把贴图应用到该环境的物体上。也可以使用贴图作为环境,把它投射到较简单的几何体上。

立方体贴图也能用来决定漫反射光照。Debevec的HDRShop程序能够从映射立方体光照环境积分出全部的漫反射贡献度,那么通过把表面法线带入预先卷积的立方体贴图,能够简单地查询漫反射贡献。

基于图像的光照为复杂的光照计算提供了综合而廉价的替代品,将一点数学加入纹理方法,可以大大拓宽“简单”IBL效果,给3D图像提供更强的的方位感。

【关键词提炼】

基于图像的光照(Image-Based Lighting,IBL)

立方体贴图环境(Cube-Map Environment )

基于图像的局部光照(Localizing Image-Based Lighting)

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GPU Gems是一本关于图形处理器(GPU)编程的经典书籍,由Nvidia公司出版。这本书的内容涵盖了各种有关GPU编程的主题,包括渲染光照、物理模拟、图像处理等。通过学习这本书,读者可以了解到如何充分利用GPU的并行计算能力来提高图形渲染的效率和质量。 为了进行GPU Gems的下载,可以通过以下几种途径实现。 首先,可以到Nvidia的官方网站上搜索GPU Gems相关的资源,并尝试下载电子版的PDF文件或者浏览在线的html版本。这需要通过分别访问各个章节的网页或者注册成为Nvidia开发者来获取下载权限。网上也有一些第三方提供GPU Gems资源下载的网站,可以通过搜索引擎查找。 其次,可以尝试在一些科研论文或者技术博客的网站上查找GPU Gems相关的下载链接。这些链接可能是其他开发者或者研究者在自己的网站或者博客上分享的资源。在这些网站上找到链接后,可以直接点击下载相应的资源。 此外,可以尝试通过一些知名的编程书籍网站或者图书馆的在线平台搜索GPU Gems相关的电子书。这些平台通常会有一些付费或者免费的电子书资源,读者可以根据自己的需求选择合适的版本进行下载。 总之,通过以上的途径,读者有很多选择来下载GPU Gems,他们可以根据自己的需求选择相应的方式。无论是通过官方网站、第三方网站,还是其他相关平台,读者都能够找到他们需要的GPU Gems资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值