第三章 2D Rendering Input Layout

Input Layout

我们通过 发送 一块数据 到显卡 来进行处理 几何体的。为了告知 Direct3D 我们定义了什么属性, 如 顺序, 大小, 等, 在此使用一种 叫做 Input Layout 的 结构, 以让API 知道 如何 具体处理 我们将要绘制的几何体。(跟我在前面说过的那样)在DirectX11中, 使用 描述 *_Desc  来进行组织 这些 “告知API 去做什么, 怎么做, 对哪些数据进行处理的” 结构体 chunk data:

typedef struct D3D11_INPUT_ELEMENT_DESC{
    LPCSTR SemanticName; //描述 本 结构体数据的 目的;“POSITION” 标明 本结构体用来 描述 vertex‘ position;“COLOR” 标明 本结构体用来描述 vertex’ color;“NORMAL” 标明 本结构体用来描述 法向量;等等。

    UINT SemanticIndex; //就是索引。对于某些vertex 可能 有多个 color 描述, 则 SemanticName 都为 “COLOR”, 那么 SemanticName = “COLOR”, SemanticIndex =0 的结构体 表示第一份 颜色描述;  SemanticName = “COLOR”, SemanticIndex =1 的结构体 表示第二份 颜色描述;更可能的是, 同一个vertex 会有多份的 纹理映射坐标, 这就需要 编号区别了。

    DXGI_FORMAT Format; // 本结构描述的 格式 , 例如 DXGI_FORMAT_R32G32B32_FLOAT 

    UINT InputSlot; // 也是索引, 不过是用来确定 vertex buffer的, 在Direct3D 中,可以同时绑定 多个 vertex buffer, 这是就需要 用 inputSlot 来指明 我们要描述的 数据所在 哪个 vertex buffer中。

    UINT AlignedByteOffset; // 在 指定 vertex buffer 中 的 开头偏移位置。

    D3D11_INPUT_CLASSIFICATION InputSlotClass; // 用以区分如何 处理 被描述的 数据, 究竟是按照 “per vertex” 还是 “per object”。

    UINT InstanceDataStepRate; // 指明同一场景中, 同时能够存在多上 实体。

}D3D11_INPUT_ELEMENT_DESC;

其中的 CreateInputLayout() 如

HRESULT CreateInputLayout(
    const D3D11_INPUT_ELEMENT_DESC *pInputElements,
 //创建的 InputLayout 通过 一组 描述_DESC创建

    UINT NumElements,   
 // 上面数组的大小, 即多少个 _DESC描述

    const void* pShaderBytecodeWithInputSignature, 
//对应的 已编译 vertex shader code, 他的 签名 要和 本input layout 一致

    SIZE_T BytecodeLength,
//上述 vertex shader bytecode的大小

    ID3D11InputLayout **ppInputLayout
 //最终 返回结果存放。

);

 自从 Direct3D 10 开始, shader 是一项作为基本流程要求 , 进行 Direct3D 的渲染工作。vertex shader 是 已经经过编译的 代码, 直接由 GPU 执行。 设备 device 对 每一个 vertex 执行 vertex shader 。 此外 Direct3D 支持 其他各种类型的 shader , 将会在 第七章中进行 详细讨论。即使是 渲染几何体 也需要使用 shaders, 下面有必要先 简单 引入 shader 以便完成 InputLayout 的工作:

 首先, 加载并编译 vertex-shader 的文本文件(本例中的是 sampleShader.fx ) 成 二进制代码, 编译后的 二进制数据 存放在 两个 buffer里面: 

ID3DBlog *vsBuffer = NULL;
ID3DBlog *errorBuffer = NULL;
// vsBuffer 是 vertex-shader-Buffer 的缩写 // ID3DBlog 定义 内存块, 用以存放大数据(的吧, 我联想到 数据库的 blog数据类型); 用处是作为 数据缓存, 可用于 存储vertex, adjacency, 以及 在处理网格优化 时的 meterial材质信息等. 还可作为 使用API 编译 vertex, geometry, pixel-shader 时的返回值(此例如是)

不过 errorBuffer 用以存储 错误、警告等信息, 实际有效地 二进制代码将会进入 vsBuffer( vertex-shader-Buffer);

第二步骤, 直接 使用 CreateVertexShader() 函数, 将编译好的 二进制数据(存放于 vsBuffer内)作为输入, 创建 vertexShapder。 

 如下所示:

// 声明定义各种 条件, 存储位置
View Code

// 第一步: 编译 shader文件
result = D3DX11CompileFromFile( 
        "sampleShader.fx", 
        0, 
        0, 
        "VS_Main", 
        "vs_4_0", 
        shaderFlags, 
        0, 
        0, 
        &vsBuffer, 
        &errorBuffer, 
        0
);

// 结果处理, 查看是否失败
View Code

//
第二步, 创建最终的 shader result = d3dDevice_->CreateVertexShader( vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), 0, &solidColorVS); // 检查是否成功 if( FAILED( result)) { if( vsBuffer) vsBuffer->Release(); return false; }


其中, 
D3DX11CompileFromFile( 
    "sampleShader.fx",     // LPCTSTR pSrcFile : 待编译 的 HLSL shader源文件
    0,                     // const D3D10_SHADER_MACRO *pDefines : shader code 使用的全局宏,使用方式和 c/c++ 的一样; 
                //  可在 c/c++ 内定义这种宏, 如定义宏 "AGE", 并其值为 18表示岁数:
  /*   const D3D_SHADER_MACRO defineMacros[] =   {   "AGE", "18",   };   */   //但在 本函数中做什么用呢? 暂未知(估计是, shader-code内部使用, 或者是 HLSL编译时用到的 "外部符号表"?呵呵。) 0, // LPD3D10INCLUDE pInclude : HLSL 内部使用的 ?? "VS_Main", // LPCSTR pFunctionName : HLSL shader 源文件内 定义的入口 函数;
                //     因为 一个 shader 文件中可能包好了多种类型的 shader ( vertex? pixel? geometry? ... ?),
                //    各种类型有对应的各种不同的入口, 而"VS_Main()" 是本例使用的入口, 估计, D3DX11CompileFromFile() 函数在编译时,
                //     只需要处理 "VS_Main()" 函数相关的代码块即可
// 此处所谓的 编译, 应该就是指 HLSL编译器进行 编译吧 "vs_4_0", // LPCSTR pProfile : HLSL 进行编译时, 采用哪种版本的 shader, vs_4_0 表示 shader4.0, vs_5_0 表示 shader5.0 // 这有啥关键之处? 我们用 c++ 编译 c的函数时, 需要引用 extern"C" 进行声明 下面的函数按照 C方式进行 修饰,
                //     否则编译器会提示无法找到 obj模块中的某个函数;
// shader4.0 和 shader5.0 版本的不同, 会导致 D3DX11CompileFromFile() 产生的二进制代码不同,
                //     放到当前固定版本的显卡时,受其支持shader版本的限制, 会导致无法运行着色。
shaderFlags, // UINT Flags1 : HLSL 编译条件/即功能选项/方式 0, // UINT Flags2 : HLSL 编译产生结果时, 将使用如何的特效 0, // ID3DX11ThreadPump *pPump : 线程相关(池?) &vsBuffer, // ID3D10Blog **ppShader : 最终编译出来的二进制数据存放未知 &errorBuffer, // ID3D10Blog **ppErrorMsgs : 编译时的错误、警告信息等 0 // HRESULT *pHResult : 结果 );

posted @ 2012-12-01 13:19  Wilson-Loo  阅读(1823)  评论(0编辑  收藏  举报