概述
不同平台OpenGL开发环境的配置大同小异,我认为可以分为4部分:
1. OpenGL库:Mac OS X、Windows已经预安装,可以直接使用,linux和unix则需要自己安装,安装方法自行Google,在此不做详解。
2. OpenGL扩展库:GLEW提供了高效的运行机制,来决定哪个OpenGL扩展在目标平台上是否支持。它将OpenGL核心和扩展功能暴露在一个头文件,以供使用。安装方法自行Google,在此不做详解。
3. 应用程序框架:OpenGL是一种应用程序编程接口,本身不具有创建窗口、接收外设事件等功能,所以需要第三方软件库。目前应用较广泛的有GLUT和GLFW等,安装方法自行Google,在此不做详解。
4. 其他实用工具库:
Mac OS X平台通用步骤:
- 链接GLUT.framwork和OpenGL.framwork库。
- 导入GLEW扩展库。
基于xcode7的示例:
- 链接GLUT.framwork和OpenGL.framwork库。
- 导入GLEW扩展库。
- 基本配置已经完成,引用OpenGL编程指南(第8版)的triangles实例,来展示一个OpenGL应用的基本结构。
triangles.cpp
#include <stdio.h>
#include <iostream>
#include <gl/glew.h>
#include <GLUT/GLUT.h>
#include "LoadShaders.h"
#define BUFFER_OFFSET(x) ((const void*) (x))
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
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[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, "/Users/LXY/Desktop/test_opengl/triangles.vert" },
{ GL_FRAGMENT_SHADER, "/Users/LXY/Desktop/test_opengl/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();
}
int main(int argc, const char * argv[])
{
glutInit(&argc, (char**)argv);
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_RGBA);
glutInitWindowSize(512, 512);
glutCreateWindow(argv[0]);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
if (GLEW_VERSION_4_1) {
std::cout << "Yay! OpenGL 4.1 is supported!" << std::endl;
}
init();
glutDisplayFunc(display);
glutMainLoop();
}
}
LoadShaders.h
//////////////////////////////////////////////////////////////////////////////
//
// --- LoadShaders.h ---
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __LOAD_SHADERS_H__
#define __LOAD_SHADERS_H__
#include <OpenGL/OpenGL.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__
LoadShaders.cpp
//////////////////////////////////////////////////////////////////////////////
//
// --- LoadShaders.cxx ---
//
//////////////////////////////////////////////////////////////////////////////
#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
result: