【计算机图形学】OpenGL+VS2015相关类库配置

WiKi

OpenGL一直是事实上的计算机图形学标准,截止2016年06月,OpenGL版本已经更新到4.5。不过DirectX发展迅速,大有OpenGL落后的态势,知乎上的该话题的讨论:https://www.zhihu.com/question/23241456。所以OpenGL为了追赶DirectX,推出 了glNext(Vulkan API),相关讨论https://www.zhihu.com/question/28039310。

2 相关资料

图形学的经典书籍是《Computer Graphics with OpenGL》,即《计算机图形学》,以OpenGL描述,在介绍图形学基础理论的同时,也提供了OpengGL的相关API和实例程序。目前(2016年6月)本书已经更新到第4版。网上第3版的PDF文档比较多,尚未发现第4版的PDF文档,不过第3版和第4版差别很小,第4版重要的更新是提供了GLSL的一个章节。
《计算机图形学》的重要性在于全面的理论知识,不过它基本不涉及Shader编程,仍然沿用固定管程的教学内容,然而当前的OpengGL都是Shader编程,读完本书你会发现对Shader了解很少。
下面三本书都是Shader编程。
《OpenGL超级宝典》和《OpenGL编程指南》是两本实用的OpengGL学习书籍,区别在于前者有更多实例,更容易按步骤进行操作,而后者着重介绍API,最好先阅读前者。
《OpenGL 4.0 Shading Language Cookbook.pdf》主要介绍Shader编程。
《OpenGL 4.0 Shading Language Cookbook.pdf》下载地址:http://download.csdn.net/detail/brillianteagle/9541959

3 相关库文件

3.1 gl、glu和glut

《计算机图形学》详细介绍了3个类库,总结起来就是
glu库:函数glu开头,设置视景和投影矩阵、用线和多边形近似法来描述对象、用线性近似法描述quadric和B-spline,处理表面绘制操作。
glut库:跨平台套件,包括了窗口操作、输入管理。
注意,包括GLUT头文件就不必包括GL和GLU头文件。
配置好这三个库就可以运行《计算机图形学》中所有的实例,但是不能进行Shader编程。

3.2 glew和freeglut

GLU库获得是比较陈旧的OpenGL API版本,可以从glew获得最新的OpenGL API版本。freeglut则是用来取代glut库的。
所以,配置好glew和freeglut两个库,完全取代glu和glut库,同时可以获得最新版本的API,可以进行Shader编程。

3.3 GLTools

GLTools是《OpenGL超级宝典》作者提供的工具包,在运行本书的实例时要用到。

3.4 GLM

GLM (OpenGL Mathematics) 也是一个工具包,在运行《OpenGL 4.0 Shading Language Cookbook.pdf》的程序时会用到。

4 库文件配置

一般配置都有两种方式,要么相关文件放到VC目录下,这样不必每次都配置;要么相关文件放到工程目录下,并包含头文件目录和lib文件目录,这样程序在在其他电脑上也可以打开。各有好处。这里介绍第二种方式。

4.1 glew和freeglut配置

glew官网:http://glew.sourceforge.net/
glew官方GitHub主页:https://github.com/nigels-com/glew
freeglut官网:https://sourceforge.net/projects/freeglut/
下载glew的最新Binaries版本(截止2016年6月9日的)为glew-1.13.0-win32.zip,freeglut最新版本为3.0版本freeglut-MSVC-3.0.0-2.mp.zip。
在VS2015中新建VC控制台程序OpenGL-Demo,在【工程目录】下新建GL文件夹和lib文件夹,然后执行下面四个步骤:
(1) 将glew-1.13.0-win32\glew-1.13.0\include\GL目录下的头文件和freeglut-MSVC-3.0.0-2.mp\freeglut\include\GL目录下的头文件都放到【工程目录】下新建GL文件夹中;
(2) 将glew-1.13.0-win32\glew-1.13.0\lib\Release\Win32目录下的glew32.lib文件和freeglut-MSVC-3.0.0-2.mp\freeglut\lib目录下的freeglut.lib放到【工程目录】下新建lib文件夹中,这里要注意,我使用的是32位版本的lib包,即便我的电脑是64位的。因为我们建立的VC工程默认是32位的。
(3) 将glew-1.13.0-win32\glew-1.13.0\bin\Release\Win32目录下的glew32.dll和freeglut-MSVC-3.0.0-2.mp\freeglut\bin目录下的freeglut.dll放到工程目录下。
(4) 在项目上右键菜单中打开配置,设置附加头文件目录和附加lib文件目录,如图。注意,$(ProjectDir)就是当前目录的意思。
【计算机图形学】OpenGL+VS2015相关类库配置_第1张图片
【计算机图形学】OpenGL+VS2015相关类库配置_第2张图片
可以用以下代码测试一下,绘制一个白色背景的窗口:

// OpenGL-Demo.cpp : Defines the entry point for the console application.
//
#pragma comment(lib,"glew32.lib")
#include 
#include 
#include 
using namespace std;
/* GLUT callback Handlers */

static void resize(GLint width, GLint height) {
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)width, 0.0, (GLdouble)height);
	glClear(GL_COLOR_BUFFER_BIT);
}
/**绘制 函数,这里是空的*/
static void display() {
}
/**更换屏幕颜色设定矩阵模式
选择正摄投影的范围*/
static void init() {
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 200.0, 0.0, 150.0);//窗口的左下角是原点
}
/* Program entry point */

int main(int argc, char *argv[]) {
	glutInit(&argc, argv);
	glutInitWindowSize(640, 480);
	glutInitWindowPosition(100, 100);//相对屏幕的左上角
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//正在使用单个帧缓存,颜色模式//为RGB,这是默认的颜色模式
	glutCreateWindow("Draw Curves");
	init();
	if (glewInit() == GLEW_OK) {
		cout << "glew初始化成功!" << endl;
	}
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutMainLoop();
}

4.2 GLTools生成

这个库由《OpenGL超级宝典》的作者提供,但是需要自己进行编译使用。这里我将本书源码进行了上传。
part1下载地址:http://download.csdn.net/detail/brillianteagle/9545333
part2下载地址:http://download.csdn.net/detail/brillianteagle/9545335
只有两个都下载后才能解压。解压后SB5\Src目录下就有GLTools文件夹。该文件夹的目录下有include和src两个文件夹。由于GLTools的编译依赖于glew,可以看到SB5\Src\GLTools\include\GL目录下就是某个版本的glew头文件,而SB5\Src\GLTools\src目录下有glew.c源文件。
由于我们已经采用了glew的1.13版本,所以这里要替换SB5\Src\GLTools\include\GL目录下的所有头文件,并采用1.13版本glew.c源文件。在glew的官网http://glew.sourceforge.net/下载Source版本,替换SB5\Src\GLTools\src目录下有glew.c源文件。
在VS2015中新建VC静态库程序GLTools,然后按下面步骤配置工程:
(1)将 SB5\Src\GLTools的include文件夹放到【工程目录】下,将SB5\Src\GLTools\src目录下的源文件放到【工程目录】下;
(2)将SB5\Src\GLTools\src目录下的所有源文件放到【工程目录】下;
(3)在工程上点击右键菜单中的属性,添加头文件。
【计算机图形学】OpenGL+VS2015相关类库配置_第3张图片
然后,就可以在relseas模式下编译该工程,结束后GLTools\Release目录下生成GLTools.lib。

4.3 GLTools配置

如何把GLTools集成到自己的工程呢?
在之前的OpenGL-Demo【项目目录】下新建GLTools文件夹。
(1) 将更新过glew最新版本的SB5\Src\GLTools的include文件夹下的所有文件拷贝到GLTools文件夹,并删除【项目目录】的GL文件夹,因为此时GL文件夹已经存在于GLTools目录下。
(2) 将GLTools.lib添加到lib文件夹。
(3) 更改附加头文件目录 ( P r o j e c t D i r ) G L 到 (ProjectDir)GL到 (ProjectDir)GL(ProjectDir) GLTools
值得注意的是,GLTools依赖于glew,所有,在添加GLTools到自己的工程时要注意依赖关系。这样,引入GLTools,也就引入了glew。
测试一下《OpengGL超级宝典(第5版)》的第一个例子,蓝色背景下绘制红色三角形。

// OpenGL-Demo.cpp : Defines the entry point for the console application.
//2016-06-09
//#pragma comment(lib,"glew32.lib")//不用

#pragma comment(lib,"GLTools.lib")

//#include //不用
#include 
#include 
#include 
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;
}

4.4 GLM配置

GLM只有头文件,只需要在官网下载后解压,glm-master\glm-master目录下的glm放到OpenGL-Demo【工程目录】下,并添加$(ProjectDir)glm即可。
glm官网:https://sourceforge.net/projects/ogl-math/
下面是《OpenGL 4.0 Shading Language Cookbook.pdf》中第一个例子,也是绘制三角形。

#pragma comment(lib,"glew32.lib")//这里要加载该静态包
#include 
#include 
#include //斜杠和反斜杠都可以
#include 

/*
完整的shader过程。
初始化→编译→链接到程序
*/
using namespace std;

/*传入shader的引用,和GLSL字符串,对shader进行编译*/
void compileShader(GLint& shader, const GLchar* shaderCode) {
	const GLchar* codeArray[] = { shaderCode };
	glShaderSource(shader, 1, codeArray, NULL);
	glCompileShader(shader);//编译shader

							/*判断编译后的结果*/
	GLint result;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &result);

	if (result == GL_FALSE) {
		cout << "shader编译错误!" << endl;
		GLint logLen;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);

		if (logLen>0) {
			char* log = (char*)malloc(logLen);
			GLsizei written;
			glGetShaderInfoLog(shader, logLen, &written, log);
			cout << log << endl;
			free(log);

		}
		exit(1);
	}
	else
	{
		cout << "shader编译成功!" << endl;
	}
}
void render(GLuint programHandle) {
	float positionData[] = {
		-0.8f, -0.8f, 0.0f,
		0.8f, -0.8f, 0.0f,
		0.0f, 0.8f, 0.0f
	};
	float colorData[] = {
		1.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 1.0f
	};

	GLuint vboHandle[2];
	glGenBuffers(2, vboHandle);
	GLuint positionbufferHandle = vboHandle[0];
	GLuint colorBufferHandle = vboHandle[1];
	glBindBuffer(GL_ARRAY_BUFFER, positionbufferHandle);
	glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);//绑定顶点数据
	glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
	glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);//绑定颜色数据

	GLuint vaoHandle;
	glGenVertexArrays(1, &vaoHandle);
	glBindVertexArray(vaoHandle);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glBindBuffer(GL_ARRAY_BUFFER, positionbufferHandle);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
	glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte*)NULL);
	glBindVertexArray(vaoHandle);
	//  绘制三角形
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glFlush();


}
void link() {
	//判断glew是否能初始化
	if (glewInit() != GLEW_OK) {
		cout << "glewInit()失败!" << endl;
		exit(1);
	}
	/*编译vertexShader*/
	const GLchar* shaderCode = "#version 400 \n in vec3 VertexPosition;in vec3 VertexColor;out vec3 Color;void main() {Color = VertexColor;gl_Position = vec4(VertexPosition, 1.0);}";
	GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	if (vertexShader == 0) {
		cout << "vertexShader无法获取!" << endl;
		exit(1);
	}
	compileShader(vertexShader, shaderCode);

	/*编译fragmentShader*/
	const GLchar* fragmentCode = "#version 400 \n in vec3 Color;out vec4 FragColor;void main() {FragColor=vec4(Color,1.0);}";
	GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	if (fragmentShader == 0) {
		cout << "fragmentShader无法获取!" << endl;
		exit(1);
	}
	compileShader(fragmentShader, fragmentCode);

	/*获得程序programHandle*/
	GLuint programHandle = glCreateProgram();
	if (programHandle == 0)
	{
		cout << "Program无法获取!" << endl;
		exit(1);

	}
	/*将shader链接到programHandle*/
	glAttachShader(programHandle, vertexShader);
	glAttachShader(programHandle, fragmentShader);
	glBindAttribLocation(programHandle, 0, "VertexPosition");
	glBindAttribLocation(programHandle, 1, "VertexColor");
	glLinkProgram(programHandle);

	/*判断链接状态*/
	GLint status;
	glGetProgramiv(programHandle, GL_LINK_STATUS, &status);
	if (status == GL_FALSE)
	{
		cout << "link失败!" << endl;
		GLint logLen;
		glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen);

		if (logLen>0) {
			char* log = (char*)malloc(logLen);
			GLsizei written;
			glGetProgramInfoLog(programHandle, logLen, &written, log);
			cout << log << endl;
			free(log);

		}
		exit(1);
	}
	else {
		cout << "link成功!" << endl;
		glUseProgram(programHandle);//使用该程序
		render(programHandle);
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);;
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(900, 600);
	glutCreateWindow("First GLUT Sample");
	/*link函数是GLSL编写的主体*/
	glutDisplayFunc(link);
	glutMainLoop();
	return 0;
}


请我喝咖啡

如果觉得写得不错,可以扫描我的微信二维码请我喝咖啡哦~

在这里插入图片描述
或者点击 打赏地址 请我喝杯茶~

你可能感兴趣的:(计算机图形学)