欣's profileAries' Matrix Ver#1.0PhotosBlogListsMore ![]() | Help |
|
Aries' Matrix Ver#1.0Daily September 12 3G通信市场前景分析 移动通信是当今全球发展最快的技术之一,从70年代末第一部模拟蜂窝移动电话的出现,到现在第二代数字移动设备的普及,以及第三代数字移动通信的快速发展,也不过20多年的时间,但其已深刻地改变了人们的生活方式,成为人们日常生活中最重要的通信方式之一,其最终目标是实现任何人可以在任何地点、任何时间与任何人进行任何方式的通信。
目前,据调查公司MCA2004年底发表的名为“全球手机市场数据2004年底版”的调查报告显示,到2004年底,全球手机用户已经达到13.5亿人,占全球人口总数的21%,同时在各种通讯方式所占有的市场份额中;GSM占71%、CDMA占14%、TDMA占7%。然而两大系统GSM和CDMA的实现技术有着本质的区别,彼此之间互不兼容,目前还不能实现全球无缝漫游通信,同时限于第二代移动通信系统所采用的技术的能力,其业务种类仍主要限于话音和低速数据(小于9.6kb/s),与目前IP技术与多媒体业务要求相距甚远,使运营商还不能提供可以满足用户要求的高速高质量的数据业务。而且伴随着移动通信市场的不断扩大,现有2G网络已不能满足工业发达国家和一部分第三世界国家(如中国、印度)大中城市手机高密度要求。
因此为了解决第二代移动通信系统的种种不足,使多种无线运行环境统一,支持多种语音和非话业务,特别是互联网业务和多媒体业务,1985年,国际电联ITU)提出了第三代移动通信系统的概念,当时称为未来公共陆地移动通信系统(FPLMTS:Future Public Land Mobile Telecommunication System),后考虑到该系统统计在2000年左右商用,且工作于2000MHz频段,故更名为国际移动通信系统IMT-2000(International MobileTelecommunications-2000)。目前,比较公认的三种第三代移动通信无线接口技术规范是:由欧洲的诺基亚和爱立信等厂商提出的WCDMA,由我国信息产业部电信科学技术研究院提出的TD-SCDMA和由美国高通公司提出的CDMA2000。
单就技术层面上来看,三种主要技术标准相对于2G时代的技术都有了很大的改进和提高,但在这个应用为王的时代,任何技术的出现及应用都离不开市场的竞争和需求的增加,3G究竟能在多长时间内商用成功,市场的需求将成为其最终命运的决裁者,成为引导3G技术发展的关键因素。
3G的应用与服务
与第二代移动通信系统替代第一代移动通信系统不同,当时由模拟转换到数字,给用户带来全新的体验和服务,技术上的差异是最主要的吸引力;而目前用户更关心的是运营商究竟能够提供怎样的服务,服务质量如何,是不是能够满足自身的需求。3G尽管代表了移动通信的领先技术,但如果不能推出更加吸引用户的服务,同样不能被用户接受。因此,能否开发出满足市场切实需求的3G业务,将成为推进3G技术成功商用的关键因素。
第三代移动通信与第二代移动通信最主要的差别是可以提供移动多媒体业务,即各种数据业务和图像业务。虽然话音业务在相当长的时期内仍是移动通信的主要业务,但随着3G的出现,因特网和移动通信网之间的相互联结更加紧密,同时手机的功能将逐步从简单的语言工具转变为数据信息终端。可以预见,移动数据业务必将是新的业务增长点。根据对现有移动数据业务的分析,未来我们提供的数据业务将主要集中在通信(如短消息、电子邮件、娱乐)、信息资讯(如综合、购物、商业、投资、定位)、实时视音频业务(如聊天、远程医疗、电话会议)和移动商务(如商品/服务采购)等方面。目前在韩国,其推出的3G服务已由早期简单的游戏和铃声发展到可以下载视频剪辑和歌曲、音乐电视、广播、肥皂剧等多媒体娱乐服务。
3G市场的国际与国内情况分析
由于3G技术可以提供令用户向往的应用服务,因此,全球的移动运营商在经历了一段低潮之后,已纷纷将3G网络的商业部署摆上近期的日程。截至今年1月,全球共有125个3G 商用网络在56个国家开通,其中WCDMA网络为45个。
目前,全球手机用户已经达到13.5亿,而到2005年1月底止,全球3G用户为15600万,其中CDMA2000 1X 用户12600万,WCDMA 用户1790万,如图1所示。虽然现在3G用户数相对来说还比较少,但其近期在世界范围内尤其是在亚洲表现出了很强的增长势头。
在日本,从2004年初开始,NTT DoCoMo的WCDMA用户出现了迅猛增长的迹象,仅半年时间,NTT DoCoMo的FOMA用户增长了50%以上,达到600万。而据最新消息,到2005年2月21日,其FOMA用户已经突破1000万大关,具体如图2所示。同时,随着其用户数的迅猛增长,其ARPU也有了很大提高,具体如图4所示。这主要得益于DoCoMo在推广3G过程中所采取的一系列积极措施,如在全国范围内不断改善其网络覆盖能力,引入新的功能更强、价格更便宜的3G手机,推出更合理的数据业务资费方式等。并且随着DoCoMo、 KDDI、Vodafone等运营商之间竞争的加剧,日本3G用户的增长势头还会继续下去,预计到2008年,在整个移动用户中所占的份额将超过25%。
同样在西欧,从2004年第二季度起,由于WCDMA 标准的网络技术和终端技术都得到了明显改善,其WCDMA 用户数也相应得到了快速发展。目前,欧洲的WCDMA 用户主要集中于和记黄埔的“3”公司。该公司2004年12月15日宣布拥有590万3G用户,其中包括意大利、英国、香港、澳大利亚、奥地利、瑞典和丹麦的用户,而数日后的12月24日,和黄董事、总经理霍建宁又宣布其全球的3G用户已达630万户,增长势头迅猛。现在除和黄外,沃达丰、德国电信、意大利电讯公司等欧洲主流移动运营商也开始加快WCDMA 网络的商用化进程,从而带动全球WCDMA移动用户数全面上扬,至2005年初,全球用户总数已达到1600万。
可见,3G不但能为广大移动用户带来生活上的便利,也必将为运营商带来巨大的市场和商业效应。但从目前国际3G商用实践看,影响3G商用进程的主要因素有经济发展水平、国家的3G政策、2G市场的发展程度、用户结构及消费习惯、运营商动机及3G制式的合理选择等。而上马3G业务的国家,如亚洲的日本、韩国,欧洲的德国、葡萄牙等,也主要集中在上述条件都已非常成熟的国家中。因此,就我国而言,目前的状况似乎并不适宜马上推3G,相比较而言,我国的3G市场还存在不足之处。
●用户的认知度低。据一项调查显示,在现有的移动用户中,除去价格因素外,愿意使用3G业务的比例为55.52%,还有更多的人对3G并不了解,而愿意使用3G的主要用户群体集中在18~35岁之间,消费能力不是很高。
●国内的2G市场还没有完全饱和,其市场利润有进一步挖掘的空间。目前,我国移动电话用户的主要需求仍然是话音业务,对宽带和数据业务的需求远没有成熟,GPRS、WAP等业务的种类和用户数偏低,发展并不理想,到2004年上半年,中国移动的数据业务在整个运营收入中的比例还不到13%,中国联通也还不到8%。
●国家对3G的政策没有完全明朗,相应的3G业务的产业链还没有形成,运营商、供应商以及业务提供商之间的步调还不一致,合作也不紧密,在利益、风险、责任三方面的关系上难以达成共识。
如上所述,目前我国发展3G还有一些问题亟需解决,但中国作为仍在继续快速增长的世界第一大移动通信市场,其未来的发展潜力还是十分巨大的。据有关方面估计,如果两三年内中国3G用户达到4000万户,3G移动终端的销售总额可能超过5000亿元,而由3G带动的相关产业可能超过1万亿美元。目前,中国的手机用户已经超过32000万户,预计到2005年底将达到40200万户。根据电信运营商预测,中国3G用户2006年将达到620万户,2008年奥运会期间将有7350万户,2010年接近2亿户。并且随着用户的持续增长,相对来说发展比较缓慢的数据业务(如GPRS业务等)也将出现快速增长,同时彩信等代表未来数据业务方向的新兴业务也将逐步打开市场,据信息产业部发布的报告显示,2004年共实现电信业务收入5205亿元,较04年同比增长12%。可见,在全球3G应用潮流的带动下,我国的3G市场引入环境正快速走向成熟而3G市场的应用前景也是一片光明。
此外,信息产业部近期已明确表示,中国将在2008年奥运会以前提供3G应用。所以现在看来,北京2008年奥运会与我国3G的发展必将是相辅相成的关系。因为有了3G的成熟应用,人们可以更及时地通过手机了解到最新赛况,欣赏到精彩赛事,2008年奥运会也将会更加成功;而奥运会所带来的巨大影响及商业利润,则会迅速提高3G业务在人们心中的地位,使3G走向成熟,且很可能成为我国从2G时代彻底走向3G时代的转折点,并随之诞生一批有国际影响力及竞争力的民族产业,如同当初韩国的汉城奥运会后造就了三星等韩国民族企业一样。但考虑到3G网络的开通需要一年时间,建网后再进行网络优化以及业务开发等,也需要半年到一年的时间,因此可以说,留给我们作出最后决定的时间已经所剩不多。据有关各方的推测,2006年将是发放3G牌照的最佳时机。这种我国通信产业就将面临着如何在现有的推出3G的环境还不是很成熟的情况下,使我国的3G产业尽快健康成长起来的问题。
因此,在我国举办奥运会之前这一段有限的时间里,我们需要在坚持我国政府部门确定发展中国3G产业的基本方针与原则的基础上,为迎接我国3G时代的到来,我们应积极从以下几个方面尽快做好充分的准备:
●积极培育现有2.5G业务市场,加大对数据增值业务的宣传和推广力度,只有让广大移动用户亲身感受到数据业务带来的好处,才能不断提高其对3G的认知度,为3G市场预热。
●打造更加完整的价值链。2G业务完全由移动运营商自己经营,而3G业务经营与2G不同,移动运营商与众多的ICP、ISP合作,共同开发用户关心的内容将是吸引用户的重要基础。
●对现有的用户群及未来的数据业务市场进行合理细分。现有的准3G业务大部分是针对年轻一族的,他们对新鲜事物敏感,而3G时代用户的年龄层次将更加丰富,因此,我们需要通过对用户及市场的细分,为不同层次的用户提供相应的业务,以使利润最大化。
●尽快对3G产业的相关政策法规进行完善,以净化电信增值业务投资环境,调动投资商的积极性,从而为广大用户提供更多更好的增值业务。
●调整现有业务资费标准,使其更加合理化、大众化,降低3G业务的使用门槛,这样才能适应严酷的市场竞争环境,迅速扩大用户群,加快业务的推广速度。 总之,我国在建设3G网络的态度上既不能盲目快进而成为国外运营商和设备商的3G试验场,也不能一味求稳而错过引入3G的最佳时机,这样才能充分利用我国潜力巨大的3G业务市场,不但培育出一批具有国际竞争力的民族企业,提高我国通信行业的国际竞争力,同时也使我国在世界通信的格局中占据重要的位置,尽早从“通信大国”转变成为一个真正的“通信强国”。(来源:泰尔网)
September 11 我们仍在向前走 拖了近4个月之后,我们的makee终于完成了改版。还是很欣喜。
这些天忙于修改大大小小的bug和内容。以前每有朋友问,你们的网站怎么样了,我都会说:在改版。而现在则说:新版刚刚上线,就要推广了。事情总是在进步,但总是比预期的要来得难一点点,在这里很有体会,这种感觉似乎跟自己的性格很有关系。
记得当时选择创业的时候抉择了好久,最后还是认真选择了志趣相投的朋友和事业。说明自己还是不甘于平凡的,自然也要一直往前走下去,这也变成了一种信仰罢。
对了,搬北京来了,人在通州。哥们们来了没事的可以找我哈,包吃包住。
前一阵去了798,确认北京的文化氛围确实比天津好很多,互联网也是如此。
如此这算是一个重要的里程杯,记录一下以兹勉励。
2007.8.1 迁都北京
2007.9.1 新版上线公测 北京星光剧场演唱会之--与非门,雨飞门。前天搬到北京,一直忙来忙去的收拾屋子,购置物资。住在通州,不算北京市区,但交通还是蛮方便的。不过到繁华地带还是要1hour左右。今晚第一次进城!和久违的哥们们一起听听音。
下了地铁便是暴雨滂沱,一路小跑冲进糖果的星光剧场。淋湿。
知道与非门的同志们显然很少,因为不是很大的剧场并没有把人装满,还是因为暴雨-_-?
女主唱长得不算很漂亮,因为据说原来是再酒吧游唱的,不能长的太漂亮。
与非门不能算是个堂堂正正的摇滚,但他们自己说有metalic的味道。呵呵。
与非门的fans们显然是跳不起来的知识分子,任凭主音怎样召唤,一齐拍掌的还是稀稀落落的。
不过评价一场演唱会,显然不是看地下的热闹程度,我觉得现场还是满爽的,最后一首乐园,挺好,唱的心里的感觉。
回来的路上,脑袋里还飘着女主唱缥缈的声音,呵呵。
可惜没有啤酒 。
明天上照片和视频。
happy birthday ,ivy.
-2007.8.1 Beijing China July 09 毕业了~。凤凰花开的路口。
===================================================================
===================================================================
===================================================================
===================================================================
又到凤凰花朵开放的时候 想起某个好久不见老朋友 记忆跟着感觉慢慢变鲜活 染红的山坡道别的路口 青春带走了什么留下了什么 剩一片感动在心窝 时光的河入海流终於我们分头走 没有哪个港口是永远的停留 脑海之中有一个凤凰花开的路口 有我最珍惜的朋友 也许值得纪念的事情不多 至少还有这段回忆够深刻 是否远方的你有同样感受 成长的坎坷分享的片刻 当我又再次唱起你写下的歌 彷佛又回到那时候 时光的河入海流终於我们分头走 没有哪个港口是永远的停留 脑海之中有一个凤凰花开的路口 有我最珍惜的朋友 几度花开花落有时快乐有时落寞 很欣慰生命某段时刻曾一起渡过 给我最珍惜的朋友 June 29 人类的一些发明阻碍了人类的进化?一日在厕所中大号,忘带读物,于是开始意淫~
忽然觉得人类的一些发明阻碍了人类的进化呢~~~~~
你说 如果手机不被发明,说不准经过几百万年后,人类就会脑电波心灵感应了~~是吧?
其他东西也一样。
国际政府组织应该有意识的组织一些阻碍人类进化的发明出现,嗯。 February 03 亚马逊:摒弃商店?商业周刊 Technology频道 2007年2月2日 12:00 AM EST
原文:Amazon:Give away the store?
我的译文如下:
亚马逊:摒弃商店?
亚马逊(AMZN)刚刚度过了一个丰收的假日购物季节。作为电子商务巨头,亚马逊在上个季度财务报告中显示有39.9亿美金的收入,达到34%的增长率,超过了估计的37.7亿美金。但是比预期要好的第四季度却不足以使那些分析师和投资商满意,使以后的日子更具挑战性。
亚马逊的股票曾以2.7%的日增展速度涨停在38.70美元。但是在紧接下来的二月交易额已经微跌。反映着投资商和分析师所关注的亚马逊的利润的收入公告,将成为公司的一个更大的开销。 利润被挤压 第四季度的毛利率表明近五年来最低的增长,这使许多分析师都大跌眼镜。在2006年的最后三个月,净收入从1.99亿美元,每股47美分,下降到0.98亿美元,每股23美分。整年的运营收入是3.89亿美元,比2005年的4.32亿美元降低了10%。亚马逊的总裁把下降归结于增加在技术和内容上的投入,以吸引更多的客户在网站上开店。 令人失望的增长幅度继续着这个趋势。去年第四季度,公司利润下降了37%(参见businessweek.com, 10/25/06, "Amazon Turns in a Smart Third Quarter")。 在电话中,亚马逊首席财政官Tom Szkutak先生对分析师们过分关注于下降幅度提出了声明。他提到,亚马逊一直专注于网站本身,低价来吸引消费者,引进新产品种类。“即使你们看到毛利率的下降,但这些新的产品种类确实对我们很重要”Szkutak说。 一些分析师指出,无论怎样,利率下降的压力是一个警告,亚马逊需要提供更好的交易来吸引买家。分析师Tim Boyd,指出公司利润的下降证明了在他的文章中提到的公司处于劣势。“对于这些人可以带来巨大的顶线增长是毫无疑问的”Boyd说,“但是最终确实下降到了底线,而且不仅仅是底线那里”。 运费之痛 Boyd将利润的压力归咎于免运费和低价。公司鼓励更多的人在网站开店和吸引更多的消费者在新的种类搜索商品。在2006的下半年,公司推出了“超级省钱运输方案”,该方案提供免费航运和对于选定物品的更长等待。比2005年2月提出的“亚马逊优惠方案”要开放更多的免运费商品,它给那些愿意交付79美元年费的用户提供2天免运费,3.99美元美国区域通宵运输。 在新闻发布会之前的电话中,亚马逊创始人兼首席执行官Jeff Bezos表示面运费将导致更多的开销。“亚马逊的会员花费的更多来支持我们提供的更多商品种类,同时他们可以从无限的免费两天运输中获得好处。” 亚马逊对于新产品种类的投资也增加了零售商的开销。公司在10月推出了一种新的汽车零配件的商店。鞋,手包等商店一经开始便一发不可收拾,同时也要提供免费的通宵运送,但回报期很长。在Toys’R’Us分开之后,公司同时也被迫开始了玩具和婴儿商店。虽然新的产品种类对销售有很大帮助,但是亚马逊必须在技术上投入更多以能适应更多的产品种类,同时在人力上投入更多来吸引新的供应商,同时花费更多的钱在如免运费之类的交易商来吸引更多人来消费新产品。 目前,另一个因素也在干扰着亚马逊在电子商务市场的竞争增长。比如,google已经开始成为许多网络消费者开始网站浏览如亚马逊之类的网站的第一步(参见businessweek.com, 11/13/06, "Jeff Bezos' Risky Bet")。 降低的增长 高盛(Goldman Sachs GS)的分析师Anthony Noto在给投资商的纪录中提到,他相信亚马逊的降低的利润在明年很有可能不会有明显的进步。“我们一直相信,公司会要求继续投资,用于在Amazon.com驱动销售和创建新的品牌”,Noto写道。 Szkutak说他预计亚马逊在2007年第一季度的收入将增展25%以上,落在28.5亿美元和30亿美元之间。亚马逊的运营收入,预计将是在0.82亿美元和1.22亿美元的浮动之间,比2006年第一季度的22%下降到16%。2007全年,公司总的运营收入预计将会在3.55亿美元到5.05亿美元之间,也就是9%的降幅或30%的增长之间。对于这些预计分析师们并不表示很认同,Noto在他的文章中写道:“我们对财务预计持怀疑,由于亚马逊目前所在的利润低谷,对亚马逊在2007年达到两位数的利润增长不太看好。” 不管公司的销售额有多少,下一个利润的降低仍然使分析师们不太看好。“他们巨大的收入增长,伴随着利润的持续下降,让我更加肯定了这一点”Boyd说。
February 02 “你们那个网站怎么样了?”每当别人问起这句话的时候,心里总是有种奇怪的感觉,像是在给别人解释,像是在给自己安慰。
其实最近工作效率不是很高,也许是前一阶段忙过头了;也许就像是习惯了一种东西,就不会再去认真关心。总之是一种学习和工作中迷茫的状态,像是敢问路在何方。
又是到2、3点,但这回时间感觉是耗过去的,心里很不舒服。
记得在刚开始的时候,我们每个人都写下过一句话,打印出来,贴在墙上,供来警醒。我记得是这么写的:“我们都在用生命中最宝贵的时间来作我们的事业,既然选择了,就一直做下去,直到有一个结果。” 我想,如果想要这段路是一个美好的结果的话,we have to fight。
lanslot在为我们的情人节活动做着宣传网页。刚刚看了他更新的blog,刚发的,也是一片醒人的文章。
我们的状态似乎有些像我们网站的流量波动曲线,现在在波谷处,就要上升。
睡觉了,明日早起,明日工作。
January 24 北京之行#1身边有人的时候总是不觉得闷,即使是每天很一致的生活。
被lanslot外派到北京和那边的软件公司一起开发需求。
公司在昌平,地广人稀,离市区坐城铁要1个多小时。
现在每天竟然7点多就起床,靠~都好几年没过过这样健康的生活了,赫赫。
上不了网,我发现我没有了互联网就是一个生活极为空虚的人,基本上就没有什么了。
抱着一个20g硬盘的老式ibm来回跑,里面就装了一部《银发的阿吉多》,翻来复去的看了n遍,每次都是不同的感悟。
北京的朋友都回天津,一个都找不到,我都服了,怀疑是集体阴谋T_T。
ivy建议我买一套《哈里坡特》,说是一天看一本正好一周看完,绝对受益匪浅。但是不幸的是,我发现这里竟然没有书店-_-
皑皑,忍了,百忍成金。
发现人一旦生活在平凡中,一点小小的事情都能引起内心的波澜。
现在和软件公司的一个女职员和一个男职员住在一起,发现软件公司的人真的是闷得可以了,晚上抱着电视竟然能看2,3个小时,不带换台的>_<。和他们聊天的时候发现,其实生活真的有些像围城,工作了的时候看到的是工作的乏味,想回到学校,学校的丰富多彩,学校的纯洁;在学校的时候却一直想出来,看看外面是什么样子的,出来了,就发现回不去了,剩下的只有围城的想望。
所以得出了一个结论,工作,就一定要和自己和的来的人,一起做自己喜欢的事业!makee together。 January 07 [转载] 说说大型高并发高负载网站的系统架构转载自:Just Do IT (http://www.toplee.com) lee@toplee.com 我在Cernet做过拨号接入平台的搭建,而后在Yahoo3721负载搜索引擎前端平台开发,又在猫扑处理过大型社区猫扑大杂烩的架构升级等工作,同时自己接触和开发过不少大中型网站的模块,因此在大型网站应对高负载和并发的解决方案上有一些积累和经验,可以和大家一起探讨一下。 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的。 大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。 上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。 1、HTML静态化 其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。 除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。 同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。 2、图片服务器分离 大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。 3、数据库集群和库表散列 大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。 在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。 上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。 4、缓存 缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。 网站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多了,.net不是很熟悉,相信也肯定有。 5、镜像 镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。 6、负载均衡 负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。 负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。 硬件四层交换 第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。 在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。 软件四层交换 大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。 软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。 一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。 对于大型网站来说,前面提到的每个方法可能都会被同时使用到,我这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。 WEB3D介绍 虚拟展示技术,通常被用于商品网络化三维展示,也有部分小场景虚拟仿真项目采用WEB3D进行制作3D图形技术并不是一个新话题,它在图形工作站以至于PC上的应用早已瓜熟蒂落。然而互联网的出现,却给3D图形技术注入了新的活力,一些微妙而深刻的变化正在进行中。“web3d”这一新词的出现就反映了这种变化的全貌。没有人严格定义web3d,但我们可以把它理解为互联网上的3D图形技术。
VRML是3D图形和多媒体技术通用的交换文件的格式,它描述交互式的3D对象和场景的几何对象的尺寸和形状、色彩、材质、灯光、动画及其交互性。它不仅应用在互联网上,也可以用在本地客户系统中,其应用范围极广。国际上有一个VRML(VRML Consortium)协会,承担起了制定互联网上的3D图形标准与规范的任务。1996年,VRML 1.0发布,1997年,VRML 97诞生。VRML 97的重大革新是:在网络上传输的是模型文件,而不是视频图像文件,故其传输量大大减小,可使任何一个3D图形爱好者都能制作可在互联网上实时渲染的3D场景模型。
然而,在1997年之后,VRML在3D图形标准上的进展缓慢,远远没有达到人们的期望。究其原因主要有:
● 互联网对3D图形的需求并不迫切,到目前为止,2D图像仍在HTML文件中占主导地位。
● 网络带宽仍然是制约网上3D图形发展的主要瓶颈。 ● VRML 97过于庞大,它几乎包罗万象。 ● 网站的访问者必须先花费10~15分钟的时间下载插件,然后再像安装软件那样安装这个插件,才能观看一个十分粗糙的3D图形。 产品群雄割据 用户苦不堪言
由于VRML协会没有及时推出VRML 97的下一代标准,因此很多互联网3D图形的制作软件并没有完全遵循VRML 97标准,许多公司推出了自己的制作工具,使用专用的文件格式和浏览器插件。类似的软件大约有30种之多。这些软件各有特色,在渲染速度、图像质量、造型技术、交互性以及数据的压缩与优化上都有胜过VRML之处。所有的公司都希望自己的解决方案能成为“事实上的国际标准”。
然而用户却不领它们的情。对用户而言,要在互联网上观看用这些软件制作的3D图形,先要下载1M~7MB的插件,然后安装在网页浏览器上。插件的种类之多,使人无所适从。要观看十个不同的网站,用户就需要下载并安装十个不同厂家的插件。这样烦琐的事情用户实在难以忍受。 为什么需要插件?
3D图形软件为什么离不开插件?其实插件就是实时渲染引擎,其作用是:解释并翻译实施场景模型文件的语法,实时渲染从服务器端传来的场景模型文件,在网页访问者的客户端逐帧、实时地显示3D图形。把实时渲染引擎做成一个插件,这是互联网3D图形软件厂商目前的通常做法。显然,实时渲染引擎是实施互联网3D图形的关键技术,它的文件大小、图形渲染质量、渲染速度以及它所能提供的交互性都直接反映了其解决方案的优劣。
研制更好的实时渲染引擎是各软件厂商竞争的焦点,于是就产生了五花八门的3D图形文件格式与相应的浏览器插件。
结束这种混乱局面的最好办法是微软在其IE浏览器中预装一个或几个实时渲染插件,这样用户就不必花费十多分钟的时间去下载和安装插件。然而,微软并未选中任何一家公司作为其合作伙伴,也许有一天微软会推出自己的一整套解决方案,从而保持它在互联网3D图形领域中的霸主地位。
新一代互联网3D图形 标准X3D诞生
1997年,VRML协会改名为web3d(Web 3D Consortium),此后web3d这一专用缩写开始在互联网上出现。2001年8月,web3d协会发布了新一代国际标准——X3D (X3D的含义是可扩展的 3D)。
X3D得到了许多软件厂商的支持,包括3Dlabs、ATI Technologies、Blaxxun、Nexternet、OpenWorlds、ParallelGraphics、Sony Electronics、US Army STRICOM、SGDL Systems等。X3D与MPEG-4和 XML兼容,并将集成到MPEG-4的3D内容之中,使用XML语法。它与VRML 97向后兼容,即X3D能提供标准VRML 97 browser的全部功能。X3D的主要任务是把VRML的功能封装到一个轻型的、可扩展的核心之中。由于X3D是可扩展的,因此任何一个开发者都可以根据自己的需求,扩展其功能。X3D渲染引擎的商业版本也在去年的SIGGRAPH ’2001的年会上推出,Parallel Graphics(web3d技术的领先软件公司)将联合几个公司开发X3D 新技术。 X3D标准为互联网3D图形的发展提供了一个广阔的发展前景,无论是小型的具有3D功能的web客户端应用,还是高性能的广播级应用,X3D都应该是大家共同遵守的一个标准,从而结束当前互联网3D图形的这种混乱局面,在统一的X3D基本框架下保证不同软件厂家开发的软件具有互操作性。
采用Java,3D图形渲染不需要插件
Java在互联网上几乎随处可见,而它在3D图形上正在显示出更大的威力。使用Java 的重要理由之一是它的平台无关性。它的平台无关性来自于Java只需部分编译。负责编译Java程序的是Java Virtual Machine (JVM),不同的平台有它自己的JVM,处理与平台相关的功能。因此,只要支持JVM,就能运行Java小程序。两种最有名的浏览器Netscape 和 IE都支持JVM。因此用Java制作的3D图形几乎可以在所有的互联网浏览器上显示。
Shout Interactive和Blaxxun两个公司使用纯Java技术开发了实时渲染引擎(大小只有50K),这个小小的Java小程序,不仅在网上自动下载,而且可以在客户端实时渲染3D场景,逐帧显示动态的3D图像。Shout Interactive和Blaxxun为用户扩充自己的3D图形功能预留了极大的空间。两个公司并没有抛弃VRML,Shout Interactive公司可以接受VRML文件,并把它变成自己的文件格式;Blaxxun公司的软件可以直接运行VRML。当然,Shout Interactive 3D的小巧灵活并不是没有代价的:它简化了VRML的功能,VRML的一些功能不能用小小50K的Java来实现。可以说这两个公司最先在它们的产品中实现了核心的X3D技术。
使用这种“无插件技术”(plug-in)的Shout Interactive公司为Macy’s and Excite web portal网站制作了栩栩如生的3D虚拟时装模特展示。而所有的展示文件只有1M~2MB,不需下载插件,且图像的质量较好,人物动画的动作流畅自然。
X3D能否成为事实上的web3d图形标准?
Flash之所以能作为2D动画在互联网上的标准,关键是只有惟一的技术和标准。而现在的web3d图形有几十种可供选择的技术和解决方案,多种文件格式和渲染引擎的存在是web3d图形在互联网上应用的最大障碍,而这种局面在今后若干年还将存在。从现在的发展态势来看,有几种技术可能在未来占有一定的优势:
● X3D: 由Web 3D Consortium制定,得到大学、政府机构及一些web3d图形公司的支持,有比较广泛的社会基础。
● Pulse3D: 在游戏娱乐领域内领先,使用该技术的游戏网站有100多个,它得到了Discreet和Entertaindom公司的资金支持,现在它正在把游戏领域的技术优势应用到e-commerce。它的插件支持QuickTime 5和RealPlayer。
● Viewpoint: 前身是MetaCreations(3D图形应用软件开发商),它卖掉了其他所有的软件产品后,改名为Viewpoint,并专们从事web3d图形技术的研发。其渲染引擎的模块化结构极易扩充,并且能与QTVR-、iPix-和XML-等标准集成。它的目标是e-commerce。该技术的最大特色是与XML集成。
● Cult3D: 开发了e-commerce的全套解决方案,已经有450个e-commerce网站使用了 Cult3D技术,有近1万个商业模型。它也在向娱乐领域扩充,提供全面解决方案,同时提供最稳定可靠的渲染引擎。
● Shockwave3D: 这是Macromedia公司的Flash插件,有着极为广大的用户群(据说世界上有1.3亿人安装),更引人注目的是Intel把它的web3d图形集成到Shockwave中。Intel web3d的图形极具特色:动态调节3D内容的分辨率,采用了曲面光滑技术和照片级逼真材质,并可制作各种特色效应。 January 05 风险资本的退出机制分析风险资本退出的四种方式 (一)股份上市(IPO) 对于风险投资者而言,要利用IPO进行退出,就必须作大量的准备工作。一般都要提前几年就开始将公司的财务、发展战略等信息向外公布,以使广大投资者能充分了解公司的真实经营状况,以期得到积极的评价,吸引更多的投资者,避免由于信息不对称而使公司股票在IPO时被过份低估,从而使风险投资者蒙受不必要的损失。IPO的手续一般也比较繁琐,还要涉及会计、法律、中介等相关费用,因此成本较高。但一旦上市成功,就会给企业和风险投资者带来回报,因此广受青睐。同时,风险投资者在为IPO进行前期准备中已大大缓解了市场的信息不对称问题,这可能会吸引一些兼并收购方,从而使风险投资者可以在权衡利弊后为自己选择一种最佳的退出方式。另外,IPO并不会影响管理层对公司的控制,因此,它还得到了管理层的欢迎和支持,这使风险投资者的退出更为顺当。 值得注意的是,为防范金融风险和增强投资者信心,EASDAQ为上市公司专门规定了锁定条款(Lock upagree ment),它要求风险投资者(被视为内幕人)必须保留一定数额的投资,只有等到该股份可自由交易后(通常两年),才能将剩余股份全部出售,实现完全的退出。风险投资者保留的股份虽然可使其能分享公司将来增长的成果,但也蕴含着收益无法实现或被推迟实现的巨大风险。因此,欧洲的不少风险投资者对IPO能否作为一种真正的退出方式持怀疑态度。总的来说,IPO方式是一种高成本的回报,对风险投资双方都最为有利的一种退出方式。但是,对不少小型企业来说,IPO可能还只是一种不切实际的选择。因此,现实中欧洲风险投资者更多的还是通过出售方式进行退出的。 (二)出售(Trade Sale) 相对IPO方式而言,出售有它自己的优势。首先,由于收购方可通过兼并获取协同效应、扩大市场份额或进入新市场,风险投资者通常可要求其支付收购溢价,从而可提高自身的回报率;其次,出售可使风险投资者实现一次性完全退出,剩余风险很小或几乎没有;第三,出售的费用成本也低于IPO方式,它面临的谈判对手只是少数几个买方,而不是整个市场,因此也比IPO简便快捷;第四,它适用于各种类型和规模的公司,对于一些小公司还可能是唯一可行的选择。 但在实践中,出售方式也表现出两大缺陷:一个是它往往受到管理层的反对;另一个是它常常难以找到买方,价格也不尽合理。前者主要是由于管理层担心企业被大公司收购后失去其独立性,影响管理层对公司的控制。这一问题通常是通过对管理者做出激励安排来协调的,这些安排包括了以下主要措施:(1)将收购价格的一定比例支付给管理层;(2)给予管理层部分股权或股票期权;(3)离职薪酬与红利安排等。这些激励安排为管理层在购并活动后的权益提供了部分保障,并使其站在投资人的角度来考虑问题。这些实际上是购并双方为实现其目标而对管理层进行的一种利益让渡。同时,“第二期购并”也是避免这一冲突的一种选择。对于第二个问题,其根源仍是信息的不对称性。针对这一问题,风险投资者只有通过自身的努力或中介机构的帮助,运用各种营销渠道和技术加强信息的传递,放开眼界,吸引更多的潜在购买者。 (三)回购(Buy back) 除了上述两种主要的退出途径外,回购也占有重要的地位。这里的回购指的是股份回购,即企业管理层或其它合伙人以现金、票据等有价证券买断风险投资者手中持有企业股份,从而使风险投资者实现投资收益的一种退出方式。当企业业绩较差,或者管理层不同意将公司股份转让给第三方时,回购应该是一种可行选择。 目前,欧洲越来越多的风险投资者已经认识到了股份回购作为一种退出方式的重要性,事实上也有不少案例采用了这种方式。但是,许多风险投资者在考虑回购时仍有不少顾虑。因为它往往要求在风险资本投资于企业之初就签订回购协议,而如果到期时企业经营得更好,回购协议就会限制风险投资者获取更高的收益。这也是股份回购不太吸引欧洲风险投资者的主要原因所在。因此,选择回购往往只是一种不得已的被动选择。 (四)清理公司(Write off) 风险投资是一种高收益高风险的投资方式,部分或完全的失败在风险投资业是很普遍的。当风险投资者意识到所投资企业确已无发展前途或无法达到预期收益时,唯一能够做的就是果断地抽身而退,即清理公司。否则,让一无前途的项目占用风险投资者的大量资金是很不划算的,还不如让退出的资金进入下一个投资循环,以谋取高回报。以清算方式退出虽然是痛苦的,但这却是避免更大损失的权宜之计。因此,及时有效地清理失败项目也是风险资本退出的重要方式。 以上是欧洲风险资本实际采用的几种主要退出方式。事实上,从欧洲风险资本发展的实践来看,退出这一环节存在相当多的问题。这些问题或困难有相当部分是外部客观环境造成的,如市场(包括货币市场、资本市场、产权交易市场等)不完善等,政府扶持与监管不力,法律法规不完备等。这些是作为市场主体的风险投资者不能规避的,只能通过宏观环境的改善来逐步得到改进。还有相当多的问题来自风险投资者自身,即内部因素,它是可以通过投资者观念的更新和不断的努力得到克服的。以下,我们将就欧洲风险投资者在实践中遇到的主要问题作一些分析。值得说明的是,强调内部因素,并不是因为宏观环境不重要,而事实上宏观环境在风险资本的发展中,特别是在发展中国家具有举足轻重的作用。但是,对于同样年轻、缺乏经验的中国风险投资者来说,吸取已有的经验同样具有重要的意义。 January 02 上海归来 上海的天气真的不算很好,虽然有很高的天和云,还有很高的楼。但是没有暖气的城市永远不会给人那种温暖如家的感觉。因为奔波一天后回到旅馆的被子里还是那种潮湿的冷。
12.29 中国互联网天使投资年会,这个投资会本身远没有它的名字来得霸气,重量级的天使投资人如方兴东,周鸿祎,刘晓人等均未出席不说,剩下的一些林林总总的投资机构也是大都蘸一下就走人了,会场十分混乱,项目露演也是差强人意,交流时间没跑成的投资人就被一大堆项目围住一脸的无奈与应接不暇。
谈到收获还是有一些的,除了收了一大圈投资商的名片之外,还和戈壁的徐晨约到星巴克,谈得还成,他提出了一些投资计划的问题,我们回来后这几天的工作大体有了规划。还有一些投资商在收到我们的投资计划后表示出兴趣。这些其实在创业的过程中还是蛮激励的。
记得几个月前在我们什么也没有的时候,投资商都不会吊人的。其实创业真的是实实在在的事情,只有拥有一定基础和对这个行业深入了解的时候自然才会有更多的关注和合作。
总结一句话:革命尚未成功,同志仍需努力。
---------------------------------
闲白:
发现自己还是不适合出门,明显的水土不服,又感冒又便秘的,在火车上来来回回难受死还睡不着。
回来的时候还碰到了一个南开的师姐,9X级企管硕士,据说在一家意大利合资公司卖f1轮胎的,分开的时候还送了一些奇怪的核桃给我们,在外面遇到南开的人感觉真的很亲切。
在上海没来得及娱乐,真的白瞎了,皑皑。
回来的时候发现天津下雪了,以前我对雪总是会有一些特别的感觉和期待,可惜物逝人非,人走茶凉。
又到考研时,虽然自己没有机会考研了,却也完完整整地经历过一回,过程的艰辛和收获欣喜都感同身受。再bless那些考研的人们吧,祝你们成功。
---------------------------------
停止回忆料,回忆像漩涡。
2007-1-2 Aries December 22 第二次对跑步有感觉 第一次对跑步有感觉是准备马拉松的那段时间,觉得跑步是一种生活的状态,积极向上。
最近的生活,是创业的状态,每天睡觉、吃饭、工作、思考、学习。但是效率不高。
自己分析自己属于运动型的神经,思维敏捷性和思维发散性都和生活的状态非常相关。
第二次对跑步有感觉,是因为今天。
之前一直有运动的冲动,跑步,羽毛球,足球,whatever。但是没有催化剂,或者说没有这个环境(因为住一起的朋友在这方面都比较懒-_-)。其实在有些事情不能确定,或者有一方面的一定的想法的时候,需要有人来支持,或者有人来帮助你做这个决定,有时自己应该做这个人(又跑题了)。今天就是如此,耀林来了,一拍即合,换上衣服就出门。
有时跑步是为锻炼身体,有时是为磨练意志,这次可以算是思考生活和享受朋友的交流。
跑步时聊天,虽然不是跑步的状态,但是running时思维和交流的直接性和深入性是我以前没有体会过的。跑的时候精神是活跃的,聊天自然也是很high。锻炼身体,思考生活,分享经历,it's a great thing。
耀林算是很可交的朋友,Do work,do entertainment,do exersice,do thinking,when I am with him,I can feel these four things,feel good in other words。
现在的生活,需要外部事件的刺激,才能保持活跃的精神状态,才能使工作和思考更有效率,至少我是这种人。
keep running!
December 18 一通歪歪引发的赌注互联网中 ip地址的难于记忆,导致产生了网址域名的出现,便于管理和规划。
域名服务商却在无形中赚了大把的money,一个好些的域名搞不好要几十w dollar。
那么手机中 手机号是否也会发展为这种形式?
在一通唧唧歪歪的争论之后,我和Lanslot同学打这个赌,期限是十年,请鉴证。 从此选择记下如果历史不被记录,那么历史就不会被复制,流传。
记得在微软夏令营的时候,曾经和微软的职业资深讲师华宏伟先生交流过毕业选择的问题,就业,研究生,或是创业。
他说,你肯定会从创业的过程中学到很多,即使是失败,那段经历也是一笔宝贵的财富。
>>跑题:微软的夏令营的回忆,很丰富。感受很多:微软的文化,如微软般的外企让我很向往;收获很多,全国各地的朋友们,树立信心、改变心态的决心;开始很多,makee创业的决定,一段难以解释的感情。跑题毕<<
这段创业到现在,不算成功。但真的有所感悟,有所体会,有所收获,所以要记下这段成长的过程。罗马不是一天建成的,成长也在于一点一滴的积累,以后拾起,也会颇有感怀。作为行为的准则。
1。决策。当断不断,非丈夫也。大大小小的决策是人生的主题,和朋友们一起作事业,白手起家,一切都变成自己决定,宝贵的时间不能浪费在犹犹豫豫。理性的分析平衡利弊,然后决定。不为自己作的任何一个决定后悔。
2。团队。其实人生最得意的便是和志向相投的朋友一起做自己的事业,互联网/朋友都在,珍惜每一分钟,珍惜一起走过。
从耀林对凯磊的态度,自己有个感觉:无论内部矛盾如何,但对待外部事件,无论是投资商或是员工或是客户,一定还要是一个team,事情才会不会更糟,矛盾才不会激化,外部才会有信心。Remember when we are a team , we are a team。闭上门,再自己解决事情。
3。执行。事情要做,不能光靠想。when something decided,well planed.do it.
其实有时思考是一种逃避,是对自己信心的不足,逃避是不会成长的,对于一定要有个结果的事情,想不通的话 做就是了,等待只会带来时间的流失,只会让自己变得更被动;而去做才会有结果和收获,无论是成功还是失败的经验。
4。激励。不断的激励也是其他人去做事情的一种动力,Lanslot有时会拿一些宏伟规划美好未来来激励,虽然很远的事情而且not easy。但是至少对我还是很受用。因为,那是种希望和信心。
5。效率。工作繁琐,工作效率便变得尤为重要。plan和按照plan执行是一种简单有效的工作效率提高的方法。能分清重要的事情和紧急的事情,是使计划不被打乱,保证质量的很好的方法。参见《效率黄金法则》。
6。认清自己。自己的特点,自己的优点,自己还差什么需要学习锻炼,自己要摒除的一些东西,自己想要的是什么。很好的认清自己才能走得更好。我是一个混合型的倾向,作为技术,比技术的人要多一些商业思想和待人处事之道,作为商业,比商业的人多些技术背景;自己的优点是fastlearning;除了上面说的12345,自信心和很好的表达能力是自己需要锻炼的地方;自己要摒除的是懒惰和一些小人思想。
今天先想到这些,宏观的准则。
以后每天有的收获,每天思维上的成长,要写在这里。
和微软技术一起成长,呵呵。
July 31 常用正则表达式写在前面: 正则表达式用于字符串处理、表单验证等场合,实用高效。但用到时总是不太把握,以致往往要查证一番。现将一些常用的表达式收集于此,以备不时之需。本贴随时会更新 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空白行的正则表达式:\n\s*\r 匹配HTML标记的正则表达式:< (\S*?)[^>]*>.*?|< .*? /> 匹配首尾空白字符的正则表达式:^\s*|\s*$ 匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 匹配网址URL的正则表达式:[a-zA-z]+://[^\s]* 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7} 匹配腾讯QQ号:[1-9][0-9]{4,} 匹配中国邮政编码:[1-9]\d{5}(?!\d) 匹配身份证:\d{15}|\d{18} 匹配ip地址:\d+\.\d+\.\d+\.\d+ 匹配特定数字: 匹配特定字符串: January 19 Direct3D9学习笔记--画一个圆锥画一个圆锥 为了便于读者理解,本节及后续章节的例程均不使用索引缓存,因此我们将在第4节例程的基础上进行修改。不过在输入下列代码之前,请先参照第5节的示例,打开Z缓存。 1 建模 圆锥由一个曲面和一个底面构成,如图21所示,用两个图元构建实体比较合理,其中每个图元各代表一个面。考虑到圆锥曲面展开后为一个扇面,所以图元格式采用三角扇形,而底面是一个圆,也采用三角扇形,取圆锥外表面做图元的正面。在图21中,A为圆锥的顶点,B为底面的圆心,把底面分成30等份,得到30个分割点C1、C2 ... ... C30,则圆锥曲面的图元所对应的顶点序列为A、C1、C2 ... ... C30、C1,共32个顶点,注意在结尾处C1点重复出现了一次,否则画出的圆锥不完整。同理底面也由32个顶点组成,依次为B、C1、C30、C29 ... ... C1。 (图21,见文章末尾) 设圆锥高为2,底面半径为1,以圆锥中心线AB(图中的蓝线)做X轴,坐标原点设在AB中点,A的坐标为(-1,0,0),则B的坐标为(1,0,0),C1至C30的坐标为(1,sinθk,cosθk)。 由于使用灯光照明,还需要提供顶点法线:对于圆锥曲面,A的顶点法线取X轴的负方向,即矢量{-1,0,0},C1至C30的顶点法线取有向线段BCk,矢量为{0,sinθk,sinθk};对于圆锥底面,顶点法线都设为X轴的正方向,矢量为{1,0,0}。请注意,在Direct3D中,要求顶点法线为单位矢量。 现在开始输入代码,首先定义两个图元的FVF,因为使用灯光渲染,顶点颜色不再需要,新的FVF包括坐标和顶点法线: (D3DWnd.cpp) ... ... #include "D3DWnd.h" //圆锥曲面的FVF格式:坐标、顶点法线 struct CUSTOMVERTEX1 { D3DXVECTOR3 position; //顶点坐标 D3DXVECTOR3 normal; //顶点法线 }; #define D3DFVF_CUSTOMVERTEX1 (D3DFVF_XYZ | D3DFVF_NORMAL) //圆锥底面的FVF格式:坐标、顶点法线 struct CUSTOMVERTEX2 { D3DXVECTOR3 position; //顶点坐标 D3DXVECTOR3 normal; //顶点法线 }; #define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZ | D3DFVF_NORMAL) ... ... 为CD3DWnd增加两个数据成员m_pVB1和m_pVB2,分别保存圆锥曲面和底面的顶点缓存区接口指针,原有的m_pVB予以删除: (D3DWnd.h) ... ... void SetupMatrices(); LPDIRECT3DVERTEXBUFFER9 m_pVB1; //圆锥曲面的顶点缓存区接口指针 LPDIRECT3DVERTEXBUFFER9 m_pVB2; //圆锥底面的顶点缓存区接口指针 ... ... 修改CD3DWnd::InitGeometry,建立圆锥的几何模型: (D3DWnd.cpp) void CD3DWnd::InitGeometry() { //建立圆锥曲面的数学模型 CUSTOMVERTEX1 vertices1[32]; vertices1[0].position = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); //点A的坐标 vertices1[0].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); //点A的法线矢量 for (int i = 1; i < 32; i++) { //计算顶点序列C1、C2 ... ... C30、C1的坐标和法线 float theta = (i-1)*12*D3DX_PI/180; vertices1[i].position = D3DXVECTOR3( 1.0f, sin(theta), cos(theta) ); vertices1[i].normal = D3DXVECTOR3( 0.0f, sin(theta), cos(theta) ); } //创建圆锥曲面的顶点缓存区,填入顶点数据 m_pDevice->CreateVertexBuffer( sizeof(vertices1), 0, D3DFVF_CUSTOMVERTEX1, D3DPOOL_DEFAULT, &m_pVB1, NULL ); void* pVertices; m_pVB1->Lock( 0, sizeof(vertices1), (void**)&pVertices, 0 ); memcpy( pVertices, vertices1, sizeof(vertices1) ); m_pVB1->Unlock(); //建立圆锥底面的数学模型 CUSTOMVERTEX2 vertices2[32]; vertices2[0].position = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); //点B的坐标 vertices2[0].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); //点B的法线矢量 for (i = 1; i < 32; i++) { //计算顶点序列C1、C30、C29 ... ... C1的坐标和法线 vertices2[i].position = vertices1[32-i].position; vertices2[i].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); } //创建圆锥底面的顶点缓存区,填入顶点数据 m_pDevice->CreateVertexBuffer( sizeof(vertices2), 0, D3DFVF_CUSTOMVERTEX2, D3DPOOL_DEFAULT, &m_pVB2, NULL ); m_pVB2->Lock( 0, sizeof(vertices2), (void**)&pVertices, 0 ); memcpy( pVertices, vertices2, sizeof(vertices2) ); m_pVB2->Unlock(); } 上述代码为每个图元定义了各自的FVF和顶点缓存区,其实如果顶点格式相同,完全可以把所有顶点放到同一个缓存区,然后在调用DrawPrimitive时,给出所绘图元的第一个顶点在缓存区中的偏移量即可。现在之所以分开存储,是出于对后续章节的考虑,在下一节中,两个图元将使用不同的顶点格式。 修改函数CD3DWnd::Cleanup,释放新增加的接口指针,代码如下: (D3DWnd.cpp) void CD3DWnd::Cleanup() { m_pVB1->Release(); //释放圆锥曲面的顶点缓存区 m_pVB2->Release(); //释放圆锥底面的顶点缓存区 m_pDevice->Release(); //释放设备对象 m_pD3D->Release(); //释放Direct3D对象 } 在初始化函数CD3DWnd::InitD3D中设置渲染状态D3DRS_NORMALIZENORMALS为TRUE,确保顶点法线总是单位矢量,不受坐标变换的影响,这有助于提高渲染的精确性,但会增加处理器负担。以前的程序为了使用顶点颜色渲染,把光照处理禁用了,现在要打开。另外,由于这一次的实体是一个封闭图形,不需要渲染背面,因此要把原来允许渲染背面的语句删掉: (D3DWnd.cpp) ... ... m_pD3D->CreateDevice( ... ... m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); //打开光照处理 m_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); //自动对法线矢量进行归一化处理 m_pDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE ); } 2 添加灯光和材质 我们使用一个白色的平行光进行照明,灯光方向指向左下方,矢量为{-1,-1,0};环境光设为一个亮度很低的灰度光;圆锥曲面的材质设为白色,底面设为黄色,没有镜面反射。 为CD3DWnd添加三个成员函数:SetLight、SetMaterial1、SetMaterial2,分别用于设置灯光、圆锥曲面材质、圆锥底面材质: (D3DWnd.h) ... ... LPDIRECT3DVERTEXBUFFER9 m_pVB2; void SetLight(); //该函数用于设置灯光 void SetMaterial1(); //该函数用于设置圆锥曲面的材质 void SetMaterial2(); //该函数用于设置圆锥底面的材质 ... ... (D3DWnd.cpp) void CD3DWnd::SetLight() { //创建一个白色的平行光 D3DLIGHT9 light; ::ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; //灯光类型 light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; light.Direction = D3DXVECTOR3( -1.0f, -1.0f, 0.0f ); light.Range = 1000.0f; //灯光的作用范围 m_pDevice->SetLight( 0, &light ); //设置灯光,参数1为灯光的索引号 m_pDevice->LightEnable( 0, TRUE );//打开灯光,参数1为灯光的索引号 //设置环境光 m_pDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_RGBA(32,32,32,0) ); } void CD3DWnd::SetMaterial1() { //创建一个白色的材质 D3DMATERIAL9 mtrl; ::ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; m_pDevice->SetMaterial( &mtrl ); //设置材质 } void CD3DWnd::SetMaterial2() { //创建一个黄色的材质 D3DMATERIAL9 mtrl; ::ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; m_pDevice->SetMaterial( &mtrl ); //设置材质 } 修改渲染函数CD3DWnd::Render,加入圆锥的绘制代码: (D3DWnd.cpp) ... ... m_pDevice->BeginScene(); SetupMatrices(); //设置变换矩阵 SetLight(); //设置灯光 //绘制圆锥曲面的图元 SetMaterial1(); //使用白色的材质 m_pDevice->SetFVF( D3DFVF_CUSTOMVERTEX1 ); m_pDevice->SetStreamSource( 0, m_pVB1, 0, sizeof(CUSTOMVERTEX1) ); m_pDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 30 ); //绘制圆锥底面的图元 SetMaterial2(); //使用黄色的材质 m_pDevice->SetFVF( D3DFVF_CUSTOMVERTEX2 ); m_pDevice->SetStreamSource( 0, m_pVB2, 0, sizeof(CUSTOMVERTEX2) ); m_pDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 30 ); m_pDevice->EndScene(); ... ... 编译运行程序,效果如图22所示。如果显示不正确,看是不是忘了打开Z缓存。
(图22,见文章末尾)
以上所画的圆锥,在由多个图元构成的实体中,只能算是一个比较简单的例子。绘制多图元实体的一般方法是:首先为图元设置各自的世界变换矩阵、材质和纹理(另外两个变换矩阵和灯光都属于全局性参数,设置一次即可);然后对该图元调用IDirect3DDevice9::DrawPrimitive方法。 Direct3D9学习笔记--灯光(Light)和材质(Material)灯光(Light)和材质(Material) 6.1基本概念 在前面的例程中,通过对顶点颜色进行插值来获取实体表面的颜色,这种简化的计算模型无法如实地反映真实世界。在自然界中,我们所看到的一切都是由光线产生的:光由光源出发,沿直线传播;当光线遇到物体时,一部分被吸收,剩余的被反射,该过程反复进行,直至光线能量耗尽,或者被人眼接收从而产生视觉。 在Direct3D中,用灯光和材质来模拟这个过程。灯光用于照亮实体,可分为环境光(Ambient Light)和直射光(Direct Light):前者均匀充满整个场景,为所有实体提供一个恒定的照明,没有方向性;后者一般由光源产生,具有方向性。材质则定义了实体表面对光线的反射属性。 Direct3D用结构D3DCOLORVALUE描述直射光和材质的颜色,它有4个浮点分量,分别代表红、绿、蓝、Alpha混合,正常取值范围0.0-1.0。其中Alpha混合用来产生透明效果,仅用于材质:0.0表示完全透明;1.0为不透明。 环境光颜色用一个4字节的整数D3DCOLOR描述,每个字节依次代表红、绿、蓝、Alpha混合,取值范围0-255,可以借助宏D3DCOLOR_RGBA来简化计算。和直射光一样,环境光也不使用Alpha混合。 虽然灯光和材质都有颜色,但其含义并不相同。灯光的颜色定义了光线中三原色的“数量”,红=绿=蓝=1.0为白光,都取0.0表示没有光。材质的颜色代表了在光线发生反射时,三原色被反射的“数量”,红=绿=蓝=Alpha=1.0表示所有光线都被反射,也就是说,材质看上去为白色,而红=绿=0.0,蓝=Alpha=1.0则表示只有蓝光被反射,即材质为蓝色。 6.2 灯光 环境光的使用比较简单,Direct3D把它作为一个渲染状态,通过调用IDirect3DDevice9::SetRenderState进行设置,对应的状态常数为D3DRS_AMBIENT。以下着重介绍直射光的应用。 按光源划分,直射光可分为三种: 1)点光源 点光源(Point Light)从一个点向周围均匀地发射光线,如图16所示,家用的白炽灯就是一个点光源。点光源有颜色、位置、作用范围,光强随距离而衰减,没有方向(因为向全部方向发射)。
(图16,17,见文章末尾)
2)平行光 平行光(Directional Light)由相互平行的光线组成,如图17所示,最常见的例子就是阳光。平行光只有颜色和方向,没有位置,也没有作用范围和衰减,因此不论实体位于场景的何处,所受到的光照都相同。
3)聚光灯 聚光灯(Spotlight)是三种直射光中最复杂的一种,常见的例子有手电筒、探照灯。它的光束是一个圆锥,其截面如图18所示,分内、外核两部分:内核最亮,且亮度保持不变;外核较暗,沿径向有一个衰减。图19是聚光灯的示意图,其中夹角Theta和Phi定义了内、外核的大小。聚光灯有颜色、位置、方向(即光束中心所指方向)、作用范围、衰减(沿光线方向)。
(图18,19,见文章末尾)
在Direct3D中,用结构D3DLIGHT9来描述直射光,它的定义如下: typedef struct _D3DLIGHT9 { D3DLIGHTTYPE Type; //类型:只能是点光源、平行光或聚光灯 D3DCOLORVALUE Diffuse; //灯光的漫反射颜色 D3DCOLORVALUE Specular; //灯光的镜面反射颜色 D3DCOLORVALUE Ambient; //灯光的环境光颜色 D3DVECTOR Position; //光源在世界坐标系的位置 D3DVECTOR Direction; //灯光的方向,建议使用单位矢量 float Range; //灯光的作用范围 float Falloff; //聚光灯内核到外核的衰减系数,通常取1.0,表示均匀过渡 float Attenuation0; //距离衰减系数之一:通常取0.0 float Attenuation1; //距离衰减系数之二:通常取一个大于0的常数 float Attenuation2; //距离衰减系数之三:通常取0.0 float Theta; //聚光灯的内核大小 float Phi; //聚光灯的外核大小 } D3DLIGHT9; 上述数据项中,最不好理解的恐怕要算灯光的颜色了,竟然有三种。在Direct3D的光照模型中,灯光效果由三部分组成:漫反射、镜面反射和环境光照。Direct3D以灯光的漫反射颜色和材质的漫反射颜色为输入参数,计算最终的漫反射效果,镜面反射与此类似。而灯光的环境光颜色则参于计算整个场景的环境光照,此前以渲染状态方式设置的环境光相当于公式中的常数项。 以上只是一个粗略的解释,读者在编程时,不妨试着分别改变这三种颜色,看看每种颜色所起的作用。如果对Direct3D的光照模型感兴趣,推荐阅读SDK中“Mathematics of Lighting”这篇文章,其中给出了详细的计算公式。 设置好D3DLIGHT9的各个成员后,调用IDirect3DDevice9::SetLight把直射光加入场景,然后还要执行IDirect3DDevice9::LightEnable激活它。 使用灯光会增加渲染的计算量,按从小到大排序,依次为:环境光、平行光、点光源、聚光灯。因此在编程时,要少用聚光灯,多用平行光和点光源。 6.3 材质 前面已经提过,材质用于描述实体的反光性能,Direct3D使用结构D3DMATERIAL9保存材质,它有如下成员: typedef struct _D3DMATERIAL9 { D3DCOLORVALUE Diffuse; //材质的漫反射颜色 D3DCOLORVALUE Ambient; //材质的环境光颜色 D3DCOLORVALUE Specular; //材质的镜面反射颜色 D3DCOLORVALUE Emissive; //材质的发射颜色 float Power; //材质的镜面反射强度 } D3DMATERIAL9; 漫反射颜色定义了材质对灯光中漫反射分量的反射性能,环境光颜色定义了材质对环境光照的反射性能,这二者结合在一起,决定了实体的外观颜色。在编程中,它们通常取相同的值。 镜面反射颜色定义了材质对灯光中镜面反射分量的反射性能,一般用于在材质表面产生高光部分,使实体看上去有光泽,通常取白或亮灰。Power决定镜面反射的强度,或者说,实体的光滑程度。Power越大,反光越强。图20是效果对比图,其中左边使用了镜面反射,Power为10。
(图20,见文章末尾)
发射颜色用于定义自身可以发光的材质,这种光只是让实体看上去更明亮,不能用来照明。 在D3DMATERIAL9中设置好材质的各项属性后,调用IDirect3DDevice9::SetMaterial把它加入场景。Direct3D9学习笔记--画一个三棱锥画一个三棱锥-索引缓存和Z缓存 本节将通过画一个三棱锥,介绍索引缓存(Index Buffer)和Z缓存(Z-Buffer)的用法。 5.1 什么是索引缓存 在Direct3D中,实体模型中的一个点可能被多个三角形面所共用,如图13所示的三棱锥,虽然只有4个顶点,却由4个三角形面组成。 (图13,见文章末尾) 如果象上一节那样,把顶点数据按对应图元的格式,直接放进顶点缓存区,该棱锥使用三角形列,4个锥面共需要4 x 3 = 12个顶点,也就是说,有8个顶点是重复的。如果实体比较复杂,重复的顶点会更多,造成资源浪费。 为此Direct3D引入了索引缓存的概念,把顶点的具体数据和代表图元格式的顶点顺序分开存储:顶点数据仍然放到顶点缓存区中,索引缓存区则按照图元格式,顺序存放顶点的索引。 以上面的棱锥的为例:首先在顶点缓存中保存A、B、C、D这4个顶点的FVF数据项,相应的索引为0、1、2、3;然后按照三角形列的组成顺序,把顶点索引值存入索引缓存区,4个三角形分别为△ACB、△ADC、△ABD、△BCD(注意顶点排列顺序和可视面的关系),则索引序列为0 2 1 0 3 2 0 1 3 1 2 3。这样原本要用12个顶点数据构建一个三棱锥,使用索引缓存后,只需要4个。当然了,索引缓存本身也要占用一些资源,不过和节约的顶点缓存相比少多了。 5.2 创建索引缓存 打开上一节的例程,为CD3DWnd添加一个数据成员,用来保存索引缓存区的接口指针: (D3DWnd.h) ... ... void SetupMatrices(); LPDIRECT3DINDEXBUFFER9 m_pIB; //索引缓存区的接口指针 ... ... 修改函数CD3DWnd::InitGeometry中的建模部分,并添加索引缓存区的创建代码: (D3DWnd.cpp) void CD3DWnd::InitGeometry() { //三棱锥的数学模型 CUSTOMVERTEX vertices[] = //FVF顶点数据 {{ 0.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(0,255,0) }, //点A,绿色 { -1.0f, -1.0f, -0.577f, D3DCOLOR_XRGB(255,0,0) }, //点B,红色 { 1.0f, -1.0f, -0.577f, D3DCOLOR_XRGB(0,255,255) }, //点C,浅蓝 { 0.0f, -1.0f, 1.155f, D3DCOLOR_XRGB(255,0,255) }}; //点D,粉红 WORD indices[] = { 0, 2, 1, 0, 3, 2, 0, 1, 3, 1, 2, 3 }; //索引序列 //创建顶点缓存区,并获取接口IDirect3DVertexBuffer9的指针 m_pDevice->CreateVertexBuffer( sizeof(vertices), //缓存区尺寸 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL ); //把顶点数据填入顶点缓存区 void* pVertices; m_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ); memcpy( pVertices, vertices, sizeof(vertices) ); m_pVB->Unlock(); //创建索引缓存区,并获取接口LPDIRECT3DINDEXBUFFER9的指针 m_pDevice->CreateIndexBuffer( sizeof(indices), //缓存区尺寸 0, D3DFMT_INDEX16, //使用16 bit的索引值 D3DPOOL_DEFAULT, &m_pIB, NULL ); //把索引值填入索引缓存区 void *pIndices; m_pIB->Lock( 0, sizeof(indices), (void**)&pIndices, 0 ); memcpy( pIndices, indices, sizeof(indices) ); m_pIB->Unlock(); } 还要在CD3DWnd::Cleanup中添加索引缓存区的释放代码: (D3DWnd.cpp) ... ... m_pIB->Release(); //释放索引缓存区 m_pVB->Release(); ... ... 5.3 渲染索引缓存 由于使用了索引缓存,因此函数CD3DWnd::Render中的渲染部分也要进行相应修改: (D3DWnd.cpp) ... ... m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) ); //绑定索引缓存区 m_pDevice->SetIndices( m_pIB ); //从索引缓存区绘制图元,参数1为图元格式,参数4为顶点数,参数6为三角形数 m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 4, 0, 4 ); m_pDevice->EndScene(); ... ... 编译运行程序,然后弹出Direct3D窗口,可以看到一个旋转的三棱锥。细心的读者可能会发现,棱锥看上去好像有点透明,这是因为没有打开Z缓存的缘故,此时Direct3D只是简单地按图元格式,顺序渲染三角形,没有考虑平面之间的遮挡关系,从而导致问题的出现。 5.4 打开Z缓存 在Direct3D中,使用深度缓存区(Depth Buffer)来进行消隐处理(隐藏面消除),以确保实体被遮挡的部分不被显示。Z缓存是最常用的一种深度缓存,它因为用Z坐标作为判断深度(远近)的依据而得名,其工作原理如图14所示,图中的渲染表面相当于Direct3D窗口,Z缓存用来保存窗口中各个像素的深度。在消隐时,Direct3D先用背景色(或纹理)填充渲染表面,Z缓存则统一设置成最大深度,即投影变换中后裁剪平面的距离,然后逐像素处理渲染表面:对于任意一个像素,Direct3D逐一测试所有与该像素重叠的三角形,如果三角形中像素对应点的Z坐标小于Z缓存中的数值,也就是说,此三角形离观察者较近,则像素取该点的颜色,同时像素在Z缓存中的深度也设为该点的Z坐标,然后继续测试下一个三角形... ... (图14,见文章末尾) Z缓存的工作原理说起来有些拗口,不过使用还是很容易的。首先在初始化函数CD3DWnd::InitD3D中添加如下代码,以便在创建设备对象的同时生成Z缓存: (D3DWnd.cpp) ... ... d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //生成16 bit的Z缓存 m_pD3D->CreateDevice( ... ... //启用Z缓存,允许消隐处理 m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); ... ... 然后修改CD3DWnd::Render中m_pDevice->Clear的调用参数,在清除后备缓存区的同时,把Z缓存统一设置为最大深度1.0: (D3DWnd.cpp) ... ... m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255), 1.0f, 0); ... ... 此时再编译运行程序,显示效果如图15所示。 (图15,见文章末尾) 除Z缓存外,Direct3D中还有一种深度缓存-W缓存(W-Buffer),用于变换后的坐标空间(w的全称是Reciprocal Homogeneous W,简写为RHW),限于篇幅,这里就不介绍了。 虽然本节使用了索引缓存绘制三棱锥,但它并不适合画多边形,因为索引缓存会产生公共顶点,其顶点法线不好确定。只不过该例程是使用顶点颜色进行渲染,没使用光照,因此不需要顶点法线。 Direct3D9学习笔记--画一个三角形(二)画一个三角形(二) [ 接Direct3D9学习笔记--画一个三角形(一)] 3 设置变换矩阵 在本例中,我们把实体放到世界坐标系的原点,让它绕Y轴做顺时针旋转,为此要用到一个定时器,在WM_TIMER的处理函数中不断改变旋转角度。 对于视角变换,观察点定在(0,3,-5),视线目标点取原点,上方向取Y轴的正向,对应矢量为{0,1,0}。 投影变换的可视角取π/4,高宽比取1,两个裁剪平面的距离分别取1和100。 下面是生成变换矩阵的代码: (D3DWnd.h) ... ... void InitGeometry(); int m_nRotateY; //实体的旋转角度(单位:度) void SetupMatrices(); //该函数用于设置三个变换矩阵 ... ... (D3DWnd.cpp) void CD3DWnd::SetupMatrices() { float angle = m_nRotateY * D3DX_PI / 180; //把旋转角换算成弧度 D3DXMATRIX matWorld; //计算世界变换矩阵 ::D3DXMatrixRotationY( &matWorld, angle ); //把世界变换矩阵设置到渲染环境 m_pDevice->SetTransform( D3DTS_WORLD, &matWorld ); D3DXVECTOR3 eye( 0.0f, 3.0f,-5.0f ); //观察点 D3DXVECTOR3 lookat( 0.0f, 0.0f, 0.0f ); //视线目标点 D3DXVECTOR3 up( 0.0f, 1.0f, 0.0f ); //上方向 D3DXMATRIX matView; //计算视角变换矩阵 ::D3DXMatrixLookAtLH( &matView, &eye, &lookat, &up ); //把视角变换矩阵设置到渲染环境 m_pDevice->SetTransform( D3DTS_VIEW, &matView ); D3DXMATRIXA16 matProj; //计算透视投影变换矩阵 ::D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); //把投影变换矩阵设置到渲染环境 m_pDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } 在CD3DWnd::OnCreate中添加定时器的初始化语句: (D3DWnd.cpp) ... ... InitD3D(); InitGeometry(); m_nRotateY = 0; SetTimer( 1, 40 ,NULL ); //定时间隔设为40毫秒 ... ... 用类向导为CD3DWnd添加WM_TIMER的消息处理函数OnTimer,在其中累加旋转角度: (D3DWnd.cpp) void CD3DWnd::OnTimer(UINT nIDEvent) { m_nRotateY += 2; //每次旋转2度 CWnd::OnTimer(nIDEvent); } 4 渲染 修改CD3DWnd::Render,在其中加入三角形的绘制语句: (D3DWnd.cpp) ... ... m_pDevice->BeginScene(); SetupMatrices(); //设置变换矩阵 //设置自定义的FVF m_pDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //绑定顶点缓存区至设备数据源 m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) ); //绘制图元,其中参数1为图元格式,参数3为三角形数目 m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); m_pDevice->EndScene(); ... ... 因为要让三角形旋转,所以Render的调用改放在时钟消息处理函数OnTimer中,原来的OnPaint函数用类向导予以删除: (D3DWnd.cpp) ... ... Render(); //渲染 m_nRotateY += 2; ... ... 最后,要禁用光照处理(缺省是打开的)。因为本例程使用顶点颜色进行渲染,如果不禁用的话,将会看到一个黑糊糊的三角形。另外,缺省情况下Direct3D只挑选三角形的正面进行渲染,当旋转到一定角度,背面朝向观察者时,图像会消失,因此要关闭该项特性。相关代码加在函数CD3DWnd::InitD3D中: (D3DWnd.cpp) ... ... m_pD3D->CreateDevice( ... ... //因为使用顶点颜色渲染,所以要禁用光照处理 m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); //关闭“挑选”功能,允许渲染背面 m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); ... ... 编译运行程序,点击工具按钮ID_D3D_BEGIN,将会出现一个旋转的彩色三角形,如图12所示。请读者妥善备份本节生成的例程,因为后面要用到它。 (图12,见文章末尾)January 18 Direct3D9学习笔记--画一个三角形(一)画一个三角形(一) 前面讲了一大堆抽象的理论,现在让我们理论联系实际,来画一个最简单的三角形。 1 建模 该三角形在本地坐标系的数学模型如图11所示,三个顶点的本地坐标分别为A(-1,-1,0)、B(0,1,0)、C(1,-1,0)。选取三角形列作为实体的图元格式,顶点排列顺序为A、B、C,正面(可视面)朝外。 (图11,见文章末尾) 2 创建顶点缓存区 首先要定义顶点格式,Direct3D采用了一种被称之为“可变形顶点格式 Flexible Vertex Format((FVF)”的技术,除顶点坐标外,还可以包括顶点的法线、颜色、纹理等数据。在本节中,用到了坐标和颜色。通常情况下,实体的外观由材质、光照和纹理决定,不需要再另外为顶点定义颜色,但目前还没有讲到这些内容,因此要给出顶点的颜色。Direct3D在渲染时,将使用顶点颜色,通过插值算法来填充三角形。 打开上一节生成的例程d3d001,在D3DWnd.cpp的开始部分中加入FVF的定义: (D3DWnd.cpp) ... ... #include "D3DWnd.h" //定义FVF的顶点结构 struct CUSTOMVERTEX { float x, y, z; //顶点坐标 DWORD color; //顶点颜色 }; //定义FVF用到的数据项:坐标 颜色 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) ... ... 在Direct3D中,FVF顶点数据按图元的格式,顺序存放在顶点缓存区(Vertex Buffer),它是一个COM对象,通过接口IDirect3DVertexBuffer9访问。以下是创建顶点缓存区的代码: (D3DWnd.h) ... ... void Cleanup(); LPDIRECT3DVERTEXBUFFER9 m_pVB; //顶点缓存区的的接口指针 void InitGeometry(); //该函数用于建模 ... ... (D3DWnd.cpp) void CD3DWnd::InitGeometry() { //三角形实体的数学模型 CUSTOMVERTEX vertices[] = {{ -1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,0,0) }, //点A,红色 { 0.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(0,255,0) }, //点B,绿色 { 1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(0,255,255) }};//点C,浅蓝 //创建顶点缓存区,并获取接口IDirect3DVertexBuffer9的指针 m_pDevice->CreateVertexBuffer( sizeof(vertices), //缓存区尺寸 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL ); //把顶点数据填入顶点缓存区 void* pVertices; m_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ); memcpy( pVertices, vertices, sizeof(vertices) ); m_pVB->Unlock(); } 修改CD3DWnd::OnCreate,加入对InitGeometry的调用: (D3DWnd.cpp) ... ... InitD3D(); InitGeometry(); //进行建模 ... ... 由于顶点缓存区是COM对象,还要在CD3DWnd::Cleanup中添加它的释放代码: (D3DWnd.cpp) ... ... m_pVB->Release(); //释放顶点缓存区 m_pDevice->Release(); ... ...
[ 剩余部分见Direct3D9学习笔记--画一个三角形(二)] Direct3D9学习笔记--3D的数学基础3D的数学基础 1 一些数学概念 在开始编程之前,读者有必要了解一些有关三维坐标系的基本概念。 1.1 三维坐标系、点、矢量 按坐标轴之间的相互关系划分,三维坐标系可分为左手坐标系和右手坐标系,如图3所示。在左手坐标系中,坐标轴的定义符合左手法则:左手四个手指的旋转方向从X轴到Y轴,大拇指的指向就是Z轴。右手坐标系依次类推。Direct3D使用左手坐标系,其中X轴表示左右,Y轴表示上下,Z轴表示远近(深度)。 (图3,见文章末尾) 取定坐标系后,空间中的任意一点可以用一组坐标值(x,y,z)来表示。矢量是空间中的一条有向线段,Direct3D用它来标识空间方向。矢量的表示方法与点坐标类似,也是用{x,y,z},不过它表示的是从原点指向点(x,y,z)的有向线段。矢量和起点无关,只要两个矢量同向(平行)且等长,就认为它们相等。在Direct3D中,点和矢量通常使用同一个结构D3DXVECTOR3保存。 矢量的计算公式很简单:假设矢量的起点为M(x1,y1,z1),终点为N(x2,y2,z2),则矢量={x2-x1,y2-y1,z2-z1}。 矢量除了方向属性外,也有大小(长度),但是Direct3D一般不用。为了避免矢量的大小给计算带来误差,可以用函数D3DXVec3Normalize把它变换成单位矢量(长度为1)。 1.2 三角形、平面法线、顶点法线 在Direct3D中,三角形是构成实体的基本单位,因为一个三角形正好是一个平面,以三角形面为单位进行渲染效率最高。大量的三角形组合在一起,构成复杂的多边形或者曲面。图4是一个球面的例子。 (图四,见文章末尾) 一个三角形由三个点构成,习惯上把这些点称为顶点(Vertex)。三角形平面有正、反面之分,由顶点的排列顺序决定:顶点按顺时针排列的表面是正面,如图5所示。其中与三角形平面垂直、且指向正面的矢量称为该平面的法线(Normal)。在Direct3D中,为了提高渲染效率,缺省条件下只有正面可见,不过可以通过IDirect3DDevice9::SetRenderState来改变设置,其对应的渲染状态常数为D3DRS_CULLMODE,具体用法请参阅SDK文档。 (图五,见文章末尾) 顶点法线(Vertex Normal)是过顶点的一个矢量,用于在高洛德着色(Gouraud Shading)中计算光照和纹理效果。在生成曲面时,通常令顶点法线和相邻平面的法线保持等角,如图6-1所示,这样进行渲染时,会在平面接缝处产生一种平滑过渡的效果。如果是多边形,则令顶点法线等于该点所属平面(三角形)的法线,如图6-2所示,以便在接缝处产生突出的边缘。 (图6-1,图6-2,见文章末尾) 1.3 Direct3D设备支持的图元(Primitive)格式 在Direct3D中,三维实体都是由一些基本图元组合而成的,总共有6种图元格式(示例参见图7-1-6): 点列(Point Lists)
由顶点组成的集合; 线列(Line Lists)
由直线段组成的集合; 线带(Line Strips)
由互相连接的直线段组成的集合; 三角形列(Triangle Lists)
由三角形组成的集合,每三个顶点构成一个三角形; 三角形带(Triangle Strips)
由相接的三角形组成的集合。在例图中,v1、v2、v3构成第一个三角形,v2、v3、v4构成第二个三角形... ...(注意:三角形带的正面由第一个三角形决定,因此第二个三角形顶点的排列顺序实际上应该为v2、v4、v3); 三角扇形(Triangle Fans)
由相接且共点的三角形组成,v1、v2、v3构成第一个三角形,v1、v3、v4构成第二个三角形... ...; (图7-1,7-2,7-3,7-4,7-5,7-6,见文章末尾) 上述图元中,后三种以三角形为单位的图元比较常用。其中三角形列适用范围较广,既能用于多边形,也可用于曲面;而三角形带和三角扇形由于存在公共顶点,如果用来创建多边形,其公共顶点的法线不好确定,因此通常只用于曲面,不过在三角形数目相同的情况下,它俩使用的顶点数目要比前者少得多。 1.4 坐标变换 1)世界变换 我们在建立三维实体的数学模型时,通常以实体的某一点为坐标原点,比如一个球体,很自然就用球心做原点,这样构成的坐标系称为本地坐标系(Local Coordinates)。实体总是位于某个场景(World Space)中,而场景采用世界坐标系(World Coordinates),如图8所示,因此需要把实体的本地坐标变换成世界坐标,这个变换被称为世界变换(World Transformation)。 (图八,见文章末尾) 在Direct3D中,坐标变换通过一个4x4矩阵来实现,对于世界变换,只要给出实体在场景中的位置信息,就可以借助Direct3D函数得到变换矩阵,具体的计算步骤如下: 首先把实体放置在在世界坐标系原点,使两个坐标系重合; 在世界空间中,对实体进行平行移动,其对应的平移变换阵TT可由函数D3DXMatrixTranslation求得; 把平移后的实体沿自身的Z轴旋转一个角度(角度大于0,表示从Z轴的正向朝原点看去,旋转方向为顺时针;反之为逆时针,下同),对应的旋转变换阵TZ用D3DXMatrixRotationZ计算; 把实体沿自身的Y轴旋转一个角度,用D3DXMatrixRotationY求出变换阵TY; 把实体沿自身的X轴旋转一个角度,用D3DXMatrixRotationX求出变换阵TX; 最后对实体进行缩放,假设三个轴的缩放系数分别为sx、sy、sz,该操作对应的变换阵TS可由函数D3DXMatrixScaling求得; 最终的世界变换矩阵TW = TS·TX·TY·TZ·TT ,在Direct3D中,矩阵乘法用函数D3DXMatrixMultiply实现,注意相乘顺序为操作的逆序。
从以上描述中,我们很容易得出:实体的运动可以通过不断改变世界变换矩阵来实现。 2)视角变换 实体确定后,接下来要确定观察者在世界坐标系中的方位,换句话说,就是在世界坐标系中如何放置摄像机。观察者(摄像机)所看到的景象,就是Direct3D窗口显示的内容。 确定观察者需要三个量: 观察者的点坐标; 视线方向,为一个矢量,不过Direct3D用视线上的一个点来替代,此时视线方向就是从观察者指向该目标点,这样表示更直观一些; 上方向,通俗地说,就是观察者的头顶方向,用一个矢量表示。
确定后,以观察者为原点,视线为Z轴,上方向或它的一个分量为Y轴(X轴可由左手法则得出,为右方向),构成了视角坐标系,如图9所示。我们需要把实体从世界空间转换到视角空间,这个坐标变换被称为视角变换(View Transformation)。 (图九,见文章末尾) 与世界变换相比,视角变换矩阵的获取要容易得多,只需调用一个函数D3DXMatrixLookAtLH,其输入参数就是决定观察者的那三个量。 3)投影变换 实体转换到视角空间后,还要经过投影变换(Projection Transformation),三维的实体才能显示在二维的计算机屏幕上。打个比方,如果把屏幕看做照相机中的胶卷,那么投影变换就相当于照相机的镜头。 Direct3D使用透视投影变换(Perspective Transformation),此时在视角空间中,可视区域是一个以视线为轴心的棱台(Viewing Frustum),如图10所示。想象一下你处在一个伸手不见五指的房间里,面前有一扇窗户,你可以透过窗户看到各种景物。窗户就是棱台的前裁剪平面,天空、远山等背景是后裁剪平面,其间的可视范围是景深。投影变换把位于可视棱台内的景物投影到前裁剪平面,由于采用透视投影,距离观察者远的对象会变小,从而更具有真实感。在Direct3D中,前裁剪平面被映射到程序窗口,最终形成了我们在屏幕上看到的画面。 (图十,见文章末尾) 透视投影变换由四个量决定: 前裁剪平面的宽度w; 前裁剪平面的高度h; 前裁剪平面到原点的距离z1; 后裁剪平面到原点的距离z2。 由于w、h用起来不是很直观,因此实际应用中,常用fov和aspect代替w、h,其中fov是Y方向上的可视角度,通常取π/4;aspect是前裁剪平面的高度与宽度之比,通常取1(由三角函数定义,易知h=2·z1·tg(fov/2),w=h/aspect)。用这四个量来调用函数D3DXMatrixPerspectiveFovLH,即可获得投影变换矩阵。 得到三个变换矩阵后,还需要调用方法IDirect3DDevice9::SetTransform把它们设置到渲染环境中,具体用法参见后面的例程。 最后,可以用三句话来概括这些变换的作用:世界变换决定实体的位置;视角变换决定观察者的位置;投影变换决定观察者的可视区域。 至此,相关的数学部分终于讲完了,可能枯燥了点,但却是掌握Direct3D的关键。作为程序员,虽然不需要我们了解这些算法的来历、推导等,但一定要知道它们是干什么用的以及如何用。
|
心得体会/收获/感悟
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|