二 OpenGL入门指南

1.OpenGL发展历程和未来趋势

  什么是OpenGL呢?

   opengl是图形硬件的一种软件接口。本质上说,他是一个3D图形和模型库,具有高度可一致性,并且具有非常快的速度。本质是一个C运行时函数库。

   当然最早是没有OpenGL的,从前有个SGI公司的图形工作站做的很牛叉,他们在开发自己产品的同时也形成了自己的一些图形处理的API函数库和一套规范。老大自然在市场上是有话语权的,其他小弟也都愿意向他靠拢,于是OpenGL ARB 体系审查委员会就诞生了(当然都是一些图形显卡厂商了)。林子大了,他一家自然也是管不住了,开源世界的力量也不容小觑,再加之SGI公司自己的跟不上时代,自己的业务也越来越不行,慢慢地也就没有实际的控制权了。opengl真正成了国际开放标准,由各大厂商共同维护,成立了新的Khronos工作组。他们的成员是一些诸如图形硬件公司和大型软件公司如微软,苹果等。

  opengl以两种形式存在,第一种形式是opengl规范,第二种是opengl实现,例如在pc上的软件驱动程序和图形卡就共同组成了一个opengl实现。

  绝大多数公司认识到从长远来看,竞争对于每家公司都是件好事,因此它们都认可并支持行业标准甚至对行业标准作出贡献。 对于未来,opengl也必定是越来越现代化,越来越好的。

2.扩展机制(Extension Mechanism)如何工作,以及它的重要性

  标准的发展总是要经过验证和审核的,发展难免会有滞后性,加之各大硬件厂商存在竞争关系,各自创新发展的新技术和新接口,不一定能很快进入标准,对新硬件的升级也可能会影响老的标准。但是为了满足向下兼容的特性,总是要有所取舍。所以扩展机制,在国际标准和软件一贯性发展上就显得尤为重要。opengl提供了一直扩展机制,让新的API可以做良好的过渡也可以很旧API做好兼容。

3.如何检测OpenGL编程错误

  opengl内部保留了一组错误标志,共四个,当一个错误发生时候,与这个错误想对应的标志就会被设置,可以调用GLGetError函数。

4.向OpenGL传递性能提示Hint

  在3D图形算法中,为了追求高性能,我们常常需要做一些权衡。或者,如果视觉逼真度是最重要的因素,那么性能就会退二求其次。glhit函数允许我们制定偏重于视觉质量还是速度,以适应各种不同类型的操作需求.

5.GLUT基础编程框架解析

  opengl开发需要opengl使用工具库,最早是AUX作为opengl的辅助函数库,后来发展了GLUT,但是由于GLUT最初并不是作为一种开放源代码的软件,因此 一种新的GLUT的实现freeglut已经崛起并取代了它的位置。

  opengl api主要通过扩展机制来发展。这种扩展机制能偶用来获得指向任何加入opengl1.0之后任何版本核心的opengl函数的函数指针。有一个实现opengl3.3. api完全存取的简单的方法,就是使用一个自动初始化所有新函数指针并包含所需类型定义、常量和枚举值的扩展加载库,这种加载库有多种选择,其中维护最好的一个就是GLEW ,GLEW被预先封装在GLTools中。 

  GLTools就是一个工具箱,里面装满了自己喜爱的工具,程序员也是如此。有一些有用并且可重用的函数,所有程序员编写几乎所有opengl都会用到它们。GLTools包含了一个用于操作矩阵和向量的3D数学库,并依靠GLEW获得用来产生和渲染一些简单3D的函数,以及视觉平截头体、相机类和变换矩阵进行管理的函数的充分支持。

  包含什么?

  GLTools.h

  GLShaderManager.h

  Glut.h  freeeGlut

  启动GLUT

  glutInit(&argc, argv) //  初始化glut库

  glutInitDispalyMode() // 使用的缓冲区窗口

代码就是最好的教程

一个三角形

// Triangle.cpp
// Our first OpenGL program that will just draw a triangle on the screen.

#include <GLTools.h>            // OpenGL toolkit
#include <GLShaderManager.h>    // Shader Manager Class

#ifdef __APPLE__
#include <glut/glut.h>          // OS X version of GLUT
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>            // Windows FreeGlut equivalent
#endif

GLBatch	triangleBatch;
GLShaderManager	shaderManager;

///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
    {
	glViewport(0, 0, w, h);
    }


///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context. 
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
	{
	// Blue background
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
    
	shaderManager.InitializeStockShaders();

	// Load up a triangle
	GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f, 
		                  0.5f, 0.0f, 0.0f,
						  0.0f, 0.5f, 0.0f };

	triangleBatch.Begin(GL_TRIANGLES, 3);
	triangleBatch.CopyVertexData3f(vVerts);
	triangleBatch.End();
	}



///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
	{
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
	triangleBatch.Draw();

	// Perform the buffer swap to display back buffer
	glutSwapBuffers();
	}


///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
	{
	gltSetWorkingDirectory(argv[0]);
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Triangle");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
		}
	
	SetupRC();

	glutMainLoop();
	return 0;
	}

  

一个可控制的正方形,带碰撞检测

// Move.cpp
// Move a Block based on arrow key movements

#include <GLTools.h>	// OpenGL toolkit
#include <GLShaderManager.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

GLBatch	squareBatch;
GLShaderManager	shaderManager;


GLfloat blockSize =0.2f;
GLfloat vVerts[] = { -blockSize, -blockSize, 0.0f, 
	                  blockSize, -blockSize, 0.0f,
					  blockSize,  blockSize, 0.0f,
					 -blockSize,  blockSize, 0.0f};

///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context. 
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
	{
	// Black background
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
    
	shaderManager.InitializeStockShaders();

	// Load up a triangle
	squareBatch.Begin(GL_TRIANGLE_FAN, 4);
	squareBatch.CopyVertexData3f(vVerts);
	squareBatch.End();
	}

// Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key, int x, int y)
    {
	GLfloat stepSize = 0.025f;

	GLfloat blockX = vVerts[0];   // Upper left X
	GLfloat blockY = vVerts[7];  // Upper left Y

	if(key == GLUT_KEY_UP)
		blockY += stepSize;

	if(key == GLUT_KEY_DOWN)
		blockY -= stepSize;
	
	if(key == GLUT_KEY_LEFT)
		blockX -= stepSize;

	if(key == GLUT_KEY_RIGHT)
		blockX += stepSize;

	// Collision detection
	if(blockX < -1.0f) blockX = -1.0f;
	if(blockX > (1.0f - blockSize * 2)) blockX = 1.0f - blockSize * 2;;
	if(blockY < -1.0f + blockSize * 2)  blockY = -1.0f + blockSize * 2;
	if(blockY > 1.0f) blockY = 1.0f;

	// Recalculate vertex positions
	vVerts[0] = blockX;
	vVerts[1] = blockY - blockSize*2;
	
	vVerts[3] = blockX + blockSize*2;
	vVerts[4] = blockY - blockSize*2;
	
	vVerts[6] = blockX + blockSize*2;
	vVerts[7] = blockY;

	vVerts[9] = blockX;
	vVerts[10] = blockY;

	squareBatch.CopyVertexData3f(vVerts);

	glutPostRedisplay();
	}





///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
	{
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
	squareBatch.Draw();

	// Flush drawing commands
	glutSwapBuffers();
	}



///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
	{
	glViewport(0, 0, w, h);
	}

///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
	{
	gltSetWorkingDirectory(argv[0]);
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Move Block with Arrow Keys");
	
	GLenum err = glewInit();
	if (GLEW_OK != err)
		{
		// Problem: glewInit failed, something is seriously wrong.
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		return 1;
		}
	
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
    glutSpecialFunc(SpecialKeys);

	SetupRC();

	glutMainLoop();
	return 0;
	}

  

一个自由运动的动画,使用动态刷新

// Bounce.cpp
// Bounce a Block around the screen

#include <GLTools.h> // OpenGL toolkit
#include <GLShaderManager.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

GLBatch squareBatch;
GLShaderManager shaderManager;


GLfloat blockSize = 0.1f;
GLfloat vVerts[] = { -blockSize - 0.5f, -blockSize, 0.0f,
blockSize - 0.5f, -blockSize, 0.0f,
blockSize - 0.5f, blockSize, 0.0f,
-blockSize - 0.5f, blockSize, 0.0f};

///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context.
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 1.0f, 1.0f );

shaderManager.InitializeStockShaders();

// Load up a triangle
squareBatch.Begin(GL_TRIANGLE_FAN, 4);
squareBatch.CopyVertexData3f(vVerts);
squareBatch.End();
}

// Respond to arrow keys by moving the camera frame of reference
void BounceFunction(void)
{
static GLfloat xDir = 1.0f;
static GLfloat yDir = 1.0f;

GLfloat stepSize = 0.005f;

GLfloat blockX = vVerts[0]; // Upper left X
GLfloat blockY = vVerts[7]; // Upper left Y

blockY += stepSize * yDir;
blockX += stepSize * xDir;

// Collision detection
if(blockX < -1.0f) { blockX = -1.0f; xDir *= -1.0f; }
if(blockX > (1.0f - blockSize * 2)) { blockX = 1.0f - blockSize * 2; xDir *= -1.0f; }
if(blockY < -1.0f + blockSize * 2) { blockY = -1.0f + blockSize * 2; yDir *= -1.0f; }
if(blockY > 1.0f) { blockY = 1.0f; yDir *= -1.0f; }

// Recalculate vertex positions
vVerts[0] = blockX;
vVerts[1] = blockY - blockSize*2;

vVerts[3] = blockX + blockSize*2;
vVerts[4] = blockY - blockSize*2;

vVerts[6] = blockX + blockSize*2;
vVerts[7] = blockY;

vVerts[9] = blockX;
vVerts[10] = blockY;

squareBatch.CopyVertexData3f(vVerts);
}

 

 

///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
squareBatch.Draw();

// Flush drawing commands
glutSwapBuffers();

BounceFunction();
glutPostRedisplay(); // Redraw
}

 

///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
}

///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("Bouncing Block");

GLenum err = glewInit();
if (GLEW_OK != err)
{
// Problem: glewInit failed, something is seriously wrong.
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return 1;
}

glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);

SetupRC();

glutMainLoop();
return 0;
}

 

posted @ 2016-03-02 15:31  倾其一生  阅读(261)  评论(0)    收藏  举报