NeHe OpenGL第四十五課 頂點快取

2021-09-05 05:32:19 字數 4310 閱讀 5762

nehe opengl第四十五課:頂點快取

頂點快取

你想更快地繪製麼?直接操作顯示卡吧,這可是當前的圖形技術,不要猶豫,我帶你入門。接下來,你自己向前走吧。

速度是3d程式中最重要的指標,你必須限制繪製的多邊形的個數,或者提高顯示卡繪製多邊形的效率。顯示卡最近增加了乙個新的擴充套件,叫做頂點快取vs,它直接把頂點放置在顯示卡中的快取記憶體中,極大的增加了繪製速度。

在這個教程裡,我們會載入乙個高度圖,使用頂點陣列高效的把網格資料傳送到opengl裡,並使用vbo擴充套件把頂點資料放入高效的視訊記憶體裡。

現在讓我們開始吧,我們先來定義一些程式引數。

#define mesh_resolution 4.0f       // 每個頂點使用的畫素#define mesh_heightscale 1.0f       // 高度的縮放比例//#define no_vbos        // 如果定義將不使用vbo擴充套件

// 定義vbo擴充套件它們在glext.h標頭檔案中被定義#define gl_array_buffer_arb 0x8892#define gl_static_draw_arb 0x88e4typedef void (apientry * pfnglbindbufferarbproc) (glenum target, gluint buffer);typedef void (apientry * pfngldeletebuffersarbproc) (glsizei n, const gluint *buffers);typedef void (apientry * pfnglgenbuffersarbproc) (glsizei n, gluint *buffers);typedef void (apientry * pfnglbufferdataarbproc) (glenum target, int size, const glvoid *data, glenum usage);

// vbo 擴充套件函式的指標

pfnglgenbuffersarbproc glgenbuffersarb = null; // 建立快取名稱

pfnglbindbufferarbproc glbindbufferarb = null; // 繫結快取

pfnglbufferdataarbproc glbufferdataarb = null; // 繫結快取資料

pfngldeletebuffersarbproc gldeletebuffersarb = null; // 刪除快取

現在我們來定義自己的網格類:

class cvert              // 頂點類

;typedef cvert cvec;            

class ctexcoord             // 紋理座標類;

//網格類

class cmesh;

大部分**都很簡單,這裡不多加解釋。

下面我們來定義一些全域性變數:

bool  g_fvbosupported = false;       // 是否支援頂點快取物件

cmesh*  g_pmesh = null;          // 網格資料

float  g_flyrot = 0.0f;         // 旋轉角度

int   g_nfps = 0, g_nframes = 0;       // 幀率計數器

dword  g_dwlastfps = 0;         // 上一幀的計數 

下面的**載入高度圖,它和34課的內容差不多,在這裡不多加解釋了:  

//載入高度圖

bool cmesh :: loadheightmap( char* szpath, float flheightscale, float flresolution )}}

// 載入紋理,它和高度圖是同一副影象

glgentextures( 1, &m_ntextureid );       

glbindtexture( gl_texture_2d, m_ntextureid );    

glteximage2d( gl_texture_2d, 0, 3, m_ptextureimage->sizex, m_ptextureimage->sizey, 0, gl_rgb, gl_unsigned_byte, m_ptextureimage->data );

gltexparameteri(gl_texture_2d,gl_texture_min_filter,gl_linear);

gltexparameteri(gl_texture_2d,gl_texture_mag_filter,gl_linear);

// 釋放紋理資料

if( m_ptextureimage )

return true;}

下面的**用來計算(x,y)處的亮度 

//計算(x,y)處的亮度

float cmesh :: ptheight( int nx, int ny )

下面的**把頂點資料繫結到頂點快取,即把記憶體中的資料傳送到視訊記憶體  

void cmesh :: buildvbos()

好了,現在到了初始化的地方了。首先我將分配並載入紋理資料。接著檢測是否支援vbo擴充套件。如果支援我們將把函式指標和它對應的函式關聯起來,如果不支援將只返回資料。 

//初始化

bool initialize (gl_window* window, keys* keys)     

// 檢測是否支援vbo擴充套件

#ifndef no_vbos

g_fvbosupported = i***tensionsupported( "gl_arb_vertex_buffer_object" );

if( g_fvbosupported )

#else

g_fvbosupported = false;

#endif

//設定opengl狀態

glclearcolor (0.0f, 0.0f, 0.0f, 0.5f);      

glcleardepth (1.0f);          

gldepthfunc (gl_lequal);         

glenable (gl_depth_test);         

glshademodel (gl_smooth);         

glhint (gl_perspective_correction_hint, gl_nicest);   

glenable( gl_texture_2d );         

glcolor4f( 1.0f, 1.0f, 1.0f, 1.0f );      

return true;            }

下面的函式用來檢測是否包含特定的擴充套件名稱 

// 返回是否支援指定的擴充套件

bool i***tensionsupported( char* sztargetextension )

return false;}

好了,幾乎結束了,我們下面來看看我們的渲染**.

void draw (void);

sprintf( sztitle, "lesson 45: nehe & paul frazee's vbo tut - %d ********s, %d fps", g_pmesh->m_nvertexcount / 3, g_nfps );

if( g_fvbosupported ) // 是否支援vbo

strcat( sztitle, ", using vbos" );

else

strcat( sztitle, ", not using vbos" );

setwindowtext( g_window->hwnd, sztitle ); // 設定視窗標題

}g_nframes++;

// 設定視口

gltranslatef( 0.0f, -220.0f, 0.0f );

glrotatef( 10.0f, 1.0f, 0.0f, 0.0f );

glrotatef( g_flyrot, 0.0f, 1.0f, 0.0f );

// 使用頂點,紋理座標陣列

glenableclientstate( gl_vertex_array );

glenableclientstate( gl_texture_coord_array );

為了使用vbo,你必須告訴opengl記憶體中的那部分需要載入到vbo中。所以第一步我們要起用頂點陣列和紋理座標陣列。接著我們必須告訴opengl去把資料的指標設定到特定的地方,glvertexpointer函式可以完成這個功能。

我們分為啟用和不啟用vbo兩個路徑來渲染,他們都差不多,唯一的區別是當你需要把指標指向vbo快取時,記得把資料指標設定null。

AGG第四十五課 效能優化

1agg path storage的全域性唯一屬性 理由 內部需要進行記憶體的動態分配,需要開銷開銷,並且會造成記憶體碎片 2 outline aa代替stroke 條件 線寬少於2畫素的情況下,速度稍微提高一些 3 統一在add path之後才render scanline渲染 4 scanlin...

第四十五課 不同的繼承方式

1 public繼承 1 父類成員在子類中保持原有的訪問級別 2 protected繼承 1 父類中的公有成員變成保護成員,其它成員保持不變 3 private繼承 1 父類成員在子類中變成私有成員 include include using namespace std class parent c...

LeetCode第四十五題 跳躍遊戲

問題簡介 這是乙個跳躍遊戲,規則是通過給定乙個非負整數陣列,最開始就處於陣列第一位即索引為0處,陣列元素數值代表可以跳躍的最大值,要求通過最小的跳躍次數達到陣列最後的索引處 舉例 輸入 2,3,1,1,4 輸出 2 解釋 這個陣列的最小跳躍值是2,第一次從索引0處跳躍1到索引1處,第二次跳躍3到結尾...