DirectX 10 学习笔记5:漫射光

这一节在渲染中加入了光照影响。由于引入了光照,所以所以框架会继续扩展,要加入一个光照类。目前的框架大概可以粗略画成这样:

frameworkchange

另外光照的渲染与多边形以及顶点的法线方向关系密切,所以顶点格式也要发生变化:添加一个法线向量。这样调用shader的类中顶点layout、模型类中顶点各成员的赋值也要随之修改。

加入光照后的shader:

加入光照后,shader中的顶点结构改变,增加了法向量,vertex shader和pixel shader的代码都要发生变化,此外光的属性(方向、颜色)是在LightClass对象中设定的,在shader渲染的时候需要知道这两个属性,所以要在shader中添加两个对应的全局变量,technique保持不变:

////////////////////////////////////////////////////////////////////////////////
// Filename: light.fx
////////////////////////////////////////////////////////////////////////////////
 
 
/////////////
// GLOBALS //
/////////////
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
Texture2D shaderTexture;
 
float4 diffuseColor;
float3 lightDirection;
 
 
///////////////////
// SAMPLE STATES //
///////////////////
SamplerState SampleType
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
 
//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
};
 
struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
    float3 normal : NORMAL;
};
 
////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType LightVertexShader(VertexInputType input)
{
    PixelInputType output;
    
    
    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;
 
    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
    // Store the texture coordinates for the pixel shader.
    output.tex = input.tex;
 
    // Calculate the normal vector against the world matrix only.
   output.normal = mul(input.normal, (float3x3)worldMatrix);
   
   // Normalize the normal vector.
   output.normal = normalize(output.normal);
 
   return output;
}
 
////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 LightPixelShader(PixelInputType input) : SV_Target
{
    float4 textureColor;
    float3 lightDir;
    float lightIntensity;
    float4 color;
 
 
    // Sample the pixel color from the texture using the sampler at this texture coordinate location.
    textureColor = shaderTexture.Sample(SampleType, input.tex);
 
    // Invert the light direction for calculations.
   lightDir = -lightDirection;
 
   // Calculate the amount of light on this pixel.
   lightIntensity = saturate(dot(input.normal, lightDir));
 
    // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity.
    color = saturate(diffuseColor * lightIntensity);
 
    // Multiply the texture pixel and the final diffuse color to get the final pixel color result.
    color = color * textureColor;
 
    return color;
}
负责加载shader的LightShaderClass:
调用shader的类(上一篇笔记中的TextureShaderClass)没有发生太多变化,由于shader中增加了描述光照的两个全局变量,所以在该类中需要添加两个指针成员,用来指向那两个成员变量:
ID3D10EffectVectorVariable* m_lightDirectionPtr;
ID3D10EffectVectorVariable* m_diffuseColorPtr;
由于顶点格式发生了变化(增加了法向量),所以在该类的初始化函数中,需要对layout进行相应的调整:
polygonLayout[2].SemanticName = "NORMAL";
polygonLayout[2].SemanticIndex = 0;
polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[2].InputSlot = 0;
polygonLayout[2].AlignedByteOffset = D3D10_APPEND_ALIGNED_ELEMENT;
polygonLayout[2].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
polygonLayout[2].InstanceDataStepRate = 0;

此外在初始化的时候还需要获得shader中分别代表光的颜色和方向的全局变量的指针:

m_lightDirectionPtr = m_effect->GetVariableByName("lightDirection")->AsVector();
m_diffuseColorPtr = m_effect->GetVariableByName("diffuseColor")->AsVector();

同样,SetShaderParameters函数也要考虑这两个新加入的变量,该函数又增加了两个参数,以及相应的set代码:

void LightShaderClass::SetShaderParameters(D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix, 
                       ID3D10ShaderResourceView* texture, D3DXVECTOR3 lightDirection, D3DXVECTOR4 diffuseColor)
{
    // Set the world matrix variable inside the shader.
    m_worldMatrixPtr->SetMatrix((float*)&worldMatrix);
 
    // Set the view matrix variable inside the shader.
    m_viewMatrixPtr->SetMatrix((float*)&viewMatrix);
 
    // Set the projection matrix variable inside the shader.
    m_projectionMatrixPtr->SetMatrix((float*)&projectionMatrix);
 
    // Bind the texture.
    m_texturePtr->SetResource(texture);
 
    // Set the direction of the light inside the shader.
    m_lightDirectionPtr->SetFloatVector((float*)&lightDirection);
 
    // Set the diffuse color of the light inside the shader.
    m_diffuseColorPtr->SetFloatVector((float*)&diffuseColor);
 
    return;
}

ModelClass的变化:

顶点格式:

struct VertexType
{
    D3DXVECTOR3 position;
    D3DXVECTOR2 texture;
    D3DXVECTOR3 normal;
};

设置vertex array现在也要考虑到法向量:

// Load the vertex array with data.
    vertices[0].position = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);  // Bottom left.
    vertices[0].texture = D3DXVECTOR2(0.0f, 1.0f);
    vertices[0].normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
 
    vertices[1].position = D3DXVECTOR3(0.0f, 1.0f, 0.0f);  // Top middle.
    vertices[1].texture = D3DXVECTOR2(0.5f, 0.0f);
    vertices[1].normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
 
    vertices[2].position = D3DXVECTOR3(1.0f, -1.0f, 0.0f);  // Bottom right.
    vertices[2].texture = D3DXVECTOR2(1.0f, 1.0f);
    vertices[2].normal = D3DXVECTOR3(0.0f, 0.0f, -1.0f);

新增加的光照类:

目前只考虑光照的颜色和方向,所以这个类比较简单:

////////////////////////////////////////////////////////////////////////////////
// Filename: lightclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _LIGHTCLASS_H_
#define _LIGHTCLASS_H_
 
 
//////////////
// INCLUDES //
//////////////
#include <d3dx10math.h>
 
 
////////////////////////////////////////////////////////////////////////////////
// Class name: LightClass
////////////////////////////////////////////////////////////////////////////////
class LightClass
{
public:
    LightClass();
    LightClass(const LightClass&);
    ~LightClass();
 
    void SetDiffuseColor(float, float, float, float);
    void SetDirection(float, float, float);
 
    D3DXVECTOR4 GetDiffuseColor();
    D3DXVECTOR3 GetDirection();
 
private:
    D3DXVECTOR4 m_diffuseColor;
    D3DXVECTOR3 m_direction;
};
 
#endif
实现:
////////////////////////////////////////////////////////////////////////////////
// Filename: lightclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "lightclass.h"
 
 
LightClass::LightClass()
{
}
 
 
LightClass::LightClass(const LightClass& other)
{
}
 
 
LightClass::~LightClass()
{
}
 
 
void LightClass::SetDiffuseColor(float red, float green, float blue, float alpha)
{
    m_diffuseColor = D3DXVECTOR4(red, green, blue, alpha);
    return;
}
 
 
void LightClass::SetDirection(float x, float y, float z)
{
    m_direction = D3DXVECTOR3(x, y, z);
    return;
}
 
 
D3DXVECTOR4 LightClass::GetDiffuseColor()
{
    return m_diffuseColor;
}
 
 
D3DXVECTOR3 LightClass::GetDirection()
{
    return m_direction;
}

视图类的变化:

在视图类中添加了LightClass指针成员,用于设置光照:

LightClass* m_Light;

在InitializeShader中创建光照对象,并设置颜色和照明方向:

// Create the light object.
m_Light = new LightClass;
if(!m_Light)
{
    return false;
}
// Initialize the light object.
m_Light->SetDiffuseColor(1.0f, 0.0f, 1.0f, 1.0f);
m_Light->SetDirection(0.0f, 0.0f, 1.0f);

最后,OnPaint函数中调用LightShaderClass的Render函数进行绘制:

m_LightShader->Render(m_device, pmesh->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, pmesh->GetTexture(),
        m_Light->GetDirection(), m_Light->GetDiffuseColor());

posted on 2012-12-15 21:52  youthlion  阅读(1331)  评论(0编辑  收藏  举报

导航