OpenGL学习笔记: (1)mac下OpenGL环境搭建

1,OpenGL是什么

OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。

2,OpenGL能做什么

OpenGL能用来开发跨平台的渲染引擎,在Android、OSX、iOS、Windows、PS等平台均可使用 OpenGL(ES)。

3,OpenGL不能做什么

OpenGL不能做物理模拟,OpenGL不能做网络通信,一句话,除了渲染以外的事情,OpenGL都做不了,OpenGL只是一个3D渲染API接口标准。

4,OpenGL VS DirectX

OpenGL和DirectX 相比有以下几点不同:

  1. OpenGL只能做渲染,DirectX除了渲染以外还能做许多其它的,比如,DirectX 里面包含d3dxmath可以用来做3D数学运算;DirectX里面包含的外部设备接口模块可以用来接受外部设备的输入。
  2. OpenGL只是一个定义了一些接口的标准,只要实现了这些接口,那么就算是实现了OpenGL,相反的,DirectX则只有微软自己实现的那一份代码,所有人都使用微软给出的那份代码。
  3. OpenGL能跨平台,几乎所有的平台都支持OpenGL,从移动设备到PC产品再到主机平台,都支持OpenGL,而DirectX则只有微软自己的XBox和Windows支持。
  4. 速度方面,DirectX完爆OpenGL,对同一硬件而言,DirectX是OpenGL 渲染速度的两倍多。

5,MAC OpenGL环境搭建

我在MAC上使用OpenGL时,使用了如下一些工具和库:Mac Ports、glfw、glew、XCode。

  1. MacPorts是MAC 平台用来安装第三方库的软件,与 Linux上的apt-install有点像,大家可以从https://www.macports.org/下载
  2. glfw,OpenGL的扩展程序,因为OpenGL只是一个渲染接口,如果要在具体平台上写OpenGL渲染代码,就要使用 qlfw等库将OpenGL 和本地窗口等环境联系起来,安装glfw只需要使用mac ports即可(sudo port install glfw)。
  3. glew,与 glfw类似,使用sudo port install glew安装。
  4. XCode,MAC平台开发唯一的神器,别告诉我在mac你还在用Eclipse写C++。

6,Demo代码

在这里,我只给出一个demo代码,即使用Gourand着色画一个正方形,代码主要包含以下几部分。

/*
 *  File:    Shader.h
 *  author:  张雄
 *  date:    2016_02_21
 *  purpose: 用于定义OpenGL shader操作的接口
 */

#ifndef __ZX_NXENGINE_SHADER_H__
#define __ZX_NXENGINE_SHADER_H__

#include "../common/NXCore.h"

namespace NX {
    class Shader{
    public:
        /*
         *  <函数功能>
         *  构造函数
         *
         *  <函数参数>
         *  szFilePath:    要使用的shader代码的路径,需要保证的是,仅使用szFilePath,在
         *                 程序中即可找到shader文件。

         *  uShaerType:    要使用的shader 代码的shader类型,此类型有GL_VERTEX_SHADER等
         *                 与OpenGL中使用的值完全相同。
         */
        Shader(const char* szFilePath, GLenum uShaderType);
        virtual ~Shader();
    public:

        /*
         *  <函数功能>
         *  编译shader,shader文件和类型由构造函数给出
         */
        virtual std::string Compile();
    public:
        operator GLuint(){
            return m_uShaderId;
        }
    private:
        std::string ReadShaderSource();
    private:
        GLuint         m_uShaderId;
        GLenum         m_uShaderType;
        std::string    m_strShaderSourceFilePath;
    };
}

#endif
#include <fstream>
#include <string>

#include "NXShader.h"
#include "NXLog.h"

NX::Shader::Shader(const char* szFilePath, GLenum uShaderType){
    m_strShaderSourceFilePath = (szFilePath);
    m_uShaderId               = 0;
    m_uShaderType             = uShaderType;
}

NX::Shader::~Shader(){
    if(m_uShaderId != 0){
        glDeleteShader(m_uShaderId);
        m_uShaderId   = 0;
        m_uShaderType = 0;
    }
}

std::string NX::Shader::Compile(){
    std::string strErr(256 + 1, 0);
    m_uShaderId   = glCreateShader(m_uShaderType);
    const std::string strShaderSrc = ReadShaderSource();
    if(strShaderSrc.empty()){
        sprintf((char*)strErr.c_str(), "shader file [%s] not exist or is empty", m_strShaderSourceFilePath.c_str());
        glb_GetLog().log("%s", strErr.c_str());
        return strErr;
    }
    const char * szShaderSrc = strShaderSrc.c_str();
    glShaderSource(m_uShaderId, 1, &szShaderSrc, NULL);
    glCompileShader(m_uShaderId);
    glGetShaderInfoLog(m_uShaderId, (GLuint)strErr.length(), NULL, &(strErr[0]));
    glb_GetLog().log("compile shader [%s] with compile msg [%s]", m_strShaderSourceFilePath.c_str(),
                     (strErr[0] == 0 ? "Compile succeed" : strErr.c_str()));
    return strErr;
}

std::string NX::Shader::ReadShaderSource(){
    std::ifstream in(m_strShaderSourceFilePath);
    std::string line;
    std::string strShaderSrc;
    while(std::getline(in, line)){
        line          += "\r\n";
        strShaderSrc += line;
    }
    in.close();
    return strShaderSrc;;
}
/*
 *  File:    Application.h
 *  author:  张雄
 *  date:    2016_02_21
 *  purpose: 用于定义OpenGL应用程序接口,注意,此接口使用了glfw和glew,需要先安装此工具库,
 *  在mac上可使用macports安装,具体操作请google macports,Linux系统使用apt-get,
 *  windows系统请直接下载库和头文件(自己编译估计有点坑)
 */

#ifndef __ZX_NXENGINE_APPLICATION_H__
#define __ZX_NXENGINE_APPLICATION_H__

#include "../common/NXcore.h"

namespace NX {
    class Application{
    public:
        Application();
        virtual ~Application();
    public:
        /*
         *  <函数功能>
         *  使用glfw和glew库初始化OpenGL环境,注意,此函数应该是构造函数之后调用的第一个类函数,
         *  在调用此函数并且成功之前,不得调用其它OpenGL函数。其它类如果继承此类,则需要首先调用
         *  此类的Init函数,再执行子类的Init代码。
         *
         *  <函数参数>
         *  vCmdLine:   命令行字符串数组,与C的main函数类似
         *  iCmdCount:  命令行字符串个数
         *  iWidth:     OpenGL使用的窗口的宽(以像素为单位)
         *  iHeight:    OpenGL使用的窗口的高(以像素为单位)

         *  <返回值>
         *  true:  初始化成功,在init之后,即可调用其它OpenGL函数
         *  false: 初始化失败
         */
        virtual bool Init(__in const char* vCmdLine[], __in const int iCmdCount,
                          __in const int iWidth, __in const int iHeight);
        /*
         *  <函数功能>
         *  游戏中的Tick函数。
         *
         *  <函数参数>
         *  iTime:   时间,以秒为单位
         */
        virtual void Tick(const double DeltaTime);

        /*
         *  <函数功能>
         *  游戏中的Render函数,主要完成游戏中的渲染
         *
         */
        virtual void Render();

        /*
         *  <函数功能>
         *  游戏中的主循环,其它类若要继承此类,最好不要重载Run函数,以免不必要的麻烦
         *
         */
        virtual void Run();

    public:

        /*
         *  <函数功能>
         *  错误处理函数
         *
         *  <函数参数>
         *  与glfw中错误处理回调函数的参数完全相同。
         */
        virtual void OnError(int error, const char* description);

        /*
         *  <函数功能>
         *  错误处理函数
         *
         *  <函数参数>
         *  与glfw中键盘事件回调函数的参数意义完全相同
         */
        virtual void OnKeyEvent(int key, int scancode, int action, int mods);
    };
}

#endif

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "NXApplication.h"
#include "../math/NXMath.h"
#include "../common/NXLog.h"

static NX::Application* g_pThis  = NULL;
static GLFWwindow*        g_window = NULL;

static void error_callback(int error, const char* description);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);

NX::Application::Application(){
    g_pThis   = NULL;
    g_window  = NULL;
}

NX::Application::~Application(){
    g_pThis    = NULL;
    g_window   = NULL;
}

bool NX::Application::Init(const char* vCmdLine[], const int iCmdCount, const int iWidth, const int iHeight){
    g_pThis = this;
    NX::InitNXMath();
    if (!glfwInit()) {
        fprintf(stderr, "Failed initialize GLFW.");
        exit(EXIT_FAILURE);
        return false;
    }
    {
        glfwSetErrorCallback(error_callback);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
    }
    {
        GLFWwindow* window = glfwCreateWindow(iWidth, iHeight, "OpenGL", NULL, NULL);
        if(!window) {
            std::fprintf(stderr, "Failed to create GLFW window.");
            glfwTerminate();
            exit(EXIT_FAILURE);
            return false;
        }
        g_window = window;
        glfwMakeContextCurrent(window);
        glfwSetKeyCallback(window, key_callback);
    }
    glb_GetLog().logToConsole("OpenGL version supported by this platform (%s)", glGetString(GL_VERSION));
    glb_GetLog().log("OpenGL version supported by this platform (%s)", glGetString(GL_VENDOR));
    glewExperimental = GL_TRUE;
    glewInit();
    return true;
}

void NX::Application::Tick(const double DeltaTime){
    static double iTotalTime = 0;
    iTotalTime += DeltaTime;
    static char Title[32];
    static int iFrameCount = 0;
    ++iFrameCount;
    if(iTotalTime >= 1.0){
        sprintf(Title, "fps: %.2f", (iFrameCount / iTotalTime));
        iFrameCount = 0;
        iTotalTime  = 0;
        glfwSetWindowTitle(g_window, Title);
    }
}

void NX::Application::Render(){
    static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
    glClearBufferfv(GL_COLOR, 0, green);
}

void NX::Application::OnError(int error, const char* description){
    std::fputs(description, stderr);
}

void NX::Application::OnKeyEvent(int key, int scancode, int action, int mods){
    if(g_window == NULL){
        return;
    }
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS){
        glfwSetWindowShouldClose(g_window, GL_TRUE);
    }
}

void NX::Application::Run(){
    static double PreTime = glfwGetTime();
    static double NowTime = glfwGetTime();
    while(!glfwWindowShouldClose(g_window)){
        NowTime = glfwGetTime();
        Tick(NowTime - PreTime);
        Render();
        glFlush();
        glfwSwapBuffers(g_window);
        glfwPollEvents();
        PreTime = NowTime;
    }
}

static void error_callback(int error, const char* description) {
    if(!g_pThis){
        return;
    }
    g_pThis->OnError(error, description);
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if(!g_window){
        return;
    }
    g_pThis->OnKeyEvent(key, scancode, action, mods);
}
#ifndef __ZX_OPENGL_APPLICATION_CHAP1_1_H__
#define __ZX_OPENGL_APPLICATION_CHAP1_1_H__

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include "../engine/render/NXApplication.h"
#include "../engine/common/NXLog.h"
#include "../engine/render/NXProgram.h"

class AppChap1_1: public NX::Application{
public:
    typedef struct vertex{
        GLfloat x;
        GLfloat y;
        GLfloat r;
        GLfloat g;
        GLfloat b;
        GLfloat a;
    }vertex;
public:
    AppChap1_1();
    virtual ~AppChap1_1();
public:
    virtual bool Init(const char* vCmdLine[], const int iCmdCount, const int iWidth, const int iHeight);
    virtual void Tick(const double DeltaTime);
    virtual void Render();
    virtual void OnKeyEvent(int key, int scancode, int action, int mods);
private:
    GLuint   m_uVBO1;
    GLuint   m_uVBO2;
    GLuint   m_uVAO1;
    GLuint   m_uVAO2;
    GLuint   m_UsedVBO;
    GLuint   m_UsedVAO;
    NX::Program*   m_pg;
};

#endif
#include <iostream>

#include "AppChap1_1.h"
#include "NXShader.h"

AppChap1_1::AppChap1_1(){
    m_uVAO1     = 0;
    m_uVAO2     = 0;
    m_uVBO1     = 0;
    m_uVBO2     = 0;
    m_UsedVBO   = 0;
}

AppChap1_1::~AppChap1_1(){

}

bool AppChap1_1::Init(const char* vCmdLine[], const int iCmdCount, const int iWidth, const int iHeight){
    if(!NX::Application::Init(vCmdLine, iCmdCount, iWidth, iHeight)){
        return false;
    }

    {//vao1
        glGenVertexArrays(1, &m_uVAO1);
        glBindVertexArray(m_uVAO1);
    }
    {//vbo1
        glGenBuffers(1, &m_uVBO1);
        glBindBuffer(GL_ARRAY_BUFFER, m_uVBO1);
        vertex v[4] = {
            {-1.0f, 1.0f,   1.0f, 0.0f, 0.0f, 1.0f},
            {1.0f,  1.0f,   0.0f, 1.0f, 0.0f, 1.0f},
            {-1.0f, -1.0f,  0.0f, 0.0f, 1.0f, 1.0f},
            {1.0f,  -1.0f,  1.0f, 1.0f, 1.0f, 1.0f}
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    {//vao2
        glGenVertexArrays(1, &m_uVAO2);
        glBindVertexArray(m_uVAO2);
    }
    {//vbo2
        glGenBuffers(1, &m_uVBO2);
        glBindBuffer(GL_ARRAY_BUFFER, m_uVBO2);
        vertex v[4] = {
            {-0.8f, 0.8f,   0.0f, 1.0f, 1.0f, 1.0f},
            {0.8f,  0.8f,   1.0f, 0.0f, 1.0f, 1.0f},
            {-0.8f, -0.8f,  1.0f, 1.0f, 0.0f, 1.0f},
            {0.8f,  -0.8f,  0.0f, 0.0f, 0.0f, 1.0f}
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    m_UsedVAO = m_uVAO1;
    m_UsedVBO = m_uVBO1;

    {//program
        m_pg = new NX::Program();
        m_pg->AddShader("./redbook/Chap1/VS1_1.glsl", GL_VERTEX_SHADER);
        m_pg->AddShader("./redbook/Chap1/FS1_1.glsl", GL_FRAGMENT_SHADER);
        m_pg->LinkProgram();
        m_pg->UseProgram();
    }
    return true;
}
void AppChap1_1::Tick(const double DeltaTime){

}

void AppChap1_1::Render(){
    m_pg->UseProgram();
    glClearColor(0.0f, 0.25f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(m_UsedVAO);
    glBindBuffer(GL_ARRAY_BUFFER, m_UsedVBO);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)8);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    //glViewport(100, 100, 400, 100);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void AppChap1_1::OnKeyEvent(int key, int scancode, int action, int mods){
    Application::OnKeyEvent(key, scancode, action, mods);

    if(action == GLFW_PRESS){
        return;
    }
    std::cout << "change buffer..." << std::endl;
    if(m_UsedVBO == m_uVBO1){
        m_UsedVBO = m_uVBO2;
    }else{
        m_UsedVBO = m_uVBO1;
    }

    if(m_UsedVAO == m_uVAO1){
        m_UsedVAO = m_uVAO2;
    }else{
        m_UsedVAO = m_uVAO1;
    }
}
#include <iostream>
#include <memory>
#include "NXShader.h"
#include "NXLog.h"
#include "NXVector.h"
#include "NXMatrix.h"
#include "DemoHeader.h"

int main(int argc, const char* argv[]){
    NX::glb_GetLog().logToConsole("begin main");
    std::auto_ptr<NX::Application> app(new AppChap1_1());
    if(!app->Init(argv, argc, 800, 800)){
        std::cout << "failed init application..." << std::endl;
        return 1;
    }
    NX::glb_GetLog().logToConsole("begin application");
    app->Run();
    NX::glb_GetLog().logToConsole("end main");
    return 0;
}
#version 410 core

in  vec4 Color;
out vec4 vFinalColor;

void main(void){
    vFinalColor = Color;
}
#version 330 core

layout(location = 0) in vec2 vPosition;
layout(location = 1) in vec4 vColor;

out vec4 Color;
void main(){
    gl_Position = vec4(vPosition, -0.5f, 1.0f);
    Color       = vColor;
}

我整个开发环境如下所示:(从后面给的Git上下载代码可直接打开的哦)

程序的结果如下:

按下键盘上任何键后(ESC则会退出渲染程序),变换成如下:

在学习OpenGL的时候,我自己封装了一些基本的类,比如 Program、shader、Texture等,这些代码我放在GitHub上,其中包含我上面列出的代码,第一个程序比较简单,我也不愿意花更多时间去讲一些东西,大家只需要从Git下过来编译即可得到相同的结果,至于 OpenGL的后序学习和我编写的代码,我将会慢慢发出来,代码部分会发至Git,有兴趣的欢迎评阅。

时间: 2024-08-03 11:49:59

OpenGL学习笔记: (1)mac下OpenGL环境搭建的相关文章

mac下lua环境搭建笔记

下载lua源码包,进入到根目录下 1.执行make macosx 2.然后再sudo make install即可 mac下lua环境搭建笔记,布布扣,bubuko.com

RF+Appium框架自动化测试系列一之(Mac下Appium环境搭建)万事开头难

Mac下Appium环境搭建: 消失了3个月,有一段时间没来园子更新博客了,各位看官见谅哈哈,消失是因为TestYao刚换了工作环境没外网,好多笔记没能及时的记录分享,以后有时间慢慢补上吧,这段时间主要接触了移动端app的自动化测试,公司为了快速把移动端自动化这块搞起来,试用几款目前流行的工具,腾讯的xtest定制版.神州数码的自动化测试平台.开源rf+appium框架. 经过一段试用最终还是选择了rf+appium主要原因有: 1.开源,网上社区活跃 2.扩展性强,针对不同项目不同的需求,封装

Mac下Boost环境搭建

Boost,一个功能强大.跨平台.开源而且免费的C++程序库,可以在其官网了解更多:http://www.boost.org,C++标准经过不断的升级完善,现在已经功能越来越吸引人了,Boost开发过程中也吸引了很多C++11新特性,从而更兼容C++的标准库了,这样,有什么理由不用它呢?虽然很多东西我们可以自己写,但是,借助功能稳定的库,可以提高生产力,节约程序员的时间,何乐不为?当然,并非让我们只是调用函数,传参数,完成任务就行了,如果不去了解下背后原理,那只能称之为码农,而不是程序员了. 由

老邓的andorid学习笔记-Android 4.0 开发环境搭建

目前android版本早已经四4.xx了,5.0的版本也快出来了.  关于基本环境搭建有好多的文章都介绍过. 我在这里简单的整理了一下,就不用自己专门写此类的文章了. Android SDK 4.0.3 开发环境配置及运行     http://bk-lin.iteye.com/blog/1477808 android 4.0 for windows 7 开发环境搭建   http://cash.iteye.com/blog/1463253 Windows搭建Eclipse+JDK+SDK的An

cocos2d-x 3.x游戏开发学习笔记(1)--mac下配置cocos2d-x 3.x开发环境

打开用户文件夹下.bash_profile文件,配置环境 vim ~/.bash_profile //按键i,进行插入编辑(假设输错d进行删除一行) 环境配置过程例如以下: 1.首先配置下android sdk,我的是在opt文件夹下 #sdk export ANDROID_SDK_ROOT=/opt/android-sdk-macosx export PATH=$PATH:$ANDROID_SDK_ROOT export PATH=$PATH:$ANDROID_SDK_ROOT/platfor

mac下android环境搭建笔记(android studio)

http://www.tuicool.com/articles/FNRfyiF 本文记录了本人在mac上配置android开发环境的一些过程,为了方便直接选用了官方的IDE– Android Studio .本文包括了android studio的安装.创建第一个hello world项目以及真机调试. 首先下载android studio 下载地址: http://developer.android.com/sdk/index.html 建议提前修改下hosts,要不稍后下载sdk特别慢 su

java学习笔记1——window7下JDK环境变量配置图解

1. 首先下载Java安装工具包   http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 点击Accept License Agreement,然后根据自己的操作系统进行下载.下载完毕并且安装在C:\Program Files(x86)目录下. 2. win7系统右键计算机打开属性→高级系统设置→点击环境变量 3.配置环境变量 在“系统变量”中,设置3项属性,JAVA_HOME.P

【selenium 3】 Mac 下测试环境搭建 Firefox 47+ gecko driver Mac

错误代码如下:File "/usr/local/lib/python2.7/dist-packages/selenium-3.0.0b2-py2.7.egg/selenium/webdriver/firefox/webdriver.py", line 65, in __init__self.service.start()File "/usr/local/lib/python2.7/dist-packages/selenium-3.0.0b2-py2.7.egg/seleniu

mac下 jenkins 环境搭建

这几天搞了一些持续集成的工作,在所难免的接触到了jenkins ,下边写一下jenkins 在 mac os 环境下的搭建和配置. 1.tomcat 下载 前往apache 官网下载所需版本的tomcat , 官网地址:http://apache.mirrors.ionfish.org/tomcat/  注意:下载 bin/ 路径下的二进制版本,下载src版本,里边包含的东西不完全. 下载并解压8.5版本代码示例: wget http://apache.mirrors.ionfish.org/t