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到結尾...