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


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

现在第一个例子:绘制三角形

  1. Initial OpenGL Canvas
  2. Load 绘制所需的資料 / 建立儲存資料的資料結構
  3. Initial OpenGL state 與 各種 OpenGL buffer objects
  4. Draw and Display
  5. 接 受各種事件,根據事件變更資料結構的內容、OpenGL State 或是 OpenGL buffer objects
  6. 反覆流程 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(); 
} 






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值