(注:【D3D11游戏编程】学习笔记系列由CSDN作者BonChoix所写,转载请注明出处:http://blog.csdn.net/BonChoix,谢谢~)

在D3D11应用程序中,对于写好的Effect程序进行编译有如下几种常见方法:

1. 在运行期编译

用这种方法,我们只管写好Effect代码即可,不用关心其编译问题,而是在C++程序中,通过调用相应的API先对Effect进行编译,得到编译后的内容,再用之来创建Effect接口。在上个例子绘制立方体时我们用的即这个方法,其相关代码再看一下:

 
  1. //两个ID3D10Blob用来存放编译好的shader及错误消息

  2. ID3D10Blob *shader(NULL);

  3. ID3D10Blob *errMsg(NULL);

  4. //编译effect

  5. HRESULT hr = D3DX11CompileFromFile(L"FX/BasicDraw.fx",0,0,0,"fx_5_0",flag,0,0,&shader,&errMsg,0);

  6. //如果有编译错误,显示之

  7. if(errMsg)

  8. {

  9. MessageBoxA(NULL,(char*)errMsg->GetBufferPointer(),"ShaderCompileError",MB_OK);

  10. errMsg->Release();

  11. return FALSE;

  12. }

  13. if(FAILED(hr))

  14. {

  15. MessageBox(NULL,L"CompileShader错误!",L"错误",MB_OK);

  16. return FALSE;

  17. }

我们通过使用ID3D10Blob接口来存放得到的编译后内容及相关编译错误信息,编译后的内容存放在shader变量中,在确保编译无误的情况下用它来创建Effect。此外,在Debug模式下,为了便于检查shader代码相关问题,我们通过flag变量来指定编译方式,如下所示:

 
  1. UINT flag(0);

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

  3. flag |= D3D10_SHADER_DEBUG;

  4. flag |= D3D10_SHADER_SKIP_OPTIMIZATION;

  5. #endif

这样在Release即可按正常模式进行。

2. 使用Effect编译工具

在安装好DirectX SDK后,在Utilities\bin目录下(无论x64还是x86),有专门用来对Shader代码进行编译的工具,即“fxc”。通过它,我们可以在运行程序前先对我们写的Effect程序进行编译,确保无误,并且输出编译好的二进制文件。在运行期,应用程序通过直接读取二进制shader代码来创建Effect即可。这样的好处还是很多的,一方面,我们可以事先把可能的问题排除掉,确保shader准备无误;另一方面,当shader代码特别庞大的时候,可以有效避免程序运行是初始化阶段因为临时对shader进行编译而造成的漫长的等待。如果用过SDK附带的Sample Browser中的示例程序的话,就会很熟悉,相当多的示例在运行时的开始阶段会有好几秒甚至几十秒的编译shader的时间,好在微软专门对我们进行提示,告诉我们程序正在编译shader,否则一般的程序初始化这么久的话真是很难容忍滴。。。还有一个好处就是,在我们不想公开自己的shader代码时,可以事先编译成二进制文件,让C++程序直接读取二进制代码即可,这样就不必把shader代码连同可执行程序一起发布了。

说了这么多,来看下如何用这个编译工具吧。

fxc用法其实很简单,常见的几个flag就那么几个,很好记住。而且就算记不住,SDK也很方便查阅。首先,当然是打开命令行啦~如果没有把该工具的目录加到系统变量中的话就要先把命令行的工作目录先调到fxc对应目录。

要编译effect,首先要指定编译所用的shader model,在我们学习d3d11过程中,一般用最高等级:fx_5_0,这跟我们effect代码中pass内指定的是一样的,前面跟 /T 。然后指明输出文件名,用 /Fo 指定,接输出文件名;最后直接注明我们要编译的文件名。这就是一个最简单的命令,如下:

fxc /T fx_5_0 /Fo BasicDraw.fxo BasicDraw.fx

如果为了Debug目的,只要多插入几个相应的编译参数即可。一般而言,在Debug过程中我们要组上编译器进行优化,通过增加 /Od 实现,显示Debug信息,增加 /Zi 参数。此外,如果对对应的汇编指令感兴趣的话,也可以让编译把汇编指令输出到一个文件当中,增加 /Fc即可。这时的命令如下:fxc /Od /Zi /T fx_5_0 /Fo BasicDraw.fxo BasicDraw.fx

fxc /Fc /Od /Zi /T fx_5_0 /Fo BasicDraw.fxo BasicDraw.fx

这就是两个我们最常用到的编译effect时的命令。想了解更详细的参数说明,请参考SDK。

对应用程序而言,重要的只有输出的二进制文件,通过C++的输入流读取该文件即可。读取二进制文件的代码如下:

 
  1. ifstream fin("FX/BasicDraw.fxo",ifstream::binary);

  2. fin.seekg(0,ifstream::end);

  3. int size = static_cast<int>(fin.tellg());

  4. fin.seekg(0,ifstream::beg);

  5. vector<char> compiledShader(size);

  6. fin.read(&compiledShader[0],size);

  7. fin.close();

  8. //从编译好的Effect创建Effect

  9. HRESULT hr = D3DX11CreateEffectFromMemory(&compiledShader[0],size,0,g_device,&g_effect);

首先创建输入流,指定二进制文件名和读取方式,这里显然设置为二进制,即ifstream::binary(或 ios::binary)。然后把输入流定位到文件末尾,保存其位置,该位置其实就是文件的大小。这时再把输入流重新定位到文件一开始,并通过调用输入流的read函数读取文件内容到vector变量当中,最后关闭输入流。这时vector当中存放的即是我们需要的编译好的effect代码。最后通过它来创建Effect即可。

3. 让Visual Studio在Build时自动帮我们编译Effect

如果不想每次都手动来编译Effect文件,我们也可以指定IDE来帮我们自动完成。方法如下:

1. 首先在工程目录中把Effect文件添加进来:右键项目名->Add-New Filter,取个名字,比如”FX“,表示我们的Effect文件

接着在该目录下把对应的effect文件添加进来:

2. 右键相应的Effect文件,选"Properties”(属性),在弹出的对话框中按下图所示选择"Custom Build Tool“(中文版选择对应的就行了):

点右下角”应用",这时,还是该对话框,左侧栏会多出一项“Custom Build Tool”,双击它,然后在右边开始输入相应内容。

对应于Debug模式,在Command Line行输入 fxc /Fc /Od /Zi /T fx_5_0 /Fo "%(RelativeDir)\%(Filename).fxo" "%(FullPath)"。看得出就是我们手动编译Effect时的命令。Outputs行输入 %(RelativeDir)\%(Filename).fxo,即输入目录及文件名。如图所示:

对应Release模式很相似,只是Command Line那一行换成我们正常手动编译Effect时对应的命令即可,即:fxc /T fx_5_0 /Fo "%(RelativeDir)\%(Filename).fxo" "%(FullPath)"。Outputs行与上面一样。配置完成,点确定。

这时,每当我们Build我们的项目时,IDE会自动帮我们编译Effect并生成相应的输出文件。在C++程序中直接读取二进制文件即可

【D3D11游戏编程】学习笔记九:编译Effect的方法相关推荐

  1. DirectX 11游戏编程学习笔记之1: 开场白

    本文由哈利_蜘蛛侠原创,转载请注明出处!有问题欢迎联系2024958085@qq.com 这是我之前的博客系列"DirectX9.0c游戏开发手记之'龙书'第二版学习笔记"的平行版 ...

  2. 【逐梦旅程Windows游戏编程学习笔记 ①】基本GDI绘图

    近半年各种忙碌,一直没写博客,现在得空学习记录一下,原书为<逐梦旅程 Windows游戏编程之从零开始>毛星云编著 实现样式与功能: 实现功能: 1,显示title:"致我们.. ...

  3. java2d游戏代码_JAVA游戏编程学习笔记(三)Java 2D游戏底层绘图框架

    前二篇记录了java如何绘制图形与动画,今天打算总结复习一下,把这些知识点集合起来,制作一个Java2D小游戏框架(暂且这么叫,好像挺牛逼似的!). Java AWT 下边提供一个 class Can ...

  4. 3D游戏编程学习笔记(七):模型与动画

    一.前言 本次3D游戏编程我们将设计一个智能巡逻兵游戏. 二.游戏基本内容及规定 游戏内容部分 创建一个地图和若干巡逻兵(使用动画): 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址.即每次 ...

  5. 3D游戏编程学习笔记(五):与游戏世界交互

    一.前言 本次3D游戏编程我们将设计一个简单打飞碟(Hit UFO)有游戏. 二.游戏基本内容及规定 游戏基本内容 游戏有 n 个 round,每个 round 都包括10 次 trial: 每个 t ...

  6. Windows游戏编程学习笔记

    1.文件类型: ipch文件夹和.sdf文件:这两个文件都是Visual Studio用来保存预编译的头文件和Intellisense用的.(可删除,对于工程开发没有影响) Debug文件夹:存放着编 ...

  7. Python微信打飞机游戏编程学习笔记01

    刚学习Python,看别人写的小游戏,照搬照学照写,纯手工手打,一步步,加深印象,加深学习 运行环境是: Python 3.7.1   pygame 1.9.4 微信很火的打飞机游戏拿了学习下 第一步 ...

  8. Python微信打飞机游戏编程学习笔记02

    继上一段的代码.继续完善中 此段代码主要 1.增加了主飞机的载入,并且是动态效果的主飞机 2.增加了主飞机的移动控制 终于有了游戏互动的感觉...继续加油 import pygame #导入pygam ...

  9. Python计算机视觉编程学习笔记 九 图像分割

    图像分割 (一)图割(Graph Cut) 1.1 从图像创建图 1.2 用户交互式分割 (二)利用聚类进行分割 (三)变分法 图像分割是将一幅图像分割成有意义区域的过程.区域可以是图像的前景与背景或 ...

  10. 数独游戏前端学习笔记及后续解数独方法

    学习于默课网学习视频的整理笔记 视频老师分享代码库 基于我本地已经安装了nmp/node所以只添加了yarn 安装yarn: npm install -g yarn 安装成功后,查看版本号yarn - ...

最新文章

  1. 常见数字IC设计、FPGA工程师面试题
  2. Linux CentOS 7 防火墙/端口设置
  3. 思维模型篇:数据分析的本质是什么?
  4. Entity Framework 数据并发访问错误原因分析与系统架构优化
  5. linux mysql更改用户权限
  6. html5录音支持pc和Android、ios部分浏览器,微信也是支持的,JavaScript getUserMedia
  7. 【新Attention】最强的Attention函数诞生啦,带给你意想不到的巨大提升!
  8. 英伟达显卡不同架构_NVIDIA显卡架构代号的另一面:他们都是伟大的科学先驱
  9. AppScan 的安装+激活以及+漏扫dvwa,生成安全报告
  10. JAVA架构师学习路线图(绝对详细)
  11. 总结JS继承的六种方式
  12. win10远程桌面查看对方计算机名,教你如何使用Win10远程桌面控制他人电脑?
  13. 书单 | 深度学习修炼秘籍
  14. MFQE 2.0: A New Approach for Multi-FrameQuality Enhancement on Compressed Video
  15. Unity实现鼠标控制摄像机围绕中心点的旋转和缩放
  16. android机器人方向,Android横版过关类游戏推荐《机器人大挑战》
  17. python识别图片中数字_Python实现识别图片上的数字
  18. 今日份安利:视频变声的软件有哪些?
  19. keras指定gpu_Keras多GPU训练指南
  20. 计算机网络的看法,浅谈计算机网络的发展趋势,你有什么看法吗?

热门文章

  1. excel使用vb统计分数_使用Excel选项按钮计算调查分数
  2. python编写django项目中报错:HTTP 错误 : 500Internal Server Error
  3. Linux下删除文件命令
  4. ue import splat map with world machine
  5. (mac)IDEA配置git
  6. docker安装部署SkyWalking实战
  7. Docker安装部署MinIO
  8. Docker 安装部署与基础操作
  9. 为什么python写文件后打开文件却为空?
  10. 3. C语言 -- 叫你一声你敢答应嘛