强行打开BING,不需要代理.
打开C:\Windows\System32\drivers\etc\hosts,加入以下内容保存.
202.89.236.211 cn.bing.com
202.89.236.211 www.bing.com
202.89.236.211 bing.com
202.89.236.211 bing.com.cn
202.89.236.211 bing.cn
如果还是打不开运行ipconfig /flushdns清空DNS缓存就可以了.
打开C:\Windows\System32\drivers\etc\hosts,加入以下内容保存.
202.89.236.211 cn.bing.com
202.89.236.211 www.bing.com
202.89.236.211 bing.com
202.89.236.211 bing.com.cn
202.89.236.211 bing.cn
如果还是打不开运行ipconfig /flushdns清空DNS缓存就可以了.
作为高级程序员,以至于系统分析员,也就是对于一个程序项目的设计者而言,除了应该具备上述全部素质之外,还需要具备以下素质:
第一,需求分析能力
对于程序员而言,理解需求就可以完成合格的代码,但是对于研发项目的组织和管理者,他们不但要理解客户需求,更多时候还要自行制定一些需求,为什么这么说呢?
一般而言,进行研发任务,也许是客户提出需求,也许是市场和营销部门提出的需求,这时候对于研发部门,他们看到的不是一个完整的需求,通常而言,该需求仅仅是一些功能上的要求,或者更正规些,可能获得一个完整的用户视图;但是这都不够,因为客户由于非技术因素多一些,他们可能很难提出完整和清晰,或者说专业性的性能需求,但是对于项目组织者和规划者,他必须能够清醒认识到这些需求的存在并在完成需求分析报告的时候适当的提出,同时要完整和清晰的体现在设计说明书里面,以便于程序员编码时不会失去这些准则。
程序设计者必须正确理解用户需求所处的环境,并针对性做出需求的分析,举例而言,同样一个软件通过ASP租用方式发布和通过License方式发布,性能需求可能就是有区别的,前者强调的是更好的支撑能力和稳定性,而后者则可能更强调在各种平台下的普适性和安装使用的简捷性。
第二,项目设计方法和流程处理能力
程序设计者必须能够掌握不少于两到三种的项目设计方法(比如自顶至下的设计方法,比如快速原型法等等),并能够根据项目需求和资源搭配来选择合适的设计方法进行项目的整体设计。
设计方法上选择不当,就会耽误研发周期,浪费研发资源,甚至影响研发效果。
一个程序设计者还需要把很多功夫用在流程图的设计和处理上,他需要做数据流图以确立数据词典;他需要加工逻辑流图以形成整体的系统处理流程。
一个流程有问题的系统,就算代码多漂亮,每个模块多精致,也不会成为一个好的系统。当然,做好流程分析并选择好项目设计方法,都需要在需求分析能力上具有足够的把握。
第三,复用设计和模块化分解能力
这个似乎又是老调重谈,前面基本素质上不是已经说明了这个问题吗?
作为一个从事模块任务的程序员,他需要对他所面对的特定功能模块的复用性进行考虑,而作为一个系统分析人员,他要面对的问题复杂的多,需要对整体系统按照一种模块化的分析能力分解为很多可复用的功能模块和函数,并针对每一模块形成一个独立的设计需求。举个例子,好比是汽车生产,最早每辆汽车都是独立安装的,每个部件都是量身定做的,但是后来不一样了,机器化大生产了,一个汽车厂开始通过流水线来生产汽车,独立部件开始具有一定的复用性,在后来标准化成为大趋势,不同型号,品牌甚至不同厂商的汽车部件也可以进行方便的换装和升级,这时候,汽车生产的效率达到最大化。软件工程也是同样的道理,一个成熟的软件行业,在一些相关项目和系统中,不同的部件是可以随意换装的,比如微软的许多桌面软件,在很多操作模块(如打开文件,保存文件等等)都是复用的同一套功能模块,而这些接口又通过一些类库提供给了桌面应用程序开发者方便挂接,这就是复用化的模块设计明显的一个佐证。
将一个大型的,错综复杂的应用系统分解成一些相对独立的,具有高度复用性的,并能仅仅依靠几个参数完成数据联系的模块组合,是作为高级程序员和系统分析员一项最重要的工作,合适的项目设计方法,清晰的流程图,是实现这一目标的重要保证。
第四,整体项目评估能力
作为系统设计人员,必须能够从全局出发,对项目又整体的清醒认识,比如公司的资源配置是否合理和到位,比如工程进度安排是否能最大化体现效率又不至于无法按期完成。评估项目整体和各个模块的工作量,评估项目所需的资源,评估项目可能遇到的困难,都需要大量的经验积累,换言之,这是一种不断总结的累计才能达到的境界。在西方一些软件系统设计的带头人都是很年长的,比如4,50岁,甚至更老,他们在编码方面已经远远不如年轻人那样活络,但是就项目评估而言,他们几十年的经验积累就是最重要和宝贵的财富。中国缺这么一代程序员,主要还不是缺那种年纪的程序员,而是那种年纪的程序员基本上都是研究单位作出来的,都不是从专业的产品化软件研发作出来的,他们没有能积累那种产品化研发的经验,这也是没有办法的事情。
第五,团队组织管理能力
完成一个项目工程,需要团队的齐心协力,作为项目设计者或研发的主管人,就应当有能力最大化发挥团队的整体力量,技术管理由于其专业性质,不大同于一般的人事管理,因为这里面设计了一些技术性的指标和因素。
首先是工作的量化,没有量化就很难做到合适的绩效考核,而程序量化又不是简单的代码行数可以计算的,因此要求技术管理人员需要能真正评估一个模块的复杂性和工作量。
其次是对团队协作模式的调整,一般而言,程序开发的协作通常分为小组进行,小组有主程序员方式的,也有民主方式的,根据程序员之间的能力水平差距,以及根据项目研发的需求,选择合适的组队方式,并能将责权和成员的工作任务紧密结合,这样才能最大发挥组队的效率。
一个代码水平高的人,未必能成为一个合格的项目研发主管,这方面的能力欠缺往往是容易被忽视的。
综上可以看到,作为一个主管研发的负责人,一个项目设计者,所需要具备的素质和能力并不是程序代码编写的能力,当然一般情况下,一个程序员通过不断的总结提高达到了这种素质的时候,他所具有的代码编写能力也已经相当不简单了,但是请注意这里面的因果关系,一个高水平的项目设计者通常已经是代码编写相当优秀的人了,但是并不是一个代码相当优秀的程序员就可以胜任项目设计的工作,这里面存在的也不是智商和课本的问题,还是在于一个程序员在积累经验,逐步提升的时候没有意识到应当思考哪方面的东西,没有有意识的就项目的组织和复用设计进行揣摩,没有经常性的文档习惯和总结习惯,不改变这些,我们的合格的项目设计者还是非常欠缺。
另外,为防止有无聊的人和我较真,补充一点,本文针对目标是作商业化的软件项目和工程,那些科研机构的编程高手,比如算法高手,比如图象处理高手,他们的工作是研究课题而非直接完成商业软件(当然最终间接成为商业产品,比如微软研究院在作的研究课题),因此他们强调的素质可能是另外的东西,这些人(专家),并不能说是程序员,不能用程序员的标准去衡量。
一个犁牛半块田,收也凭天,荒也凭天
粗茶淡饭饱三餐,早也香甜,晚也香甜
布衣得暖胜丝绵,长也可穿,短也可穿
草舍茅屋有几间,行也安然,待也安然
雨过天青驾小船,鱼在一边,酒在一边
夜归儿女话灯前,今也有言,古也有言
日上三竿我独眠,谁是神仙,我是神仙
南山空谷书一卷,疯也痴癫,狂也痴癫
最近没啥好八卦的,拿这个来充数.HOHO.0day在文章最后面.
|=---------------------------------------------------------------------------=| |=----------------------=[ 专访wordexp ]=---------------------=| |=---------------------------------------------------------------------------=| |=---------------------------------------------------------------------------=| |=-------------------=[ By wordexp ]=------------------=| |=---------------------------------------------------------------------------=|
[目录] 1. 据您所知现在都还有哪些严重的0DAY没被公开? 2. 挖漏洞有什么窍门?可以具体谈谈fuzzer怎样构造样本么? 3. 请问您对0day市场有什么看法? 4. 您建立wordexp这个blog的初衷是什么?为什么叫wordexp,而不是pdfexp或者是exclexp? 5. 请问0day是咋来的? 6. 请问在安全圈子谁是您的偶像? 7. 请问溢出这面红旗还能打多久? 8. 您对我们杂志以及我们小组的发展有什么建议? 一、据您所知现在都还有哪些严重的0DAY没被公开? 主流应用软件方面目前微软公司的IE6/7和PPT 2003 SP3前一阵子就有EXP在外面跑了, adobe公司的FLASH产品中也有一个能被利用的漏洞,拿到的人应该也不少,往后的一到三个月 内就应该出补丁或是有相关新闻,当然以我们目前的视界能看到的只有很少很少的一部分,其 实国外的很多安全机构比如:idefense和zdi可以确定还有不少没被公开的漏洞,只是这些漏 洞可能并不是我们想象的那么通用,成功率也许有限。 其实经常听到朋友问这个问题,说白了就是个消息的打听,这个一方面要提高自已的敏感 度,注意随时关注国内外相关网站的新闻,比如NORTON和MCAFEE的网站经常有一些抓到的0DAY 样本的新闻,有时还有一些细节。还有就是消息的共享,你提前能知道消息并告知朋友,以后 也许人家也会这样对你。 二、挖漏洞有什么窍门?可以具体谈谈fuzzer怎样构造样本么? 这个问题太为难我了,很多人比我更有资格回答这个问题。我只是斗胆胡说几句。 要说窍门,应该是不同软件的洞窍门还不一样,然后还要看挖洞的目的,如果是为了出名 在bugtraq之类的邮件列表上能多露几次脸,那么可以尽可能的找那种用户少关注少的软件特 别是WEB脚本程序的洞。如果是公司有任务必须往CVE、MS上报多少条漏洞那么可以找大公司 的二三线产品的漏洞或是有一定用户数但版本很久不更新的软件的洞,而且这些洞是不一定 要可利用的。如果是为了混zdi、idefense那么可以把fuzz到的POC只要看起来有可能被利用 的都提交上去,也可以找默认情况下不支持的功能的洞,多少可以骗点钱。 如果是要挖卖得出去也能利用的洞,比较通用的一些窍门我能想到的是: 1. 找大众软件生僻功能,生僻协议/文件格式的洞 2. 找几乎没有文档化的功能的洞 3. 新版本软件为了向下兼容所支持的老协议/老文件格式的洞 4. 新版本软件增加的新功能/新格式 5. 不容易fuzz到的洞,比如数据是加密/压缩/编码过的,或是有验效的 6. 某软件某功能刚出了漏洞,马上测试其它同类软件同类功能是否有类似漏洞 7. 多分析老漏洞,善于总结前人挖漏洞的经验技巧,很多不同的洞其实都有相类似的发 掘方式和思路 第二个问题,我以文件型漏洞举例子,fuzz样本的构造,首先是按照上述几个窍门来生成 原始模版,这样相对可以弄出一些人家不太容易fuzz到的数据格式结构,当然在生成原始模版 的前期功课也是很花时间的。做好样本后就是写具体的fuzz程序, 如果对文件格式比较熟, 那么可以节约很多的时间,我比较喜欢的一个办法是fuzz某一些功能的洞,那么就先看格式, 把数据在文件中的位置先手工定位,然后小粒度的测试,要注意的是可能与某功能相关联的数 据比较杂乱数据很可能并不是连续存放的。一般1-4KB的数据要不了多少时间就可以手工测 试完毕。另外具体测试时,数据替换的长度(一次替换几个字节),替换的内容也是非常重要的。 为此我们将提供一个PPT 2003 sp3的“0day”poc,在这个“0day”中数据替换的步进就必须为1 字节,而且值也必须为一个固定的值才能触发出错。最后要注意的就是错误的捕捉,有些洞是 打开就退出进程,有些是打开要停顿一定时间才退出进程,有些是CPU 100%程序挂起,有些是 关闭时触发,甚至有些是文档打开后进行某种操作才会触发,当然还有一种情况进程不退出, 也没有提示,也不出错,象这种情况一般依靠进程/窗口/CPU来检测错误的fuzz就失效了。 三、请问您对0day市场有什么看法? 很复杂的一个圈子,搞技术的不搞技术的啥人都有,不过目前看来很多都是为了各种利益 混这个圈子。简单说就是: 池塘不大但人杂,水深。 四、您建立wordexp这个blog的初衷是什么?为什么叫wordexp,而不是pdfexp或者是exclexp? 初衷就是团队成员工作之余发发劳骚,聊聊八卦的地方,希望大家别见怪。另外这个名字 是因为我们几个人搞客户端的漏洞都比较多,所以随便就取了这么个名字。 五、请问0day是咋来的? 最初当然是某个人找出来的。从这个0DAY的发掘者到最终的用户中间可能会只有一层关 系,也可能会有N层关系,也许直到这个0DAY被补上,使用者也不知道洞是谁挖到的。下面举几 个例子吧: 情况一:A挖到一个0day,但对黑产没有了解或接触,或者也不想靠这个赚钱,或者觉得漏 洞不值钱,或者压根以为漏洞不能够被利用,那么A有可能把这个漏洞公开给类似PST的网站, 网站上的代码通常是POC或是只有一部分细节。这时黑产中的漏洞研究者B,很快会看到这个 消息,并且分析POC然后写出EXP。随后B再联系具体的使用者C或是自已使用。最终或是因为 这个0DAY的POC被公开,也或许因为EXP被杀毒软件公司抓到样本等等,软件厂商推出补丁。在 这个过程中B可能是一个人也可能是很多水平各不相同的人,所以公开的0DAY的EXP有时是千 差万别,有的好用,有的很差。 情况二:A是黑产中的一员,挖到一个0DAY并卖给X,或是接受使用者X的定制并找到0DAY, X偷偷的使用0DAY,这样的情况一般0DAY的生存期会比较长一些,因为这才算是真正的私洞,知 道的人不多。但是在X的使用中,EXP可能被别的黑产从业者Y抓到样本,然后Y把样本提供给技 术员T分析并重新写出EXP,而成果Y和T分享。这时T可能再次把EXP卖给其它的黑产使用者W, 同样X或Y在使用一段时间后也可能交换或者再出手给其它的买家,而且这个过程是可以无限 次重复的,当然时间越久知道的人越多,0DAY就越掉价。 情况三:白帽子A挖到一个0day,并提交给软件厂商B。假设A是个真真正正的白帽子,也假 设这个0day的确也只被A发现了,但0day到了厂商B那儿,最终会找公司内负责安全的部门对漏 洞进行研究,假设这个公司内部的研究者是C,C有可能在圈子中也有其它从事黑产的朋友或是 自已本身就偷偷的在参与黑产,那么在金钱或是感情的作用下C完全有可能违背道德,写出EXP 出售或是使用。象这种情况,0day可能刚出来没几天就被补上了,或者圈子里的很多人根本就 没机会见到0day,知道有这么个东东的时候早就被补上了。 情况四:软件厂商B在代码审计或软件测试过程中发现了漏洞,自已在新版本中偷偷的补 上了漏洞,但并没有在相对老的版本中打补丁,也没有公开任何细节和公告。 研究人员A通过 补丁比较,直接定位出老版本中的漏洞位置,然后动态调试找到触发方式,并写出EXP,由于很 多情况下老版本的软件反而用户更多,所以这样的0day还是有一定的价值。 情况五:研究员A挖到了一个Nday而这个Nday以前在圈内并不为人所知,或是研究员A研究 出某Nday的新利用方式,比如说可以和某某软件结合看起来和以前的EXP完全不一样,或是成 功率有很大的提高。研究员A以较低的价格出售给中间人B。B拿到EXP后,发现圈内还没人有, 成功率各方面也还不错,于是号称0day到处叫卖。如果买家发现问题,B就装傻说自已也上当 了。现在象B这样的人其实也是不少的, 因为很多最终用户对技术并不是特别懂,而且有些 Nday测试起来也不是那么简单,如果刚好EXP效果不错,可能就忽悠过去了。那么我们能看到 的情况就是,江湖传言又出了个0day,或是某某手上有0day,但等呀等就是见不到东东,最终传 言不了了之或是被人家揭发出来。 所以要搞到0day可以自已挖,可以补丁比较,也可以分析已公开信息快速写出EXP,可以买, 也可以换,不要命也可以偷抢骗,技术手段非技术手段都是可能的。也正是因为上述情况的多 样性,所以经常有不怎么搞技术的人,手上也有些0day。 六、请问在安全圈子谁是您的偶像? 我的偶象是那种啥技术不懂,还能发大财的,不PF不行。 七、请问溢出这面红旗还能打多久? 仅仅是溢出这块,我们团队里面意见也大不相同,另外几个成员还是比较乐观的,如果比 较全面的分析这个问题,首先要看站在什么人的角度来看这个问题,是黑产工作者是安全公司 还是软件生产商。假设以黑产工作者的角度来看,那么我是非常非常悲观的,因为溢出漏洞从 技术角度上说:有一个通用性和成功率的问题,直观的说就是有一个效果的问题,再深一点说 就是经济成本的问题。往后走溢出漏洞单从个数上说还是会有很多的。但是现在从编译器和 OS(/GS、/SafeSEH、/DYNAMICBASE、DEP、PEB随机等等)到CPU(NX),软件公司和硬件厂商已 经越来越关注安全问题,几十年来溢出漏洞最关键的命脉无非是数据能够被当做代码来执行, 以前这一点基本上不被软硬件厂商所重视,这几年来人家开始重视了,开始从体系上解决这个 问题,那么这个命脉也将因为各种防范检测技术的运用被卡得越来越死,另外现在很多软件也 有自动升级功能了。 往后走是个什么样的情况,我想应该是上面提到的各种技术随着新型CPU和OS的占有率越 来越高,被越来越多的应用。一个溢出漏洞的成功率将会大大下降,再加上主流软件公司的产 品也越来越安全,以后那种一个漏洞打天下的局面将会越来越少(现在黑产工作者的网马都是 漏洞合集了,无非就是提高成功率),具体的情况也许就是现在我有一个IE的0DAY,100个人看 也许能中10-20个,以后可能手上能用的就变成某个第三方控件的0DAY,100个人看网页就能中 1-2个吧。当你使用溢出漏洞的时间,人力,金钱成本和产出完全不成正比的时候,也基本上算 溢出这面红旗倒下的时候。 估计也就三四年以后,具体指标就是上面提到的各种检测技术的普及率,至少往后的发展 不会是车到山前必有路。如果把挖溢出漏洞当成一个产业,也就是个夕阳产业。 八、您对我们杂志以及我们小组的发展有什么建议? 不走商业路线是正确的,反正你们那群人也不差钱,就不定期搞搞科普工作吧,为普及中 国安全事业做点贡献,同时也可以锻炼你们各方面的能力,继续努力! -EOF-
某类领导
在我们眼里,他们没文化,没水平,没魄力,他一无是处
但是他对上级忠诚,唯命是从,鞍前马后,忠诚得像一条哈巴狗
凭借着这种忠诚,甚至是卑贱,他总是有骨头啃,总是能明目张胆地拿着鸡毛当令箭
这种人创造的,往往都是一种非常压抑的气氛
他不停地给你找事做,他尽可能剥夺你学习时间和上进的机会,他不希望任何他能影响的人,变得比他聪明
你若反对他,他就变成狼狗,悄悄地却狠狠地咬你,咬你的时候他还装作自己也很受伤的样子
若有告状的,上级领导就会出来说:“xx其实是个好人,他也不容易,相互理解支持嘛”
年底,xx必然有各种奖状,“勤勤恳恳、大胆泼辣、敢于管理”
等到某一天,xx求我办事
这事跟他切身利益直接相关,我一手把握的,我才突然感觉他很可怜
但是,谁又来可怜我呢
山不转路转,路不转水转,水不转人转,终于转到老子手上
呵呵,不符合游戏规则的,没办法处理的,统统法办
相信你肯定可以理解我的
就像当年我可以理解你的那样
组织,是有胸怀的
每一个人,总是要有觉悟和勇气为自己的所作所为付出代价的
不能把握的东西,你还不如不去占有
1.缺乏信任
该问题源于成员大都害怕成为别人攻击的对象。大家不愿意互相敞开心扉,承认自己的缺点和弱项,导致无法建立相互信任的基础
建议准备做项目和正在做项目的都来看看,吸取一下教训。
1.过多的工作压到了同一个人身上
在很多小公司[或小项目组]里,总有那么一个核心程序员,负担了几乎所有的编程任务。这个人即使是个天才,也会被繁重的工作压的没有学习和自我提高的时间。
GameBryo拥有一套复杂的材质系统,这套材质系统可以根据渲染对象的状态和属性生成不同的shader代码,提高了渲染流程的适应性,可以使你定义一套材质能适应多种渲染对象。同时,GameByro将shader的初始化和使用插件化,方便与美术工具集成,并且实现了平台无关性。为了实现这些目的,GameByro使用了一套复杂的机制,本文主要解析GameByro如何生成、编译并使用shader代码。
GameBryo的shader的接口封装在NiShader中,顶点数据流声明,常量表的访问,渲染状态的设置都是通过这个类(有点类似于D3Deffect)。在程序运行NiShader是由NiShaderFactory负责管理的,NiShaderFactory通过NiShaderLibrary从文件中创建shader,用全局性的map管理起来。NiShaderLibrary通过解析shader文本创建NiShader对象,并调用3D图形接口编译shader代码,将这个类以dll的形式封装,就可以作为插件来使用。NiShader类的创建可以通过解析文件来进行,也可以通过C++的类来定制,只需从NiShader上继承即可。GameByro为PC平台提供了一个NiD3DXEffectShaderLib库,这个库提供了解析shader文件和初始化shader对象的功能。用户只需按GameByro定义的格式编写shader代码的语意和注释,NiD3DXEffectShaderLibrary就会根据文本来创建NiD3Dshader对象,在应用程序中就可以通过Techinqe的名称来访问这个对象。通过这种机制,我们将shader文本文件放在相关美术工具指定的目录下,在工具中就可以使用这些shader,并且能够通过shader的语意和注释为相关参数和变量生成UI,方便美术调试。
WIN平台上的整个流程如下:
1. 应用程序在启动时会先初始化整个shader系统,接下来导入Shader解析库和加载库(dll的形式)。
2. 接下来应用程序将NiD3DShader的初始化工作委托给NiShaderLibrary来处理,NiShaderLibrary首先通过NiD3DXEffectLoader载入所有的shader文本文件,并通过NiD3DXEffectParser解析文本生成NiD3DXEffectFile对象,同时NiD3DXEffectLoader还负责将shader代码编译成二进制形式的GPU程序。
3. 最后由NiD3DXEffectTechnique负责通过NiD3DXEffectFile上的信息生成NiD3Dshader对象。
4. 所有的shader对象创建后,NiShaderLibrary的初始化就结束了,最后由NiShaderFactory负责统一管理。
NiMaterial为渲染对象生成和定义Shader,NiMaterialInstance为渲染对象分配 和Cach Shader。NiFragmentMaterial提供了一个Shader Tree框架,在它的继承类中可以使用这个框架搭建shader tree。这个机制允许NiFragmentMaterial根据对象不同的渲染状态生成不同的shader代码,Cach在内存中,并保存到磁盘文件。GameByro描述符的概念大量使用,包括前面提到的Shader解析过程也是通过描述符来传递信息。在材质系统中主要使用了NiMaterialDescriptor和NiGPUProgramDescriptor这个两个类做描述符,这两个类中保存的信息是兼容的,都是为了描述某种材质在渲染对象的某一特定渲染状态下所对应的GPU程序的特征。NiFragmentMaterial通过渲染目标的状态和属性生成NiMaterialDescriptor,并通过NiMaterialDescriptor查找匹配的shader,如果找不到,则通过shader tree生成相应的shader程序,并保存到磁盘文件中。当下一次应用程序启动时就可以通过这个文件直接创建NiShader对象。可以说通过NiFragmentMaterial生成的shader代码是为特定的渲染对象在特定的情况下量身打造的。
整个过程的详细流程如下:
1. 在每次渲染一个物体之前,NiMaterialInstance会先判断这个物体的shader程序是否需要更新,如果不需要更新,就直接返回当前Cach的NiShader;如果需要更新, NiMaterialInstance首先会根据物体的渲染状态为其生成一个NiMaterialDescriptor,然后将这个NiMaterialDescriptor和当前Cach住的NiShader进行比较,如果匹配仍然返回当前Cach的NiShader,如果不匹配,将获得shader的工作转交给NiMaterial进行。
2. NiMaterial首先通过这个NiShaderFactory 查询匹配这个NiMaterialDescriptor的NiShader,如果找不到,就通过NiMaterialDescriptor生成NiShader,同时生成一段Shader代码,并保存到以shader描述符中的特征码来命名对应的shader文件。
3. 当获得相应的NiShader对象后,NiMaterialInstance会调用NiShader的SetupGeometry接口,在这个接口中会进行顶点声明。
以下是NiMaterialInstance为Geometry选择shader的代码:
NiShader* NiMaterialInstance::GetCurrentShader(NiRenderObject* pkGeometry,
const NiPropertyState* pkState,
const NiDynamicEffectState* pkEffects)
{
if (m_spMaterial)
{
bool bGetNewShader = m_eNeedsUpdate == DIRTY;
if (m_eNeedsUpdate == UNKNOWN)
bGetNewShader = pkGeometry->GetMaterialNeedsUpdateDefault();
// Check if shader is still current
if (bGetNewShader && m_spCachedShader)
{
bGetNewShader = !m_spMaterial->IsShaderCurrent(m_spCachedShader,
pkGeometry, pkState, pkEffects, m_uiMaterialExtraData);
}
// Get a new shader
if (bGetNewShader)
{
NiShader* pkNewShader = m_spMaterial->GetCurrentShader(
pkGeometry, pkState, pkEffects, m_uiMaterialExtraData);
if (pkNewShader)
{
NIASSERT(m_spCachedShader != pkNewShader);
ClearCachedShader();
m_spCachedShader = pkNewShader;
if (!pkNewShader->SetupGeometry(pkGeometry, this))
ClearCachedShader();
}
else
{
ClearCachedShader();
}
}
m_eNeedsUpdate = UNKNOWN;
}
return m_spCachedShader;
}
如果想通过NiFragmentMaterial实现自己的shader tree就需要在NiFragmentMaterial提供的接口中实现自己拼装代码的逻辑,代码块由NiMaterialLibraryNode封装,NiMaterialLibraryNode既可以直接写C++代码来定义,也可以先写成XML脚本,再由专门的解析工具转换成C++代码。
由NiStandardMaterial生成的shader代码文件如下图所示:
文件名就是NiMaterialDescriptor的掩码,用来标识的shader代码的行为。
Shader代码的行为描述如下:
Shader description:
APPLYMODE = 1
WORLDPOSITION = 0
WORLDNORMAL = 0
WORLDNBT = 0
WORLDVIEW = 0
NORMALMAPTYPE = 0
PARALLAXMAPCOUNT = 0
BASEMAPCOUNT = 1
NORMALMAPCOUNT = 0
DARKMAPCOUNT = 0
DETAILMAPCOUNT = 0
BUMPMAPCOUNT = 0
GLOSSMAPCOUNT = 0
GLOWMAPCOUNT = 0
CUSTOMMAP00COUNT = 0
CUSTOMMAP01COUNT = 0
CUSTOMMAP02COUNT = 0
CUSTOMMAP03COUNT = 0
CUSTOMMAP04COUNT = 0
DECALMAPCOUNT = 0
FOGENABLED = 0
ENVMAPTYPE = 0
PROJLIGHTMAPCOUNT = 0
PROJLIGHTMAPTYPES = 0
PROJLIGHTMAPCLIPPED = 0
PROJSHADOWMAPCOUNT = 0
PROJSHADOWMAPTYPES = 0
PROJSHADOWMAPCLIPPED = 0
PERVERTEXLIGHTING = 1
UVSETFORMAP00 = 0
UVSETFORMAP01 = 0
UVSETFORMAP02 = 0
UVSETFORMAP03 = 0
UVSETFORMAP04 = 0
UVSETFORMAP05 = 0
UVSETFORMAP06 = 0
UVSETFORMAP07 = 0
UVSETFORMAP08 = 0
UVSETFORMAP09 = 0
UVSETFORMAP10 = 0
UVSETFORMAP11 = 0
POINTLIGHTCOUNT = 0
SPOTLIGHTCOUNT = 0
DIRLIGHTCOUNT = 0
SHADOWMAPFORLIGHT = 0
SPECULAR = 1
AMBDIFFEMISSIVE = 0
LIGHTINGMODE = 1
APPLYAMBIENT = 0
BASEMAPALPHAONLY = 0
APPLYEMISSIVE = 0
SHADOWTECHNIQUE = 0
ALPHATEST = 0
NiStanderMaterial就是根据这些掩码的数据来生成shader代码,用户可以通过重载GenerateVertexShadeTree、GeneratePixelShadeTree、CreateShader这些接口来定义自己的shader生成规则。
通过前几节我们可以了解到,想定义自己的材质,一是通过编写shader代码完成。在应用程序初始化的时候,这些shader代码会被初始化成NiShader对象,进一步的通过NiShader对象来初始化NiSingleShaderMaterial对象,并分配给渲染对象。在GameByro默认的渲染流程中,这些步骤都是自动进行的,美术只需在3DMAX插件中为几何体的材质指定Shader程序,导出到nif文件,应用程序就能正确加载并渲染;二是定义自己的NiMaterialFragment类,在类中定义如何生成shader,在应用程序运行时只要将这个类的实例指派给几何体,这个类就会自动为几何体生成shader。这两种方式对于美术人员来说,主要区别在于,采用第一种方法定义的材质,其渲染数据的设置必须严格符合shader代码中所需的数据,否则就会报错。(比如说,顶点数据流必须严格符合shader程序的定义,必须为shader中每个采样器提供格式正确的纹理);而采用第二种方法定义的材质,就有很高的容错和适应性,但是这种容错性和适应性需要自己写代码来完成,GameByro提供的NiStanderMaterial就提供了这套完整的机制。每个贴图槽内的贴图如果你设置就会生成相应的贴图处理流程,如果不设置,就没有这张贴图的处理流程。
为了验证这个过程,笔者尝试增加了一个自己的shader特效——SubSurfaceScattering,简称3s,其原理是模拟光在半透明物体中散射的效果。由于该效果无须预处理过程,所有的贴图均来自磁盘文件,所以比较容易融合到GameByro工作流中。
笔者将在FX COMPOSER中调试通过的fx文件放入SDK中的SDK\Win32\Shaders\Data目录下,在3DMAX的材质面板选择GameByroShader,然后就可在显示shader的组合框中看到文件中定义的Techinqe,选择点击apply按钮,就会出现自定义的参数调整界面。
通过调整参数,最终得到皮肤和玉器的渲染效果如下:
皮肤
玉器
GameByro的这套开发流程非常方便直观,但是美术仅能为shader程序分配静态的数据源,比如说光照图等,CubeMap等;而一些在程序中实时生成的纹理数据则无法整合到美术工具中,比如说阴影图、折射图、反射图等,这些都需要程序写代码来实现。调试起来就不大方便了。大部分情况下,我们只需要使用GameByro提供的NiStanderMaterial就可以完成大部分材质的需求,特殊的效果可以自己写shader或者通过引擎提供的shader库来完成,只有当我们需要即根据复杂的情况做很多不同的处理时,我们才需要重载NiFragmentMaterial搭建自己的shader tree。不过搭建shader tree的程序一般比较复杂,编写难度大,虽然引擎允许通过XML文件来编写材质节点,但是使用起来仍然不方便。GameByro并没有提供相关的后期处理的开发工具,后期处理的特效并不能所见即所得,这方面还需完善。
GameByro为几何体在特定的环境下生成专用的shader代码,具有一定的灵活性,但是也付出了以下代价:
l 分析几何体的属性和当前状态,为其生成shader代码的过程有性能损耗。
l Shader代码生成后会保存到磁盘文件中,这个过程如果不使用异步,可能会引起阻塞。
l 生成的NiShader对象会有内存消耗。由于GameByro默认的实现是将所有的shader文件初始化成NiShader对象,所以当游戏运行的时间久了以后会生成大量的shader文件,这时候内存的消耗可能会很可观,同时加载的时间也会增加。不过可以自己控制加载的流程,在这里进行性能优化。