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

这篇博客详细介绍了在HLSL中实现高斯模糊的步骤和常见问题,包括FX文件格式、结构体定义、纹理采样、Alpha融合、渲染框架等关键点。作者分享了调试过程中的错误总结,并提供了GitHub上的源码链接。
摘要由CSDN通过智能技术生成

代码已经上传至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 = <BlurTex>;
    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);
   //用于模糊操作的
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值