有一段时间了,我一直想着进入某些视频游戏开发领域. 对于OpenGL我也很感兴趣,并且因此我也想到了为什么不深入去研究研究OpenGL,再去做一款视频游戏呢?我已经有了许多我想要去探索的游戏的点子,但第一都是得要婴儿学步的不是吗?
我的原始计划是要去构建: 一个类似AI的 Pong 游戏克隆 一个 几何战争 游戏的克隆 开始着手实现属于我自己的疯狂想法
然而,我最近在浏览HackerNew时偶然发现了 (游戏机制探索器)Game Mechanic Explorer. 它是一个有John Watson 创建的真正很酷的站点,那里面他使用 Phaser 游戏框架创建了一大堆不同的游戏机制. 他给它们中的每一个都分配了一个单独的页面,带上了可以试玩的示例,还有代码和介绍. 这是一个令人着迷的网站,我强烈呼吁大家花几分钟时间来看看它.
看到该网站后,我决定更换我的原来的计划#1但是使用OpelGL重新创建我的作品.我认为这比创造Pong clone更有雄心,但是我仍能实现. 我已经发现一些资源来帮助我开始OpenGL的开发.我将在这里一一列举以供参考,但是详细解说不在此文章的范围之内.
然而.关于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列表中.
让我们做一个简单的程序在屏幕上显示一个三角形:

我会分别说明这些代码的用途,全部的源代码在here.
在 GLFW中有许多的回调.我们只需要两个用于这项工作.第一个是打印输出任何错误信息,二是声明当按下ESC键时,项目停止.以下函数定义了怎么做,当我们准备我们的项目时,我们注册它.
02 | void error_callback( int error, const char * description) { |
03 | fputs (description, stderr); |
07 | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { |
08 | if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) |
10 | glfwSetWindowShouldClose(window, GL_TRUE); |
为了建立一个OpenGL程序渲染,有许多事情需要做。下面的代码添加了注释,对主要的部分进行了解释。 03 | fprintf (stderr, "Failed initialize GLFW." ); |
08 | glfwSetErrorCallback(error_callback); |
12 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); |
13 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); |
15 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
17 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
19 | glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); |
22 | GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL" , NULL, NULL); |
26 | fprintf (stderr, "Failed to create GLFW window." ); |
32 | glfwMakeContextCurrent(window); |
35 | glfwSetKeyCallback(window, key_callback); |
37 | printf ( "OpenGL version supported by this platform (%s): \n" , glGetString(GL_VERSION)); |
40 | glewExperimental = GL_TRUE; |
着色器是一个GL的应用程序的重要组成部分。它们是运行在显卡上并最终决定什么被渲染到屏幕上的程序。请注意,在我们的代码中,我们使用版本410 core。这必须配合我们正在使用的OpenGL版本,它的核心配置文件是4.1版,因此选用410 core。 03 | static const char * vs_source[] = |
05 | "#version 410 core \n" |
09 | " const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n" |
10 | " vec4(-0.25, -0.25, 0.5, 1.0), \n" |
11 | " vec4( 0.25, 0.25, 0.5, 1.0)); \n" |
13 | " gl_Position = vertices[gl_VertexID]; \n" |
18 | static const char * fs_source[] = |
20 | "#version 410 core \n" |
26 | " color = vec4(0.0, 0.8, 1.0, 1.0); \n" |
在渲染我们的着色器之后,我们需要实时的编译他们并绑定他们到我们的GL程序以便于显卡使用他们。 02 | program = glCreateProgram(); |
05 | GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); |
06 | glShaderSource(fs, 1, fs_source, NULL); |
10 | GLuint vs = glCreateShader(GL_VERTEX_SHADER); |
11 | glShaderSource(vs, 1, vs_source, NULL); |
15 | glAttachShader(program, vs); |
16 | glAttachShader(program, fs); |
18 | glLinkProgram(program); |
21 | glGenVertexArrays(1, &vao); |
22 | glBindVertexArray(vao); |
一旦我们告诉显卡利用绑定的着色器来使用我们的程序,那么我们开始绘制东西吧。接下来的代码块是我们的渲染循环。我们不断地画三角形到银幕上,直到该程序存在。 02 | while (!glfwWindowshouldclose(window)) |
05 | static const GLfloat green[]={0.25f,0.0f,1.0f}; |
07 | glDrawBufferfv{GL_TRIANGLES,0,3); |
09 | glfwSwapBuffers(window); |
这是大量的好的代码,如果你没有阅读它或者充分地理解它。我已经评论过它并试图解释,但是某些概念我仍要企图掌握它。有两种主要的外卖,我想在这儿开车回家。
1.有大量设置的代码。 2.也有着色器的源代码。保持他们作为静态的“const char,是粪便。
对于我的下一篇文章,我将详细从我们的c++代码里面来如何移动着色器源代码,以至于它不在那儿纠结,更容易编辑。 着色器是非常重要的图形并且完全不实用,如果他们被卡在我们的c++代码里面。对于以后的帖子,我将表明我已经做了在其他类和模块里面,重构了大量的已经设置的代码。
同样,如果你喜欢看见我最近的源代码,那么它就在Github上面
后会有期! |