原文:DirectX11笔记(十二)--Direct3D渲染8--EFFECTS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010333737/article/details/78838316


概述

  Effect Framework 是一个工具代码的集合, 他提供了一个框架用于组织 shader 和渲染状态, 并由他们共同实现某种效果.

  在 DX11 中使用 Effect 需要包含 d3dx11Effect.h 头文件, 并链接 D3DX11Effects.lib 和 D3DX11EffectsD.lib 库. 头文件在 DirectX SDK\Samples\C++\Effects11\Inc 目录下, 两个需要使用的库需要构建 Effects11 自行生成.


Effect Files

  .fx 文件和 .cpp 文件 .h 文件一样, 也是普通的文本文件. 他存储着之前我们见到的 shader 程序.

  在 fx 文件中多出来的是 technique 和 pass. 一个 effect 至少包含一个 technique, 而一个 technique 至少包含一个pass. 每个 pass 至少包含一个 VS, [GS, tessellation 可选], 一个 PS ( 可选但是一般都会有 ), [渲染状态 可选]. 每个 technique 至少有一个 pass 用来实现特定的渲染效果.

  下面是一个完整的 Effect Files例子.

cbuffer cbPerObject
{
float4x4 gWorldViewProj;
};
struct VertexIn
{
float3 Pos : POSITION;
float4 Color : COLOR;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float4 Color : COLOR;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
// Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.Pos, 1.0f), gWorldViewProj);
// Just pass vertex color into the pixel shader.
vout.Color = vin.Color;
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
return pin.Color;
}
technique11 ColorTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetPixelShader( CompileShader( ps_5_0, PS() ) );
}
}

  对于渲染状态, 我们也可以在 fx 文件中直接设置, 当有一些特别需求的时候这个特性是方便的, 但是当状态很多时我们还是应该在应用层面上进行管理, 这样才便于对复杂的渲染状态进行切换.

  下面是一个直接设置 Rasterizer State 的示例.

RasterizerState WireframeRS
{
FillMode = Wireframe;
CullMode = Back;
FrontCounterClockwise = false;
// Default values used for any properties we do not set.
};
technique11 ColorTech
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetPixelShader( CompileShader( ps_5_0, PS() ) );
SetRasterizerState(WireframeRS);
}
}

Compiling Shaders

  实现某种效果的第一步便是将之前 .fx 文件中存储的 shader 程序进行编译. 我们需要用到 DX11 中的 D3DX11CompileFromFile 方法.

HRESULT D3DX11CompileFromFile(
LPCTSTR pSrcFile,
CONST D3D10_SHADER_MACRO *pDefines,
LPD3D10INCLUDE pInclude,
LPCSTR pFunctionName,
LPCSTR pProfile,
UINT Flags1,
UINT Flags2,
ID3DX11ThreadPump *pPump,
ID3D10Blob **ppShader,
ID3D10Blob **ppErrorMsgs,
HRESULT *pHResult);
  1. pSrcFile: .fx 文件的名字.
  2. pFunctionName: 这是 shader 的入口函数名, 但是这只在单独编译 shader 时有用, 在使用 Effect 框架的时候传空就可以了, 这个入口函数已经在 technique 的 pass 中声明好了.
  3. pProfile: 指明 shader 的版本.
  4. Flags1: 表示我们将如何编译 shader, 他有若干个有效值, 我们会用到两个, D3D10_SHADER_DEBUG 和 D3D10_SHADER_SKIP_OPTIMIZATION ( 只在 debug 时有效 )
  5. ppShader: 函数返回的一个 ID3D10Blob 的指针, 他存储着编译出来的 shader.
  6. ppErrorMsgs: 函数返回的一个 ID3D10Blob 的指针, 他存储着编译时的报错信息.
  7. 其他的属性都是跟高级的用法, 我们在学习过程中不需要使用, 设置为默认值即可.

  其中 ID3D10Blob 表示的其实就是一个内存块, 他只有 GetBufferPointer 和 GetBufferSize 两个方法用来操作这块内存.


创建 Effect

  在编译完 shader 之后我们需要使用 D3DX11CreateEffectFromMemory 方法来创建 effect.

HRESULT D3DX11CreateEffectFromMemory(
void *pData,
SIZE_T DataLength,
UINT FXFlags,
ID3D11Device *pDevice,
ID3DX11Effect **ppEffect);
  1. pData: .fx 文件的内容.
  2. DataLength: .fx 文件的长度.
  3. FXFlags: 与之前编译 shader 时的 Flags2 对应.
  4. pDevice: 渲染设备指针.
  5. ppEffect: 返回的 Effect 指针.

示例

DWORD shaderFlags = 0;

#if defined(DEBUG) || defined(_DEBUG)

shaderFlags |= D3D10_SHADER_DEBUG;
shaderFlags |= D3D10_SHADER_SKIP_OPTIMIZATION; #endif ID3D10Blob* compiledShader = 0;
ID3D10Blob* compilationMsgs = 0;
HRESULT hr = D3DX11CompileFromFile(L"color.fx", 0,
0, 0, "fx_5_0", shaderFlags,
0, 0, &compiledShader, &compilationMsgs, 0); // compilationMsgs can store errors or warnings.
if(compilationMsgs != 0)
{
MessageBoxA(0, (char*)compilationMsgs->GetBufferPointer(), 0, 0);
ReleaseCOM(compilationMsgs);
} // Even if there are no compilationMsgs,
// check to make sure there were no other errors.
if(FAILED(hr))
{
DXTrace(__FILE__, (DWORD)__LINE__, hr,
L"D3DX11CompileFromFile", true);
}
ID3DX11Effect* mFX;
HR(D3DX11CreateEffectFromMemory(
compiledShader->GetBufferPointer(),
compiledShader->GetBufferSize(),
0, md3dDevice, &mFX)); // Done with compiled shader.
ReleaseCOM(compiledShader);

DirectX11笔记(十二)--Direct3D渲染8--EFFECTS的更多相关文章

  1. DirectX11笔记(十)--Direct3D渲染6--PIXEL SHADER

    原文:DirectX11笔记(十)--Direct3D渲染6--PIXEL SHADER 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u01033 ...

  2. 《C++游戏开发》笔记十二 战争迷雾:初步实现

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9475979 作者:七十一雾央 新浪微博:http:/ ...

  3. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  4. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  5. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  6. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  7. 《深入理解Java虚拟机》读书笔记十二

    第十二章  Java内存模型与线程 1.硬件效率与一致性 由于计算机的存储设备与处理器的运算速度有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cac ...

  8. swift 笔记 (十二) —— 下标

    下标 swift同意我们为 类.结构体,枚举 定义下标,以更便捷的方式訪问一大堆属性.比方Array和Dictionary都是结构体,swift的project师已经为这两个类型提供好了下标操作的代码 ...

  9. ROS学习笔记十二:使用gazebo在ROS中仿真

    想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...

随机推荐

  1. python基础-re正则

    一:什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则. (在Python中)它内嵌在Python中,并通过 ...

  2. Leetcode959. Regions Cut By Slashes由斜杠划分区域

    在由 1 x 1 方格组成的 N x N 网格 grid 中,每个 1 x 1 方块由 /.\ 或空格构成.这些字符会将方块划分为一些共边的区域. (请注意,反斜杠字符是转义的,因此 \ 用 &quo ...

  3. [转]WPF中的动画

    WPF中的动画                                                                                  周银辉 动画无疑是WP ...

  4. 快速体验 Sentinel 集群限流功能,只需简单几步

    ️ Pic by Alibaba Tech on Facebook 集群限流 可以限制某个资源调用在集群内的总 QPS,并且可以解决单机流量不均导致总的流控效果不佳的问题,是保障服务稳定性的利器. S ...

  5. 使用edac工具来检测服务器内存故障.

    随着虚拟化,Redis,BDB内存数据库等应用的普及,现在越来越多的服务器配置了大容量内存,拿DELL的R620来说在配置双路CPU下,其24个内存插槽,支持的内存高达960GB.对于ECC,REG这 ...

  6. Shell 工具之 sed

    sed编辑器称为流编辑器(stream editor).可以根据输入命令行的命令或者存储在命令文本文件中的命令处理数据.每次从输入读取一行数据,将该数据与所提供的编辑器命令进行匹配,根据命令修改数据流 ...

  7. PAT甲级——A1029 Median

    Given an increasing sequence S of N integers, the median is the number at the middle position. For e ...

  8. python初学小记

    使用PyCharm向世界打招呼! print (“Hello world!”) 介绍自己的基本信息的方法 name = input("name:")age = int(input( ...

  9. 3.appium定位方法

    1.使用id定位: driver.find_element_by_id('id的名称').click() 2.使用className定位: driver.find_element_by_class_n ...

  10. UVA11722 Jonining with Friend

    Joining with Friend You are going from Dhaka to Chittagong by train and you came to know one of your ...