zoukankan      html  css  js  c++  java
  • [翻译]XNA 3.0 Game Programming Recipes之fortyfour

    PS:自己翻译的,转载请著明出处格
                                                                    6-8 用HLSL定义一个聚光灯
    问题
                            一个光照点作为在前面定义的一样,闪耀的光从一个点向所有方向。你想定义一个聚光灯,它它的行为完全像一个点光源,除了它照耀的象一个光核一样,如图6-10所显示。

    解决方案
                            在你的象素着色器中,判断当前的象素是否在光照核内。你可以通过使用点乘积在光的方向和核的方向之间来实现这个。
    它是如何工作的
                            开始前面小节的代码。由于一个聚光灯比一个光照点更个性化,你添加这些额外的XNA-to-HLSL变量到你的.fx文件中:
    1 float xLightStrength;
    2 float3 xConeDiection;
    3 float xConeAngle;
    4 float xConeDecay;
                            第一个变量将允许你增加/减少你的光照的强度。这同样很有用为任何光照的类型也是非常有必要的,当你有多个光照在你的屏幕中。接下来,你可以指定聚光灯核心的中心方向,和核心的宽度。最后,你可以指定多大的光照强度应该减少朝着核心的边缘。
                             除了这个,你需要扩展一下你的象素着色器。一般来说,你将会做相同的per-pixel光照点,但是你要添加一个检查去核实象素在光的核心中:
     1 SLPixelToFrame SLPixelShader(SLVertexToPixel PSIn):COLOR0
     2 {
     3      SLPixelToFrame Output=(SLPixelToFrame)0;
     4      float4 baseColor=float4(0,0,1,1);
     5      float3 normal=normalize(PSIn.Normal);
     6      float3 lightDirection=normalize(PSIn.LightDirection);
     7      float coneDot=dot(lightDirection,normalize(xConeDiection));
     8      float shading=0;
     9      if(coneDot>xConeAngle)
    10      {
    11               float coneAttenuation=pow(coneDot,xConeDecay);
    12               shading=dot(normal,-lightDirection);
    13               shading*=xLightStrength;
    14               shading*=coneAttenuation;
    15      }
    16      Output.Color=baseColor*(shading+xAmbient);
    17      return Output;
    18 }
                              一旦你已经规格化法线和光照方向,你应该检测当前的象素是否在光的核心内。要做到这一点,你要检查两个方向之间的角度:
                            1。当前象素和光源之间的方向。
                            2。核心的中心方向。
                              第一个方向是lightDirection,同时第二个被指定在xConeDirection变量。只有在这个角度是低于某一临界值,像素应点亮。
                              一种为这个的快速检查是通过接收点乘积在两个方向之间 。一个值接近到1,意思是一个非常小的角度在两个方向之间,同时值越小表明角度越大。
                             为了测定角度是否太大,你检查这点乘积是否比临界值小,保存在xConeAngle内,如果象素是在核心内,你计算光照因子,称为shading.为了削弱光照效果接近于核心的边,你使用coneDot值到指定的强度在xConeDecay里,作为一个结果,coneDot值等于或者比1小,象素将变的更小,它离核心中心方向就越远。
                             核心以外的象素会得到一个shading值为0,所以光将有没有影响这些象素。
    代码
                             你的完整的象素着色器已经列出来了。
                             在你的XNA代码的Draw方法中,一个有活力的效果,设置它的参数,绘制到你的屏幕中:
     1 effect.CurrentTechnique=effect.Technique["SpotLight"];
     2 effect.Parameters["xWorld"].SetValue(Matrix.Identity);
     3 effect.Parameters["xView"].SetValue(fpsCam.ViewMatrix);
     4 effect.Parameters["xProjection"].SetValue(fpsCam.ProjectionMatrix);
     5 effect.Parameters["xLightDirection"].SetValue(new Vector3(5.0f,2.0f,-15.0f+variation));
     6 effect.Parameters["xAmbient"].SetValue(2.0f);
     7 effect.Parameters["xConeDirection"].SetValue(new Vector3(0,-1,0));
     8 effect.Parameters["xConeAngle"].SetValue(0.5f);
     9 effect.Parameters["xConeDecay"].SetValue(2.0f);
    10 effect.Parameters["xLightStrength"].SetValue(0.7f);
    11 effect.Begin();
    12 foreach(EffectPass pass in effect.CurrentTechnique.Passes)
    13 {
    14      pass.Begin();
    15      device.VertexDeclaration=myVertexDeclaration;
    16      device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,vertices,0,6);
    17      pass.End();
    18 }
    19 effect.End();
  • 相关阅读:
    Constants and Variables
    随想
    C#基础篇之语言和框架介绍
    Python基础19 实例方法 类方法 静态方法 私有变量 私有方法 属性
    Python基础18 实例变量 类变量 构造方法
    Python基础17 嵌套函数 函数类型和Lambda表达式 三大基础函数 filter() map() reduce()
    Python基础16 函数返回值 作用区域 生成器
    Python基础11 List插入,删除,替换和其他常用方法 insert() remove() pop() reverse() copy() clear() index() count()
    Python基础15 函数的定义 使用关键字参数调用 参数默认值 可变参数
    Python基础14 字典的创建修改访问和遍历 popitem() keys() values() items()
  • 原文地址:https://www.cnblogs.com/315358525/p/1544604.html
Copyright © 2011-2022 走看看