开始在 OS X 开发 OpenGL 应用 【已翻译100%】

  1. 云栖社区>
  2. 博客>
  3. 正文

开始在 OS X 开发 OpenGL 应用 【已翻译100%】

青衫无名 2017-06-02 14:58:00 浏览1144
展开阅读全文

有一段时间了,我一直想着进入某些视频游戏开发领域. 对于OpenGL我也很感兴趣,并且因此我也想到了为什么不深入去研究研究OpenGL,再去做一款视频游戏呢?我已经有了许多我想要去探索的游戏的点子,但第一都是得要婴儿学步的不是吗?

我的原始计划是要去构建:

1.一个类似AI的 Pong 游戏克隆

2.一个 几何战争 游戏的克隆

3.开始着手实现属于我自己的疯狂想法

然而,我最近在浏览HackerNew时偶然发现了 (游戏机制探索器)Game Mechanic Explorer. 它是一个有John Watson 创建的真正很酷的站点,那里面他使用 Phaser 游戏框架创建了一大堆不同的游戏机制. 他给它们中的每一个都分配了一个单独的页面,带上了可以试玩的示例,还有代码和介绍. 这是一个令人着迷的网站,我强烈呼吁大家花几分钟时间来看看它.

看到该网站后,我决定更换我的原来的计划#1但是使用OpelGL重新创建我的作品.我认为这比创造Pong clone更有雄心,但是我仍能实现.

我已经发现一些资源来帮助我开始OpenGL的开发.我将在这里一一列举以供参考,但是详细解说不在此文章的范围之内.

  • The OpenGL SuperBible OpenGL超级(截至记者发稿时,第6版的OpenGL V4.3是最新的)
  • OpenGL Programming Guide: The Official Guide to Learning OpenGLOpenGL编程指南:官方指南学习OpenGL (在撰写本文时,对OpenGL V4.3第8版是最新的)
  • Open.gl(现代在线指南OpenGL开发,看起来像它的针对OpenGL 3.2的)

然而.关于The OpenGL SuperBible我要说一件事(我买的是这本书)和我同一个书圈的人都有相同的.抱怨.本书中作者抽象了太多代码称为书中的库.这对于新手来说理解和追查OpenGL有些困难.如果你跟着书中的代码,将会容易理解.如果你不理解库在做什么,你将会迷失在库中和书中.

在文章的其余部分,我将探讨如何才能设置 Mac OS X开始使用OpenGL进行开发 ,同时展示一个简单的三角形.

在开始之前,你能在gist发现这篇博客的全部代码.如果你想看到我们目前的整个项目,你可以在Github上找到它.

所以在开始在OS X使用OpenGL开发,如果你还没有,我建议去获得Homebrew.我们需要做的第一件事就是获得两个个libraries.这都不是必须的,有一些是可以替代的,当然我们必须有其中的一种.

现在让我们一起熟悉我们将使用的Makefile:

如果你熟悉Makefiles.这应该是非常标准的.有一点需要注意的是第19行:the linker flags.OS X 自带的 OpenGL.所以我们应该特别的去指定它.当然我们也应该链接上刚刚安装的两个libraries.当我们添加更多的文件时,我们应该加到OBJS列表中.

让我们做一个简单的程序在屏幕上显示一个三角形:

image

我会分别说明这些代码的用途,全部的源代码在here.

在 GLFW中有许多的回调.我们只需要两个用于这项工作.第一个是打印输出任何错误信息,二是声明当按下ESC键时,项目停止.以下函数定义了怎么做,当我们准备我们的项目时,我们注册它.

// The error callback will just print any errors that GLFW hits.
void error_callback(int error, const char* description) {
  fputs(description, stderr);
}

// The key callback generally handles any input, but we'll just use the ESC key in this example.
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
  {
    glfwSetWindowShouldClose(window, GL_TRUE);
  }
}

为了建立一个OpenGL程序渲染,有许多事情需要做。下面的代码添加了注释,对主要的部分进行了解释。

// Initialize GLFW, and if it fails to initialize for any reason, print it out to STDERR.
if (!glfwInit()) {
  fprintf(stderr, "Failed initialize GLFW.");
  exit(EXIT_FAILURE);
}

// Set the error callback, as mentioned above.
glfwSetErrorCallback(error_callback);

// Set up OpenGL options.
// Use OpenGL verion 4.1,
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
// GLFW_OPENGL_FORWARD_COMPAT specifies whether the OpenGL context should be forward-compatible, i.e. one where all functionality deprecated in the requested version of OpenGL is removed.
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Indicate we only want the newest core profile, rather than using backwards compatible and deprecated features.
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Make the window resize-able.
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

// Create a window to put our stuff in.
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);

// If the window fails to be created, print out the error, clean up GLFW and exit the program.
if(!window) {
  fprintf(stderr, "Failed to create GLFW window.");
  glfwTerminate();
  exit(EXIT_FAILURE);
}

// Use the window as the current context (everything that's drawn will be place in this window).
glfwMakeContextCurrent(window);

// Set the keyboard callback so that when we press ESC, it knows what to do.
glfwSetKeyCallback(window, key_callback);

printf("OpenGL version supported by this platform (%s): \n", glGetString(GL_VERSION));

// Makes sure all extensions will be exposed in GLEW and initialize GLEW.
glewExperimental = GL_TRUE;
glewInit();

着色器是一个GL的应用程序的重要组成部分。它们是运行在显卡上并最终决定什么被渲染到屏幕上的程序。请注意,在我们的代码中,我们使用版本410 core。这必须配合我们正在使用的OpenGL版本,它的核心配置文件是4.1版,因此选用410 core。

// Vertex shader source code. This draws the vertices in our window. We have 3 vertices since we're drawing an triangle.
// Each vertex is represented by a vector of size 4 (x, y, z, w) coordinates.
static const char * vs_source[] =
{
    "#version 410 core                                                 \n"
    "                                                                  \n"
    "void main(void)                                                   \n"
    "{                                                                 \n"
    "    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n"
    "                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n"
    "                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n"
    "                                                                  \n"
    "    gl_Position = vertices[gl_VertexID];                          \n"
    "}                                                                 \n"
};

// Fragment shader source code. This determines the colors in the fragment generated in the shader pipeline. In this case, it colors the inside of our triangle specified by our vertex shader.
static const char * fs_source[] =
{
    "#version 410 core                                                 \n"
    "                                                                  \n"
    "out vec4 color;                                                   \n"
    "                                                                  \n"
    "void main(void)                                                   \n"
    "{                                                                 \n"
    "    color = vec4(0.0, 0.8, 1.0, 1.0);                             \n"
    "}                                                                 \n"
};

在渲染我们的着色器之后,我们需要实时的编译他们并绑定他们到我们的GL程序以便于显卡使用他们。

// This next section we'll generate the OpenGL program and attach the shaders to it so that we can render our triangle.
program = glCreateProgram();

// We create a shader with our fragment shader source code and compile it.
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);

// We create a shader with our vertex shader source code and compile it.
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);

// We'll attach our two compiled shaders to the OpenGL program.
glAttachShader(program, vs);
glAttachShader(program, fs);

glLinkProgram(program);

// Generate vertex arrays for our program. More explanation on this will come in the future.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// We'll specify that we want to use this program that we've attached the shaders to.
glUseProgram(program);

一旦我们告诉显卡利用绑定的着色器来使用我们的程序,那么我们开始绘制东西吧。接下来的代码块是我们的渲染循环。我们不断地画三角形到银幕上,直到该程序存在。

//As long as our window remains  open(ESC IS not  pressed),we'll continue to render things.
while(!glfwWindowshouldclose(window))
{
  //set up our  green background color
static  const  GLfloat green[]={0.25f,0.0f,1.0f};
//clear the  entire  buffer with  our  green  color(sets  the  background to  be  green).
  glDrawBufferfv{GL_TRIANGLES,0,3);
//SWAP THE  BUFFERS  SO  THAT  WHAT  WE  DREW WILL APPEAR on the sreen.
glfwSwapBuffers(window);
glfwpollEvent();
}

这是大量的好的代码,如果你没有阅读它或者充分地理解它。我已经评论过它并试图解释,但是某些概念我仍要企图掌握它。有两种主要的外卖,我想在这儿开车回家。

1.有大量设置的代码。

2.也有着色器的源代码。保持他们作为静态的“const char,是粪便。

对于我的下一篇文章,我将详细从我们的c++代码里面来如何移动着色器源代码,以至于它不在那儿纠结,更容易编辑。着色器是非常重要的图形并且完全不实用,如果他们被卡在我们的c++代码里面。对于以后的帖子,我将表明我已经做了在其他类和模块里面,重构了大量的已经设置的代码。

同样,如果你喜欢看见我最近的源代码,那么它就在Github上面

后会有期!

网友评论

登录后评论
0/500
评论
青衫无名
+ 关注