一步步学shader系列(1):环境光照(Ambient light)

来源:互联网 发布:floor php 编辑:程序博客网 时间:2024/06/07 05:17

环境光照(Ambient light)

OK,我们终于到了最后一步,实现shader!不坏吧?首先,什么是“Ambient light” ? 环境光是场景中的基本光源。如果你进入一个漆黑的屋子,环境光通常是零,但走到外面时,总是有光能让你看到。环境光没有方向(译者:所以也将其称为“全局光照模型”),在这里应确保对象不会自己发光,它有一个基本的颜色。环境光的公式是:

I = Aintensity* AmbientColor

其中I是光的实际颜色, Aintensity是光的强度(通常在0.0和1.0之间),AmbientColor 环境光的颜色,这个颜色可以是固定值,参数或纹理。好吧,现在开始实现Shader。首先,我们需要一个矩阵表示世界矩阵和光照颜色值,还有光照强度:

float4x4 matViewProjection;
float4   ambientMtl;
float    Aintensity;

在shader顶端声明这个矩阵(作为全局变量)然后,我们需要知道vertex shader向pixel shader传递了哪些值。这可以通过建立一个结构(可以命名为任何值)实现:

struct VS_OUTPUT 
{
   float4 Position : POSITION0;
   float4 Color    : COLOR0;
};

我们创建了一个名为OUT的结构,其中包含一个float4类型的名叫Pos的变量。“:”后面的POSITION告诉GPU在哪个寄存器(register)放置这个值?嗯,什么是寄存器?寄存器是GPU中保存数据的一个容器。GPU使用不同的寄存器保存位置,法线,纹理坐标等数据,当定义一个shader传递到pixel shader的变量时,我们必须决定在GPU的何处保存这个值。 看一下vertex shader,我们在pixel shader中进行环境光的算法:

float4x4 matViewProjection;
float4   ambientMtl;
float    Aintensity;
struct VS_INPUT 
{
   float4 Position : POSITION0;
};
struct VS_OUTPUT 
{
   float4 Position : POSITION0;
   float4 Color    : COLOR0;
};
VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
   Output.Position = mul( Input.Position, matViewProjection );
   Output.Color    = Aintensity * ambientMtl;
   return( Output );
  
}

我们创建了一个VS_OUTPUT 类型的函数,它的参数是VS_INPUT 类型的Pos:POSITION。这是模型文件/应用程序/游戏中定义的顶点位置。然后,我们建立一个名叫output的VS_OUTPUT结构实例。这个结构必须被填充并从函数返回,以便后继过程处理。输入参数中的Pos不参与后继过程的处理,但需要乘以worldviewprojection矩阵使之以正确放置在屏幕上。现在开始处理pixel shaders,VS的输入即PS的输出,PS的输出只有一个颜色值:

 

struct PS_INPUT
{
   float4 Position : POSITION0;
   float4 Color    : COLOR0;
};

float4 ps_main(PS_INPUT input) : COLOR0
{  
   return input.Color;
  
}

这里我们使用上面的公式计算目前像素的颜色。Ai是环境光强度,Ac是环境光颜色。最后,我们必须定义technique并将pixel shader和vertex shader函数绑定到technique上:

technique AmbientLight{    pass P0    {        VertexShader = compile vs_1_1 VertexShader();        PixelShader = compile ps_1_1 PixelShader();    }}