RenderMonkey基本使用方法
http://www.cnblogs.com/mixiyou/archive/2009/10/05/1578208.html
楔子:
差不多从年中开始由于工作需要,开始研究Direct3D,这是继大二开始自学DX开始,睽违了6年后再重新学习DX。虽然时间很久了,但是幸亏还是有点基础,所以上手还是比较顺利的。当然由于DX本身难度就比较大,再经过了一两个月的熟悉后,后来发现刚开始写的代码很累赘很复杂且不知所以,所以说脱离实际的自学与实际中根据目标的自学所学到的东西是完全两码子事儿,这就是所谓的“博学而笃志,近问而切思,仁在其中矣”,不要好高骛远,不要脱离实际。
好了,废话说了这么多,该说正经的了。在重新出发学习DX的时候,尤其是Shader的时候,因为隐约记得大学自学的时候并没有接触这一块,所以上手就稍微费力了一点,特别是关于Shader的资料很难找到入门级的,大多数都在DXSDK中零星的分布。当然这里我并不想也没有那个水平去写一篇Shader的教程,只是想分享一下自己在学习Shader过程中使用到的一个工具--AMD的RenderMonkey。
关于RenderMonkey的使用,最基本的当然是参看其自带的SDK文档了,但是这个SDK除了介绍RenderMonkey的使用方法外,几乎没有其它与Shader相关的部分,这是很痛苦的。后来从网上狗狗也只找到些许与RenderMonkey相关的文章,当然写的很好,有基础入门的,也有提高篇的,但是有个唯一的缺点就是,它们使用的都是老版本的RenderMonkey,而我现在则使用AMD最新版本的RenderMonkey,其界面和使用方法与老版本是有一定差异的,所以只有靠自己摸索了。下面正式开始~
////////////////////////////////////////////////// 华丽的分割线 /////////////////////////////////////////////////////////
首先,从AMD开发者网站上下载最新版本的RenderMonkey,截至到本文发布之时,可以下到1.82版本的RenderMonkey。安装很简单,一路Next下去就OK。双击运行,弹出的Splash,果然就是一只猴子,囧~程序的界面,嗯,长的和VC6很像嘛!!
Effect Workspace就和VC6中的Solution的概念相似,即可以在这个名为"Effect Workspace"的解决方案下添加不同的“Project”。当然,在RenderMonkey中Effect Workspace是作为“根”(Root)节点出现的,其下可以添加其它的子节点,这点上并不像VC的Project了。
现在可以尝试在“Effect Workspace”这个根节点下添加其它的子节点,就是在这个根节点上点击鼠标右键,会发现弹出一个多级菜单,这其中有许多选项我都不打算去触碰,因为我也没有完全搞清楚。现在先来看看“Add Effect Group”,其实这个很像VC6中添加一个文件夹,其实只是为了方便管理代码而已,本身不会影响代码的运行。
回想在VC中,当我们创建一个空的Project后,可以自己添加.h/.cpp/.rc。但如果我们使用了VC自带的工程向导的话,就很简单地就可以创建一个应用程序,例如一个基于MFC的对话框程序等等,然后我们就可以在这个工程上根据自己的需要修改相应的.h/.cpp来实现自己所需要的功能。同样地,在RenderMonkey也有类似的操作,你既可以在一个空的Effect Workspace上单独添加一个一个节点,也可以直接使用RenderMonkey提供的默认所谓的“Default Effect”,然后我们在这个Default Effect上根据自己的需要进行修改。这里,我们使用RenderMonkey默认的最简单的DX效果Add Default Effect->DirectX->DirectX。
经过这样的操作后,可以看到在渲染窗口中出现了一个红色的球体。展开Default_Direct_Effect节点后的结果也如图所示,可以看到有很多奇怪的节点图标,下面就一一为您详解它们的前世今生。(还请先阅读一下RenderMonkey的SDK文档了解相关知识)
matViewProjection是RenderMonkey提供的预定义变量(类型为4*4矩阵),之所以知道是“预定义”,是因为这个图标左下角有一个绿色的P字母,代表PreDefined。这里出现的matViewProjection节点相当于固定管线中声明并定义了一个4*4的矩阵变量。
接下来的Stream Mapping节点不知道翻译为“流映射”节点是否合适?该节点的作用是绑定数据流到输入寄存器中供shaders使用。RenderMonkey将会直接使用来自模型的数据来自动产生这个流(例如前面我们下面将要讲到的Model节点就只有位置信息,那么如果你双击这个Stream Mapping节点,就会看到POSITION信息了。)或者你通过用户接口来定义流通道,然后由应用程序获取和输出该流中的信息。按照我的理解,这个Stream Mapping实际上对应了固定管线中声明FVF的过程,而下面的流映射参考节点(Stream Mapping Reference)则对应了固定管线中的IDirect3DDevice9::SetFVF函数的功能。
Model节点是做什么的呢?一个Effect要通过一个几何模型才能过表现出来,即要有一个载体。RenderMonkey用模型(Model)和模型参考(Model Reference)节点来允许用户指定哪个模型被渲染。按照我的理解,设置Model节点就是固定管线中的根据FVF创建顶点缓冲并对其赋值的过程,而Model Reference则是固定管线中IDirect3DDevice9::SetStreamSource的调用,指示当前的渲染对象是哪些顶点(这些Vertext即构成了这里的Model)。
一个效果至少要有一个Pass(这说明RenderMonkey中的效果实际上也和固定管线中IEffect的概念一样),默认为Pass 0。在Pass节点中包含的大多是引用类型的节点(除了Shader之外)。
Pass中一般有两个Shader:Vertex Shader和Pixel Shader,分别代表顶点着色器和像素着色器,这两个节点是整个Effect中最重要也是唯一需要编写代码的地方。
在Vertex Shader中:首先声明了一个类型为float4x4的全局变量matViewProjection,可以看到这个变量的名字和左边Workspace 内的matViewProjection节点的名字一样,这并不是巧合!回想在固定管线中向Shader传送变量的过程,我们首先从IEffect接口中获取Shader中某个全局变量的对应的D3DXHANDLE,然后就可以向这个D3DXHANDLE中传递参数(被映射到Shader的全局变量上),而这个参数最终被用在Shader中。在RenderMonkey中,没有固定渲染管线这个玩意儿,那么它是怎样实现向Shader中传入参数的操作的呢?答案就是Workspace中的变量节点和Shader中定义的全局变量是同名名字。就是说如果你想在Shader中使用外部传入的变量参数的话,就必须声明一个名字和类型都和Effect节点下一致的节点,而我们在Workspace中是可以直接双击某个可编辑的节点进行编辑的(当然这个节点必须是可以“被编辑的 ”,而例如RM预定义的那些变量就是不可被编辑的),那么就相当于实时的改变了Shader中相应的全局变量。
Pixel Shader的用法也大概和Vertex Shader和一样。
在Effect中添加一个纹理也是很简单的,例如如果想添加一个2D纹理,那么就直接Add Texture->Add 2D Texture->2D Texture(这里不使用RM资源库中预先定义好的纹理),这样就创建了一个空的纹理,而如果想将其绑定到某个图像文件,就可以直接双击该节点并选择一个图像即可。这一步就相当于固定管线中的D3DXCreateTextureFromFile一样。类似于模型参考和流映射参考,我们还需要在Pass中添加一个纹理对象(Texture Object,为什么不叫Texture Reference呢?不晓的),并将其指向刚刚创建的纹理。感觉这一步就像是固定管线中的IDirect3DDevice9::SetTexture一样。而双击这个纹理对象后,就更会发现一些与固定管线中函数SetSamplerState和SetTextureStageStatus相似的东东了,而且可以对它们进行设置,就像SetSamplerState和SetTextureStageStatus所做的事情一样。
OK,基本上,DirectX的Default Effect上的基本元素就这么多了,个人所理解的也只有这么多了,下面来看看Shader中最常用到的Render Target究竟时个什么玩意儿!
关于RenderTarget的概念,可以参见RenderMonkey中默认的DirectX Effect--“Render To Texture”实例。我们可以先删除这个例子下的RenderTarget相关的节点,然后来学习如何使用RenderTarget--首先需要在Workspace下创建一个Renderable Texture节点,双击这个节点会发现一些有趣的东西,如Width/Height/Format,这些怎么这么眼熟?不就是IDirect3DDevice9::CreateTexture中的一些参数一致么?既然创建了RenderTarget,那么就要首先在这个RenderTarget中做一些渲染的操作,具体来说,就是在第一个Pass中Add Render Target并将其“指向”刚才添加的Renderable Texture(这似乎和以前的添加参考对象是一样的含义?),双击这个节点(就是前面有一个红色圆心的节点),又可以发现一些与固定管线相像的玩意儿:Clear?Depth Buffer?可以猜想,这个操作实际与固定管线中如下代码是一样的含义:
g_pD3D9Device->GetRenderTarget(0, &pOldRenderTarget);
g_pRenderTarget->GetSurfaceLevel(0, &pRenderSurface);
g_pD3D9Device->SetRenderTarget(0, pRenderSurface);
g_pD3D9Device->Clear(0, 0, D3DCLEARTARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_X#000000, 1, 0);
RenderMonkey中并没有显式的获取Old RenderTarget和恢复Old RenderTarget的过程,但是这却是固定管线中必须有的,所以可以肯定RenderMonkey也一定做了相同的动作,只是不给我们看而已。
渲染完RenderTarget后,就需要回到原来的帧缓存中(即调用IDirect3D9Device::SetRenderTarget将原来保存的Old RenderTarget恢复回去,这一步在RenderMonkey里面是看不到的),并将已经渲染好的Renderable Texture设置到设备的某个纹理层上即可。在RenderMonkey中表现为在第二个Pass中(注意,该Pass的Index号必须比上述渲染RenderTarget的Pass要大,即一定要先渲染RenderTarget再渲染帧缓存),创建一个普通的纹理对象Add Texture Object并将其指向Renderable Texture,就和使用普通的纹理一样。
多个RenderTarget的渲染和单个比起来并没有什么不同,只是多了几个节点而已。但是有一点要强调的是当在一个Pass中出现多个纹理对象的时候,它们实际上是安装多“层”纹理而不是多“次”纹理来渲染的,因为当我们把鼠标移动到Texture Object节点上时候可以看到会提示到“Texture Stage x”,其中x为0开始的数字,这难道不会让你联想到固定管线中的SetTexture的第一个参数或者SetTextureStage函数么?
OK,关于RenderMonkey的几个基本节点(实际上个人才疏学浅,目前也只了解这些了)就到此到一段落了。以后有时间再讲讲如何将RenderMonkey中编写好的Shader文件直接交予应用程序使用,因为毕竟使用RenderMonkey来设计编写调试Shader代码是比较方便的。
参考资料:
1.《RenderMonkey Toolsuite》
http://developer.amd.com/gpu/rendermonkey/Pages/default.aspx
2.《用RenderMonkey进行shader开发》
http://school.ogdev.net/ArticleShow.asp?id=5551&categoryid=5
http://school.ogdev.net/ArticleShow.asp?id=5552&categoryid=5
3.《Direct3D提高篇:HLSL编程实现PhotoShop滤镜效果》
http://tech.it168.com/n/2007-03-29/200703291522292.shtml
RenderMonkey基本使用方法的更多相关文章
- RenderMonkey基本使用方法【转】
RenderMonkey基本使用方法 楔子: 差不多从年中开始由于工作需要,开始研究Direct3D,这是继大二开始自学DX开始,睽违了6年后再重新学习DX.虽然时间很久了,但是幸亏还是有点基础,所以 ...
- javaSE27天复习总结
JAVA学习总结 2 第一天 2 1:计算机概述(了解) 2 (1)计算机 2 (2)计算机硬件 2 (3)计算机软件 2 (4)软件开发(理解) 2 (5) ...
- FX Composer VS RenderMonkey 【转】
http://blog.csdn.net/debugconsole/article/details/50905398 FX COMPOSER 其实编辑一个shader到debug它,有很多方法,很多方 ...
- 一步一步学RenderMonkey
http://blog.csdn.net/tianhai110/article/details/5668832 转载请注明出处:http://blog.csdn.net/tianhai110/ 网上一 ...
- Cg与RenderMonkey 之旅
http://news.mydrivers.com/1/15/15020_all.htm [前言] 您可能还没有意识到---您手头的这块显卡(或者说这块GPU)---它不仅仅是一个应用工具(游戏.平面 ...
- mapreduce多文件输出的两方法
mapreduce多文件输出的两方法 package duogemap; import java.io.IOException; import org.apache.hadoop.conf ...
- 【.net 深呼吸】细说CodeDom(6):方法参数
本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...
- IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法
直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
随机推荐
- c/c++的一些小知识点3
---恢复内容开始--- ---恢复内容结束---
- P1009 阶乘之和
P1009 阶乘之和 题目提供者洛谷OnlineJudge 标签数论(数学相关)高精1998NOIp提高组NOIp普及组 难度普及- 通过/提交1139/3791 提交该题 讨论 题解 记录 题目描述 ...
- 2.5链表 链式A+B
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAowAAAGpCAIAAACI2PCZAAAgAElEQVR4nO2d3YsdSX6m++/wXf8Fxu ...
- php中生成随机密码的自定义函数代码
这篇文章主要分享下php中生成随机密码的方法,原理就是把一些要生成的字符预置一个的字符串包括数字拼音之类的以及一些特殊字符,这样我们再随机取字符组成我们想要的随机密码了 代码一: 生成一个随机密码的函 ...
- sqlalchemy——基本操作
以下所有代码片段都使用了统一的引用,该引用如下: from sqlalchemy import create_engine, ForeignKey from sqlalchemy.ext.declar ...
- 关于mosquitto_internal.h:40:25:#include <uuid/uuid.h> 致命错误的解决
一.安装mosquitto1.4的时候使用make的时候报以下错误: mosquitto_internal.h:40:25: 致命错误:openssl/ssl.h:没有那个文件或目录 #include ...
- requests ip代理池单ip和多ip设置方式
reqeusts库,在使用ip代理时,单ip代理和多ip代理的写法不同 (目前测试通过,如有错误,请评论指正) 单ip代理模式 省去headers等 import requests proxy = { ...
- 教你如何写一个 Yii2 扩展
前言 把一系列相关联的功能使用模块开发,好处多多,维护起来很方便,模块还可以单独发布出去,让下一个项目之间使用,真是方便. 下面我就写一个开发扩展的简单教程. Gii gii 自带帮助我们生成一个基本 ...
- iOS UITableViewCell UITableVIewController 纯代码开发
iOS UITableViewCell UITableVIewController 纯代码开发 <原创> .纯代码 自定义UITableViewCell 直接上代码 ////// #imp ...
- NCL 小图对其问题
从昨天下午开始的折腾终于告一段落,虽然解决得不甚完善,只是图可以用了…… 问题起自想把之前手动拼成的一页四张的图用脚本自动生成,这样一方面应该对得更齐一点,另一方面大大节省人工. 这本来应该是件很容易 ...