標籤:

在 OS X 下怎麼寫新版本的 OpenGL?

我要瘋了……整整兩天,我就想問問,蘋果能不能用 OpenGL 3 或以上寫代碼?蘋果說自己可以……但是……如果有的話請讓我看看……

網上的教程幾乎不能畫出三角形,固定管線(glBegin())可以,但是過時了。

OpenGL Step by Step 這個教程,第一步讓畫點,點能畫出來,但是到下一張簡單的替換成三角形就畫不出來了,函數調用什麼的都一樣,理論上來說點能畫出來為什麼三角形就畫不出來……表現為一個黑黑的窗口什麼都沒有。

這個教程 http://www.learnopengl.com/ 提供的代碼 https://raw.githubusercontent.com/JoeyDeVries/LearnOpenGL/master/src/1.getting_started/2.hello_triangle/hellotriangle2.cpp 不能編譯,因為沒有 glGenVertexArrays 這一系列函數,Stackoverflow 上搜,說加一個 OpenGL/gl3.h 頭就有了,加上的確編譯過了。但 GLFW 窗口創建失敗,窗口指針為空。

這個教程 OpenGL基礎知識 上面說 OS X 只支持 OpenGL 2 ,然後提供了一些 OpenGL 2 的移植代碼,但是蘋果說新版本的已經能支持了OS X 10.9 Core Profile OpenGL Information。我希望還是用新版本的,心想可能教程過時了。

這個教程網頁上的代碼和下載下來的代碼不一樣,網頁上的代碼是用 glGenBuffers 等一系列函數操作緩衝區的。可以編譯通過,GLSL也能編譯鏈接,但是就不給我顯示三角形啊!!!和第一個教程一樣!!!!!

下載下來的代碼是用 glGenVertexArrays,同樣找不到這個函數,然後加上 gl3.h, 給出的例子也編譯過了,依然是 GLFW 窗口創建失敗,和第二個教程一樣!!!!!!

搜索了一下,說這是正確的行為,不允許創建窗口……WTF c++ - Creating OpenGL 3.3 Context with GLFW in Mac OS X 10.9 什麼鬼,說要聲明為 core 什麼的,設置了沒有用啊……

然後又去 stackoverflow 找了一下,找到別人的解決方法 c++ - Can"t draw triangle using Opengl 給了兩段代碼,OpenGL 3 的運行錯誤,GLSL 沒辦法編譯,錯誤信息不支持這個版本,OpenGL 2 能夠運行…

我要死了……要被搞死了


OSX對於GL 2.1以上只支持Core Profile.

GLFW支持創建Core Profile Context.

glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

注意Core Profile下有不少區別和坑, 以及glew不適用於Core Profile.

補充一下就是glfw有啥問題看代碼比較簡單能知道為啥, 比如關於nsgl context

https://github.com/glfw/glfw/blob/master/src/nsgl_context.m#L101


2017.02.06添加

使用meshula/mkvfx,而不是Polytonic/Glitter

mkvfx支持的功能比Glitter更多,支持Alembic、OpenSubdiv、OSL等特效開發庫,支持boost.python和qt。基本上Blender開發過程中需要的類庫都包含了。

而且mkvfx支持牛逼至極的bgfx,如果使用bgfx而非glfw創建窗口,你基本上可以編寫同時支持幾乎所有3D API的程序。

============================

2016.12.31添加

用了點時間,吧LearnOpenGL的全部源碼用移植到了Glitter上

THISISAGOODNAME/learnopengl-glitter

============================

原答案:

最近發現非常適合新人學習圖形學的一個框架

Polytonic/Glitter

這個已經配置了glfw,glad,assimp,stb,bullet,glm,學習圖形學(opengl)的話應該是完全足夠,不需要什麼其他庫了

在mac上使用的話,clone下來之後運行

# Mac OSX
cmake -G "Xcode" ..

當然,更推薦用clion直接打開該項目

運行時建議第一次先build_all,以後運行把項目選擇Glitter即可

PS:osx10.11以後肯定是支持opengl 4.1 core的,有回答說只支持opengl 2應該是比較老的版本了。

PS2:osx的opengl在獲取GL_VERSION的時候應該有bug,我主動設置opengl版本為3.3,但是獲取的GL_VERSION值會顯示為4.1,不過shader編譯正常,運行也正常

PS3:glfw可能需要glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 此行用來給Mac OS X系統做兼容

PS4:retina屏的Mac在設置viewport時直接設置成窗口的寬高會有尺寸問題,應該從緩衝獲取窗口的寬高

// 獲取視口
int width, height;
glfwGetFramebufferSize(window, width, height);
glViewport(0, 0, width, height);


隨便選一個框架

glfw/glfw

cinder/Cinder

openframeworks/openFrameworks

island-org/island


樓主還差一個教程,那就是 Tutorial 1 : Opening a window , 我剛開始學OpenGL的時候也是在Mac下,你需要用glfw來幫你管理系統的OpenGL,所以你要先學會配好GLFW,而配GLFW,還需要再配glew,可以參考Youtube這個教程 https://www.youtube.com/watch?v=lTmM3Y8SMOM 。順便說下, http://www.learnopengl.com/ 這個教程是最好的OpenGL教程了吧。

更多相關內容:我的知乎導航 - 知乎專欄


維納斯比三角形稍微好看點

最後生產上下文的代碼都會變成如圖右邊類似的格式,按不同的條件創建而已,可以自己對對。

或者看UE4/Sources/Runtime/OpenGLDrv/Private/Mac/MacOpenGLContext.cpp - CreateContext 直接看人家怎麼初始化的OpenGL上下文的。

這個教程 http://www.learnopengl.com/ 提供的代碼 https://raw.githubusercontent.com/JoeyDeVries/LearnOpenGL/master/src/1.getting_started/2.hello_triangle/hellotriangle2.cpp 不能編譯,因為沒有 glGenVertexArrays 這一系列函數,Stackoverflow 上搜,說加一個 OpenGL/gl3.h 頭就有了,加上的確編譯過了。但 GLFW 窗口創建失敗,窗口指針為空

GLFW窗口創建失敗返回nullptr的問題我遇到過了,窗口創建失敗是前面提交的配置不對,調試步進看什麼失敗了,在最外面加對應的配置就可以fix, 我當時遇到的是glfw/src/context.c _glfwIsValidContextConfig函數中if (ctxconfig-&>forward ctxconfig-&>major &< 3)驗證失敗的鍋,所以在初始化的時候加了這麼一句就ok了。

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

完整的是

glfwInit();

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);


畫三角形

Migrate your OpenGL Applications to OpenGL 3.2

The OpenGL 3.2 Core profile provides a clean break from earlier versions of OpenGL in favor of a simpler shader-based pipeline. For better compatibility with future hardware and OS X releases, migrate your applications away from legacy versions of OpenGL. Many of the recommendations listed above are required when your application uses OpenGL 3.2.

OpenGL on the Mac Platform

os x下使用OpenGL3需要用到core profile,純可編程流水線模式,不兼容被廢棄的函數

題主是不是沒有加上這個參數

glutInitDisplayMode(GLUT_3_2_CORE_PROFILE );


看了一下這差不多是兩年前的問題了,也讀了各位菊苣的回答,感覺對於新人來說,還不是很適合從零開始配環境。【大佬可以繞路了】

本答案以紅寶書第八版第一個例子作為框架,詳細記錄了mac OS X使用OpenGL的全過程。

原文鏈接:【OpenGL on macOS】紅寶書第八版第一個程序

答案和原文基本沒區別,不過排版看起來不太舒服。

------------------分割線-----------------------

一、配環境

新建命令行(Command Line Tool)工程,在工程設置里引入兩個庫:OpenGL.frameworks和GLUT.frameworks

之後,修改search path,把Always Search User Paths改為Yes:

沒錯,似乎這樣環境就ok了。不用折騰什麼glfw之類,不過如果有需要的話,這個鏈接的文章值得參考:

https://zrz0f.com/2016/02/21/glfw/

接著往下看,坑在後面。

二、敲代碼

紅寶書的官網在這方面有點不人性化,居然只能下第九版書本的源碼(官方我求你更新慢一點好嗎),並且還和第八版存在一些明顯的差異(包括用的庫都不一樣)。後來在51CTO上面找到了資源http://down.51cto.com/data/2193129。不過為了下載方便一點,還是請用下面的度盤鏈接:

鏈接: https://pan.baidu.com/s/1bppISqF 密碼: dqhm

拿到源碼以後:居然沒有第一個例子的代碼(triangle.cpp)!

強烈推薦手敲一遍,一方面可以再仔細讀一遍源碼,另一方面還可以理解一下源碼的流程和思想。豈不美哉。ps.千萬別去複製第九版的代碼。

好吧我知道有人不願意敲(比如我自己一開始就不願意,後來…),在這裡貼上來:

//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////

#include &
using namespace std;

#include "vgl.h"
#include "LoadShaders.h"

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;

//----------------------------------------------------------------------------
//
// init
//

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, "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);
}

//----------------------------------------------------------------------------
//
// display
//

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);

glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);

glFlush();
}

//----------------------------------------------------------------------------
//
// main
//

int main(int argc, char ** argv)
{
glutInit(argc, argv);

glutInitDisplayMode(GLUT_RGBA);

glutInitWindowSize(512,512);

glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);

glutCreateWindow(argv[0]);

if(glewInit())
{
cerr &<&< "Unable to initialize GLEW ... exiting" &<&< endl; exit(EXIT_FAILURE); } init(); glutDisplayFunc(display); glutMainLoop(); }

把main.cpp重命名成triangle.cpp後,碼完上述代碼。

之後,將oglpg-8th-edition/lib/LoadShaders.cpp,和oglpg-8th-edition/include/LoadShaders.h拖入工程。為了防止對源文件的改動,我們勾選「Copy items if needed」

現在運行程序還是會報很多錯的,下面開始修改代碼。

三、修改代碼

1.頭部

既然開頭就是要引入vgl.h,那不妨先看看這個頭文件里有些啥:

一堆條件編譯,以及有關freeglut/glew的聲明。然而,mac用不上glew(至少這個例子用不上),我們也不用去使用freeglut..所以我們只需要把頭文件里最有用的bufferoffset的定義放到main函數中,並引入glut庫。

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

參考:http://markzhang.cn/blog/2014/01/06/hellogl-on-macosx/,這也是一篇很好的教程,本文下面的內容有部分參考自此處

之後刪掉(如果不放心可以選擇注釋掉)#include 「vgl.h」

2.main函數

  • 在main函數中增加一行代碼:

cout &<&< "Supported GLSL version is: " &<&< glGetString(GL_SHADING_LANGUAGE_VERSION) &<&< endl;

這是為了獲取目前openGL的版本,在程序運行後,就可以根據這個版本號去修改相關著色器的version了。

  • 刪除這些代碼:

glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);

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

刪除上面兩行的理由是,我們這裡沒有使用書中的freeglut,因為Xcode自帶了GLUT(應該是openglut),所以就沒有必要再安裝一個類似的庫了。 而Xcode自帶的GLUT,是沒有上述的兩個函數的;刪除下面一段的理由是,我們這裡不使用glew庫。

  • 關鍵的地方:

glutInitDisplayMode(GLUT_RGBA);

改成:

glutInitDisplayMode(GLUT_RGBA);

這是因為在上面刪掉了

glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);

之後,我們沒有指定版本號,所以在顯示模式里加以指定。

3.改.frag和.vert

這個地方要感謝Stack Overflow上面的提問者Matthew James Briggs和回答者bames53、gonglong。

源問題鏈接:https://stackoverflow.com/questions/34385540/opengl-red-book-with-mac-os-x/37561780#37561780?newreg=0bfd40bef37541a3bb68cc21b5b9af59

雖然我不知道是否有更簡單的做法,不過按照他們的過程確實做出了想要的結果。

  • triangle.cpp

在頭部常量定義的部分加上:

const char *pTriangleVert ="#version 410 core

layout(location = 0) in vec4 vPosition;

void

main()

{

gl_Position= vPosition;

}";

const char *pTriangleFrag = "#version 410 core

out vec4 fColor;

void

main()

{

fColor = vec4(0.0, 0.0, 1.0, 1.0);

}";

為什麼要加上這些?因為似乎Xcode下面讀文件有問題,也就是說,用.vert和.frag文件並寫上相關的代碼交給著色器,著色器並不買賬。(我做出來的結果是:無論如何修改結點的fColor,三角形均為白色)

所以,我們相當於把兩個文件中的內容改成了字元串,直接交給著色器去讀,效果是一樣的。

注意:這個地方的#version 410 core要填成你自己的openGL版本號!

修改ShaderInfo:

ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, pTriangleVert},
{ GL_FRAGMENT_SHADER, pTriangleFrag },
{ GL_NONE, NULL }
};

  • LoadShaders.h

#include &

改成:

#include &

並把ShaderInfo結構體里的 filename 改成 source

  • LoadShaders.cpp

把與glew相關的代碼刪掉:

#define GLEW_STATIC
#include &

把所有的 _DEBUG 改為 DEBUG

之後刪掉:

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;

改成

glShaderSource(shader, 1, entry-&>source, NULL);

刪掉

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

------------------分割線-----------------------

為了方便,把做完所有修改後的代碼粘在下面:

  • triangle.cpp

//
// triangle.cpp
// gl_c1
//
// Created by SillyDog on 2017/4/19.
// Copyright ? 2017年 SillyDog. All rights reserved.
//

//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////

#include &
using namespace std;

//#include "vgl.h"
#include "LoadShaders.h"
#include &

#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;
const char *pTriangleVert ="#version 410 core

layout(location = 0) in vec4 vPosition;

void

main()

{

gl_Position= vPosition;

}";

const char *pTriangleFrag = "#version 410 core

out vec4 fColor;

void

main()

{

fColor = vec4(0.0, 0.0, 1.0, 1.0);

}";

//----------------------------------------------------------------------------
//
// init
//

void init()
{
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, "triangles.vert" },
{ GL_FRAGMENT_SHADER, "triangles.frag" },
{ GL_NONE, NULL }
};*/

ShaderInfo shaders[] = {
{ GL_VERTEX_SHADER, pTriangleVert},
{ GL_FRAGMENT_SHADER, pTriangleFrag },
{ GL_NONE, NULL }
};

GLuint program = LoadShaders(shaders);
glUseProgram(program);

glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
}

//----------------------------------------------------------------------------
//
// display
//

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);

glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);

//glutSwapBuffers();
glFlush();
}

//----------------------------------------------------------------------------
//
// main
//

int main(int argc, char ** argv)
{
glutInit(argc, argv);

glutInitDisplayMode(GLUT_RGBA | GLUT_3_2_CORE_PROFILE);

//glutInitDisplayMode(GLUT_RGBA);

glutInitWindowSize(512,512);

//glutInitContextVersion(4, 3);
//glutInitContextProfile(GLUT_CORE_PROFILE);

glutCreateWindow(argv[0]);

/*
if(glewInit())
{
cerr &<&< "Unable to initialize GLEW ... exiting" &<&< endl; exit(EXIT_FAILURE); } */ cout &<&< "Supported GLSL version is: " &<&< glGetString(GL_SHADING_LANGUAGE_VERSION) &<&< endl; init(); glutDisplayFunc(display); glutMainLoop(); }

  • LoadShaders.h

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

#ifndef __LOAD_SHADERS_H__
#define __LOAD_SHADERS_H__

#include &
//#include &

#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;
*/

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

GLuint LoadShaders( ShaderInfo* );

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

#ifdef __cplusplus
};
#endif // __cplusplus

#endif // __LOAD_SHADERS_H__

  • LoadShaders.cpp

//////////////////////////////////////////////////////////////////////////////
//
// --- LoadShaders.cxx ---
//
//////////////////////////////////////////////////////////////////////////////

#include &
#include &

//#define GLEW_STATIC
//#include &
#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&(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;
*/
glShaderSource(shader, 1, entry-&>source, NULL);

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

工程目錄:

運行結果:

祝OpenGL旅途愉快:)


我用的N年前的Macbook Pro, 沒在Xcode下運行, 用的是macvim, OpenGL在mac OS上除了上面各位的描述, 還要一條glfwWindowHint(GL_OPENGL_FORWARD_COMPAT, GL_TRUE), 這樣就可以在Mac上愉快的玩耍了...


@Ocean-藏心 提到的油管的教就可以了,如果想用命令行,將 glfw 和 glew 編譯完直接使用OpenGL 和 GLUT framework用以下命令:

g++ main.cpp -framework OpenGL -framework GLUT -lglfw -lglew

如果用Glad的話就不用直接引入OpenGL的framework,命令如下:

g++ -x c++ main.cpp -x c glad.c -lglfw

這裡需要添加glad.c的文件替代上面OpenGL的依賴,由glad來管理OpenGL的版本,具體見官網。源自LearnOpenGL


如果想在Xcode中快速學習OpenGL3.3的話可以直接按照opengl-turorial(Tutorial 1 : Opening a windowTutorial 1 : Opening a window)的要求下載3.3版本的程序,並按照要求進行編譯即可。opengl-tutorial中建議Mac OS使用2.1版本(當時「忽悠」住我了,我就一直沒敢用3.3版本的程序),我個人感覺這跟樓主是一個問題,因為是OS10.9之後才開始支持3.3以上版本,我回答問題的時候OS已經是10.12了,所以有點站著說話不腰疼的感覺了。編譯成功後,用Xcode打開工程之後會發現Header Search Paths中多了很多路徑,這是工程中Cmake產生的,會發現都是在工程目錄下的幾個文件夾中,比如glefw,glew和glm等,因為tutorial提供的相關代碼是自帶著這些庫文件的。如果想編寫自己的程序中帶有這些庫,只需要安裝glfw,glew和glm等到系統路徑/usr/local/include 和/usr/local/lib即可,這可以通過Homebrew快速安裝,然後修改相關的Header Search Paths即可。


不支持固定流水線了吧,只能用shader


你看看上面的評論,設置顯示模式時候,這樣

// 顯示模式:雙緩衝、RGBA,OpenGL3.2(默認2.1)

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA|GLUT_3_2_CORE_PROFILE);


glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_3_2_CORE_PROFILE);

const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回當前OpenGL實現的版本號

OpenGL實現的版本號:4.1 INTEL-10.14.73


。。。我也是。。。坑死。。。快來幫我。。。哭哭哭

xcode自帶OpenGL庫是2.0,但現都是可編程管線應該用OpenGL3.x啊,那怎麼用3.x呢? - 遊戲開發


推薦閱讀:

初學OpenGL 用的是OpenGL2.1加MFC 但是感覺好難啊!難度是兩方面的啊?
初學者學習opengl是用紅寶書好還是藍寶書好?
Nehe OpenGL 教程是否過時?
如何利用shader在文字上添加漸變陰影的效果?

TAG:macOS | OpenGL |