緩存
緩存:指圖形處理器能夠控制和管理的連續(xù)RAM,程序從CPU的內(nèi)存復(fù)制數(shù)據(jù)到OpenGL ES的緩存,在GPU取得一定的所有權(quán)之后,運(yùn)行在CPU中的程序理想的情況下將不在接觸這個(gè)緩存。為緩存提供數(shù)據(jù)有如下7個(gè)步驟:
1.生成(Generate) :請(qǐng)求OpenGL ES 為圖形處理器控制的緩存生成一個(gè)獨(dú)一無二的標(biāo)識(shí)符。
2.綁定(Bind):告訴OpenGL ES為接下來的運(yùn)算使用一個(gè)緩存。
3.緩存數(shù)據(jù)(Buffer Data):讓OpenGL ES為當(dāng)前綁定的緩存分配并初始化足夠的連續(xù)內(nèi)存(通常是從CPU控制的內(nèi)存復(fù)制數(shù)據(jù)到分配的內(nèi)存)。
4.啟用(Enable)或者禁止(Disable):告訴OpenGL ES在接下來的渲染中是否使用緩存中的數(shù)據(jù)。
5.設(shè)置指針(Set Pointers):告訴OpenGL ES在緩存中的數(shù)據(jù)類型和所需要訪問的數(shù)據(jù)的內(nèi)存偏移值。
6.繪圖(Draw):使用當(dāng)前綁定并啟用的緩存中的數(shù)據(jù)渲染整個(gè)場(chǎng)景或者某個(gè)場(chǎng)景的一部分。
7.刪除(Delete):刪除以前生成的緩存并釋放相關(guān)的資源。
OpenGL ES為一種類型的緩存在使用過程中的每一個(gè)步驟的執(zhí)行定義了下面的C語言函數(shù),同時(shí)為其他的類型緩存提供了類似的函數(shù)
- glGenBuffers() ----為圖形處理器控制的緩存生成一個(gè)獨(dú)一無二的標(biāo)識(shí)符。
- glBindBuffer() -----為接下來的運(yùn)算使用一個(gè)緩存。
- glBufferData() 或glBufferSubData() ----為當(dāng)前綁定的緩存分配并出水啊足夠的連續(xù)內(nèi)存。
- glEnableVertexAttribArray()或glDisableVertexAttribArray() ----在接下來的渲染中是否使用緩存中的數(shù)據(jù)。
- glVertexAttribPointer() ----在緩存中的數(shù)據(jù)的類型和所有需要訪問的數(shù)據(jù)的內(nèi)存偏移值
- glDrawArrays() 或者glDrawElements----使用當(dāng)前綁定并啟用的緩存中的數(shù)據(jù)渲染整個(gè)場(chǎng)景或者某個(gè)場(chǎng)景的一部分。
- glDeleteBuffers() ----刪除以前生成的緩存并釋放相關(guān)的資源。
畫一個(gè)簡(jiǎn)單的三角形 --示例代碼
#import "ViewController.h"
@interface ViewController ()
{
GLuint vertexBufferID;
}
@property(nonatomic,strong)GLKBaseEffect *baseEffect;
@end
@implementation ViewController
@synthesize baseEffect;
typedef struct{
GLKVector3 positionCoords;
}scenVertex;
static const scenVertex vertices[] =
{
{{-0.5f,-0.5f,0.0}}, //左下角
{{0.5f,-0.5f,0.0}}, //右下角
{{-0.5f,0.5f,0.0}} //左上角
};
- (void)viewDidLoad {
[super viewDidLoad];
GLKView *view = (GLKView *)self.view;
NSAssert([view isKindOfClass:[GLKView class]],@"這個(gè)View不是GLKitViewController的View");
view.context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:view.context];
self.baseEffect = [[GLKBaseEffect alloc]init];
self.baseEffect.useConstantColor = GL_TRUE;
//用白色來渲染三角形,意味著在三角形中每一個(gè)像素都有相同的顏色值。
self.baseEffect.constantColor = GLKVector4Make(1.0f, //Red
1.0f, //Green
1.0f, //Blue
1.0f); //Alpha
//設(shè)置當(dāng)前上下文的“清除顏色” 為不透明黑色,用戶上下文的幀緩存被清除時(shí)候初始化每個(gè)像素的顏色值
glClearColor(0.0f, //Red
0.0f, //Green
0.0f, //Blue
1.0f); //Alpha
/* 步驟一:為緩存生成一個(gè)獨(dú)一無二的標(biāo)識(shí)符。
*/
glGenBuffers(1, //第一個(gè)參數(shù)是生成緩存標(biāo)識(shí)符的數(shù)量。
&vertexBufferID); //第二個(gè)參數(shù)是一個(gè)指針 指向生成標(biāo)識(shí)符的內(nèi)存保存位置,
/* 步驟二:為接下來的運(yùn)算綁定緩存,綁定指定標(biāo)識(shí)符的緩存到當(dāng)前緩存
*/
glBindBuffer(GL_ARRAY_BUFFER, //第一個(gè)參數(shù)是常量,用于指定綁定哪一種類型的緩存 有GL_ARRAY_BUFFER和
//GL_ELEMENT_ARRAY_BUFFER;其中GL_ARRAY_BUFFER用于指定一個(gè)頂點(diǎn)屬性的數(shù)組。
vertexBufferID); //
/* 步驟三:復(fù)制數(shù)據(jù)到緩存中,復(fù)制應(yīng)用的頂點(diǎn)數(shù)據(jù)到當(dāng)前的上下文所綁定的頂點(diǎn)緩存中
*/
glBufferData(GL_ARRAY_BUFFER, //第一個(gè)參數(shù)指定要更新當(dāng)前上下文中所綁定的哪一個(gè)緩存
sizeof(vertices), //第二個(gè)參數(shù)指定要復(fù)制進(jìn)這個(gè)緩存的字節(jié)的數(shù)量
vertices, //第三個(gè)參數(shù)要復(fù)制字節(jié)的地址
GL_STATIC_DRAW); //第四個(gè)參數(shù)是緩存在未來的運(yùn)算中可能將會(huì)被怎樣使用,其中GL_STATIC_DRAW提示會(huì)告訴上下文緩存中的內(nèi)容適合復(fù)制到GPU控制的內(nèi)存 因?yàn)楹苌傩薷?可以幫助OpenGL ES優(yōu)化內(nèi)存使用,而使用GL_DYNAMIC_DRAW提示會(huì)告訴上下文緩存中的數(shù)據(jù)會(huì)頻繁改變,并提示OpenGL ES以不同的方式來處理緩存數(shù)據(jù)。
// Do any additional setup after loading the view, typically from a nib.
}
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
[self.baseEffect prepareToDraw];
glClear(GL_COLOR_BUFFER_BIT);
/*步驟四:啟動(dòng),通過glEnableVertexAttribArray()來啟動(dòng)頂點(diǎn)緩存渲染操作
*/
glEnableVertexAttribArray(GLKVertexAttribPosition);
/*步驟五:設(shè)置指針
*/
glVertexAttribPointer(GLKVertexAttribPosition, //第一個(gè)參數(shù):當(dāng)前綁定的緩存包含每個(gè)頂點(diǎn)的位置信息
3, //第二個(gè)參數(shù):每個(gè)位置有三個(gè)部分
GL_FLOAT, //第三個(gè)參數(shù):每個(gè)部分都保存為一個(gè)浮點(diǎn)值類型
GL_FALSE, //第四個(gè)參數(shù):小數(shù)點(diǎn)固定數(shù)據(jù)是否被改變。
sizeof(scenVertex), //第五個(gè)參數(shù):“步幅”
NULL); //第六個(gè)參數(shù):NULL 則說明從當(dāng)前綁定的頂點(diǎn)魂村的開始位置訪問頂點(diǎn)數(shù)據(jù)
/*步驟六:繪圖
*/
glDrawArrays(GL_TRIANGLES, // 第一個(gè)參數(shù):怎么處理頂點(diǎn)緩存內(nèi)的頂點(diǎn)數(shù)據(jù)
0, //第一個(gè)頂點(diǎn)的位置
3); //渲染頂點(diǎn)的數(shù)量
}
-(void)viewDidUnload{
GLKView *view = (GLKView *)self.view;
[EAGLContext setCurrentContext:view.context];
if (vertexBufferID != 0) {
glDeleteBuffers(1,
&vertexBufferID);
vertexBufferID = 0;
}
((GLKView *)self.view).context = nil;
[EAGLContext setCurrentContext:nil];
}