您的位置:首页 > 编程语言 > VB

OpenGL简介-基于VBO绘制三角形

2017-04-21 08:31 405 查看
OpenGL Vision                               OpenGL Shading Language      Version
OpenGL 4.0GLSL 4.0
OpenGL 3.3GLGL 3.3
OpenGL 3.2GLSL 1.5
OpenGL 3.1GLSL 1.4
OpenGL 3.0GLSL 1.3
OpenGL 2.1GLSL 1.2
OpenGL 2.0GLSL 1.1
现在第一个例子:绘制三角形
Initial OpenGL Canvas
Load 绘制所需的資料 / 建立儲存資料的資料結構
Initial OpenGL state 與 各種 OpenGL buffer objects
Draw and Display
接 受各種事件,根據事件變更資料結構的內容、OpenGL State 或是 OpenGL buffer objects
反覆流程 4 與流程 5 直至程式結束

首先是流程 2,在這個例子裡只要準備三角形的資料、Vertex Shdaer 程式碼與 Fragment Shader 程式碼,因為都直接寫死放在程式的變數內,所以只需要有變數的宣告就可以把Init () 省略。

首先三角形的資料很簡單,使用一個 Array 儲存三角形頂點資料即可。

GLfloat afVertex[][3]=

{

{-0.75,-0.5,0.0},

{0.75,-0.5,0.0},

{0.0,0.75,0.0}

};
三個三角形頂點資料
而 Vertex Shader 與 Fragment Shader,也簡單使用 char pointer 來存。

Vertex Shader 程式碼
const char* cpVShader = { 

#version 150

in vec3 vPos;

void main() {

gl_Position = vec4(vPos,1);

}

};
"in vec3 vPos;" 表示 Vertex Shader 會接受 三個 float 的 Vertex Attribute 「Vpos」變數輸入。

然後 Vertex Shader 的預設 Vertex 輸出為內建的變數 gl_Position,Type 為 4個 float 的 Vector 。

因為只有要畫單純的三角形,並沒有要對三角形多做處理,所以在Vertex Shader 裡面 直接把輸入的 vPos 變成 homogenious coordinate 也就是後面再加個 1,放到 gl_Position 裡 。

Fragment Shader 程式碼
const char* cpFShader = { 

#version 150 

out vec4 fColor;

void main() {

fColor = vec4( 1, 1, 1, 1 );

;}

};
"out vec4 fColor;" 宣告輸出的 Fragment 變數名稱。

然後設定三角形上面的每個 Fragment 用 ( 1, 1, 1, 1) 的白色輸出。

接下來資料都準備好了,開始進行流程 3 撰寫 initGL 的內容。
void initGL()

 
glGenBuffers(1,&uVbo ); 

glBindBuffer(GL_ARRAY_BUFFER,uVbo); 

glBufferData(GL_ARRAY_BUFFER,sizeof(afVertex), afVertex, GL_STATIC_DRAW );
產生一個 Vertex Buffer Object ,並且把GL_ARRAY_BUFFER 設定為 uVbo ,然後將Array的頂點資料存到這個 GL_ARRAY_BUFFER 設定的 uVbo 這個buffer object裡。
uProgram = glCreateProgram();

AttachProgram( uProgram, cpVShader , GL_VERTEX_SHADER );

AttachProgram( uProgram, cpFShader , GL_FRAGMENT_SHADER );

glLinkProgram( uProgram );
產生一個 Shader Program,然後分別把Vertex Shader、Fragment Shader attach 至program上,最後 Link 起來可以在 Draw時使用這個 Shader Program。
uPos = glGetAttribLocation( uProgram, "vPos" );取得 Shader Program 裡面 vPos 這個變數的位置。
glClearColor( 0.0, 0.0, 1.0, 1.0 );設 定OpenGL Canvus 背景顏色。
} 
這邊 InitGL() 主要作了四件事,分別是產生一個 Vertex Buffer Object ,一個 Shader Program ,取得 Shader Program 裡面 vPos 變數的輸入位置。

最後就是顯示的部分 Display 這個 Function:
glUseProgram(uProgram);設定現在使用的 Shader Program為 uProgram
glBindBuffer( GL_ARRAY_BUFFER, uVbo );設定現在使用的 GL_ARRAY_BUFFER 為uVbo
glVertexAttribPointer( uPos, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );設定 GL_ARRAY_BUFFER 裡面 Vertex 資料的格式,並且設定資料是當作 Shader Program 內 uPos 位置的變數內容
glEnableVertexAttribArray( uPos );Enable uPos 這個 Vertex attribute array
glDrawArrays( GL_TRIANGLES, 0, 3 );最後在 Vertex Array 裡從第 0 個開始取三個 Vertex 當成三角形來畫
這樣就可以畫出一個白色的三角形了。

一些概念

OpenGL 的運作是一個 State Machine,所以程式執行是根據 OpenGL 內部各種 State 的狀況,因此常見的模式就是設定某些 State 狀態,呼叫 Function 針對現在的 State 執行,透過如此的反覆進行完成一個 OpenGL程式。

代码如下:

/**
* OpenGL 3.x with GLEW and GLUT - Example 02
*
* author	Po-Ying Li bylee@nchc.org.tw
* version	1.0
*
* Homepage: http://viml.nchc.org.tw *
* Copyright Po-Ying Li
*/

#include<stdio.h>
#include<stdlib.h>
#include<GL/glew.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#define BUFFER_OFFSET(offset) ((GLvoid*)offset)

GLfloat afVertex[][3]=
{
{-0.75,-0.5,0.0},
{0.75,-0.5,0.0},
{0.0,0.75,0.0}
};

const char* cpVShader = {
"#version 150\n"
""
"in vec3 vPos;"
""
"void main() {"
"  gl_Position = vec4(vPos,1);"
"}"
};

const char* cpFShader = {
"#version 150\n"
""
"out vec4 fColor;"
""
"void main() {"
"  fColor = vec4( 1, 1, 1, 1 );"
"}"
};

GLuint uVbo;
GLuint uPos;
GLuint uProgram;

bool AttachProgram( GLuint uProgram, const char* cpShader, GLenum eShaderType )
{
GLuint  uShader;
GLint   iCompleted;

uShader = glCreateShader( eShaderType );
glShaderSource( uShader, 1, &cpShader, NULL );
glCompileShader( uShader );
glGetShaderiv( uShader, GL_COMPILE_STATUS, &iCompleted );

if ( !iCompleted )
{
GLint  len;
char*  msg;
glGetShaderiv( uShader, GL_INFO_LOG_LENGTH, &len );
msg = (char*) malloc( len );
glGetShaderInfoLog( uShader, len, &len, msg );
fprintf( stderr, "Vertex shader compilation failure:\n%s\n", msg );
free( msg );
return false;
}else
{
glAttachShader( uProgram, uShader );
return true;
}
}

//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
void initGL()
{

glGenBuffers(1,&uVbo );
glBindBuffer(GL_ARRAY_BUFFER,uVbo);
glBufferData(GL_ARRAY_BUFFER,sizeof(afVertex), afVertex, GL_STATIC_DRAW );

uProgram = glCreateProgram();
AttachProgram( uProgram, cpVShader , GL_VERTEX_SHADER );
AttachProgram( uProgram, cpFShader , GL_FRAGMENT_SHADER );
glLinkProgram( uProgram );

uPos = glGetAttribLocation( uProgram, "vPos" );

glClearColor( 0.0, 0.0, 1.0, 1.0 );

}
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

void display()
{
glClear( GL_COLOR_BUFFER_BIT );

glUseProgram(uProgram);
glBindBuffer( GL_ARRAY_BUFFER, uVbo );
glVertexAttribPointer( uPos, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( uPos );
glDrawArrays( GL_TRIANGLES, 0, 3 );

glutSwapBuffers();
}
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

void reshape( int width, int height )
{
glViewport( 0, 0, width, height );
}

//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

void keyboard( unsigned char key, int x, int y )
{
switch( key ) {
case 033: // Escape Key
exit( EXIT_SUCCESS );
break;
}
glutPostRedisplay();
}

//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

int main( int argc, char* argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );

glutCreateWindow( argv[0] );
glewInit();

initGL();

glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutMainLoop();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐