着色器和效果——2.4 样例应用程序:散射光照(下)

来源:互联网 发布:苹果平板刷windows 编辑:程序博客网 时间:2024/05/09 02:45

2.4 样例应用程序:散射光照(下)

阅读此文表明您已同意文末的声明

既然我们已经看到了实际的顶点着色器的代码,那么就让我们改变方式来看看应用程序的代码。这个应用程序有下列相关的全局变量:

IDirect3DVertexShader9* DiffuseShader = 0;

ID3DXConstantTable* DiffuseConstTable = 0;

 

ID3DXMesh* Teapot               = 0;

 

D3DXHANDLE ViewMatrixHandle     = 0;

D3DXHANDLE ViewProjMatrixHandle = 0;

D3DXHANDLE AmbientMtrlHandle    = 0;

D3DXHANDLE DiffuseMtrlHandle    = 0;

D3DXHANDLE LightDirHandle       = 0;

 

D3DXMATRIX Proj;

我们有变量来代表顶点着色器及其常量表。我们有一个茶壶的网格变量,跟着是一集D3DXHANDLE,其变量名描述了了他们引用的变量:

Setup函数执行下列任务:

n          创建茶壶网格

n          编译顶点着色器

n          根据已编译代码创建顶点着色器

n          通过常量表获取着色器程序中的几个变量的句柄

n          通过常量表初始化这几个着色器变量

注意:对于本应用程序,我们的顶点结构不需要任何自由顶点格式不能描述的额外的分量。因此,在本例中,我们使用一个自由顶点格式来代替顶点声明。回想一下,自由顶点格式描述最终在内部被转换为一个顶点声明。

bool Setup()

{

     HRESULT hr = 0;

 

     //

     // Create geometry:

     //

 

     D3DXCreateTeapot(Device, &Teapot, 0);

 

     //

     // Compile shader

     //

 

     ID3DXBuffer* shader      = 0;

     ID3DXBuffer* errorBuffer = 0;

 

     hr = D3DXCompileShaderFromFile(

          "diffuse.txt",

          0,

          0,

          "Main", // entry point function name

          "vs_1_1",

          D3DXSHADER_DEBUG,

          &shader,

          &errorBuffer,

          &DiffuseConstTable);

 

     // output any error messages

     if( errorBuffer )

     {

        ::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);

        d3d::Release<ID3DXBuffer*>(errorBuffer);

     }

 

     if(FAILED(hr))

     {

        ::MessageBox(0, "D3DXCompileShaderFromFile() - FAILED", 0, 0);

        return false;

     }

 

     //

     // Create shader

     //

 

     hr = Device->CreateVertexShader(

          (DWORD*)shader->GetBufferPointer(),

          &DiffuseShader);

 

     if(FAILED(hr))

     {

        ::MessageBox(0, "CreateVertexShader - FAILED", 0, 0);

        return false;

     }

 

     d3d::Release<ID3DXBuffer*>(shader);

 

 

     //

     // Get Handles

     //

 

     ViewMatrixHandle = DiffuseConstTable->GetConstantByName(

                        0, "ViewMatrix");

     ViewProjMatrixHandle = DiffuseConstTable->GetConstantByName(

                            0, "ViewProjMatrix");

     AmbientMtrlHandle = DiffuseConstTable->GetConstantByName(

                         0, "AmbientMtrl");

     DiffuseMtrlHandle = DiffuseConstTable->GetConstantByName(

                         0, "DiffuseMtrl");

     LightDirHandle    = DiffuseConstTable->GetConstantByName(

                         0, "LightDirection");

 

//

// Set shader constants:

//

 

// Light direction:

D3DXVECTOR4 directionToLight(-0.57f, 0.57f, -0.57f, 0.0f);

DiffuseConstTable->SetVector(Device, LightDirHandle,

                            &directionToLight);

 

// Materials:

D3DXVECTOR4 ambientMtrl(0.0f, 0.0f, 1.0f, 1.0f);

D3DXVECTOR4 diffuseMtrl(0.0f, 0.0f, 1.0f, 1.0f);

DiffuseConstTable->SetVector(Device,AmbientMtrlHandle,&ambientMtrl);

DiffuseConstTable->SetVector(Device,DiffuseMtrlHandle,&diffuseMtrl);

DiffuseConstTable->SetDefaults(Device);

// Compute projection matrix.

D3DXMatrixPerspectiveFovLH(

     &Proj, D3DX PI * 0.25f,

     (float)Width / (float)Height, 1.0f, 1000.0f);

 

return true;

}

Display函数非常简单。它检测用户输入(译者注:这里指的是用户输入的传入着色器程序的变量),并相应的更新视图矩阵。但是,因为我们在着色器中执行这个视图矩阵变换,所以我们还必须更新着色器中的视图矩阵变量。我们用常量表完成这件事情。

bool Display(float timeDelta)

{

     if( Device )

     {

          //

          // Update view matrix code snipped...

          //

 

          D3DXMATRIX V;

          D3DXMatrixLookAtLH(&V, &position, &target, &up);

 

          DiffuseConstTable->SetMatrix(Device, ViewMatrixHandle, &V);

 

          D3DXMATRIX ViewProj =V *Proj;

          DiffuseConstTable->SetMatrix(Device, ViewProjMatrixHandle,

                                      &ViewProj);

          //

          // Render

          //

 

          Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

                        0xffffffff, 1.0f, 0);

          Device->BeginScene();

 

          Device->SetVertexShader(DiffuseShader);

 

          Teapot->DrawSubset(0);

 

          Device->EndScene();

          Device->Present(0, 0, 0, 0);

     }

     return true;

}

同样注意,就在DrawSubset调用之前,我们允许了这个我们希望使用的顶点着色器。

清理也需要被完成;我们简单的释放了这个已分配接口:

void Cleanup()

{

     d3d::Release<ID3DXMesh*>(Teapot);

     d3d::Release<IDirect3DVertexShader9*>(DiffuseShader);

     d3d::Release<ID3DXConstantTable*>(DiffuseConstTable);

}

[声明]:本文译自Frank Luna的《Introduction to 3D Game Programming with DirectX 9.0》,限于译者水平,文中难免错漏之处,欢迎各位网友批评指正;本文仅用于学习交流与参考用途,不得用于任何形式的商业用途;如需转载需事先征得作者本人和译者的同意,保持文章的完整性,并注明作者、译者和出处,作者保留对译文的所有权利。对于违反以上条款造成的后果,译者对此不负任何责任。我的MSNRaymond_King123@hotmail.com,欢迎热爱3D图形和游戏,并有一定图形编程经验的朋友与我进行交流。