第一章
OpenGL简介
本章目标
描述什么是OpenGL ,在用计算机生成图像时,他能做什么,不能做什么。
了解一个OpenGL程序的基本结构
了解组成OpenGL渲染管线的着色器
这章主要是简单的介绍了一下OpenGL。我们分成以下几个部分分别去讨论:
- “啥是OpenGL?”:解释了OpenGL到底是个啥玩意儿,他能干啥不能干啥,以及他是咋工作的。
- “初窥OpenGL程序”:展示了一个OpenGL程序是长啥样的。
- “OpenGL语法”:它的语法约定
- “OpenGL的渲染管线”:讨论OpenGL用于生成图像的渲染管线。
- “第一个OpenGL程序的相关细节”:剖析这个程序。
啥是OpenGL?
OpenGL其实就是个图形硬件API。
在OpenGL 4.3中包括了超过500条函数,这些函数用来生成物体或图像,创建交互式3D程序。(相比之前貌似精简了一些)
OpenGL 被设计成一种streamlined,独立于不同硬件或操作系统的接口。为实现这一点,OpenGL并不包含某些用于窗口任务或用户输入的函数,因为这些东西在不同平台上往往是大相径庭的。
举个栗子:假如在OpenGL中设计了响应鼠标事件的函数,我们把编写的OpenGL游戏从windows平台移植到Android平台时,玩家就只能呵呵了。不过并不是说我们用OpenGL就不能实现这样的操作,实现这些操作的函数被定义在某些其他的工具库中,这些后面会说到。
OpenGL本身也并不提供创造3D物体或读取图像文件(例如JPEG)的功能,程序员只能利用为数不多的例如点,直线和三角形这样的基本图形去创造复杂的3D物体。
。。。
初窥OpenGL程序
OpenGL能做的事情实在是太多了,一个OpenGL程序往往也会变得庞大和复杂。不过所有的OpenGL程序也无非是做了以下两件事:
- 初始化那些我们要去渲染的物体的状态
- 指定要渲染哪些物体
在我们看一些代码之前,我们有必要交待一些图形学术语。渲染——通过模型创造图像的过程。渲染模式也并非独一无二的,常见的有“辐射着色”,“光线追踪”和“栅格化”。而OpenGL是一个基于栅格化(也可以叫做光栅化)的渲染系统。“辐射着色”,“光线追踪”已经超出了本书的范畴,不过这些渲染模式仍然可以用OpenGL去显示图像或在创建图像时计算出这些图像的信息。
我们之后会提到的术语“模型”和“物体”都是由基本的集合图形组成的(点,直线,三角形),这些基本图形则都是由顶点构成的。
还有一个必须提到的基本概念是着色器——由图形硬件去执行的特定函数。我们可以把着色器想象成专为你的GPU编译的小程序。OpenGL内置的编译工具可以把所有的着色器代码编译成GPU可以执行的代码。在OpenGL中有4种着色器,最常见的就是顶点着色器——处理顶点数据,同样重要的还有片段着色器——处理来自光栅化器的数据。不论顶点着色器还是片段着色器都是每个OpenGL程序必不可少的。
最终生成的图像是由画在显示器上的像素点组成的。像素点是能在显示器上显示的最小元素。所有的像素点都存储在缓冲帧中,这些缓冲帧则存储在我们所说的显存中并发送给显示器显示。
1 /////////////////////////////////////////////////////////////////////// 2 // 3 // triangles.cpp 4 // 5 /////////////////////////////////////////////////////////////////////// 6 #include <iostream> 7 using namespace std; 8 #include "vgl.h" 9 #include "LoadShaders.h" 10 enum VAO_IDs { Triangles, NumVAOs }; 11 enum Buffer_IDs { ArrayBuffer, NumBuffers }; 12 enum Attrib_IDs { vPosition = 0 }; 13 GLuint VAOs[NumVAOs]; 14 GLuint Buffers[NumBuffers]; 15 const GLuint NumVertices = 6; 16 //--------------------------------------------------------------------- 17 // 18 // init 19 // 20 void init(void) 21 { 22 glGenVertexArrays(NumVAOs, VAOs); 23 glBindVertexArray(VAOs[Triangles]); 24 GLfloat vertices[NumVertices][2] = { 25 { -0.90, -0.90 }, // Triangle 1 26 { 0.85, -0.90 }, 27 { -0.90, 0.85 }, 28 { 0.90, -0.85 }, // Triangle 2 29 { 0.90, 0.90 }, 30 { -0.85, 0.90 }}; 31 32 glGenBuffers(NumBuffers, Buffers); 33 glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]); 34 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), 35 vertices, GL_STATIC_DRAW); 36 37 ShaderInfo shaders[] = { 38 { GL_VERTEX_SHADER, "triangles.vert" }, 39 { GL_FRAGMENT_SHADER, "triangles.frag" }, 40 { GL_NONE, NULL }}; 41 42 GLuint program = LoadShaders(shaders); 43 glUseProgram(program); 44 glVertexAttribPointer(vPosition, 2, GL_FLOAT, 45 GL_FALSE, 0, BUFFER_OFFSET(0)); 46 glEnableVertexAttribArray(vPosition); 47 } 48 //--------------------------------------------------------------------- 49 // 50 // display 51 // 52 void display(void) 53 { 54 glClear(GL_COLOR_BUFFER_BIT); 55 glBindVertexArray(VAOs[Triangles]); 56 glDrawArrays(GL_TRIANGLES, 0, NumVertices); 57 glFlush(); 58 }
代码看起来有点长,不过在以后的开发中你会发现这基本上是每个OpenGL程序所必需的了。我们会用一些非OpenGL官方提供的工具库去创建窗口,接受鼠标键盘输入。当然我们也可以自己写一些函数或类库去实现类似的功能。OpenGL是个C语言编写的类库,不过我们的例子基本上都是用一些比较简单的C++编写的。事实上我们使用C++也不过是为了实现vectors和matrices这样的数据结构。
。。。
OpenGL语法
。。。
OpenGL渲染管线
。。。
第一个OpenGL程序的相关细节
- 本博客文章除注明转载外,均为本人原创或者翻译。
- 本博客文章欢迎各种形式的转载,但请具有完全民事行为能力的转载者注明文章出处,尊重我的劳动,也尊重你的智商。