【问题标题】:OpenGL Red Book with Mac OS XOpenGL 红皮书与 Mac OS X
【发布时间】:2016-03-26 22:17:42
【问题描述】:

我想在 Mac OS X 上使用 Xcode 完成 OpenGL 红皮书The OpenGL Programming Guide, 8th edition

我无法运行第一个代码示例 triangles.cpp。我已经尝试包含 Xcode 附带的 GLUT 和 GL 框架,并且我已经搜索了足够多的内容,发现我不太可能自己解决这个问题。

假设我全新安装了 Mac OS X,并且我使用 Xcode 命令行工具全新安装了 Xcode,能够运行三角形的分步说明是什么。 cpp 在那个环境中?

this 问题不同,我的偏好是 使用 Cocoa、Objective-C 或 Swift。我的偏好是只留在 C++/C 中。只有当我可以一步一步地遵循它并最终得到一个正在运行的 triangles.cpp 程序时,答案才是正确的。

我的首选是 Mac OS X 10.9,但正确答案可以假设为 10.9、10.10 或 10.11。

谢谢。

///////////////////////////////////////////////////////////////////////
//
// triangles.cpp
//
///////////////////////////////////////////////////////////////////////

#include <iostream>
using namespace std;

#include "vgl.h"
#include "LoadShader.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 },  // Triangle 1
        {  0.85, -0.90 },
        { -0.90,  0.85 },
        {  0.90, -0.85 },  // Triangle 2
        {  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]);

     glewExperimental = GL_TRUE;

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

     init();

     glutDisplayFunc(display);

     glutMainLoop();
}

编辑 1: 回应第一条评论,这是天真的努力。

  • 在 Mac OS X 10.9.5 上打开 Xcode 5.1.1
  • 创建一个新的 C++ 命令行项目。
  • 用 triangles.cpp 的内容粘贴 main.cpp 的内容。
  • 单击项目 -> 构建阶段 -> 将二进制文件与库链接
  • 添加 OpenGL.framework 和 GLUT.framework

结果:“/Users/xxx/Desktop/Triangles/Triangles/main.cpp:10:10: 'vgl.h' 文件未找到”

编辑 2: 添加了 vgh 翻译单元和 LoadShaders 翻译单元,还将 libFreeGlut.a 和 libGlew32.a 添加到我的项目编译/链接中。将所有 OpenGL Book 的 Include 内容移至我的项目源目录。必须更改几个包含语句以使用带引号的包含而不是有角度的包含。感觉这更接近工作,但找不到 LoadShader.h。请注意,OpenGL 下载中的翻译单元称为 LoadShaders(复数)。将 triangles.cpp 更改为引用 LoadShaders.h 修复了包含问题,但该翻译单元的内容似乎与从 triangles.cpp 调用的内容的签名不匹配。

【问题讨论】:

  • 您面临的问题是什么?是否存在编译器错误或链接器错误?还没开始吗?
  • 我不倾向于用我的锤子来解决这个问题(我目前无法验证它是否解决了问题)但我认为这个问题已经回答了here。跨度>
  • 查看this answer,问题可能与您的包含有关。试试#include &lt;OpenGL/vgl.h&gt;
  • 我现在正在关注这些线索,同时请不要关闭这个问题。这些链接都不是让它工作的分步指南,这可能对其未来的其他人有价值。
  • 我认为对 LoadShaders() 的调用应该只是 LoadShaders(shaders)shaders 已经是 ShaderInfo* 类型。

标签: c++ c xcode macos opengl


【解决方案1】:

源代码和 oglpg-8th-edition.zip 中的文件存在一些问题:

triangles.cpp 使用不包含在 glut 中的非标准 GLUT 函数,而只是 freeglut 实现的一部分(glutInitContextVersionglutInitContextProfile)。 freeglut 并不真正支持 OS X,而构建它依赖于额外的 X11 支持。我不会告诉你怎么做,而是修改源代码以使用 OS X 的 GLUT 框架构建。

代码依赖glew,而且书的源下载显然不包含你可以使用的二进制文件,所以你需要自己构建它。

使用以下命令构建 GLEW:

git clone git://git.code.sf.net/p/glew/code glew
cd glew
make extensions
make

现在:

  • 创建一个 C++ 命令行 Xcode 项目

  • 将可执行文件设置为与 OpenGL 和 GLUT 框架以及您刚刚构建的 glew dylib 链接。

  • 修改项目“Header Search Paths”以包含您构建的库的 glew 头文件的位置,然后是 oglpg-8th-edition/include 的路径

  • 将 oglpg-8th-edition/lib/LoadShaders.cpp 添加到您的 xcode 项目中

  • 将 triangles.cpp 源粘贴到 Xcode 项目的 main.cpp 中

  • 修改源:将#include "vgl.h"替换为:

    #include <GL/glew.h>
    #include <OpenGL/gl3.h>
    #include <GLUT/glut.h>
    #define BUFFER_OFFSET(x)  ((const void*) (x))
    

    还要确保您在问题中包含的 triangle.cpp 版本中的拼写错误已修复:当它应该是“LoadShaders.h”时包含“LoadShader.h”,而 LoadShaders(*shaders); 应该是 @987654328 @。 (我这本书中打印的代码不包含这些错误。)

  • 删除对glutInitContextVersionglutInitContextProfile的调用。

  • glutInitDisplayMode的参数改成GLUT_RGBA | GLUT_3_2_CORE_PROFILE

此时代码构建、链接和运行,但是运行程序会为我显示一个黑色窗口,而不是预期的三角形。

【讨论】:

  • 谢谢,这很有帮助。我有同样的空白窗口。
  • 非常感谢 bames53 的帮助! GLEW 似乎对我不起作用(输入 make 后出现一些编译错误)。所以我从“git clone github.com/nigels-com/glew.gitglew”克隆了一个新副本。黑色窗口的原因是缺少 triangle.vert 和 triangle.frag 文件,我认为这些文件的内容将被发送到 opengl shade 编译。我终于得出了正确的结果,并将给出另一个答案!再次感谢您的帮助!
【解决方案2】:

您可以使用此链接中的示例。这几乎是一样的。它使用 glfw 而不是 glut。

http://www.tomdalling.com/blog/modern-opengl/01-getting-started-in-xcode-and-visual-cpp/

/*
 main

 Copyright 2012 Thomas Dalling - http://tomdalling.com/

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

//#include "platform.hpp"

// third-party libraries
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>

// standard C++ libraries
#include <cassert>
#include <iostream>
#include <stdexcept>
#include <cmath>

// tdogl classes
#include "Program.h"

// constants
const glm::vec2 SCREEN_SIZE(800, 600);

// globals
GLFWwindow* gWindow = NULL;
tdogl::Program* gProgram = NULL;
GLuint gVAO = 0;
GLuint gVBO = 0;


// loads the vertex shader and fragment shader, and links them to make the global gProgram
static void LoadShaders() {
    std::vector<tdogl::Shader> shaders;
    shaders.push_back(tdogl::Shader::shaderFromFile("vertex-shader.txt", GL_VERTEX_SHADER));
    shaders.push_back(tdogl::Shader::shaderFromFile("fragment-shader.txt", GL_FRAGMENT_SHADER));
    gProgram = new tdogl::Program(shaders);
}


// loads a triangle into the VAO global
static void LoadTriangle() {
    // make and bind the VAO
    glGenVertexArrays(1, &gVAO);
    glBindVertexArray(gVAO);

    // make and bind the VBO
    glGenBuffers(1, &gVBO);
    glBindBuffer(GL_ARRAY_BUFFER, gVBO);

    // Put the three triangle verticies into the VBO
    GLfloat vertexData[] = {
        //  X     Y     Z
         0.0f, 0.8f, 0.0f,
        -0.8f,-0.8f, 0.0f,
         0.8f,-0.8f, 0.0f,
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    // connect the xyz to the "vert" attribute of the vertex shader
    glEnableVertexAttribAxrray(gProgram->attrib("vert"));
    glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL);

    // unbind the VBO and VAO
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}


// draws a single frame
static void Render() {
    // clear everything
    glClearColor(0, 0, 0, 1); // black
    glClear(GL_COLOR_BUFFER_BIT);

    // bind the program (the shaders)
    glUseProgram(gProgram->object());

    // bind the VAO (the triangle)
    glBindVertexArray(gVAO);

    // draw the VAO
    glDrawArrays(GL_TRIANGLES, 0, 3);

    // unbind the VAO
    glBindVertexArray(0);

    // unbind the program
    glUseProgram(0);

    // swap the display buffers (displays what was just drawn)
    glfwSwapBuffers(gWindow);
}

void OnError(int errorCode, const char* msg) {
    throw std::runtime_error(msg);
}

// the program starts here
void AppMain() {
    // initialise GLFW
    glfwSetErrorCallback(OnError);
    if(!glfwInit())
        throw std::runtime_error("glfwInit failed");

    // open a window with GLFW
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    gWindow = glfwCreateWindow((int)SCREEN_SIZE.x, (int)SCREEN_SIZE.y, "OpenGL Tutorial", NULL, NULL);
    if(!gWindow)
        throw std::runtime_error("glfwCreateWindow failed. Can your hardware handle OpenGL 3.2?");

    // GLFW settings
    glfwMakeContextCurrent(gWindow);

    // initialise GLEW
    glewExperimental = GL_TRUE; //stops glew crashing on OSX :-/
    if(glewInit() != GLEW_OK)
        throw std::runtime_error("glewInit failed");

    // print out some info about the graphics drivers
    std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
    std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
    std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;

    // make sure OpenGL version 3.2 API is available
    if(!GLEW_VERSION_3_2)
        throw std::runtime_error("OpenGL 3.2 API is not available.");

    // load vertex and fragment shaders into opengl
    LoadShaders();

    // create buffer and fill it with the points of the triangle
    LoadTriangle();

    // run while the window is open
    while(!glfwWindowShouldClose(gWindow)){
        // process pending events
        glfwPollEvents();

        // draw one frame
        Render();
    }

    // clean up and exit
    glfwTerminate();
}


int main(int argc, char *argv[]) {
    try {
        AppMain();
    } catch (const std::exception& e){
        std::cerr << "ERROR: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

【讨论】:

    【解决方案3】:

    关于修复 Matthew 和 Bames53 cmets 中提到的黑窗问题

    1. 关注 bames53 的回答
    2. 将着色器定义为字符串

      const char *pTriangleVert = "#version 410 核心\n\ vec4 vPosition 中的布局(位置 = 0);\n\ 无效\n\ 主()\n\ {\n\ gl_Position= vPosition;\n\ }";

      const char *pTriangleFrag = "#version 410 核心\n\ 出 vec4 fColor;\n\ 无效\n\ 主()\n\ {\n\ fColor = vec4(0.0, 0.0, 1.0, 1.0);\n\ }";

    我的 iMac 支持 OpenGl 4.1,所以我将版本更改为 410

    ShaderInfo  shaders[] = {
        { GL_VERTEX_SHADER, pTriangleVert},
        { GL_FRAGMENT_SHADER, pTriangleFrag },
        { GL_NONE, NULL }
    };
    
    1. 稍微修改 ShaderInfo 结构 改变

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

    进入

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

    1. 稍微修改loadShader函数 注释关于从文件中读取着色器的代码

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

    最好开启DEBUG,以防出现着色器编译错误

    【讨论】:

      【解决方案4】:

      我在这里为 MAC 调整了项目: https://github.com/badousuan/openGLredBook9th

      项目可以成功构建,大多数演示可以按预期运行。不过原代码是基于openGL 4.5,而MAC只支持4.1版本,一些新的API调用可能会失败。如果某些target不能正常工作,你应该考虑这个版本问题并进行一些调整

      【讨论】:

        【解决方案5】:

        我使用本教程中的代码:http://antongerdelan.net/opengl/hellotriangle.html,它适用于我的 mac。 这是我运行的代码。

        #include <GL/glew.h> // include GLEW and new version of GL on Windows
        #include <GLFW/glfw3.h> // GLFW helper library
        #include <stdio.h>
        
        int main() {
            // start GL context and O/S window using the GLFW helper library
            if (!glfwInit()) {
                fprintf(stderr, "ERROR: could not start GLFW3\n");
                return 1;
            }
        
            // uncomment these lines if on Apple OS X
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        
            GLFWwindow* window = glfwCreateWindow(640, 480, "Hello Triangle", NULL, NULL);
            if (!window) {
                fprintf(stderr, "ERROR: could not open window with GLFW3\n");
                glfwTerminate();
                return 1;
            }
            glfwMakeContextCurrent(window);
        
            // start GLEW extension handler
            glewExperimental = GL_TRUE;
            glewInit();
        
            // get version info
            const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
            const GLubyte* version = glGetString(GL_VERSION); // version as a string
            printf("Renderer: %s\n", renderer);
            printf("OpenGL version supported %s\n", version);
        
            // tell GL to only draw onto a pixel if the shape is closer to the viewer
            glEnable(GL_DEPTH_TEST); // enable depth-testing
            glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
        
            /* OTHER STUFF GOES HERE NEXT */
        
            float points[] = {
                0.0f,  0.5f,  0.0f,
                0.5f, -0.5f,  0.0f,
                -0.5f, -0.5f,  0.0f
            };
        
            GLuint vbo = 0; // vertex buffer object
            glGenBuffers(1, &vbo);
            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);
        
            GLuint vao = 0; // vertex array object
            glGenVertexArrays(1, &vao);
            glBindVertexArray(vao);
            glEnableVertexAttribArray(0);
            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        
            const char* vertex_shader =
            "#version 400\n"
            "in vec3 vp;"
            "void main() {"
            "  gl_Position = vec4(vp, 1.0);"
            "}";
        
            const char* fragment_shader =
            "#version 400\n"
            "out vec4 frag_colour;"
            "void main() {"
            "  frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
            "}";
        
            GLuint vs = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vs, 1, &vertex_shader, NULL);
            glCompileShader(vs);
            GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fs, 1, &fragment_shader, NULL);
            glCompileShader(fs);
        
            GLuint shader_programme = glCreateProgram();
            glAttachShader(shader_programme, fs);
            glAttachShader(shader_programme, vs);
            glLinkProgram(shader_programme);
        
            while(!glfwWindowShouldClose(window)) {
                // wipe the drawing surface clear
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glUseProgram(shader_programme);
                glBindVertexArray(vao);
                // draw points 0-3 from the currently bound VAO with current in-use shader
                glDrawArrays(GL_TRIANGLES, 0, 3);
                // update other events like input handling
                glfwPollEvents();
                // put the stuff we've been drawing onto the display
                glfwSwapBuffers(window);
            }
        
            // close GL context and any other GLFW resources
            glfwTerminate();
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2015-08-22
          • 1970-01-01
          • 2021-08-18
          • 1970-01-01
          • 1970-01-01
          • 2012-08-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多