1. 程式人生 > 實用技巧 >計算機圖形學

計算機圖形學

計算機圖形學期末複習

第一章 緒論

  • 計算機圖形學定義:計算機圖形學是研究通過計算機將資料轉換成圖形,並在專門顯示裝置上顯示的原理、方法和技術

第二章 計算機裝置及硬體系統

知識點

  • 陰極射線管(CRT)

  • 光柵掃描圖形顯示器:垂直回掃、水平回掃

  • 液晶顯示器

    • 工作原理:利用液晶的光電顯示效應,通過施加電壓改變液晶的光學特性,從而造成對入射光的調製,使通過液晶的透射光或反射光受所加電壓的控制,達到顯示的目的。

      (通過對液晶電場的控制可以實現光線的明暗變化,從而達到資訊顯示的目的)

  • 光柵掃描圖形顯示子系統的結構(p35)

    • 重要部件:幀緩衝儲存器、顯示控制器
    • 幀緩衝儲存器(視訊記憶體):儲存畫素的顏色(灰度)的儲存器,可由顯示控制器直接訪問
    • 顯示控制器:依據設定的顯示工作方式,讀取視訊記憶體裡的資料,並轉換成三原色並配以同步訊號給顯示器

注意事項

  • 液晶顯示器的亮度沒有CRT的高
  • 掃描轉換過程:畫素資訊從應用程式轉化並放入幀緩衝區的過程

第四章 圖形的表示與資料結構

  • 基本元素:
    • 定義:指可以用一定的幾何引數和屬性引數描述的最基本的圖形元素
    • 組成:點、線、面、環、體等
  • 幾何資訊與拓撲資訊:
    • 幾何資訊:一般指形體在歐氏空間的位置和大小
    • 拓撲資訊:形體各分量(點、線、面)的數目及相互間的連線關係(9中拓撲關係)

第五章 基本圖形生成演算法

  • 直線掃描轉換:

    數值微分法(DDA) 中點Bresenham演算法 Bresenham演算法
    判別式 有,取中點,判別d 有,判別誤差e
    取捨 四捨五入,有誤差 不做四捨五入 不作除法、無四捨五入
  • 多邊形的掃描轉換/多邊形填充:

    • 定義:從多邊形頂點表示點陣表示
    • x掃描線演算法:左閉右開的原則
    • 改進的有效邊表演算法(y連貫性演算法):
  • 邊緣填充演算法

  • 區域填充演算法

  • 反走樣:

    • 走樣(圖形失真):離散量表示連續量而引起的失真
    • 反走樣(圖形保真技術):用於減少或消除走樣的現象的技術
    • 造成走樣的原因:直線段或曲線段的數學描述是連續的,而光柵顯示器上顯示的直線段或曲線段是由一些離散的、面積不為0的畫素點組成的
    • 避免走樣的方法:
      • 過取樣(後濾波):在高於顯示解析度的較高解析度下用點取樣方法計算,然後對幾個畫素的屬性進行平均,得到較低解析度下的畫素屬性
      • 區域取樣(前濾波):根據圖形物件在每個畫素點上的覆蓋率來確定畫素點的亮度,這種計算覆蓋率的方法

第六章 二維變換級二維觀察

二維變換

  • 基本幾何變換都是相對於座標原點和座標軸進行的

裁剪

  • 直線段裁剪:編碼裁剪、中點分割裁剪、樑友棟演算法

  • 多邊形裁剪:

第七章 三維變換及三維觀察

三維變換

  • 注意:三維變換中,繞y軸的旋轉變換的特殊

三維觀察

(規定以逆時針旋轉方向為正向;三檢視:以Z軸正向朝上)

  • 平面幾何投影:

    • 透視投影:投影中心到投影面的距離有限
    • 平行投影:投影中心到投影面的距離無限
    • 正投影:三檢視、正軸側投影(對任意平面做投影)
      • 斜投影:投影方向不垂直於投影面;投影方向和投影面成45°

投影在x0y平面

  • 正軸測投影變換矩陣:

  • 斜軸測投影變換矩陣:

    • α=45°,β=30°或者45°
透視投影
  • 投影矩陣:(中間的為透視變換矩陣)
  • 主滅點:座標軸方向的平行線在投影面上形成的滅點

  • 根據主滅點個數分為:一點透視、二點透視、三點透視

  • 觀察座標系:

  • OpenGL中的變換

    • OpenGL視點變換函式:OpenGL視點變換函式用於確定觀察參考座標系,即確定視點的位置和觀察方向,預設情況視點位於原點,觀察方向為Z軸負向。

      void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz,GLdouble upx, GLdouble upy, GLdouble upz);
      
    • OpenGL投影函式

      • 平行投影:

      • 透視投影:

第八章 曲線與曲面

  • 樣條曲線中的邊界條件:自由端、夾持端、拋物端

  • 樣條曲線:

    • 定義:指由多項式曲線段連線而成的曲線,在每段的邊界處滿足特定的連續條件
  • hermite插值樣條:

    • 可以區域性調整,因為每個曲線段僅依賴於端點約束
    • 當曲線的端點及端點的切線方向確定時,若給定不同的切線長度,將有不同形狀的Hermite曲線。
  • Bezier曲線/曲面:

    • 是一個階數比控制點少一的多項式
    • 只有第一個點和最後一個點在曲線上
    • 不能對曲線形狀進行區域性控制,任意改變一控制點,整條曲線受影響
    • Bezier曲線的性質:
      • 端點:曲線總是通過起點和終點
      • 一階導數:起點的切線位於前兩個控制點的連線上,終點的切線位於最後兩個的連線上
      • 二階導數:曲線在起始點和終止點處的r階導數由起點或終止點和它們的r個相鄰的控制點決定
      • 對稱性
      • 凸包性:
      • 幾何不變性:曲線形狀只與控制多邊形各頂點的相對位置有關,與座標系的選擇無關
      • 變差減少性:曲線比控制多邊形更加光滑
      • 控制頂點變化對曲線形狀的影響
  • B樣條曲線/曲面:

    • 性質:

第九、十章 消隱、真實感圖形繪製

消隱

  • 物體空間的消隱演算法:是將物體表面上的k個多邊形中的每一個面與其餘的k-1個面進行比較,精確地求出物體上每條稜邊或每個面的遮擋關係(多 邊形的區域排序演算法)
  • 影象空間的消隱演算法:對螢幕的每一畫素進行判斷,以決定物體上哪個多邊形在該畫素點上是可見的(如深度快取演算法)

簡單光照模型

入射光=反射光+透射光+散射光+吸收光
簡單光反射模型=漫反射光+環境光+鏡面反射光

  • 環境光:是光在物體和周圍環境之間多次反射的結果,即是來自周圍的環境對光的反射。環境光的特點是:它不是直接自光源,而是照射在物體上的光來自周圍各個方向,且又均勻地向各個方向反射

    Ie=Ia·Ka

  • 漫反射光:漫反射光是在光的照射下,物體表面發射的反射光均勻地射向各個方向

    Id=Ip·Kd·cos(a)

  • 鏡面反射光:鏡面反射是點光源照射在一個與物體光澤的表面(如鏡子、光亮的金屬等)有關的反射光。它的特點是光源來自一個光方向,並沿某特定方向(反射方向)離開

  • OpenGL繪製函式:

    • OpenGL消隱處理:

    • OpenGL光照與材質:

    • OpenGL紋理貼圖:

程式設計

編碼裁剪

//編碼定義
char clipCode(const GPoint2d &pt, const GRect2d &rc)
{
    char code = 0;
    if(pt.y() > rc.y1()) code |= 0x01;
    else if(pt.y() < rc.y0()) code |= 0x02;
    if(pt.x() > rc.x1()) code |= 0x04;
    else if(pt.x() < rc.x0()) code |= 0x08;
    return code;
}

//裁剪
bool gltLineClip2d(GPoint2d &pt0, GPoint2d &pt1, const GRect2d &rc)
{
    char c0, c1;
    while(true)
    {
        c0 = clipCode(pt0, rc);
        c1 = clipCode(pt1, rc);
        if((c0 & c1) != 0) return false;//按位與,兩點在同一個測
        if(c0 == 0 && c1 == 0) return true;//兩點在視窗內

        if(c0 == 0)
        {
            swap(pt0, pt1);
            swap(c0, c1);
        }

        if(c0 & 0x01) // 在 Yt 之上
        {
            pt0.setX(pt0.x()-(pt0.y()-rc.y1())*(pt0.x()-pt1.x())/(pt0.y()-pt1.y()));
            pt0.setY(rc.y1());
        }
        else if(c0 & 0x02) // 在 Yb 之下
        {
            pt0.setX(pt0.x()-(pt0.y()-rc.y0())*(pt0.x()-pt1.x())/(pt0.y()-pt1.y()));
            pt0.setY(rc.y0());
        } 
        else if(c0 & 0x04) // 在 Xr 之右
        {
            pt0.setY(pt0.y()-(pt0.x()-rc.x1())*(pt0.y()-pt1.y())/(pt0.x()-pt1.x()));
            pt0.setX(rc.x1());
        }
        else if(c0 & 0x08) // 在 Xl 之左
        {
            pt0.setY(pt0.y()-(pt0.x()-rc.x0())*(pt0.y()-pt1.y())/(pt0.x()-pt1.x()));
            pt0.setX(rc.x0());
        } 
    }
}

Bezier曲線

//bezier的Castel推分演算法
double bezierCastel(double x[],int n,double t){
	for(int r=1;r<n;r++){
        for(int i=0;i<n-r;i++){
            x[i] = (1-t)*x[i]+t*x[i+1];
        }
    }
    return x[0];
}

void gltBezier2d(const GPoint2dArray &points){
    if(points.count<2)
        return;
    double x0,y0,x1,y1;
    double t,dt;
    GPoint2d pt;
    int n = points.count();
    dt = 1.0f/(n*20);
    double *x = new double[n];
    double *y = new double[n];
    pt = points.at(0);
    x0 = pt.x();
    y0 = pt.y();
    for(int i = 0;i<n;i++){
        pt = points.at(i);
        x[i] = pt.x();
        y[i] = pt.y();
    }
    
    for(t=dt;t<1;t+=dt){
        x1 = bezierCastel(x,n,t);
        y1 = bezierCastel(y,n,t);
        gltLine2d(x0,y0,x1,y1);
		x0 = x1;
        y0 = y1;
    }
    pt = points.at(n-1);
    gltLine2d(x0,y0,pt.x().pt.y());
    delete []x;
    delete []y;
}

B樣條曲線

//b樣條基函式
void cubicBSplineBase(int begin,const GPoint2dArray &points,double t,GPoint &pt){
    float fh1 = (-t*t*t+3*t*t-3*t+1)/6;
    float fh2 = (3*t*t*t-6*t*t+4)/6;
    float fh3 = (-3*t*t*t+3*t*t+3*t+1)/6;
    float fh4 = (t*t*t)/6;
    GPoint pt0 = points.at(begin);
    GPoint pt1 = points.at(begin+1);
    GPoint pt2 = points.at(begin+2);
    Gpoint pt3 = points.at(begin+3);
    pt.setX(fh1 * pt0.x() + fh2 * pt1.x() +fh3 * pt2.x() + fh4 * pt3.x());
    pt.setY(fh1 * pt0.y() + fh2 * pt1.y() +fh3 * pt2.y() + fh4 * pt3.y());
}

void gltBSpline2d(const GPoint2dArray &points){
    if(points.count()<4)
        return ;
    double x0,y0;
    double t,dt;
    GPoint pt;
    int n = points.count();
    dt = 0.05;
    for(int i=0;i<n-3;i++){
        cubicBSplineBase(i,points,0,pt);
        x0 = pt.x();
        y0 = pt.y();
        for(t=dt;t<1;t+=dt){
            cubicBsplineBase(i,points,t,pt);
            gltLine2d(x0,y0,pt.x(),pt.y());
            x0 = pt.x();
            y0 = pt.y();
        }
        cubicBSplineBase(i,points,t,pt);
        gltLine2d(x0,y0,pt.x(),pt.y());
    }
}