• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            3D圖形數學(1)

            新建網頁 1

             

            圖形管道概述

            我們將討論渲染一幅帶有基本光照的單個圖像的大體過程,這里不考慮動畫和全局光照,如陰影和輻射度。

            此外,注意這里只從概念上講解通過圖形管道的數據流,其順序并不是固定的。實踐中,我們也許會為了性能的優化而并行或亂序執行一些任務。比如,考慮到不同的渲染API,我們可能首先變換和照明所有頂點,然后才進一步的處理(進行裁剪和剔除),或者會并行處理二者,也可能在背面剔除之后再進行光照會得到更高效率。

            還有一個我們將不詳細討論的要點,即工作負擔如何在CPU與渲染硬件間分配。正確地組織渲染任務,以求得最大的并行效果對高效渲染是至關重要的。

            考慮上述簡化,就得到了圖形管道中數據流的概況,如下所示:

            (1)建立場景:開始渲染之前,需要預先設定對整個場景有效的一些選項。比如,要建立攝像機位置,或者更具體些,要選擇進行渲染的出發點---視點,渲染的輸出---視圖。還需要設定光照與霧化選項,同時準備z緩沖。

            (2)可見性檢測:選好了攝像機,就必須檢測場景中哪些物體是可見的。可見性檢測對實時渲染極為重要,因為我們不愿意浪費時間去渲染那些根本看不到的東西。

            (3)設置物體級的渲染狀態:一旦發現某物體潛在可見,就到了把它實際繪制出來的時候。每個物體的渲染設置可能是不同的,在渲染該物體的任何片元之前,首先要設置上述選項,最常見的此類選項是紋理映射。

            (4)幾何體的生成與提交:接著實際向API提交幾何體,通常提交的數據是種種形式的三角形,或是獨立的三角形,或是索引三角網格與三角帶。此階段,我們可能會應用LOD,或者漸進式生成幾何體。

            (5)變換與光照:一旦渲染API得到了三角形數據,由模型空間向攝像機空間的頂點坐標轉換與頂點光照計算即開始。

            (6)背面剔除與裁剪:然后,那些背對攝像機的三角形被去除("背面剔除");三角形在視椎外的部分也被去除,稱作裁剪---這可能導致產生多于三個邊的多邊形。

            (7)投影到屏幕空間:在3D裁剪空間中經裁剪產生的多邊形,被投影到輸出窗口的2D屏幕空間里。

            (8)光柵化:當把裁剪后的多邊形轉換到屏幕空間后,就到了光柵化階段。光柵化指計算應繪制三角形上的哪些像素的過程,并為接下來的像素著色階段提供合理的插值參數(如光照和紋理映射坐標)。

            (9)像素著色:最后,在管道的最后階段計算三角形的色彩,此過程稱作"著色"。接著把這些顏色寫至屏幕,這是可能需要alpha混合與z緩沖。

            下面的偽代碼描述了渲染管道,為了達到概觀的目的,大量細節被省去了。同時,由于渲染平臺和API的不同,實踐中會有許多不同的形式。

                Listing 15.1: Pseudocode for the graphics pipeline
               
               
            // First, figure how to view the scene
               
            setupTheCamera();
               
               
            // Clear the zbuffer
               
            clearZBuffer();
               
               
            // Setup environmental lighting and fog
               
            setGlobalLightingAndFog();
               
               
            // Get a list of objects that are potentially visible
               
            potentiallyVisibleObjectList = highLevelVisibilityDetermination(scene);
               
               
            // Render everything we found to be potentially visible
               
            for (all objects in potentiallyVisibleObjectList) 
                {
                    
            // Perform lower-level VSD using bounding volume test
               
                if (!object.isBoundingVolumeVisible()) 
                        
            continue;
               
                    
            // Fetch or procedurally generate the geometry
               
                triMesh = object.getGeometry()
               
                    
            // Clip and render the faces
               
                for (each triangle in the geometry) 
                    {
                        
            // Transform the vertices to clip space, and perform vertex-level lighting
               
                    clipSpaceTriangle = transformAndLighting(triangle);
               
                        
            // Is the triangle backfacing?
               
                    if (clipSpaceTriangle.isBackFacing()) continue;
               
                        
            // Clip the triangle to the view volume
               
                    clippedTriangle = clipToViewVolume(clipSpaceTriangle);
               
                        
            if (clippedTriangle.isEmpty()) 
                            
            continue;
               
                        
            // Project the triangle onto screen space and rasterize
               
                    clippedTriangle.projectToScreenSpace();
               
                        
            for (each pixel in the triangle) 
                        {
                            
            // Interpolate color, zbuffer value, and texture mapping coords
               
                            // Perform zbuffering and alpha test
               
                        if (!zbufferTest()) 
                                
            continue;
               
                            
            if (!alphaTest()) 
                                
            continue;
               
                            
            // Shade the pixel.
               
                        color = shadePixel();
               
                            
            // Write to the frame buffer and zbuffer
               
                        writePixel(color, interpolatedZ);
                        }
                    }
                }

            設定視圖參數

            渲染場景之前,首先必須建立攝像機和輸出窗口。即必須決定從哪個位置進行觀察渲染(視點位置、方向、縮放)以及把渲染結果送到哪里(屏幕上的目標矩形區域)。上述二者中,輸出窗口較為簡單,故先討論輸出窗口。

             

            指定輸出窗口

            我們不一定要把圖像渲染到整個屏幕。比如,一個分屏的多人游戲,每個玩家只占據顯示屏幕的一部分。輸出窗口即指輸出設備中圖像將要渲染到的那部分,如圖15.1所示:

            窗口位置由左上角像素(winPosxwinPosy給出,整數winResxwinResy是以像素為單位的窗口大小,如此定義,使用窗口大小而不是右下角的坐標,可避免整數像素坐標系帶來一些麻煩。同時要注意窗口的實際物體大小和像素大小的區別。

            要知道我們不一定在屏幕上渲染,也許只是將渲染結果保存到一個TGA文件里,或是AVI的一幀,也許只是渲染到一個紋理上---作為主渲染器的一個子過程而已,因此,名詞"幀緩沖"一般指用來保存我們正渲染圖像的那塊內存。

             

            像素縱橫比

            不管是渲染到屏幕還是緩沖區,我們必須知道像素的縱橫比。它是像素高對寬的比值,一般為1("方形"像素),不過并非總是如此。下面給出其計算公式(公式5.1):

            pixPhys指像素物理尺寸。一般來說,度量單位并無關系,比例才是重要的。devPhys是顯示設備的物理高與寬比,尺寸可能是英寸、英尺、picas等,但也只有比例才是重要的。比如,標準的桌面顯示器,尺寸各異但卻擁有相同的比值4:3---視區寬大于高約33%。另一個常見比例是高清晰電視和DVD上的16:9。整數devResxdevResy是x、y方向的像素比,如640 x 480devResx=640,devResy=480。

            如前所述,比值為1的方形像素最為常見。如標準桌面顯示器,有4:3的物理縱橫比,而許多常見解析度:320 x 240640 x 480800 x 600,1024x 7681600 x 1200也都是4:3,因此像素是方形的。

            注意計算中未用到窗口的尺寸及位置,這是合理的,窗口性質不影響像素的物理屬性。但是,窗口尺寸在視場問題中十分重要,而位置對攝像機到屏幕的映射是關鍵。

             

            是攝像機可見的空間體積,看上去像截掉頂部的金字塔,如圖15.2所示:

            視錐是由6個裁剪面圍成的。構成視錐的4個側面稱為上、左、下、右面,它們對應著輸出窗口的四邊。為防止物體離攝像機過近,設置近剪面,從而去除金字塔形的頂端。同理,也設置了視野的遠端,因為太遠的物體實際上太小而不可見,故可有效而安全地去掉。

             

            視場與縮放

            攝像機同其他物體一樣有位置和朝向,同時它還具有"視場"這一額外的屬性。另一名詞"縮放"你也許已經很熟悉,直觀上,你早就知道放大和縮小。但拉近時,物體顯大;拉遠時,物體顯小,這太常見了。

            視場是視錐所截的角。實際上需要兩個角:分別對應水平視場和垂直視場。這里只在2D中討論其中一個,圖15.3從上方顯示了視錐,精確的展示了水平視場角,坐標軸的標記用的是攝像機空間。

            縮放表示物體實際大小和物體在90視場中顯示大小的比。所以大比值表示放大,小比值表示縮小。比如,2.0的縮放表示物體在屏幕上比用90視場時大兩倍。縮放的幾何解釋如圖15.4所示:

            應用基本三角知識,就能推導出縮放和視場角之間的轉換公式:

            在3D中,需要兩個縮放值,一個水平的,一個垂直的。可以隨意給值,但如果二者比例不恰當,圖像便像被拉伸過似的(好比寬銀幕電影在電視上播出)。為了維持恰當的比例,縮放要和輸出窗口的尺寸對應:

            假設輸出為正常比例,許多渲染引擎允許僅用一個視場角(或zoom)設定攝像機,然后自動計算另一個。例如,可以指定水平視場角,自動計算垂直視場角,反之亦然;或者指定視場角中較大的一個,自動計算較小的。

            posted on 2008-03-04 19:47 lovedday 閱讀(2299) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            国产精品一区二区久久精品无码| 久久国产亚洲精品| 99精品国产在热久久无毒不卡| 精品熟女少妇a∨免费久久| 热re99久久精品国产99热| 日本亚洲色大成网站WWW久久 | 亚洲AV无码成人网站久久精品大| 国产一区二区久久久| 99麻豆久久久国产精品免费| 欧美精品福利视频一区二区三区久久久精品| 久久亚洲国产最新网站| 99久久精品免费看国产一区二区三区 | 99久久精品费精品国产一区二区| 国产精品九九久久免费视频 | 69久久精品无码一区二区| 欧美日韩中文字幕久久久不卡| 精品熟女少妇AV免费久久| 欧美激情精品久久久久| 精品久久久久香蕉网| 久久久一本精品99久久精品88| 精品水蜜桃久久久久久久| 99久久99久久精品免费看蜜桃| 久久久久久久免费视频| 久久久久人妻一区精品| 久久精品国产91久久麻豆自制| 久久亚洲精精品中文字幕| 少妇被又大又粗又爽毛片久久黑人 | 99久久精品免费| 国产精品无码久久综合| 色综合久久无码中文字幕| 久久青青国产| 免费一级做a爰片久久毛片潮| 精品视频久久久久| 久久精品国产精品亚洲下载| 国产精品免费看久久久香蕉| 久久青草国产精品一区| 久久美女人爽女人爽| 国产精品美女久久久网AV| 久久WWW免费人成—看片| 久久久久亚洲?V成人无码| 欧美性大战久久久久久|