zoukankan      html  css  js  c++  java
  • 记录下Directx11中几个易错点_C++和HLSL的变量绑定

        最近遇到几个Directx11的bug,有些最后弄懂了,有些没有,记录下避免下次再犯错。

        一个bug是在Directx11推荐用的数学库xnamath,里面的XMCOLOR居然无法和HLSL里面的float4绑定,如果你要用颜色的变量和HLSL的float4绑定,必须得用XMFLOAT4,或者Directx10的数学库里面的D3DXCOLOR都可以。(D3DXVECTOR4没测试过,可能也可以)。

        一个bug很弱智,如果不用Effect框架,那么在Vertex shader里面VSSetConstantBuffers绑定了一个constant buffer等,在Pixel shader如果用到,必须用PSSetConstantBuffers再绑定一次。

       最后一个是我虽然糊里糊涂debug出来,但却依然最不明白。是C++和HLSL的类里面的变量排列问题。

       如果想在Directx和HLSL里面定义一个同样的结构体

       在HLSL里面:

    struct Light
    {
     float3 pos;
     float3 dir;
     float4 ambient;
     float4 diffuse;
     float4 spec;
     float3 att;
     float  spotPower;
     float  range;
    };

    在Directx里面你就必须注意float pad1,和floatpad2.

    __declspec(align(16)) struct Light
    {
     XMFLOAT3 pos;

    float pad1;
     XMFLOAT3 dir;

    float pad2;
     XMFLOAT4 ambient;
     XMFLOAT4 diffuse;
     XMFLOAT4 spec;
     XMFLOAT3 att;//表示点光源或聚光灯源的距离影响的因子:a0+a1*d+a2*d*d的三个系数a0,a1,a2。
     FLOAT spotPower;//表示在聚光灯源中,偏离的角度对光照的影响因子:max((-LightDir*dir),0)^spotPower
     FLOAT range;//表示光照的范围距离
    };

        为什么会有float pad1,float pad2恩?《Intro to d3d10》里面如下解释:

      The preceding effect file has a constant buffer with a Light instance. We would like to be able to set this value with one function call. Therefore, in the C++ code we define a structure very similar to the HLSLLight structure:

    struct Light
    {
        Light()
        {
            ZeroMemory(this, sizeof(Light));
        }
    
        D3DXVECTOR3 pos;
        float pad1;       // not used
        D3DXVECTOR3 dir;
        float pad2;       // not used
        D3DXCOLOR ambient;
        D3DXCOLOR diffuse;
        D3DXCOLOR specular;
        D3DXVECTOR3 att;
        float spotPow;
        float range;
    };
    

     

      The issue with the “pad” variables is to make the C++ structure match the HLSL structure. In the HLSL, structure padding occurs so that elements are packed into 4D vectors, with the restriction that a single element cannot be split across two 4D vectors. Consider the following example:

    struct S
    {
        float3 pos;
        float3 dir;
    };
    

      If we have to pack the data into 4D vectors, you might think it is done like this:

    vector 1: (pos.x, pos.y, pos.z, dir.x)
    vector 2: (dir.y, dir.z, empty, empty)
    

      However, this splits the element dir across two 4D vectors, which is not allowed — an element is not allowed to straddle a 4D vector boundary. Therefore, it has to be packed like this:

    vector 1: (pos.x, pos.y, pos.z, empty)
    vector 2: (dir.x, dir.y, dir.z, empty)
    

      Thus, the “pad” variables in our C++ structure are able to correspond to those empty slots in the padded HLSL structure (since C++ does not follow the same packing rules as HLSL).

        但我不明白的是按照它的说法In the HLSL, structure padding occurs so that elements are packed into 4D vectors, with the restriction that a single element cannot be split across two 4D vectors,这么说我不用float pad1,和float pad2也可以啊。毕竟D3DXVECTOR3 pos和D3DXVECTOR3 dir也会被分在两个4D vector里。但是经试验是不行的,如果没有float pad1,float pad2。变量的绑定就会莫名其妙。

       估计依然是C++和HLSL里面变量绑定的问题。在HLSL定义一个constant buffer,在C++定义一个相应的如下:

      下面这样子是ok是:

      C++:

    __declspec(align(16)) struct PerFrameCBuffer
    {
     INT gLightType;//光的类型
     XMFLOAT3 gEyePosW;//眼睛在世界坐标系的位置
     Light gLight;//光的结构及变量
    };

     

      HLSL:

    cbuffer cbPerFrame:register(b0)
    {
     int gLightType;//光的类型
     float3 gEyePosW;//眼睛在世界坐标系的位置
     Light gLight;//光的结构及变量
    }

       但是把几个变量的顺序换下就不ok了,比如把int gLightType这个变量放到结构体最后面,那么在HLSL中就识别不了了。

    下面这样子是不ok是:

    C++:

    __declspec(align(16)) struct PerFrameCBuffer
    {

    Light gLight;//光的结构及变量

    XMFLOAT3 gEyePosW;//眼睛在世界坐标系的位置

    INT gLightType;//光的类型

    };

    HLSL:

    cbuffer cbPerFrame:register(b0)
    {

    Light gLight;//光的结构及变量

    float3 gEyePosW;//眼睛在世界坐标系的位置

    int gLightType;//光的类型
    }

       换个这样样子后,在HLSL里面就识别不了gLightType这个变量了,但是gLight还是可以识别。(gEyePosW无法确定)

       所以说在用Directx和HLSL里面变量绑定的时候要非常小心啊。


     

  • 相关阅读:
    实时获取管道信息的一个小框架
    multiprocessing还是threading?
    QThread的一些使用心得
    super超类继承特点小结
    打靶总结
    简析Colorspace
    第一个Unity3D脚本
    一个新的计划,写在年末
    lambda函数的特性
    Nuke Python module的使用
  • 原文地址:https://www.cnblogs.com/bester/p/3255796.html
Copyright © 2011-2022 走看看