使用 OpenGL ES 和代码处理 FSGL 库的结果:
接下来我将描述它是如何编程的,以及如何解决各种有趣问题。
首先,我们将初始化 OpenGL ES 上下文,正如我在上一篇文章中所写的那样。此外,我们将仅考虑渲染和代码的简要描述。
黑客帝国正在注视着你
视频中 Miku 的这个形象由三角形组成。要在 OpenGL 中绘制三角形,需要指定坐标为 x、y、z 的三个点。在 OpenGL 上下文的 2D 坐标中。
由于我们需要绘制包含 3D 坐标的图形,因此需要使用投影矩阵。我们还需要旋转、放大或任何我们想要对模型执行的操作——为此,使用了模型矩阵。 OpenGL 中没有相机的概念;事实上,对象围绕静态相机旋转。为此,使用了视图矩阵。
简化 OpenGL ES 的实现它不包含矩阵数据。您可以使用添加缺失功能的库,例如 GLM。
着色器
为了允许开发人员以任何方式绘制任何内容,OpenGL ES 必须实现顶点和片段着色器。顶点着色器必须接收渲染坐标作为输入,使用矩阵执行转换,并将坐标传递给 gl_Position。片段或像素着色器 –已经绘制颜色/纹理、应用叠加等。
我用 GLSL 编写了着色器。在我当前的实现中,着色器作为 C 字符串直接内置到主应用程序代码中。
缓冲区
顶点缓冲区包含顶点(vertices)的坐标;该缓冲区还包含纹理的坐标以及着色器所需的其他数据。生成顶点缓冲区后,需要将指针绑定到顶点着色器的数据。这是通过 glVertexAttribPointer 命令完成的,您需要在其中指定元素数量、指向数据开头的指针以及用于遍历缓冲区的步长。在我的实现中,完成了像素着色器的顶点坐标和纹理坐标的绑定。不过,值得一提的是,数据(纹理坐标)到片段着色器的传输是通过顶点着色器进行的。为了实现这一点,使用variing声明坐标。
这样OpenGL就知道以什么顺序绘制三角形的点–您将需要一个索引缓冲区(索引)。索引缓冲区包含数组中的顶点编号;使用三个这样的索引,可以获得一个三角形。
纹理
首先您需要加载/生成 OpenGL 纹理。为此,我使用了 SDL_LoadBMP,纹理是从 bmp 文件加载的。不过,值得注意的是,只有 24 位 BMP 适合,并且其中的颜色不是按通常的 RGB 顺序存储,而是以 BGR 存储。即加载后需要将红色通道替换为蓝色通道
纹理坐标以以下格式指定: UV,即只需要传递两个坐标即可。纹理输出在片段着色器中完成。为此,您需要将纹理绑定到片段着色器中。
没什么多余的
因为,根据我们的指示,OpenGL 通过 2D 绘制 3D ——然后实现深度,并选择不可见的三角形–您需要使用剔除和深度缓冲区(Z-Buffer)。在我的实现中,我设法避免使用两个命令手动生成深度缓冲区:glEnable(GL_DEPTH_TEST);和选择 glEnable(GL_CULL_FACE);
另外一定要检查投影矩阵的近平面是否大于零,因为使用近平面的空值检查深度将不起作用。
渲染
要使用有意识的东西填充顶点缓冲区、索引缓冲区,例如 Miku 模型,您需要加载此模型。为此,我使用了 assimp 库。 Miku被放置在Wavefront OBJ格式文件中,使用assimp加载,并实现了assimp到顶点和索引缓冲区的数据转换。
渲染分几个阶段进行:
- 使用模型矩阵旋转来旋转 Miku
- 清除屏幕和深度缓冲区
- 使用 glDrawElements 命令绘制三角形。
下一阶段–使用 Emscripten 在 WebGL 中实现渲染。
源代码:
https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/8-sdl-gles-obj-textured-assimp-miku
型号:
https://sketchfab.com/models/7310aaeb8370428e966bdcff414273e7