zoukankan      html  css  js  c++  java
  • 在场景中添加光线——使用HLSL定义聚光灯

    问题

    前面教程中定义的点光源从一个点发出四面八方的光。你想定义一个聚光灯,它与点光源很很像,但光线只照亮一个圆锥区域,如图6-10。

    image

    图6-10 定义一个聚光灯的变量

    解决方案

    在pixel shader中,判断当前像素是否在光照圆锥中,这可以通过将光线方向和圆锥方向进行点乘做到。

    工作原理

    开始的代码与前面的教程中的是一样的。因为聚光灯比点光源需要设置的东西更多,你需要将下列XNA-to-HLSL变量添加到. fx文件中:

    float xLightStrength; 
    float3 xConeDirection; 
    float xConeAngle; 
    float xConeDecay; 

    第一个变量让你可以增加/减少光照强度。这个变量对其他类型的光也是很有用的,当场景中有多个光源时它也是必须的(见教程6-10)。然后定义光锥的中心线方向、光锥宽度。最后定义光照的衰减。

    除此之外,你还要扩展pixel shader。基本上与逐像素点光源中(见教程6-7)做的一样,只是多了一个检查像素是否在光锥中的步骤:

    SLPixelToFrame SLPixelShader(SLVertexToPixel PSIn) : COLOR0 
    {
        SLPixelToFrame Output = (SLPixelToFrame)0; 
        
        float4 baseColor = float4(0,0,1,1); 
        float3 normal = normalize(PSIn.Normal); 
        float3 lightDirection = normalize(PSIn.LightDirection); 
        float coneDot = dot(lightDirection, normalize(xConeDirection)); 
        
        float shading = 0; 
        if (coneDot > xConeAngle) 
        {
            float coneAttenuation = pow(coneDot, xConeDecay); 
            shading = dot(normal, -lightDirection); 
            shading *= xLightStrength; 
            shading *= coneAttenuation; 
        }
        Output.Color = baseColor*(shading+xAmbient); 
        
        return Output; 
    }

    归一化法线和光线方向之后,你需要检测当前像素是否在光锥之内。这可以检测两个方向间的夹角做到:

    • 当前像素到光源的方向
    • 光锥的中心线的方向

    第一个方向就是lightDirection,第二个方向由xConeDirection变量定义。只有这两个方向的夹角小于某个临界值,像素才会被照亮。

    检测的一个快速方法是计算这两个方向的点乘。结果接近于1表示两者的夹角很小,结果越小表示夹角越大。

    要判断角度是否太大,你要检测点乘结果是否小于某个临界值,这个临界值存储在ConeAngle变量中。如果像素在光锥中,就计算光照因子。要在接近光锥边缘的地方减弱光照,你要计算变量coneDot的xConeDecay次幂。结果是,对那些远离光锥中心线方向的像素来说,当coneDot变量小于等于1时,幂的结果会变得更小(见图6-11的右图)。

    光锥之外的像素光照值为0,光线对这些像素没有影响。

    代码

    完整的pixel shader代码前面已经有了。

    在XNA代码的Draw方法中,开启effect,设置参数并绘制场景:

    effect.CurrentTechnique = effect.Techniques["SpotLight"]; 
    effect.Parameters["xWorld"].SetValue(Matrix.Identity); 
    effect.Parameters["xView"].SetValue(fpsCam.ViewMatrix); 
    effect.Parameters["xProjection"].SetValue(fpsCam.ProjectionMatrix); 
    effect.Parameters["xAmbient"].SetValue(0.2f); 
    effect.Parameters["xLightPosition"].SetValue(new Vector3(5.0f, 2.0f, -15.0f+variation)); 
    effect.Parameters["xConeDirection"].SetValue(new Vector3(0,-1,0)); 
    effect.Parameters["xConeAngle"].SetValue(0.5f); 
    effect.Parameters["xConeDecay"].SetValue(2.0f); 
    effect.Parameters["xLightStrength"].SetValue(0.7f); 
    
    effect.Begin(); 
    foreach (EffectPass pass in effect.CurrentTechnique.Passes) 
    {
        pass.Begin(); 
        device.VertexDeclaration = myVertexDeclaration; 
        device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleStrip,vertices, 0, 6); 
        pass.End(); 
    }
    effect.End(); 

    image

  • 相关阅读:
    Virtual Drive Manager V1.3.2(小巧实用的虚拟光驱)绿色版
    WimTool(Wim映像处理工具) V1.30.2011.501 免费绿色版
    WinHex V18.7(16进制编辑器) 多国语言绿色版
    WinSnap屏幕截图 V4.5.6 官方最新版
    Wsyscheck(系统检测维护工具) v1.68.33绿色版
    XueTr 0.45 (手工杀毒辅助工具) 绿色版
    Colorful(Folders星语多彩文件夹) v1.7绿色版
    飞雪桌面日历软件 V8.6 免费绿色版
    Notepad++ V6.9.0 中文绿色便携版
    屏幕尺子(电脑尺子) 1.0 免费绿色版
  • 原文地址:https://www.cnblogs.com/AlexCheng/p/2120095.html
Copyright © 2011-2022 走看看