HLSL效果框架实例之高斯模糊

代码已经上传至git hub 见:https://github.com/Jeromecen/GaussianBlur

实例目的

1.提供了一个完整的fx框架编写Shader可运行程序,解决掉了编写过程中遇到的所有问题。验证了在FX框架可以不用GetParameterByName获取句柄的,直接用字符串作为句柄即可。
2.对高斯模糊图片提供了一个思路,就是高斯过滤矩阵通过程序设置给Shader,相比在Shader中做高斯运算性能更高
或者相比在Shader中写死高斯过滤矩阵,但是这样会不够灵活。
3.合理使用GPU Shader可以有效的提高图形程序性能,运用GPU强大的并行大量数据计算能力,简单随意测试了下CPU降低了大概10%。

调试错误和经验总结

//1).获取效果文件,hlsl注意fx要是asscii格式,不能是utf8格式
//2).结构体不能VS_OUTPUT outData = VS_OUTPUT(0);而是直接VS_OUTPUT outData就好了。
//3).顶点着色器输入输出都要float4类型,且像素着色器不能输入顶点,因为已经是在光栅化阶段了。
// 顶点着色器的输入
//struct VS_INPUT
//{
//    float4 POS : POSITION;
//    float2 UV : TEXCOORD0;
//};
//// 顶点着色器的输出
//struct VS_OUTPUT
//{
//    float4 POS : POSITION;
//    float2 UV : TEXCOORD0;
//};
// 4).纹理需要用Sampler正确,不能用texture代替sampler,或者输入texture当sampler来用的方式
// 5).alpha融合需要注意,否则会导致渲染层次有问题,融合结果

// 6).渲染框架要正确,无论是固定管线还是着色器,每帧的Clear,BeginSecne,渲染设置顶点格式/顶点数据/索引数据/Draw函数,EndScene
// 都是要首先正确的。
// 7).对于顶点部分:
// 顶点位置要正确,索引下标要正确,还有世界视图投影变换,特别是索引如果是拷贝的那么很容易什么都不提交PIX也看不到原因
// 8). 对于像素部分:颜色没有出来,可能是光照没有关闭又没有设置材质,也可能是纹理缺失或者设置错误,alpha融合和各种融合情况
// 9).注意视口外裁剪不可见,背面剔除,深度剔除,模板过滤,导致物体绘制不出来。
// 10).要使用上述思维进行代码分析,errorBuffer/Control panel/#define D3D_DEBUG_INFO/PIX来调试分析,反复对比注释提高理论查找问题
// 如果有N卡用NVIDIA Nsight,GPA分析问题和性能更好。
// 11).图像异常:UV坐标没对,PIX传入都没对,那么是UV相关设置出了问题,最后对比发现是顶点声明出了问题:
//D3DVERTEXELEMENT9 Decl_Element [] =
//{
//    {eBlurDT_Pos, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0},
//    {eBlurDT_UV, 0, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
//    D3DDECL_END()
//};
//而不是:
    //D3DVERTEXELEMENT9 Decl_Element [] =
    //{
    //    {0, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0},
    //    {0, 16, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
    //    D3DDECL_END()
    //};


源码

blur.fx

// Globals
// 纹理
texture BlurTex;

// 世界视图投影矩阵
matrix WorldViewProj;

// 纹理大小
float2    TexSize;
// 高斯过滤矩阵,暂时用3x3的
float3x3 ArrayGaussianFilter;

sampler BlurSampler = sampler_state
{
    Texture = ;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
};
//
// Structures
// 顶点着色器的输入
struct VS_INPUT
{
    float4 POS : POSITION;
    float2 UV : TEXCOORD0;
};
// 顶点着色器的输出
struct VS_OUTPUT
{
    float4 POS : POSITION;
    float2 UV : TEXCOORD0;
};

VS_OUTPUT VS_Main( VS_INPUT input )
{
    VS_OUTPUT outData;    
    outData.POS = mul( input.POS, WorldViewProj);
    outData.UV = input.UV;
    return outData;
}

// 像素着色器的输入
struct PS_INPUT
{
     float2 UV : TEXCOORD0;
};
// 像素着色器的输出
struct PS_OUTPUT
{
    vector diffuse : COLOR0;
};


//用来做滤波操作的函数
float4 dip_filter3(float3x3 _filter , sampler2D _image, float2 _xy, float2 texSize)

{
     //纹理坐标采样的偏移
     float2 _filter_pos_delta[3][3] =

     {

        { float2(-1.0 , -1.0) , float2(0,-1.0), float2(1.0 , -1.0) },

        { float2( -1.0 , 0.0) , float2(0.0, 0.0), float2(1.0 ,  0.0) },

        { float2( -1.0 , 1.0) , float2(0, 1.0), float2(1.0 ,  1.0) },

     };

     //最终的输出颜色
     float4 final_color = float4(0.0,0.0,0.0,1.0f);
     //对图像做滤波操作

     for(int i = 0 ; i < 3 ; i++ )

     {
         for(int j = 0 ; j < 3 ; j++ )

         {

              //计算采样点,得到当前像素附近的像素的坐标
              float2 _xy_new = float2(_xy.x + _filter_pos_delta[i][j].x ,

                                  _xy.y + _filter_pos_delta[i][j].y);

              float2 _uv_new = float2(_xy_new.x/texSize.x , _xy_new.y/texSize.y);

              //采样并乘以滤波器权重,然后累加
              final_color += tex2D( _image, _uv_new ) * _filter[i][j];

         }
     }

     return final_color;
}

PS_OUTPUT PS_Main( PS_INPUT input)
{

   PS_OUTPUT output;
   float2  intXY = float2(input.UV.x * TexSize.x , input.UV.y * TexSize.y);
   //用于模糊操作的滤波器
   // output.diffuse = tex2D(BlurSampler, input.UV);
   output.diffuse = dip_filter3( ArrayGaussianFilter , BlurSampler , intXY, TexSize);
   return output;
}

// 效果框架
technique BurTechnique
{
    pass P0
    {
        // 状态设置
        Lighting      = false;
        // 编译
        vertexShader = compile vs_2_0 VS_Main();  
        
        AlphaBlendEnable = false;
        StencilEnable = false;
        pixelShader = compile ps_2_0 PS_Main();
    }
}

d3dUtility.h

/*LPDIRECT3D9等加入*/
//#define D3D_DEBUG_INFO

#include 
#include 
#include 
#include 

/*D3DXMATRIX加入*/
#include 
/*LPDIRECT3D9等加入*/
#pragma comment(lib,"d3d9.lib")
/*D3DXMatrixPerspectiveFovLH加入*/
#pragma comment(lib,"d3dx9.lib")
// 媒体相关的库,用于抵挡的游戏音频和游戏手柄
#pragma comment(lib, "winmm.lib")
// 工程属性->清单工具->输入输出->嵌入清单->是改为否
#include 
#include 
#include 

namespace d3d
{
	//
	// Init
	//
	bool InitD3D(
		HINSTANCE hInstance,       // [in] Application instance.
		int width, int height,     // [in] Backbuffer dimensions.
		bool windowed,             // [in] Windowed (true)or full screen (false).
		D3DDEVTYPE deviceType,     // [in] HAL or REF
		IDirect3DDevice9** device);// [out]The created device.

	int EnterMsgLoop( 
		bool (*ptr_display)(float timeDelta));

	LRESULT CALLBACK WndProc(
		HWND hwnd,
		UINT msg, 
		WPARAM wParam,
		LPARAM lParam);

	//
	// Cleanup
	//
	template void Release(T t)
	{
		if( t )
		{
			t->Release();
			t = 0;
		}
	}
		
	template void Delete(T t)
	{
		if( t )
		{
			delete t;
			t = 0;
		}
	}
} 

d3dUtility.cpp

#include "d3dUtility.h"

// vertex formats
const DWORD d3d::Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;


bool d3d::InitD3D(
    HINSTANCE hInstance,
    int width, int height,
    bool windowed,
    D3DDEVTYPE deviceType,
    IDirect3DDevice9** device)
{
    //
    // Create the main application window.
    //

    WNDCLASS wc;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = (WNDPROC)d3d::WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = 0;
    wc.lpszClassName = "Direct3D9App";

    if( !RegisterClass(&wc) )
    {
        ::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
        return false;
    }
        
    HWND hwnd = 0;
    hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App",
        WS_EX_TOPMOST,
        0, 0, width, height,
        0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);

    if( !hwnd )
    {
        ::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
        return false;
    }

    ::ShowWindow(hwnd, SW_SHOW);
    ::UpdateWindow(hwnd);

    //
    // Init D3D:
    //

    HRESULT hr = 0;

    // Step 1: Create the IDirect3D9 object.

    IDirect3D9* d3d9 = 0;
    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

    if( !d3d9 )
    {
        ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
        return false;
    }

    // Step 2: Check for hardware vp.

    D3DCAPS9 caps;
    d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

    int vp = 0;
    if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
        vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    // Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
 
    D3DPRESENT_PARAMETERS d3dpp;
    d3dpp.BackBufferWidth            = width;
    d3dpp.BackBufferHeight           = height;
    d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferCount            = 1;
    d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality         = 0;
    d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow              = hwnd;
    d3dpp.Windowed                   = windowed;
    d3dpp.EnableAutoDepthStencil     = true;
    d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
    d3dpp.Flags                      = 0;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

    // Step 4: Create the device.

    hr = d3d9->CreateDevice(
        D3DADAPTER_DEFAULT, // primary adapter
        deviceType,         // device type
        hwnd,               // window associated with device
        vp,                 // vertex processing
        &d3dpp,             // present parameters
        device);            // return created device

    if( FAILED(hr) )
    {
        // try again using a 16-bit depth buffer
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
        
        hr = d3d9->CreateDevice(
            D3DADAPTER_DEFAULT,
            deviceType,
            hwnd,
            vp,
            &d3dpp,
            device);

        if( FAILED(hr) )
        {
            d3d9->Release(); // done with d3d9 object
            ::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
            return false;
        }
    }

    d3d9->Release(); // done with d3d9 object
    
    return true;
}

int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) )
{
    MSG msg;
    ::ZeroMemory(&msg, sizeof(MSG));

    static float lastTime = (float)timeGetTime();

    while(msg.message != WM_QUIT)
    {
        if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        else
        {    
            float currTime  = (float)timeGetTime();
            float timeDelta = (currTime - lastTime)*0.001f;

            ptr_display(timeDelta);

            lastTime = currTime;
        }
    }
    return msg.wParam;
}

GaussianBlur.h

#ifndef _GAUSSIANBLUR_H_
#define _GAUSSIANBLUR_H_
class CGaussianBlur
{
public:
	CGaussianBlur(){};
	~CGaussianBlur(){};
	// 计算高斯权值
	void CalculateGaussianFilter(int nLength, float rho);
	float* GetFilter3();
	float* GetFilter4();
	float GaussianFilter3[9];
private:
	// 参数高斯权值
	float GetGaussianDistribution( float x, float y, float rho );
	// 是否接近0
	inline bool FEqual(float fValue1, float fValue2 );

	// 高斯模糊矩阵,提供3x3的和4x4的
	
	float GaussianFilter4[16];
};
#endif

GaussianBlur.cpp

#include "GaussianBlur.h"
#include 
#include 
static const int N_FilterLength3 = 3;
static const int N_FilterLength4 = 4;

bool CGaussianBlur::FEqual(float fValue1, float fValue2 )
{
	if( fabs(fValue1 - fValue2) < FLT_EPSILON )
	{
		return true;
	}
	else
	{
		return false;
	}
}

float CGaussianBlur::GetGaussianDistribution( float x, float y, float rho )
{
	float g = 1.0f / sqrt( 2.0f * 3.141592654f * rho * rho );
	return g * exp( -(x * x + y * y) / (2 * rho * rho) );
}

void CGaussianBlur::CalculateGaussianFilter(int nLength, float rho)
{
	int nSideLength = (int)floor(nLength * 0.5f);
	int nIndex = 0;
	float fTotalWeight = 0;
	for( int j = -nSideLength; j <= nSideLength ; j++ )
	{
		for( int i = -nSideLength; i <= nSideLength; i++ )
		{
			if( nLength == N_FilterLength3 )
			{
				GaussianFilter3[nIndex] = GetGaussianDistribution(i, j, rho);
				fTotalWeight += GaussianFilter3[nIndex];
			}
			else if( nLength == N_FilterLength4 )
			{
				GaussianFilter4[nIndex] = GetGaussianDistribution(i, j, rho);
				fTotalWeight += GaussianFilter4[nIndex];
			}
			else
			{
				// ERROR Log
				return;
			}

			nIndex++;
		}
	}

	// 避免除0
	if( FEqual( fTotalWeight, 0.0f) )
	{
		// ERROR Log
		return;
	}

	nIndex = 0;
	// 归一化一下
	for( int i = 0; i < nLength; i++ )
	{
		for( int j = 0; j < nLength; j++ )
		{
			if( nLength == N_FilterLength3 )
			{
				GaussianFilter3[nIndex] = GaussianFilter3[nIndex] / fTotalWeight;
			}
			else if( nLength == N_FilterLength4 )
			{
				GaussianFilter4[nIndex] = GaussianFilter4[nIndex] / fTotalWeight;
			}
			nIndex++;
		}
	}
}

float* CGaussianBlur::GetFilter3()
{
	return GaussianFilter3;
}

float* CGaussianBlur::GetFilter4()
{
	return GaussianFilter4;
}

Blur.cpp

#include "d3dUtility.h"
#include "GaussianBlur.h"

LPDIRECT3DDEVICE9 Device = NULL;
LPD3DXEFFECT BlurTexEffect = NULL;
LPDIRECT3DVERTEXDECLARATION9 VT_DECL = NULL;
LPDIRECT3DVERTEXBUFFER9 VB_Pos = NULL;
LPDIRECT3DVERTEXBUFFER9 VB_UV = NULL;
LPDIRECT3DINDEXBUFFER9 IB = NULL;

D3DXHANDLE WorldViewProjectHandle  = NULL;
D3DXHANDLE BlurTechHandle = NULL;
CGaussianBlur g_BlurFilter;

LPDIRECT3DTEXTURE9 TexObj = NULL;

const int Width  = 640;
const int Height = 480;
// 模糊的顶点数和索引缓存数
static const int N_Blur_Vertex_Count = 4;
static const int N_Blur_Index_Count = 6;
static bool g_bChangeFilter = false;

// 顶点声明的数据流索引
enum BlurVertexDeclType
{
	eBlurDT_Pos,
	eBlurDT_UV
};

//struct tagTextureVertex
//{
//	float x, y, z;
//	float u, v;
//
//	tagTextureVertex(float ax, float ay, float az, float au, float av )
//	{
//		x = ax; y = ay; z = az;
//		u = au; v = av;
//	}
//	static const DWORD FVF;
//};
//
//const DWORD tagTextureVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1;

bool Setup()
{
	// 顶点声明
	 D3DVERTEXELEMENT9 Decl_Element [] = 
	 { 
		 {eBlurDT_Pos, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0},
		 {eBlurDT_UV, 0, D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
		 D3DDECL_END()
	 };

	if( FAILED(Device->CreateVertexDeclaration(Decl_Element,&VT_DECL) ) )
	{
		return false;
	}
	/* Device->CreateVertexBuffer( 4 * sizeof( tagTextureVertex ),
								 D3DUSAGE_WRITEONLY, 
								tagTextureVertex::FVF, 
								D3DPOOL_MANAGED,
								&VB_Pos,
								0
								);*/
	// 顶点位置
	if( FAILED( Device->CreateVertexBuffer(4 * sizeof(D3DXVECTOR4), D3DUSAGE_WRITEONLY,
                                         0, D3DPOOL_MANAGED, &VB_Pos, 0) ) )
	{
		return false;
	}
	D3DXVECTOR4 *pPos = NULL;
	if( FAILED (VB_Pos->Lock(0, 0, (void**)&pPos, 0) ) )
	{
		return false;
	}

	//tagTextureVertex *pPos = (tagTextureVertex*)VertexData;
	float fHalfWidth = Width * 0.5f;
	float fHalfHeight = Height * 0.5f;
	pPos[0] = D3DXVECTOR4(-1.0f, -1.0f, 1.0f,  1.0f);
	pPos[1] = D3DXVECTOR4(-1.0f, 1.0f, 1.0f, 1.0f);
	pPos[2] = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
	pPos[3] = D3DXVECTOR4(1.0f, -1.0f, 1.0f, 1.0f);
	/*pPos[0] = tagTextureVertex(-1.0f,  -1.0f,1.0f,  0.0f, 1.0f);
	pPos[1] = tagTextureVertex(-1.0f,  1.0f,  1.0f, 0.0f, 0.0f);
	pPos[2] = tagTextureVertex( 1.0f,   1.0f,  1.0f,1.0f, 0.0f);
	pPos[3] = tagTextureVertex( 1.0f,  -1.0f, 1.0f, 1.0f, 1.0f);*/
	VB_Pos->Unlock();

	//// 顶点UV
	if( FAILED( Device->CreateVertexBuffer(4 * sizeof(D3DXVECTOR2), D3DUSAGE_WRITEONLY,
                     0, D3DPOOL_MANAGED, &VB_UV, 0) ) )
	{
		return false;
	}
	D3DXVECTOR2 *UV_Data = NULL;
	if( FAILED( VB_UV->Lock(0,0,(void**)&UV_Data, 0)) )
	{
		return false;
	}
	UV_Data[0] = D3DXVECTOR2(0.0f, 1.0f);
	UV_Data[1] = D3DXVECTOR2(0.0f, 0.0f);
	UV_Data[2] = D3DXVECTOR2(1.0f, 0.0f);
	UV_Data[3] = D3DXVECTOR2(1.0f, 1.0f);
	VB_UV->Unlock();

	// 索引缓存
	if( FAILED( Device->CreateIndexBuffer( 6 * sizeof( WORD ), D3DUSAGE_WRITEONLY, 
                     D3DFMT_INDEX16, D3DPOOL_MANAGED, &IB, 0) ) )
	{
		return false;
	}
	WORD *IB_Buffer = NULL;
	if( FAILED( IB->Lock(0,0, (void**)&IB_Buffer, 0) ) )
	{
		return false;
	}
	IB_Buffer[0] = 0;IB_Buffer[1] = 1;IB_Buffer[2] = 2;
	IB_Buffer[3] = 0;IB_Buffer[4] = 2;IB_Buffer[5] = 3;
	IB->Unlock();

	// 纹理对象设置进去就好了
	
	D3DXIMAGE_INFO imageInfo;
	D3DXCreateTextureFromFileEx(
		Device,
		"crate.png",
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		D3DFMT_UNKNOWN,
		D3DPOOL_MANAGED,
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		&imageInfo,
		NULL,
		&TexObj);

	/*Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);*/

	ID3DXBuffer* errorBuffer = 0;
	if( FAILED( D3DXCreateEffectFromFile(
		Device,
		"blur.fx",
		0,                // no preprocessor definitions
		0,                // no ID3DXInclude interface
		D3DXSHADER_DEBUG, // compile flags
		0,                // don't share parameters
		&BlurTexEffect,
		&errorBuffer) ) )
	{
		if( errorBuffer )
		{
			::MessageBox(0, (char*)errorBuffer->GetBufferPointer(), 0, 0);
			d3d::Release(errorBuffer);
		}
		return false;
	}

	// output any error messages
	//D3DXHANDLE TextureHandle =  BlurTexEffect->GetParameterByName(0, "BlurTex");
	BlurTexEffect->SetTexture(/*TextureHandle*/"BlurTex", TexObj);
	if ( TexObj != NULL )
	{
		TexObj->Release();
		TexObj = NULL;
	}
	FLOAT texSize[2] = {imageInfo.Width * 1.0f, imageInfo.Height * 1.0f};
	D3DXHANDLE TextureSizeHandle =  BlurTexEffect->GetParameterByName(0, "TexSize");
	BlurTexEffect->SetFloatArray(/*TextureSizeHandle*/"TexSize", texSize, 2);

	D3DXMATRIX W, P;
	D3DXMatrixIdentity(&W);
	//Device->SetTransform(D3DTS_WORLD, &W);
	
	D3DXVECTOR3 position( 0.0f, 0.0f, -2.0f );
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &position, &target, &up);

	//Device->SetTransform(D3DTS_VIEW, &V);
	/*D3DXMatrixLookAtLH(&V, &position, &target, &up);
	Device->SetTransform(D3DTS_PROJECTION, &V);*/
	Device->SetRenderState( D3DRS_LIGHTING, FALSE);

	D3DXMatrixPerspectiveFovLH(
		&P,	D3DX_PI * 0.25f, // 45 - degree
		(float)Width / (float)Height,
		1.0f, 1000.0f);
	//D3DXMatrixOrthoLH(&P, float(Width), float(Height), 1.0f, 1000.0f);
	//Device->SetTransform(D3DTS_PROJECTION, &P);

	D3DXMATRIX worldViewProj = W * V * P;
	D3DXHANDLE MatrixHandle =  BlurTexEffect->GetParameterByName(0, "WorldViewProj");
	BlurTexEffect->SetMatrix(/*MatrixHandle*/"WorldViewProj", &worldViewProj);

	if( !g_bChangeFilter )
	{
		g_BlurFilter.CalculateGaussianFilter(3, 8.5f);
	}
	//float* fArray9 = g_BlurFilter.GetFilter3();
	D3DXHANDLE filterHandle =  BlurTexEffect->GetParameterByName(0, "ArrayGaussianFilter");
	BlurTexEffect->SetFloatArray(/*filterHandle*/"ArrayGaussianFilter", 
                                  g_BlurFilter.GaussianFilter3, 9);

	BlurTechHandle = BlurTexEffect->GetTechniqueByName("BurTechnique");

	return true;
}

void Cleanup()
{
	d3d::Release(BlurTexEffect);
	d3d::Release(VB_Pos);
	d3d::Release(VB_UV);
	d3d::Release(IB);
	d3d::Release(Device);
}

bool Display(float timeDelta)
{
	if( Device == NULL || VB_Pos == NULL || VB_UV == NULL || IB == NULL )
	{
		return false;
	}
	Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
	Device->BeginScene();
	Device->SetVertexDeclaration(VT_DECL);
	Device->SetStreamSource(eBlurDT_Pos, VB_Pos, 0, sizeof(D3DXVECTOR4));
	Device->SetStreamSource(eBlurDT_UV, VB_UV, 0, sizeof(D3DXVECTOR2));
	Device->SetIndices(IB);
	/*Device->SetFVF(tagTextureVertex::FVF);
	Device->SetStreamSource(0, VB_Pos, 0, sizeof( tagTextureVertex ));*/

	//Device->SetTexture(0, TexObj);
	
	BlurTexEffect->SetTechnique("BurTechnique"/*BlurTechHandle*/);
	UINT numPasses = 0;
	BlurTexEffect->Begin(&numPasses, 0);
	for( int i = 0; i <  numPasses; i++ )
	{
		BlurTexEffect->BeginPass(i);
		BlurTexEffect->CommitChanges();
		// 绘制
		Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4,0, 2);

		BlurTexEffect->EndPass();
	}
	//Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4,0, 2);
	BlurTexEffect->End();

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

	return true;
}

//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;

	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);

		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
	HINSTANCE prevInstance, 
	PSTR cmdLine,
	int showCmd)
{
	if(!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}

	if(!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}

	d3d::EnterMsgLoop( Display );

	Cleanup();

	Device->Release();

	return 0;
}


你可能感兴趣的:(DirectX)