OpenGL(1)——环境搭建

来源:互联网 发布:淘宝网儿童背包 编辑:程序博客网 时间:2024/06/03 17:21

转载自:http://johnhany.net/2014/01/environment-for-opengl-with-vs2010/

OpenGL 简介

        OpenGL(Open Graphics Library)是一个开放的、跨编程语言、跨平台的API库,提供了大量的针对图形硬件的软件接口,主要用于绘制高性能的二维和三维图形。它的一个子集OpenGL ES主要针对嵌入式系统,比如手机、平板等,目前也开始流行起来。

        GLSL(OpenGL Shading Language)是OpenGL 2.0版本开始引入的编程语言,用来编写运行在GPU上的着色程序,以代替之前所采用的固定功能管线(fixed-function pipeline)。直到3.x版本起,固定功能管线被彻底弃用,而完全被基于着色器(shader)的新功能所代替。OpenGL 3.0是最后一个同时存在新老两种功能的版本。

        目前OpenGL最新版本是4.4,GLSL的最新版本是4.4。

        由于OpenGL本身只包含涉及渲染的核心函数,而不包括平台相关的UI、文件输入输出、键盘鼠标交互等功能,在不同平台上一般采用不同的扩展库来辅助开发。在UNIX、Linux和Mac OS X平台上一般采用GLUT库实现图形界面,但已经很久没有更新了;在Windows平台上,freeglut会更实用一些。因为调用OpenGL的函数时需要频繁地调用和管理函数指针,可以使用GLEW代替这些繁琐的操作,而且GLEW还会根据你的平台决定使用哪些扩展。


检查兼容性

        OpenGL版本众多,而且各显卡厂商也有自己开发的扩展库。要想使用某个版本进行开发,既需要显卡本身支持所需的功能,又需要驱动程序能兼容这个版本。决定使用哪一个版本之前,先要用GPU Caps Viewer检查一下支持的OpenGL和GLSL的最高版本和具体支持哪些扩展。我的笔记本比较老,仅能支持OpenGL 3.0和GLSL 1.3。

gpu-caps-viewer
image-448

准备文件

        在http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip下载GLUT;

        在https://sourceforge.net/projects/glew/files/glew/1.10.0/glew-1.10.0-win32.zip/download下载GLEW。

        可以在http://www.transmissionzero.co.uk/software/freeglut-devel/下载freeglut。为了尽可能减少干扰因素,下文的样例程序没有用freeglut,而仅使用GLUT库。

        把解压得到的glutdlls37beta文件夹中的glut.h,和glew-1.10.0-win32\glew-1.10.0\include\GL文件夹中的glew.h、glxew.h、wglew.h共4个文件拷贝到C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\gl目录下。(粗体的2个文件是必需的)

include-gl
image-449

        把解压得到的glutdlls37beta文件夹中的glut.libglut32.lib,和glew-1.10.0-win32\glew-1.10.0\lib\Release\Win32文件夹中的glew32.lib、glew32s.lib,还有glew-1.10.0-win32\glew-1.10.0\lib\Release MX\Win32文件夹中的glew32mx.lib、glew32mxs.lib共6个文件拷贝到C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib目录下。(粗体的3个文件是必需的)

lib
image-450

        把解压得到的glutdlls37beta文件夹中的glut.dll、glut32.dll,和glew-1.10.0-win32\glew-1.10.0\bin\Release\Win32文件夹中的glew32.dll拷贝到C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin目录下。(粗体的2个文件是必需的)

bin
image-451

        如果发现这样运行下面的样例代码时提示缺少lib或dll文件,可以参考这篇文档修改添加文件的位置。

        所需的文件也可以在这里下载。

        如果想使用freeglut,其.h、.lib和.dll文件的位置与GLUT和GLEW是相同的。


配置工程

        打开Visual Studio 2010,新建一个Visual C++的Win32 Console Application,选项使用默认的,即Application Type为Console Application,Additional Options选Precompiled Header,其他选项都不勾选。

        打开项目Properties窗口,找到Configuration Properties -> Linker -> Input ->Additional Dependencies,添加glew32.lib。如果使用了freeglut,还要添加freeglut.lib。

linker-input
image-452

        如果还使用了freeglut库,还需要在Configuration Properties -> VC++ Directories -> Include Directories中增加 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\freeglut。

include-directories
image-453


样例代码

        把下面的代码粘贴到main.cpp文件(如果使用了 fleeglut,需要把第 8 行的“gl/glut.h”改为“freeglut.h”):

#include <stdafx.h>#include <stdio.h>#include <stdlib.h>#include <gl/glew.h>#ifdef __APPLE__#  include <gl/glut.h>#else#  include <gl/glut.h>#endifstatic struct {GLuint vertex_buffer, element_buffer, color_buffer;GLuint vertex_shader, fragment_shader, program;//用于保存CPU端的object名称struct {GLint position;GLint inColor;} attributes;//用于保存GPU端attribute变量的地址} names;static const GLfloat position_data[] = { 0.0, 0.6,-0.6, -0.4,0.6, -0.4};static const GLfloat color_data[] = {1.0, 0.0, 0.0, 1.0,0.0, 1.0, 0.0, 1.0,0.0, 0.0, 1.0, 1.0};static const GLushort element_data[] = { 0, 1, 2 };static void infoLog(GLuint object, PFNGLGETSHADERIVPROC glGet__iv, PFNGLGETSHADERINFOLOGPROC glGet__InfoLog){GLint log_length;char *log;glGet__iv(object, GL_INFO_LOG_LENGTH, &log_length);log = (char *)malloc(log_length);glGet__InfoLog(object, log_length, NULL, log);fprintf(stderr, "%s", log);free(log);}void *readShader(const char *filename, GLint *length){FILE *f = fopen(filename, "r");void *buffer;if (!f) {fprintf(stderr, "Unable to open %s for reading\n", filename);return NULL;}fseek(f, 0, SEEK_END);*length = ftell(f);fseek(f, 0, SEEK_SET);buffer = malloc(*length+1);*length = fread(buffer, 1, *length, f);fclose(f);((char*)buffer)[*length] = '\0';return buffer;}static GLuint initShader(GLenum type, const char *filename){GLint length;GLchar *source = (GLchar *)readShader(filename, &length);GLuint shader;GLint shader_ok;if (!source)return 0;shader = glCreateShader(type);//创建shader objectglShaderSource(shader, 1, (const GLchar**)&source, &length);//导入shader的代码//count - string的行数//length - 指向包含string每行字数的数组free(source);glCompileShader(shader);//编译shader代码glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok);//查询shader的状态,导出可能的编译错误if (!shader_ok) {fprintf(stderr, "Failed to compile %s:\n", filename);infoLog(shader, glGetShaderiv, glGetShaderInfoLog);glDeleteShader(shader);getchar();}return shader;}static void installShaders(void){names.vertex_shader = initShader(GL_VERTEX_SHADER, "HelloWorld-vs.glsl");names.fragment_shader = initShader(GL_FRAGMENT_SHADER, "HelloWorld-fs.glsl");GLint program_ok;names.program = glCreateProgram();glAttachShader(names.program, names.vertex_shader);glAttachShader(names.program, names.fragment_shader);//把shader依附在同一个program上,以连接两个shaderglLinkProgram(names.program);//链接program,在GPU端创建相应可执行文件,并初始化uniform变量及其地址glGetProgramiv(names.program, GL_LINK_STATUS, &program_ok);//查询program的状态,并导出可能的错误if (!program_ok) {fprintf(stderr, "Failed to link shader program:\n");infoLog(names.program, glGetProgramiv, glGetProgramInfoLog);glDeleteProgram(names.program);getchar();}glUseProgram(names.program);//激活program后才能为shader指定uniform变量的值}static void initBuffers(void){names.attributes.position = glGetAttribLocation(names.program, "position");names.attributes.inColor = glGetAttribLocation(names.program, "inColor");//获取GPU端attribute变量的地址保存在本地变量中,用于值的传递glGenBuffers(1, &names.vertex_buffer);//产生1个buffer object的名称,并分配显存空间glBindBuffer(GL_ARRAY_BUFFER, names.vertex_buffer);//把产生的buffer object与相应target绑定,以改变其值glBufferData(GL_ARRAY_BUFFER, sizeof(position_data), position_data, GL_STATIC_DRAW);//GL_STATIC_DRAW其他可用参数://STATIC - 长时间不更改的值DYNAMIC - 需要频繁改变的值STREAM - 需要偶尔重写整个buffer的值//DRAW - 保存于GPU用于绘制的值READ - 保存于CPU用于读取的值COPY - 折衷glVertexAttribPointer(names.attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*2, (void*)0);glEnableVertexAttribArray(names.attributes.position);glGenBuffers(1, &names.color_buffer);glBindBuffer(GL_ARRAY_BUFFER, names.color_buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(color_data), color_data, GL_STATIC_DRAW);glVertexAttribPointer(names.attributes.inColor, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, (void*)0);glEnableVertexAttribArray(names.attributes.inColor);glGenBuffers(1, &names.element_buffer);glBindBuffer(GL_ARRAY_BUFFER, names.element_buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, names.element_buffer);}static void idleFunc(void){}static void displayFunc(void){glClearColor(1.0, 1.0, 1.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glDrawElements(GL_TRIANGLE_STRIP, 3, GL_UNSIGNED_SHORT, (void*)0);glutSwapBuffers();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);glutInitWindowSize(400, 400);glutCreateWindow("Hello World");glutIdleFunc(&idleFunc);glutDisplayFunc(&displayFunc);glewInit();if (!GLEW_VERSION_2_0) {fprintf(stderr, "OpenGL 2.0 not available\n");getchar();}//与glew扩展库相关的函数要在glewInit()后执行installShaders();initBuffers();glutMainLoop();return 0;}

在工程内新建一个名为HelloWorld-vs.glsl的文件,内容如下:

#version 130attribute vec2 position;attribute vec4 inColor;varying vec4 outColor;void main(){    gl_Position = vec4(position, 0.0, 1.0);outColor = inColor;}
再新建一个名为HelloWorld-fs.glsl的文件,内容如下:
#version 130varying vec4 outColor;void main(){    gl_FragColor = outColor;}

运行结果

triangle-ibo

0 0