欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Win32 OpenGL編程(11) 光照

系統 1695 0

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

最近跟風,看了《思維導圖》,用XMind為此節畫了個思維導圖,事實上感覺這種書說起來不一定完全沒有用,但是為了顯示有用似乎說的太過夸張了,基本上,我認可一圖勝千言吧。。。。另外,XMind還算比較好用,特別是上傳然后共享的方式比較方便:)基礎版還開源。

上面這種圖用于解釋概念就略顯簡單,但是用于梳理脈絡,復習時回憶概念還算是比較有用的。

上帝說,要有光,就有了光。---- 《舊約?創世紀》

使用OpenGL時,程序員可以暫時充當一下上帝的角色(其實犯了妄自稱上帝的戒律),你對電腦說要有光,于是,顯示的時候就有了光,呵呵。當然,說的時候需要用電腦的語言。

相對來說,光照在OpenGL中是屬于那種概念理解比較簡單,但是使用卻比較復雜的功能之一,因為光照屬于比較容易影響顯示效果的因素,所以光照的用法太多,導致可以使用的定制手段相當多,這也就加深了使用的復雜度,基本上,遵循理解核心概念,需要時再去查文檔理解每個函數的具體參數使用和意義是種不錯的學習方式,當然,要想精通,恐怕對各種光照應用的情況都得有個了解才行。上述思維導圖就是核心概念的一個簡要列表,以下以此圖展開來討論。

為啥需要光

上帝為啥創造光?上帝沒有光看不見東西嗎?。。。。。。。?;蛘咭驗樯系壅J為黑暗是不好的,不想呆在黑暗之中。。。。。只有上帝知道

那我們為啥需要光呢?因為我們的世界有上帝創造的光,而OpenGL本質上是對現實世界的一種建模,既然現實世界有太陽,有光,那么模擬現實世界顯示的OpenGL怎么能沒有光呢?(以上純屬無聊的廢話)

以前畫3D圖形的時候我有意的將物體的每個面都設置成不同的顏色(比如以前那個三角錐),這樣我們才能夠較為清楚的看出來這是個3D的圖形,為什么會這樣說呢?那我們先看看事實上,假如我沒有那樣做,我們看到的是啥。這里以《 Win32 OpenGL編程(6) 踏入3D世界 》一文的glSmoothColorPyramid一例為修改藍本,(原來的源代碼見/2009-10-21/glSmoothColorPyramid/),將其4面顏色全部設置為紅色。

即將其源代碼中表示顏色的數組改為如下形式:

    
      static 
    
    
      GLfloat fPyramidColors
    
    
[] = { 1.0, 0.0, 0.0,
    1.0, 0.0, 0.0,
    1.0, 0.0, 0.0,
    1.0, 0.0, 0.0};
  

我們看看效果。

image

為節省篇幅僅貼出關鍵片段,完整源代碼見我博客源代碼的 2009-11-9/glSimpleColorPyramid/目錄,獲取方式見文章最后關于獲取博客完整源代碼的說明。

事實上,即便是整個三角錐正以3D的方式不停的旋轉,我們看到的效果也類似于一張三角形的紅紙片不停的晃悠而已。3D效果蕩然無存,很顯然,這是有問題的,不能說一個純色的物體的3D效果會受到影響吧?這算是我們需要光的最簡單的一層了。一個三角錐還好說一點,我們看看一個球。此例利用了glut的具體畫實心體的函數,以后不再全部利用自己的復雜手工代碼來創造那簡陋的三角錐了,作為一些概念的講解,那樣的三角錐已經有點過于簡單了。(當然,可以用的時候還是會用)因為利用了glut,畫球就很簡單了(事實上不用也不難),只需要設置好紅色,然后用

    
      glutSolidSphere
    
    
(0.5, 30, 16);
  
    就能畫出下面這種半徑為窗口寬度1/4的球。
  

image 有人能看出來上面的那個是球?我們看到的僅僅是一個圓而已,數學中我們也常常會將某個方向的球的圖形抽象成一個圓,但是現實中我們還是很容易看出一個球就是一個球而不是一個圓的面,為啥呢?光啊,因為光照的存在,同一個球在我們眼里事實上不會是如上面那樣純紅色的就整個球都是純紅色,會根據光照的方向,強度等因素的不同導致各個部位顯示不同。下面是一個加上了光照的紅色球體的例子。(上傳U酷后顏色變了-_-!可能是因為U酷在上傳后進行了2次壓縮編碼導致的顏色混亂,光源移動效果基本一致,需要真實體驗的可以下載源代碼編譯后運行)

為節省篇幅僅貼出關鍵片段,完整源代碼見我博客源代碼的2009-11-9/LightSimple/ 目錄,獲取方式見文章最后關于獲取博客完整源代碼的說明。

主要源代碼如下:

      
        //OpenGL初始化開始
      
      
void SceneInit( int w, int h)
{
GLenum err = glewInit();
if (err != GLEW_OK)
{
MessageBox(NULL, _T( "Error" ), _T( "Glew init failed." ), MB_OK);
exit(-1);
}

GLfloat mat_specular[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat mat_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat mat_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glColor3f(0.0, 0.0, 0.0);
}

//這里進行所有的繪圖工作
void SceneShow(GLvoid)
{
static GLfloat light_position[] = { 1.0, 0.0, -3.0, 0.0 };
static GLfloat angle = 1.0;

glClear(GL_COLOR_BUFFER_BIT); // 清空顏色緩沖區

glPushMatrix();
glRotatef(angle, 0.0, 1.0, 0.0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glPopMatrix();
angle += 1.0;

glutSolidSphere(0.5, 30, 16);

glFlush();
}

這里啟用光照的順序就像是上面那個思維導圖中表示的一樣,一下解釋一下各步驟:

1.定義物體的法線

這一步其實很重要,但是我們在這個例子中看不到,原因在于glutSolidSphere函數已經完成了這樣的定義,法線的定義有點類似我們以前確定物體表面時用逆/正時針的頂點指定順序來確定一個物體的正背面一樣,法線定義了光線入射時物體相對于光源的方向,這算是個額外的小題目,以后有機會再論及,可以參考《OpenGL 編程指南》的第2.5節。基本上知道法線的概念后,需要調用的就是glNormal*函數,但是法線的計算并不總是那么容易。。。。。。比如此例的球體,還好,此例因為是使用現成的函數,省了此步。

2.創建和選擇光源,并設置位置

glEnable ( GL_LIGHTING );
glEnable ( GL_LIGHT0 );

兩句表示啟用了第0號光源,此光源默認顏色為白色,位置為(0.0,0.0,1.0, 0.0)。我們利用了其默認顏色。

glLight*函數是專門的光照配置控制函數。

OpenGL Programming Guide 》:

glLight — set light source parameters
C Specification
void glLightf( GLenum light,
GLenum pname,
GLfloat param);
void glLighti( GLenum light,
GLenum pname,
GLint param);
Parameters

light

Specifies a light.
The number of lights depends on the implementation,
but at least eight lights are supported.
They are identified by symbolic names of the form GL_LIGHT
i,
where i ranges from 0 to the value of GL_MAX_LIGHTS - 1.
pname

Specifies a single-valued light source parameter for light.
GL_SPOT_EXPONENT,
GL_SPOT_CUTOFF,
GL_CONSTANT_ATTENUATION,
GL_LINEAR_ATTENUATION, and
GL_QUADRATIC_ATTENUATION are accepted.
param

Specifies the value that parameter pname of light source light
will be set to.

事實上,此函數遠遠不如看起來的那么簡單,上面說了,因為光照屬于比較容易影響顯示效果的因素,所以光照的用法很多,上述的pname參數指定的n個值就可見一斑。但是本例中使用的方式卻很簡單,僅僅使用此函數來設定0號光源的位置而已。光照的分類其實包括環境光,散射光,鏡面光,發射光(實際指物體的發射顏色emissive color)等屬性,這里不詳述了。

    
      glLightfv
    
    
(
    
      GL_LIGHT0
    
    
, 
    
      GL_POSITION
    
    
, 
    
      light_position
    
    
);
  

因為光照模型的位置指定是使用了模型視圖,所以我們也可以用模型變換的方式來指定光源的位置,就像光源是個普通的物體一樣,此例中使用了旋轉模型視圖的函數旋轉了光源的位置,旋轉方式是以Y軸為旋轉軸,看到的效果也就是如視頻所示,類似月相變化的動畫。

3.創建和選擇光照模型

光照在OpenGL中有兩種模型,一種叫無限遠觀察者模式,一種叫本地觀察者模式,通過glLightModel*函數設置,默認為無限遠觀察者模型,這里沒有修改,即使用了默認值,區別在于是否考慮到觀察者位置對物體觀察角度不同引起變化,相對來說本地觀察者模型會更加逼真一些,但是因為有額外的光照計算,性能也會受到影響。。。。按照OpenGL管理,默認選擇的往往是性能更優的,而不是效果更好的。但是,就這么簡單的例子,我看不出區別。

OpenGL Programming Guide 》:

glLightModel — set the lighting model parameters
C Specification
void glLightModelf( GLenum pname,
GLfloat param);
void glLightModeli( GLenum pname,
GLint param);
Parameters

pname

Specifies a single-valued lighting model parameter.
GL_LIGHT_MODEL_LOCAL_VIEWER,
GL_LIGHT_MODEL_COLOR_CONTROL, and
GL_LIGHT_MODEL_TWO_SIDE are accepted.
param

Specifies the value that param will be set to.

我們可以通過

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

的調用切換至本地觀察者模型。

4.定義物體的材料屬性

光是定義了光源而不定義物體怎么反射光,在OpenGL中是不行的,物體的材料屬性決定了其將會怎么對光進行反應,與光源屬性對應,也有幾種與反射光相關材料屬性可以設置。我們通過glMateriall*來設置材料屬性。

OpenGL Programming Guide 》:

glMaterial — specify material parameters for the lighting model
C Specification

void glMaterialfv( GLenum face,
GLenum pname,
const GLfloat * params);
void glMaterialiv( GLenum face,
GLenum pname,
const GLint * params);
Parameters

face

Specifies which face or faces are being updated.
Must be one of
GL_FRONT,
GL_BACK, or
GL_FRONT_AND_BACK.
pname

Specifies the material parameter of the face or faces that is being updated.
Must be one of
GL_AMBIENT,
GL_DIFFUSE,
GL_SPECULAR,
GL_EMISSION,
GL_SHININESS,
GL_AMBIENT_AND_DIFFUSE, or
GL_COLOR_INDEXES.
params

Specifies a pointer to the value or values that pname will be set to.

上例中:

    
      GLfloat mat_specular
    
    
[] = { 1.0, 0.0, 0.0, 1.0 };

    
      GLfloat mat_shininess
    
    
[] = { 50.0 };

    
      GLfloat mat_ambient
    
    
[] = { 1.0, 0.0, 0.0, 1.0 };

    
      GLfloat mat_diffuse
    
    
[] = { 1.0, 0.0, 0.0, 1.0 };


    
      glMaterialfv
    
    
(
    
      GL_FRONT
    
    
, 
    
      GL_SPECULAR
    
    
, 
    
      mat_specular
    
    
);

    
      glMaterialfv
    
    
(
    
      GL_FRONT
    
    
, 
    
      GL_SHININESS
    
    
, 
    
      mat_shininess
    
    
);

    
      glMaterialfv
    
    
(
    
      GL_FRONT
    
    
, 
    
      GL_AMBIENT
    
    
, 
    
      mat_ambient
    
    
);

    
      glMaterialfv
    
    
(
    
      GL_FRONT
    
    
, 
    
      GL_DIFFUSE
    
    
, 
    
      mat_diffuse
    
    
);
  

這樣8行,定義了4中材料的屬性,并且我們都是使用GL_FRONT定義正面受到光照(即默認背面無光照),GL_SPECULAR表示鏡面顏色,GL_SHININESS表示鏡面指數,GL_AMBIENT表示環境顏色,GL_DIFFUSE表示散射顏色,其中散射顏色和環境顏色影響物體所反色的散射光和環境光顏色,(與光源屬性對應)有直接光照時,人體主要感知還是以散射顏色為主,無光照時,環境顏色才會占重要地位。鏡面顏色決定鏡面反射產生的亮點,GL_SHININESS參數設置亮點的大小和亮度,發射光顏色會讓物體微微發光(此例未用)。因為比較復雜,上述文字僅僅大概描述了一個概念,具體的參數還是參考《 OpenGL Programming Guide 》 并且實際的調整不同數值體驗效果為好。其中,《 OpenGL Programming Guide 》一書中推薦的 Nate Robin的OpenGL教程 的教學程序程序中有兩個實例與光照有關,能夠體驗數值改變時顯示的效果。假如大家不想自己編程調試,可以使用教程中的lightposition,lightmateria兩個例子體驗。

本系列其他文章見OpenGL專題 《 Win32 OpenGL系列專題

參考資料

1. 《 OpenGL Reference Manual 》,OpenGL參考手冊

2. 《OpenGL 編程指南》(《 OpenGL Programming Guide 》),Dave Shreiner,Mason Woo,Jackie Neider,Tom Davis 著,徐波譯,機械工業出版社

3. 《Nehe OpenGL Tutorials》,Nehe著,在 http://nehe.gamedev.net/ 上可以找到教程及相關的代碼下載,(有PDF版本教程下載)Nehe自己還做了一個面向對象的框架,作為演示程序來說,這樣的框架非常合適。也有 中文版 ,各取所需吧。

4. 《OpenGL入門學習》 ,eastcowboy著,這是我在網上找到的一個比較好的教程,較為完善,而且非常通俗。這是第一篇的地址: http://bbs.pfan.cn/post-184355.html

完整源代碼獲取說明

由于篇幅限制,本文一般僅貼出代碼的主要關心的部分,代碼帶工程(或者makefile)完整版(如果有的話)都能用Mercurial在Google Code中下載。文章以博文發表的日期分目錄存放,請直接使用Mercurial克隆下庫:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法見《 分布式的,新一代版本控制系統Mercurial的介紹及簡要入門

要是僅僅想瀏覽全部代碼也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

原創文章作者保留版權 轉載請注明原作者 并給出鏈接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

Win32 OpenGL編程(11) 光照


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日本国产视频 | 亚洲成人免费网站 | 国产精品久久久久久久久久久久 | 欧美黑人玩白人巨大极品 | 一级免费看片 | 久久99草| 国产精品玖玖玖在线观看 | 青娱乐免费视频在线观看 | 午夜影晥 | 亚洲综合图片人成综合网 | 99精品视频一区在线视频免费观看 | 午夜影视网 | 极品嫩模私拍后被潜在线观看 | 在线观看视频一区 | 爽毛片 | 日日操日日操 | 免费看成年人网站 | 国产精品va在线观看无 | 最新国产网址 | 国产99久久精品一区二区 | 香蕉成人啪国产精品视频综合网 | 色婷婷久久免费网站 | 日韩一区中文字幕 | 中文字幕一区二区三区四区不卡 | 我的朋友丈夫 | 久久久久久国产精品免费免费 | 日韩婷婷 | 久久久国产一区二区三区 | 91精品久久 | 亚洲国产成人在线视频 | 91文字幕巨乱亚洲香蕉 | 毛片免费观看网址 | 欧美精品导航 | 国产亚洲欧洲国产综合一区 | 日韩在线观看视频网站 | 国产亚洲精品精品国产亚洲综合 | 日韩在线播放一区 | 色爱综合区五月小说 | 1024污视频 | 亚洲精品第一国产综合高清 | 久久国产精品视频 |