Win7 64位 + VS2013 环境下配置新版本OpenGL方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010009145/article/details/52693470

OpenGL库不仅分静态库和动态库,还要分Debug库和Release库,总之库要对上才行!

在学习OpenGL,第一件事就是下载并配置OpenGL环境,很大部分人(包括我)都是在网上找方法,但是网上的方法大致相同,直接上来就是说下载1998年版本的OpenGL库glut,然后把某个东西拷贝到哪,最后建个工程,运行一个Demo,说明OpenGL配置成功了。我只想说,1998年版本的OpenGL库确实好配,我在另外一篇帖子中有详细配置过程。但是我这次接触的书是《OpenGL编程指南》(原书第8版),这本书直接介绍的是OpenGL 4.3版本,想跟随时代脚步的我,就不想再安装1998年版的glut库了。因为从OpenGL3.0版本后,整个编程模式都发生了改变,并在后续版本中添加了很多新的特性,1998年版的glut库一直没有更新,所以新的特性就不能使用了。现在比较主流的是freeglut和glew库,这两个库都有人在维护。虽然《OpenGL编程指南》(原书第8版)的附带源码中有静态库,但是在自己机子上不可能没有动态库吧。想不使用书附带的代码,自己一行一行敲第一个OpenGL程序,并跑起来,真是折腾了几天,这些碰壁都是一点点的经验教训。好了,前面巴拉巴拉…说一大推,其实就是想把这几天折腾遇到的问题记录下来。首先是让自己再走一遍配置过程,其次是为了更多的人少花时间在配置上面,将更多的时间留给学习OpenGL。

首先,说一下VS2013配置OpenGL的几个要点:includelibdll。需要明白的就是这个lib,因为其中的坑就是它。这个lib分为静态库和动态库,又分为debug库和release库,我在这里遇到无法解析外部符号的错误,error LNK2001: 无法解析的外部符号 __imp____glewBindVertexArrayerror LNK2001: 无法解析的外部符号 __imp____glewGenVertexArrays,这种错误是由于链接时找不到函数的定义出的错。有些人是因为没有配置lib目录导致的;也有些人是配了lib目录,但是没有配置.lib文件导致的。而我,这些都做了,始终还出这种问题,而且就出那么一两个函数链接不上,讲道理,如果链接不上,全部glew打头的函数都应该解析不了,这我就受不了了,必须搞清楚。最后发现是我使用的lib库是从网上下载的(包括官网下载的),这些都是release版本,而我是在Debug模式下运行,所以库的版本与运行的环境不对,就出了这种问题,至于为什么就出这两个解析错误,我也不知道!说这么长废话,就是让大家知道,库不仅分静态库和动态库,还要分Debug库和Release库,最后还要分x86和x64,总之库要对上才行!

明白上面的道理后,那么想得到freeglut库和glew库,就需要到各自的官网下载其源码,自己编译对应的文件。

1. freeglut库的编译

freeglut库的编译有点麻烦,需要CMake工具。

  • 下载安装CMake工具

    CMake工具下载安装及其使用,我就不再废话了,官方有给说明。

    1. Download CMake (http://www.cmake.org/cmake/resources/software.html).
      Get one of the releases from the binary distribution section.

    2. Run the CMake installer, install wherever you like.

    3. Launch CMake via Start > Program Files > CMake 3.6 > CMake (GUI)
      (note that the shortcut put by the installer on your desktop does NOT point to the CMake GUI program!)

    4. In the “Where is the source code” box, type or browse to the root directory of your freeglut source (so that’s /freeglut, not /freeglut/src).

    5. In the “Where to build the binaries” box, type or browse to any
      folder you like - this will be where the Visual Studio solution will be generated. This folder does not have to exist yet.

    6. Hit the Configure button near the bottom of the window.

    7. Pick your target compiler, make sure that its installed on your
      system of course!

    8. Answer Ok when asked if you want to create the build directory.

    9. Wait for the configure process to finish.

    10. The screen will now have some configuration options on it, for
      instance specifying whether you want to build static and/or shared libraries (see below for a complete list). When you’ve selected your options, click the Configure button again.

    11. The Generate button at the bottom will now be enabled. Click Generate.

    12. The build files will now be generated in the location you picked.
      You can now navigate to the build directory you specified in step 5.
      Open the freeglut.sln file that was generated in your build directory, and compile as usual.

  • 编译freeglut源码

    1. 下载freeglut源码,下载地址http://freeglut.sourceforge.net/index.php
    2. 解压,解压后的文件其中有srcinclude,然后用CMake编译,需要提醒的是,在选择编译器的时候选择Visual Studio 12 2013,这点很重要,这个生成的freeglut是32位的。
    3. 在得到CMake的编译结果目录中,用VS2013打开freeglut.sln解决方案,然后根据需要,在Debug版本和Release版本下分别按F7编译整个解决方案,得到Debug版本和Release版本的freeglut库,我们需要的文件目录分别是lib,bin

2. glew库的编译

  1. 下载glew源码,下载地址http://glew.sourceforge.net/
  2. 解压,解压后的文件其中有srcinclude
  3. 用VS2013打开./bulid/vc12/glew.sln,这个解决方案用VS2013打开后会升级,这都不用管。然后根据需要,在Debug版本和Release版本下分别按F7编译整个解决方案,得到Debug版本和Release版本的freeglut库,我们需要的文件目录分别是lib,bin

3. 组装属于自己的OpenGL文件夹

在某处新建一个名为OpenGL文件夹,名字可以任意。然后在其下面新建includelibbin三个文件夹。首先到freeglut解压文件夹下拷贝include下的所有头文件到新建的include文件夹中,同样拷贝glew解压文件夹下的include中所有头文件。接下来拷贝lib文件,到freeglut的VS2013编译结果文件下,拷贝lib目录中的DebugRelease文件夹到新建的lib文件夹中,同样操作glew的lib。最后是bin文件夹,到freeglut的VS2013编译结果文件夹下,拷贝bin目录下所需的dll文件,同样操作glew的bin文件夹。

这个环节不太好叙述,最后给出文件的目录结构,参照这个结构图去拷贝相应文件即可。

OpenGL
|
|--include
|     |
|     |--GL
|        |
|        |--freeglut.h freeglut_ext.h freeglut_std.h glut.h
|        |--eglew.h glew.h glxew.h wglew.h
|
|--lib
|   |
|   |--Debug
|   |    |
|   |    |--freeglut_staticd.lib freeglutd.exp freeglutd.lib glew32d.exp glew32d.lib glew32sd.lib
|   |
|   |--Release
|        |
|        |--freeglut_static.lib freeglut.exp freeglut.lib glew32.exp glew32.lib glew32s.lib
|    
|--bin
|   |
|   |--Debug
|   |    |
|   |    |--freeglutd.dll glew32d.dll glewinfod.exe visualinfod.exe
|   |
|   |--Release
|        |
|        |--freeglut.dll glew32.dll glewinfo.exe visualinfo.exe

4. 环境配置

为了方便,我们把这三个玩意分别放到应该待的地方,这样方便我们开发。那么这三个玩意应该配置到哪呢?

  • 配置include
    如果VS2013是默认安装路径,则将include\GL目录中的头文件拷入C:\Program Files (x86)\Windows Kits\8.1\Include\um\gl目录下。这里说明一下,这个路径不是绝对固定的,可以放在任意一个目录下,然后在项目的属性页中配置VC++包含目录,总之能让VS能找到就可以了。
    如果不清楚安装路径在哪,那么就新建一个控制台程序,然后输入#include<gl\让vs2013自己弹出路径,见下图。
    gl目录所在位置截图

  • 配置lib
    如果VS2013是默认安装路径,则将lib\Debuglib\Release目录中的文件拷入C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib目录下,这个其他版本相应的找即可,12.0对应的是vs2013。
    lib目录所在位置截图

  • 配置dll
    dll文件的配置跟操作系统的位数有关,如果操作系统是32位则将bin\Debugbin\Release目录下的文件拷入C:\Windows\System32目录中,如果操作系统是64位系统则将bin\Debugbin\Release目录下的文件拷入C:\Windows\SysWOW64目录中。

5.《OpenGL编程指南》(原书第8版)第一个例子

为了心情急迫的大家尽快看到配置成功的结果,下面附上我自己一行一行手敲的代码(跟书上的相比有小改动),让大家体验下配置成功的喜悦心情。

5个文件LoadShader.h main.cpp LoadShader.cpp triangles.vert triangles.frag

//////////////////////////////////////////////////////////////////////////////
//
//  --- LoadShaders.h ---
//
//////////////////////////////////////////////////////////////////////////////

#ifndef __LOAD_SHADERS_H__
#define __LOAD_SHADERS_H__


#include <GL/gl.h>
#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

//----------------------------------------------------------------------------
//
//  LoadShaders() takes an array of ShaderFile structures, each of which
//    contains the type of the shader, and a pointer a C-style character
//    string (i.e., a NULL-terminated array of characters) containing the
//    entire shader source.
//
//  The array of structures is terminated by a final Shader with the
//    "type" field set to GL_NONE.
//
//  LoadShaders() returns the shader program value (as returned by
//    glCreateProgram()) on success, or zero on failure.
//

typedef struct {
    GLenum       type;
    const char*  filename;
    GLuint       shader;
} ShaderInfo;

GLuint LoadShaders( ShaderInfo* );

//----------------------------------------------------------------------------

#ifdef __cplusplus
};
#endif // __cplusplus

#endif // __LOAD_SHADERS_H__
// main.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"  //预编译需要,如果是空项目可以去掉

#include <iostream>
#include <gl\glew.h>
#include <gl\freeglut.h>
#include "LoadShaders.h"


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


using namespace std;
enum VAO_IDs {Triangles, NumVAOs};
enum Buffer_IDs {ArraryBuffer, NumBuffers};
enum Attrib_IDs {vPosition = 0};

GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];

const GLuint NumVertices = 6;

#define BUFFER_OFFSET(x)  ((const void*) (x))


void init(void)
{
    glGenVertexArrays(NumVAOs, VAOs);
    glBindVertexArray(VAOs[Triangles]);
    GLfloat vertices[NumVertices][2] = {
        {-0.90, -0.90},
        { 0.85, -0.90},
        {-0.90,  0.85},
        { 0.90, -0.85},
        { 0.90,  0.90},
        {-0.85,  0.90}
    };

    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArraryBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    ShaderInfo shaders[] = {
        {GL_VERTEX_SHADER, "triangles.vert"},
        {GL_FRAGMENT_SHADER, "triangles.frag"},
        {GL_NONE, NULL}
    };

    GLuint program = LoadShaders(shaders);
    glUseProgram(program);
    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBindVertexArray(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush();
    glutSwapBuffers();
}
int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(800, 600);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitContextVersion(4, 4);
    glutInitContextProfile(GLUT_CORE_PROFILE);

    glutCreateWindow(argv[0]);

  //glewExperimental = GL_TRUE;  //有些人需要

    if (glewInit())
    {
        cerr << "Unable to initialize GLEW ... exiting" << endl;
        exit(EXIT_FAILURE);
    }

    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
//  --- LoadShaders.cxx ---
//
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"  //预编译需要,如果是空项目可以去掉
#include <cstdlib>
#include <iostream>

//#define GLEW_STATIC
#include <GL/glew.h>
#include "LoadShaders.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

//----------------------------------------------------------------------------

static const GLchar*
ReadShader( const char* filename )
{
#ifdef WIN32
    FILE* infile;
    fopen_s( &infile, filename, "rb" );
#else
    FILE* infile = fopen( filename, "rb" );
#endif // WIN32

    if ( !infile ) {
#ifdef _DEBUG
        std::cerr << "Unable to open file '" << filename << "'" << std::endl;
#endif /* DEBUG */
        return NULL;
    }

    fseek( infile, 0, SEEK_END );
    int len = ftell( infile );
    fseek( infile, 0, SEEK_SET );

    GLchar* source = new GLchar[len+1];

    fread( source, 1, len, infile );
    fclose( infile );

    source[len] = 0;

    return const_cast<const GLchar*>(source);
}

//----------------------------------------------------------------------------

GLuint
LoadShaders( ShaderInfo* shaders )
{
    if ( shaders == NULL ) { return 0; }

    GLuint program = glCreateProgram();

    ShaderInfo* entry = shaders;
    while ( entry->type != GL_NONE ) {
        GLuint shader = glCreateShader( entry->type );

        entry->shader = shader;

        const GLchar* source = ReadShader( entry->filename );
        if ( source == NULL ) {
            for ( entry = shaders; entry->type != GL_NONE; ++entry ) {
                glDeleteShader( entry->shader );
                entry->shader = 0;
            }

            return 0;
        }

        glShaderSource( shader, 1, &source, NULL );
        delete [] source;

        glCompileShader( shader );

        GLint compiled;
        glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
        if ( !compiled ) {
#ifdef _DEBUG
            GLsizei len;
            glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &len );

            GLchar* log = new GLchar[len+1];
            glGetShaderInfoLog( shader, len, &len, log );
            std::cerr << "Shader compilation failed: " << log << std::endl;
            delete [] log;
#endif /* DEBUG */

            return 0;
        }

        glAttachShader( program, shader );

        ++entry;
    }

#ifdef GL_VERSION_4_1
    if ( GLEW_VERSION_4_1 ) {
        // glProgramParameteri( program, GL_PROGRAM_SEPARABLE, GL_TRUE );
    }
#endif /* GL_VERSION_4_1 */

    glLinkProgram( program );

    GLint linked;
    glGetProgramiv( program, GL_LINK_STATUS, &linked );
    if ( !linked ) {
#ifdef _DEBUG
        GLsizei len;
        glGetProgramiv( program, GL_INFO_LOG_LENGTH, &len );

        GLchar* log = new GLchar[len+1];
        glGetProgramInfoLog( program, len, &len, log );
        std::cerr << "Shader linking failed: " << log << std::endl;
        delete [] log;
#endif /* DEBUG */

        for ( entry = shaders; entry->type != GL_NONE; ++entry ) {
            glDeleteShader( entry->shader );
            entry->shader = 0;
        }

        return 0;
    }

    return program;
}

//----------------------------------------------------------------------------
#ifdef __cplusplus
}
#endif // __cplusplus
//triangles.vert
#version 440 core
layout(location = 0) in vec4 vPosition;
void main()
{
    gl_Position = vPosition;
}
//triangles.frag
#version 440 core
out vec4 fColor;
void main()
{
    fColor = vec4(0.0, 0.0, 1.0, 1.0);
}

最后附上运行结果截图
运行结果截图

6. 总结

配置环境好累,当遇到问题时,百度完后,再Google都解决不了那一刻,我的内心是焦急的,然而最后通过努力,把问题吭掉之后,我的心情却是甜美的。但是,最后写博客更加累,毕竟这是另外一件活!

最后希望,本博客能帮助到更加多学习OpnGL的人吧!

猜你喜欢

转载自blog.csdn.net/u010009145/article/details/52693470