<h3>使用光源</h3> <p>要模擬真實世界,僅有環境光是不夠的,須要指定更多的光源來提高真實感。OpenGL至少提供8種光源,能夠在場景中的任意位置甚至是可視區域以外。你能夠指定光源位於無限遠處以得到平行光束,或者光源位於近處向外發射光束。還能夠製造出聚光燈的效果。</p> <h4>選擇哪一種方式?</h4> <p>你能夠指定一個光源位於哪裏朝哪一個方向發射光線。一般光源朝全部方向發射光線,但也能夠爲它指定方向。在指定的方向的光源環境下,並不是每一個多邊形都須要被照射到。咱們能夠製造物體的陰影效果。OpenGL能夠計算光線和物體的角度。</p> <p>以下圖:光源發射出的光線照射到四邊形上,造成一個入射角,再反射到觀察者眼中造成一個反射角。根據這個入射角和反射角結合光源和材料的屬性咱們能夠計算出該點應呈現出什麼樣的顏色。</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225236_46lU.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225237_9mjX.png" width="465" height="190"></a></p> <p>在編程的角度上看,每個多邊形由一系列的頂點建立的。多邊形就是由點組成的,那麼如何計算光線與點之間的角度。咱們沒法在3D空間中找到一個切確的線與點之間的角度,所以咱們爲每個點設置一個法線。三維平面的法線是垂直於該平面的三維<a href="http://zh.wikipedia.org/wiki/%E5%90%91%E9%87%8F">向量</a>。曲面在某點P處的法線爲垂直於該點<a href="http://zh.wikipedia.org/w/index.php?title=%E5%88%87%E5%B9%B3%E9%9D%A2&action=edit&redlink=1">切平面</a>的向量。(wiki)</p> <h4>平面法線</h4> <p>法線向量是一條垂直於真實平面或虛擬平面的線。下圖是2D和3D中的法線向量。</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225238_BWnE.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225238_KA4G.png" width="477" height="172"></a></p> <p>爲何須要爲每一個頂點設置法線向量,而不是爲一個多邊形指定一個法線向量。其中的緣由是,並非全部的物體的表面都是平的,有時法線向量並不須要精確地垂直於物體的表面。經過扭曲平面的法線向量能夠製造出光滑的曲面的視覺效果。</p> <h4>指定法線</h4> <p><a href="http://static.oschina.net/uploads/img/201310/10225238_X3Df.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225239_pecf.png" width="562" height="297"></a></p> <p>如上圖:爲多邊形的頂點(1,1,0)處指定一個法線向量,咱們能夠選定一另個點(1,10,0),並以(1,1,0)爲起點鏈接第二個點(1,10,0),所造成的線就是法線向量。第二個點說明了法線向量的方向是y軸向上。法線向量的方向還能夠用於代表多邊形的正面和反面。法線是由正面指向外面的(或者說從法線的箭頭方向往下看到的就是多邊形的正面)。</p> <p>用法線的第二個點減去第一個頂點,所得的結果就是相對於x、y和z的單位距離。 <p> (1,10,0) - (1,1,0) = (0,9,0) <p>若是把這個頂點移動到原點,上面兩點相減得出的點指定了和表面呈90度角的方向。以下圖:</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225239_OcrL.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Image[1]" border="0" alt="Image[1]" src="http://static.oschina.net/uploads/img/201310/10225240_94EX.png" width="504" height="371"></a></p> <p>向量的方向告訴OpenGL頂點所在多邊形的面朝哪一個方向的。下面的例子演示如何指定法線向量 <p>glBegin(GL_TRIANGLES); <p> glNormal3f(0.0f, -1.0f, 0.0f); <p> glVertex3f(0.0f, 0.0f, 60.0f); <p> glVertex3f(-15.0f, 0.0f, 30.0f); <p> glVertex3f(15.0f, 0.0f, 30.0f); <p>glEnd(); <p>glNormal3f接受3個表示座標的值,指定一條垂直於三角形表面的法線向量。上面的例子的三個頂點的法線具備相同的方向。 <h4>單位法線</h4> <p>單位法線即長度爲1的法線向量。已知法線向量(x,y,z)求單位法線,先求出法線向量的長度即<a href="http://static.oschina.net/uploads/img/201310/10225241_rGVv.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225242_OTHI.png" width="240" height="87"></a>,再用(x,y,z)除以這個長度,就獲得單位法線。這個過程叫歸一化(normalization)。在光照計算的中全部的法線向量都會歸一化。</p> <p>可讓OpenGL自動把法線向量轉換爲單位法線,經過調用glEnable接受一個參數GL_NORMALIZE;</p> <p>glEnable(GL_NORMALIZE);</p> <p>這種作法在某些實現上,會帶來性能的開銷。最好的方式在指定法線向量的時候,就直接指定爲單位法線,而不是依靠OpenGL來幫你作轉換。</p> <p><font style="background-color: #ffff00">PS:glScale縮放函數也會縮放法線的長度。若是一塊兒使用glScale和光照,有可能會獲得不是你想要的光照效果。</font></p> <p>若是每一個頂點指定的法線都是單位法線,而且glScale使用相同的比例進行縮放的狀況下,有一個替代方案是使用GL_RESCALE_NORMALS替代GL_NORMALIZE.</p> <p>glEnable(GL_RESCALE_NORMALS);</p> <p>這樣就告訴了OpenGL,你的法線向量不是單位長度的,可是能夠經過相同比例因子的縮放來把它轉化爲單位長度(單位法線)。這樣OpenGL會檢查你的模型視圖變換矩陣來逆轉換。這樣在每一個頂點所作的數學操做要少一些。</p> <p>我的理解:</p> <p>一個單位法線向量(1.0,1.0,1.0),在進行過glScalef(2.0, 2.0, 2.0)以後,就變爲了(2.0,2.0,2.0),那麼在啓用了GL_RESCALE_NORMALS以後,OpenGL會檢查模型視圖矩陣得知,能夠經過反向的縮放把法線向量轉換會單位法線即等比例的縮小2倍乘以0.5.又獲得了(1.0, 1.0, 1.0)。</p> <p>PS:最佳實踐是在一開始爲頂點指定法線時,就指定爲單位法線。</p> <h4>尋找法線</h4> <p>當一個多邊形不平行於任何一個軸面時,經過簡單的觀察來指定一個法線會比較困難。因此須要一個簡單的方法來計算3D空間中任意多邊形的法線。</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225242_otEG.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225243_xVh3.png" width="525" height="270"></a></p> <p>能夠經過多邊形上的任意三個點來計算法線。</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225243_vtfO.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225244_bx8r.png" width="544" height="220"></a></p> <p>如上圖,知道了P1,P2,P3點以後。由P1和P2能夠求出向量V1,P1和P3能夠求出向量V2,再用V1 X V2(叉乘)計算得出正交於V1和V2的法線向量。</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225244_260n.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225246_vjUX.png" width="561" height="236"></a></p> <p>math3d代碼示例:</p> <div><pre class="csharpcode"><span class="kwrd">void</span> m3dFindNormal(M3DVector3f vNormal, <span class="kwrd">const</span> M3DVector3f vP1, <span class="kwrd">const</span> M3DVector3f vP2, <span class="kwrd">const</span> M3DVector3f vP3)<br>{<br> M3DVector3f v1, v2;<br> v1[0] = vP2[0] - vP1[0];<br> v1[1] = vP2[1] - vP1[1];<br> v1[2] = vP2[2] - vP1[2];<br><br> v2[0] = vP3[0] - vP1[0];<br> v2[1] = vP3[1] - vP1[1];<br> v2[2] = vP3[2] - vP1[2];<br><br> m3dCrossProduct(vNormal, v1, v2);<br>}</pre></div> <h4>設置光源</h4> <p>建立一個位於左上角的溫和的白光光源。</p> <div id="codeSnippetWrapper"><pre id="codeSnippet" class="csharpcode">GLfloat ambientLight[] = {0.3f, 0.3f, 0.3f, 1.0f};<br>GLfloat diffuseLight[] = {0.7f, 0.7f, 0.7f, 1.0f};<br><br><span class="rem">//設置和開啓光源light0</span><br>glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);<br>glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);<br><br><span class="rem">//開啓光照</span><br>glEnable(GL_LIGHT0);<br><br><span class="rem">//設置光源位置</span><br>GLfloat lightPos[] = {-50.f, 50.f, 100.0f, 1.0f};<br>glLightfv(GL_LIGHT0, GL_POSITION, lightPos);<br><br><br></pre><br></div> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <div> </div> <div>lightPos中最後一個值1.0說明這個lightPos指定了光源的位置,若是這個值是0.0,則指定了光源在無限遠處。 <h4>設置材料屬性</h4> <p>開啓顏色追蹤</p> <p>glEnable(GL_COLOR_MATERIAL);</p> <p>glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);</p> <h4>設置多邊形和法線向量</h4> <div id="codeSnippetWrapper"><pre id="codeSnippet" class="csharpcode">...<br>...<br>{<br> M3DVector3f vPoints[3] = {{ 15.0f, 0.0f, 30.0f},<br> { 0.0f, 15.0f, 30.0f},<br> { 0.0f, 0.0f, 60.0f}};<br><br> <span class="rem">// 計算法線向量</span><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> } <br>...<br>... </pre><br></div>噴氣式飛機的完整代碼:</div> <div id="codeSnippetWrapper"><pre id="codeSnippet" class="csharpcode"><span class="rem">// LitJet.cpp</span><br><span class="rem">// OpenGL SuperBible</span><br><span class="rem">// Demonstrates OpenGL Lighting</span><br><span class="rem">// Program by Richard S. Wright Jr.</span><br><br><span class="preproc">#include</span> <span class="str">"gltools.h"</span> <span class="rem">// gltools library</span><br><span class="preproc">#include</span> <span class="str">"math3d.h"</span> <span class="rem">// 3D Math Library</span><br><br><span class="rem">// Rotation amounts</span><br><span class="kwrd">static</span> GLfloat xRot = 0.0f;<br><span class="kwrd">static</span> GLfloat yRot = 0.0f;<br><br><br><span class="rem">// Called to draw scene</span><br><span class="kwrd">void</span> RenderScene(<span class="kwrd">void</span>)<br>{<br> M3DVector3f vNormal; <span class="rem">// Storeage for calculated surface normal</span><br><br> <span class="rem">// Clear the window with current clearing color</span><br> glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br><br> <span class="rem">// Save the matrix state and do the rotations</span><br> glPushMatrix();<br> glRotatef(xRot, 1.0f, 0.0f, 0.0f);<br> glRotatef(yRot, 0.0f, 1.0f, 0.0f);<br><br><br> <span class="rem">// Nose Cone - Points straight down</span><br> <span class="rem">// Set material color</span><br> glColor3ub(128, 128, 128);<br> glBegin(GL_TRIANGLES);<br> glNormal3f(0.0f, -1.0f, 0.0f);<br> glNormal3f(0.0f, -1.0f, 0.0f);<br> glVertex3f(0.0f, 0.0f, 60.0f);<br> glVertex3f(-15.0f, 0.0f, 30.0f);<br> glVertex3f(15.0f,0.0f,30.0f);<br><br><br> <span class="rem">// Verticies for this panel</span><br> {<br> M3DVector3f vPoints[3] = {{ 15.0f, 0.0f, 30.0f},<br> { 0.0f, 15.0f, 30.0f},<br> { 0.0f, 0.0f, 60.0f}};<br><br> <span class="rem">// Calculate the normal for the plane</span><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> } <br><br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f, 0.0f, 60.0f },<br> { 0.0f, 15.0f, 30.0f },<br> { -15.0f, 0.0f, 30.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> <span class="rem">// Body of the Plane ////////////////////////</span><br> {<br> M3DVector3f vPoints[3] = {{ -15.0f, 0.0f, 30.0f },<br> { 0.0f, 15.0f, 30.0f },<br> { 0.0f, 0.0f, -56.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f, 0.0f, -56.0f },<br> { 0.0f, 15.0f, 30.0f },<br> { 15.0f,0.0f,30.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> glNormal3f(0.0f, -1.0f, 0.0f);<br> glVertex3f(15.0f,0.0f,30.0f);<br> glVertex3f(-15.0f, 0.0f, 30.0f);<br> glVertex3f(0.0f, 0.0f, -56.0f);<br><br> <span class="rem">///////////////////////////////////////////////</span><br> <span class="rem">// Left wing</span><br> <span class="rem">// Large triangle for bottom of wing</span><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f,2.0f,27.0f },<br> { -60.0f, 2.0f, -8.0f },<br> { 60.0f, 2.0f, -8.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> {<br> M3DVector3f vPoints[3] = {{ 60.0f, 2.0f, -8.0f},<br> {0.0f, 7.0f, -8.0f},<br> {0.0f,2.0f,27.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{60.0f, 2.0f, -8.0f},<br> {-60.0f, 2.0f, -8.0f},<br> {0.0f,7.0f,-8.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{0.0f,2.0f,27.0f},<br> {0.0f, 7.0f, -8.0f},<br> {-60.0f, 2.0f, -8.0f}};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> <span class="rem">// Tail section///////////////////////////////</span><br> <span class="rem">// Bottom of back fin</span><br> glNormal3f(0.0f, -1.0f, 0.0f);<br> glVertex3f(-30.0f, -0.50f, -57.0f);<br> glVertex3f(30.0f, -0.50f, -57.0f);<br> glVertex3f(0.0f,-0.50f,-40.0f);<br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f,-0.5f,-40.0f },<br> {30.0f, -0.5f, -57.0f},<br> {0.0f, 4.0f, -57.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f, 4.0f, -57.0f },<br> { -30.0f, -0.5f, -57.0f },<br> { 0.0f,-0.5f,-40.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{ 30.0f,-0.5f,-57.0f },<br> { -30.0f, -0.5f, -57.0f },<br> { 0.0f, 4.0f, -57.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f,0.5f,-40.0f },<br> { 3.0f, 0.5f, -57.0f },<br> { 0.0f, 25.0f, -65.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> {<br> M3DVector3f vPoints[3] = {{ 0.0f, 25.0f, -65.0f },<br> { -3.0f, 0.5f, -57.0f},<br> { 0.0f,0.5f,-40.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br> {<br> M3DVector3f vPoints[3] = {{ 3.0f,0.5f,-57.0f },<br> { -3.0f, 0.5f, -57.0f },<br> { 0.0f, 25.0f, -65.0f }};<br><br> m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);<br> glNormal3fv(vNormal);<br> glVertex3fv(vPoints[0]);<br> glVertex3fv(vPoints[1]);<br> glVertex3fv(vPoints[2]);<br> }<br><br><br> glEnd();<br><br> <span class="rem">// Restore the matrix state</span><br> glPopMatrix();<br> <span class="rem">// Display the results</span><br> glutSwapBuffers();<br>}<br><br><span class="rem">// This function does any needed initialization on the rendering</span><br><span class="rem">// context. </span><br><span class="kwrd">void</span> SetupRC()<br>{<br> <span class="rem">// Light values and coordinates</span><br> GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };<br> GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };<br><br> glEnable(GL_DEPTH_TEST); <span class="rem">// Hidden surface removal</span><br> glFrontFace(GL_CCW); <span class="rem">// Counter clock-wise polygons face out</span><br> glEnable(GL_CULL_FACE); <span class="rem">// Do not calculate inside of jet</span><br><br> <span class="rem">// Enable lighting</span><br> glEnable(GL_LIGHTING);<br><br> <span class="rem">// Setup and enable light 0</span><br> glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);<br> glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);<br> glEnable(GL_LIGHT0);<br><br> <span class="rem">// Enable color tracking</span><br> glEnable(GL_COLOR_MATERIAL);<br><br> <span class="rem">// Set Material properties to follow glColor values</span><br> glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);<br><br> <span class="rem">// Light blue background</span><br> glClearColor(0.0f, 0.0f, 1.0f, 1.0f );<br><br> glEnable(GL_NORMALIZE);<br>}<br><br><span class="rem">/////////////////////////////////////////////////////</span><br><span class="rem">// Handle arrow keys</span><br><span class="kwrd">void</span> SpecialKeys(<span class="kwrd">int</span> key, <span class="kwrd">int</span> x, <span class="kwrd">int</span> y)<br>{<br> <span class="kwrd">if</span>(key == GLUT_KEY_UP)<br> xRot-= 5.0f;<br><br> <span class="kwrd">if</span>(key == GLUT_KEY_DOWN)<br> xRot += 5.0f;<br><br> <span class="kwrd">if</span>(key == GLUT_KEY_LEFT)<br> yRot -= 5.0f;<br><br> <span class="kwrd">if</span>(key == GLUT_KEY_RIGHT)<br> yRot += 5.0f;<br><br> <span class="kwrd">if</span>(key > 356.0f)<br> xRot = 0.0f;<br><br> <span class="kwrd">if</span>(key < -1.0f)<br> xRot = 355.0f;<br><br> <span class="kwrd">if</span>(key > 356.0f)<br> yRot = 0.0f;<br><br> <span class="kwrd">if</span>(key < -1.0f)<br> yRot = 355.0f;<br><br> <span class="rem">// Refresh the Window</span><br> glutPostRedisplay();<br>}<br><br><br><span class="rem">//////////////////////////////////////////////////////////</span><br><span class="rem">// Reset projection and light position</span><br><span class="kwrd">void</span> ChangeSize(<span class="kwrd">int</span> w, <span class="kwrd">int</span> h)<br>{<br> GLfloat fAspect;<br> GLfloat lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };<br><br> <span class="rem">// Prevent a divide by zero</span><br> <span class="kwrd">if</span>(h == 0)<br> h = 1;<br><br> <span class="rem">// Set Viewport to window dimensions</span><br> glViewport(0, 0, w, h);<br><br> <span class="rem">// Reset coordinate system</span><br> glMatrixMode(GL_PROJECTION);<br> glLoadIdentity();<br><br> fAspect = (GLfloat) w / (GLfloat) h;<br> gluPerspective(45.0f, fAspect, 1.0f, 225.0f);<br><br> glMatrixMode(GL_MODELVIEW);<br> glLoadIdentity();<br><br> glLightfv(GL_LIGHT0,GL_POSITION,lightPos);<br> glTranslatef(0.0f, 0.0f, -150.0f);<br>}<br><br><span class="kwrd">int</span> main(<span class="kwrd">int</span> argc, <span class="kwrd">char</span>* argv[])<br>{<br> glutInit(&argc, argv);<br> glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);<br> glutInitWindowSize(800,600);<br> glutCreateWindow(<span class="str">"Lighted Jet"</span>);<br> glutReshapeFunc(ChangeSize);<br> glutSpecialFunc(SpecialKeys);<br> glutDisplayFunc(RenderScene);<br> SetupRC();<br> glutMainLoop();<br><br> <span class="kwrd">return</span> 0;<br>}<br></pre><br></div>php
<p>效果</p> <p><a href="http://static.oschina.net/uploads/img/201310/10225246_SIt6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://static.oschina.net/uploads/img/201310/10225247_pC89.png" width="244" height="240"></a></p>算法