月度归档:2010年08月

程序员从初级到中级的10个秘诀

#1: 学习另一门语言

其实你学的是哪一门语言并没有关系,但是学习另一门语言(不管你已经了解多少种语言)将把你打造为更好的程序员。能学会一门与你日常使用的语言风格迥异的语言则更佳。打个比方,如果你是C#程序员,学习VB.NET或者Java对你的帮助就没有学习Ruby或者Groovy大。

我说“学另一门语言”的意思是要真正学会它。学习一门语言包括三个领域的知识:语法、内置操作符和库,以及“如何使用”。前面两个简单;我认为一名有经验的程序员,根据语言的不同,能在半小时到几小时内掌握足以维护代码的语法知识。操作符和库只不过是知识逐步积累的过程,你什么时候想清楚要了解什么了,再去查阅参考材料也不迟。只有第三项,“如何使用它”
- 要花上你几个月的时间去跟这门语言打交道,真正的奇迹就在此发生。我建议用这门语言的风格去做一个适合该语言的项目。

真正学会了另一门语言之后,我敢保证你的程序员水平一定会突飞猛进。

#2: 学习先进的搜索技术、手段和及策略

作为一名好的程序员,不仅仅是技能的问题了,而是你寻找信息的技巧,这个趋势越来越明显。对大部分人而言,仅仅输入“现代语言及开发框架”,这都是泛泛之谈,记不住多少的。因此,你完成工作的能力通常取决于你的检索能力。不幸的是,了解到如何找到准确而高质量的信息可不仅仅是跑到TechRepublic来找答案,或者在你选好的搜索引擎上敲几个字那么简单。

“技术(Techniques)”、
“手段(tactics)”和“策略(strategies)”看起来是一回事,实际上并非如此。你需要学会的技术是掌握你喜爱的搜索引擎的高级搜索系统;你需要了解诸如布尔操作符,如何过滤结果(像“非”关键字,域限制等等),关键字的词序扮演什么角色,等等。一句话,RTFM(Read
The Fucking Manual,读那些他妈的手册)吧。

你应该学会这些手段,诸如如何接近特定的搜索,以及了解自己实际上想查些什么。查错误很容易 — 只需查出错代码即可 —
但是许多搜索的关键字选择要困难得多。

至于策略,你需要学会的东西,包括像应该使用哪种搜索引擎(提示:普通的搜索引擎不一定就是最佳选择),
使用普通搜索引擎前应该访问哪个网站,甚至是应该到哪个论坛去寻求帮助,等等。

#3: 帮助别人

教别人始终是学习一切东西的最好方法之一。相对而言,由于你在开发领域还是个新手,认为自己没什么可教给人家的,这可以理解。但这毫无意义。记住,你所学到的一切都是你从别人或别处学到的;因此请尝试一下,成为另外一个人要请教的“别人”。每天尽量花一点时间试着回答TechRepublic上的问题,其他网站的亦可。读读其他会员的回答,你也可以学到很多东西。

#4: 有耐心,常练习

研究表明,要成为一名“专家”,需要花费10年,或者10000到20000小时的刻意练习时间。 真的很久。还有,成为专家不尽然就是执行10年同样的任务;通常这意味着要在特定领域内执行广泛的任务。需要花费大量的时间和精力才能成为”专家”;做几年程序员是不够的。想在30岁左右成为一名高级软件开发工程师 ?要么尽早接受教育/培训,要么你得愿意在闲暇时间进行大量的工作、阅读和练习。我从高中开始编程,还牺牲了许多休息时间去跟踪行业发展、学习新技能等等。结果,我获得中级和高级程序员的时间就比我的大部分同事都要早得多,随着时间的推移,这些就转化成为很多的金钱。

#5: 对教条拒之门外

是时候开诚布公了:也许初级程序员了解的东西还不足以说出做某件事情有一种最好的方式。尊重朋友或者权威的观点是好的,但直到你更有经验之前,不要把他们的观点说成是你自己的。很简单,如果你所了解的不足以让你独立地找出这些东西来,你又怎么会认为你知道哪一位“专家”是对的呢?话是难听了点,不过请相信我;由于受某些愚蠢建议的蛊惑,或者追随某些根本不知道自己在说些什么的所谓专家,白白把自己的职业生涯耽搁了几年,这样毛头小伙程序员,我见过多了。 这一点有一个很好的例子,就是面向对象结构的滥用。 比如说,许多初级者读了一些有关面向对象的信息后,突然间,他们那简单的应用程序的类图看起来就像埃菲尔铁塔一样了。

#6: 深入学习一点先进理念

成为一名中级程序员,很大一部分是要在代码里面体现出一些所擅长的概念。就我而言,是多线程/并行性,
是正则表达式,以及如何对动态语言进行变化(后两个在我离Perl渐行渐远后开始退化)。这是如何发生的?多线程和并行处理是因为我读了相关文章,觉得它看起来很有趣,然后再自己把它弄清楚了;然后我就一直使用这些技术来写应用。我做过一件工作,是用Perl写的,里面运用了大量的正则表达式。我也用一个过程引擎模板和内置数据库系统写过我自己的电子商务引擎;那时我几乎花了2年时间在这上面。

找到真正令你着迷的东西。也许是图像处理,也许是数据库设计,等等。即便你是一个入门级的程序员,也要尝试一下成为某一自己所关注领域的专家。这会让你相当快速地进入到中级水平,一旦你到了那个水平,你的专家之路也走到一半了。

#7: 学习你的领域里面的基本理论

写出“Hello
World”,跟理解那些字是如何显示到屏幕上的是两码事。通过学习支撑你所从事的工作的“基础/底层工作(groundwork)”,你会变得更加在行。为什么?因为你会理解事物为何会以这种方式运作,当东西坏了就能知道是哪里的问题,等等。通过掌握工作的底层机制,你变会得更出色。

如果你是Web程序员,读读HTTP RFCHTML规范。如果你使用代码生成器,好好看看它生成的代码;如果你使用数据库工具,看看它生成的底层SQL语句,不一而足。

#8: 看看高级程序员的代码

在工作中看看高级程序员写的代码,然后问一问事情是如何以某种特别的方式完成的,为什么?可能的话看看开源的项目。甚至即使其他程序员没有最好的编程习惯,你也会学到许多编程经验。当然,要小心别学到坏习惯。我的意思是说不要生搬硬套人家的东西;你要能领会到哪些是能行的通的,哪些是有道理的,然后再模仿人家。

#9: 学习好的习惯

愚蠢的变量名,糟糕的缩进习惯以及其他一些凌乱的迹象就是一个没有经验的程序员的最好标记。一个程序员在学会如何编程时,却经常没有被传授到那些不那么有趣的细节,像代码格式编排
。甚至尽管学习这些东西并不会令你的代码更好,也不会令你成为更好的程序员,它也会确保你不被同事视为入门级的程序员。甚至即使某人是高级程序员,如果他的变量是以他那97只猫的名字来命名,或者其函数叫做“doSomething()”的,他们看起来也不像是知道自己在干什么的人。而且会令其代码在过程中更难以维护。

#10: 要玩的开心

想要痴迷于单调乏味的工作?痛恨工作吧。要想升级为中级程序员可不仅仅是为了拿到不断增长的工资不达目的誓不罢休,而是要真正享受工作。如果你不喜欢自己的工作,且还是初级程序员,你怎么会认为成为中级或高级程序员情况就会有所好转呢?换工作或改职业吧。反过来说,如果你喜爱所从事的工作,那就好!只要你坚持下去,我保证你能成为一名更好的程序员。

各种光照的算法原理

原文链接:http://www.nitrogen.za.org/viewtutorial.asp?id=5

这个教程用到了向量数学知识,如果你对向量数学还不是很了解,请先阅读向量教程:read the tutorial。

光照与物体表面的相互作用可以通过将一些数学公式应用于基于per
pixel(区别于基于顶点)的着色,从而模拟出真实生活中的各种材质效果。比如浮雕效果,波浪效果,油漆效果等。

在这个教程中,我们有如下假定:

第一,我们讨论的是基于像素着色(per-pixel
basis),每个pixel有它自己的位置向量,法线向量以及表面颜色(Surface
color,在这里可以是来自纹理的颜色,也可以是RGB颜色(flat color));

第二,表面颜色(Surface color)通常是由R,G,B三部分组成,在这个教程中,我们把它当作一个向量看待;

第三,输入表面颜色(光照处理前的表面颜色,这里的“输入”可以理解为函数的输入参数的“输入”)只是普通的颜色(单纯的纹理颜色或者RGB颜色),而输出表面颜色(光照处理后的表面颜色)是光照作用于表面的合成颜色,如可以是有阴影,高光等效果的颜色。

第四,这个教程中假设每个场景中只有一个灯光。对于多灯光的场合,对每一个灯光循环进行这些运算(环境光除外)。

好了,让我们开始讲解各种光照的算法原理

Ambient Lighting 环境光

在真实生活里,有光线的房子里的物体不会是全黑的,总有一些光量子照亮物体表面,即使这个表面是背对光源的,这就是环境光的原因。我们不考虑环境光的照射方向,我们总认为场景中的物体,不论它在什么位置,总会受到一定数量的环境光照射(全局照明)。环境光照算法如下:

Inputs:

      
Col – 物体原表面颜色

       
AmbAmount – 场景中环境光的强弱程度 (介于0 到 1之间)

    
Outputs:

       
SurfaceColor – 环境光照作用之后的表面颜色

       
SurfaceColor = Col*AmbAmount;

 

环境光照效果图:

 

Lambert Shading (郎伯特着色,郎伯特:物理上的亮度单位,在这里就是漫射光作用)

现在我们真正开始考虑一束光照射在物体表面上的作用过程,我们使用最常见的光照算法-------漫反射光照着色或者说郎伯特余弦定律或郎伯特着色(三个都一回事),这个算法是将入射光与表面法线向量的点积当作漫反射光照强度因子,下面我们看看环境光照与漫射光照共同作用的算法:

Inputs:

       
LCol – 照射在表面上的漫射光

       
Pos – 表面上被照射的位置

       
LPos – 漫射光源的位置

       
N -表面上被照射的位置处的法向量

       
Col –物体原表面颜色

       
AmbAmount -场景中环境光的强弱程度 (0 to 1)

Outputs:

       
SurfaceColor -环境光照与漫射光照共同作用之后的表面颜色

 

       
VectorToLight = Normalise(LPos - Pos);

       
DiffuseFactor = Dot(VectorToLight, Normal); //DiffuseFactor ranges
from 0 to 1

//光线与表面法线夹角大于90度,想像下光线在表面背面射过来,正表面肯定没有光照

   if(DiffuseFactor
< 0)

       
then DiffuseFactor = 0;

 

       
//环境光照与漫射光照共同作用

   
SurfaceColor = Col*AmbAmount + Col*DiffuseFactor*LCol;

 

环境光与漫射光共同作用效果

Specular Highlights镜面高光

现在我们考虑物体表面有光泽的效果,这种效果是将Phong反射模型,结合前面两个光照作用而成。这中光照效果计算需要知道观察者在场景中的位置,而先前的环境光照与漫射光照效果计算都与观察者所在位置无关的。

这种光照计算是这样的,首先我们计算入射光在表面处的反射光线,然后再将反射光线与视线(观察者的眼睛与表面观察点的连线)之间的点积值当作反射到观察者眼中的光照强度因子,因为表面上高亮的部分是反射光线反射到观察者眼睛或照相机中较多的地方,这些地方的反射光线与视线之间的夹角非常小,点积值就越大。

Inputs:

       
ViewPos – 观察者的位置

       
SpecAmount – 镜面光强弱. (from 0 to about 200)

       
SpecCol – 镜面光颜色(通常为白色).

 

       
LCol – 照射在表面上的漫射光

       
Pos – 表面上被照射的位置

       
LPos – 漫射光源的位置

       
N -表面上被照射的位置处的法向量

       
Col –物体原表面颜色

       
AmbAmount -场景中环境光的强弱程度 (0 to 1)

 

Outputs:

       
SurfaceColor -环境光照,漫射光照与镜面光共同作用之后的表面颜色

       

       
DiffuseFactor = ... //经前两个光照作用得来的颜色

       

       
DirectionToViewer = Normalise(ViewPos - Pos);

       
VectorToLight = Normalise(LPos - Pos);

       
//计算反射光

       
ReflectanceRay = 2 * Dot(N, VectorToLight) * N - VectorToLight;

   

   
//计算镜面光照因子. 数学公式 SpecFac = (R dot N)^Spec

   
SpecularFactor = Pow(Dot(ReflectanceRay, DirectionToViewer),
SpecAmount);

   

       
//环境光照,漫射光照与镜面光共同作用

   
SurfaceColor = Col*AmbFactor + Col*DiffuseFactor*LCol +
SpecCol*SpecularFactor;

 

环境光照,漫射光照与镜面光共同作用

Note:可以在一个场景中使用多个漫射光照与镜面光作用

 

Fresnel Term 菲涅尔准则

菲涅尔效果是根据观察者的观察表面来调整反射率来实现的。比如你从水面,油漆表面或者丝绸的正上方看,反射光泽的柔和效果基本没有,如果侧着或平着看的话,反射光泽的柔和效果就很明显,这就是菲涅尔效果。我们简单地通过点积操作计算表明法线与视线之间夹角的余弦值,再将这个值加权。对于较平滑表面,加权系数设置在1.0-5.0之间(油漆效果,丝绸等),对于比较凹凸的表面,加权系数设置为8.0或更高(水波,液体等)

Inputs:

       
ViewPos – 观察者的位置

       
FresAmount – 边缘或表面的尖锐程度. (油漆丝绸:1,液体: 2-8)

       
FresCol - frenel 反射光 (通常使用reflection map or 类似的东西).

 

       
LCol – 照射在表面上的漫射光

       
Pos – 表面上被照射的位置

       
LPos – 漫射光源的位置

       
N -表面上被照射的位置处的法向量

       
Col –物体原表面颜色

       
AmbAmount -场景中环境光的强弱程度 (0 to 1)

 

Outputs:

       
SurfaceColor -环境光照,漫射光照与镜面光,菲涅尔反射共同作用之后的表面颜色

       

       
DiffuseFactor = ... //环境光照,漫射光照作用得来的颜色

       
SpecularFactor = ... //镜面高光作用得来的颜色

 

       
DirectionToViewer = Normalise(ViewPos - Pos);

       
//计算fresnel因子.
我们计算视线与表面法向量间夹角的余弦值(在[-1..1]之间),然后加一,移动到区间[0..2],然后再加权。

       
FresnelTerm = Pow(Dot(N, DirectionToViewer)+1, FresAmount);

   

       
//确保因子的在正常范围内

       
if (FresnelTerm > 1)

              
then FresnelTerm = 1;

   
//无菲涅尔反射的场合: Ambient light, Diffuse Light and Specular Light

        
NonReflective = Col*AmbFactor + Col*DiffuseFactor*LCol +
SpecCol*SpecularFactor;

 

       
Reflective = FresCol;

       
//环境光照,漫射光照与镜面光,菲涅尔反射共同作用

   
SurfaceColor = NonReflective*(1-FresnelTerm) +
Reflective*FresnelTerm;

               

漫射无菲涅尔反射时效果                   
漫射有菲涅尔反射时效果

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kesalin/archive/2008/03/30/2230774.aspx