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

时间: 2024-10-17 02:00:49

RenderMonkey基本使用方法的相关文章

几种卡通渲染方法的解析

代码全部出自RenderMonkey的样例文件NPR.rfx,下载地址: http://developer.amd.com/tools-and-sdks/archive/games-cgi/rendermonkey-toolsuite/ 龙书上讲的卡通渲染的方法一直没有看懂,两个faceNormal一直不明白是怎么算出来的 =_=||| ,看了其他DX sample,只看到有计算切法线之类的,也并没有看到能计算"临近边"的法线的...而且也想不通如果一个顶点被很多人公用的话怎么想都没法

一步一步学RenderMonkey

http://blog.csdn.net/tianhai110/article/details/5668832 转载请注明出处:http://blog.csdn.net/tianhai110/ 网上一些关于renderMonkey的教程: <RenderMonkey的基本使用方法> http://www.cnblogs.com/mixiyou/archive/2009/10/05/1578208.html <用RenderMonkey 进行shader开发(一)> http://s

Cg与RenderMonkey 之旅

http://news.mydrivers.com/1/15/15020_all.htm [前言] 您可能还没有意识到---您手头的这块显卡(或者说这块GPU)---它不仅仅是一个应用工具(游戏.平面设计或诸如此类)---它还是一个开发工具. 游戏开发者的硬件配置似乎总比我们普通用户的要高(当然是指3D游戏的开发者,现在没有游戏不是3D的了吧?抛开多如牛毛的FPS不说,一直是2D唱主角的RTS,如魔兽争霸III到命令与征服-将军也都已毫不例外的转到了3D),在"ATi的魔咒日-程序员的训练课程&

FX Composer VS RenderMonkey 【转】

http://blog.csdn.net/debugconsole/article/details/50905398 FX COMPOSER 其实编辑一个shader到debug它,有很多方法,很多方式,也有很多工具. 目前市面上,不管收费还是免费,名气最大的要数RenderMonkey和FX Composer. 一些用户还会选择shaderFX,还有些人会选择 notpad + 3dmax/maya.可以说每一种工具或者方式都对某一些shader来说很好很方便,但是对其他的shader来说很不

Unity 崩溃问题解决方法——之一

友情提示:工作随记,不喜勿喷 注意:文艺青年可以略过,暴力青年欢迎采纳 Library文件夹 Unity每次编译都会生成这个东西,不用担心丢失的问题.所以,干掉他! 选中 + Delete   或者  选中 + Shift  + Delete 网上看了很多方法,就觉得这个简单,粗暴,是我喜欢的类型. 优点:上面说了 缺点:如果工程过大,重新编译时间会比较长.(但是对于查Log日志来说,相对快点)

Java TM 已被阻止,因为它已过时需要更新的解决方法

公司的堡垒机需要通过浏览器登陆,且该堡垒机的网站需要Java的支持,最近通过浏览器登陆之后总是提示"java TM 已被阻止,因为它已过时需要更新的解决方法"导致登陆之后不能操作, 但是操作系统中确实已经安装了比较新的JDK,安装的JDK版本是jdk-7u67-windows-i586,因为太烦人,所以决定搞清楚报错的原因,一劳永逸,彻底解决这个问题 准备工作:安装JDK,安装版本jdk-7u67-windows-i586.exe,因为机器的Eclipse还依赖64位的JDK,所以另安

win7 64位系统 PB连接oracle数据库出现“oracle library oci.dll could not be loaded”问题的解决方法

今天与大家分享一个自己的学习笔记,希望能给遇到同样问题的人带来帮助. 不知道大家在win7 64位系统下用 PB连接oracle数据库时,是否遇到过“oracle library oci.dll could not be loaded”问题. 今天,在win7 64位系统下用 PB连接oracle数据库时,一直出现上述错误,在百度上找了很久,都没有找到一个完整的解决方案,咨询了很多人,(他们都说是我的PB和oracle没装好,但我装的时候没出现任何问题,一切都很顺利,而且PB和oracle都能正

C#与数据库访问技术总结(八)之ExecuteNonQuery方法

ExecuteNonQuery方法 ExecuteNonQuery方法主要用来更新数据. 通常使用它来执行Update.Insert和Delete语句. 该方法返回值意义如下: 对于Update.Insert和Delete语句,返回值为该命令所影响的行数. 对于所有其他类型的语句,返回值为-1. Command对象通过ExecuteNonQuery方法更新数据库的过程非常简单,需要进行的步骤如下: (1)创建数据库连接. (2)创建Command对象,并指定一个SQL Insert.Update

android开发之onCreate( )方法详解

onCreate( )方法是android应用程序中最常见的方法之一,那么,我们在使用onCreate()方法的时候应该注意哪些问题呢? 先看看Google Android Developers官网上的解释: onCreate(Bundle) is where you initialize your activity. Most importantly, here you will usually call setContentView(int) with a layout resource d