Chapter 3. Following the Pipeline(模仿工厂的流水线)

周一到周五,每天一篇,北京时间早上7点准时更新~,中英文对照,一边学编程一边弹吉他,做一个奇葩码农!

请不要怀疑翻译是否有问题,我们的翻译工程师是蓝翔毕业的呢!

What You’ll Learn in This Chapter(你将会学到啥)

What each of the stages in the OpenGL pipeline does(渲染管线的每个阶段都干了什么)
How to connect your shaders to the fixed-function pipeline stages(如何把你的shader与硬件中那些固定的功能进行拼接,凑成完整的渲染管线)
How to create a program that uses every stage of the graphics pipeline simultaneously(如何创建那些可以在每个渲染阶段都并行的GPU程序)
In this chapter, we will walk all the way along the OpenGL pipeline from start to finish(在本章中,我们将把整个OpenGL的渲染管线走一遍), providing insight into each of the stages(深入的了解每个步骤), which include fixed-function blocks and(这就包含了固定功能部分和可编程的shader部分) programmable shader blocks. You have already read a whirlwind introduction to the vertex and fragment shader stages(你已经快速的看过了vertex和fragment shader的处理阶段的介绍了). However, the application that you constructed simply drew a single triangle at a fixed position(然而,你构建的那个程序只是在固定的地方画了一个三角形而已). If we want to render anything interesting with OpenGL(如果我们想使用OpenGL渲染点有趣的东西的话), we’re going to have to learn a lot more about the pipeline and all of the things you can do with it(我们需要去学习关于渲染管线的知识以及你可以用它来干些啥). This chapter introduces every part of the pipeline(本章节介绍渲染管线的每一个部分), hooks them up to one another, and provides an example shader for each stage(把他们一个一个串起来,并且提供每个阶段的样本shader代码)

Passing Data to the Vertex Shader(给vertex shader传递数据)

The vertex shader is the first programmable stage in the OpenGL pipeline and has the distinction of being the only mandatory stage in the graphics pipeline(vertex shader阶段是第一个OpenGL渲染管线中的处理阶段,而且它必须存在,否则后面都没得玩了). However, before the vertex shader runs, a fixed-function stage known as vertex fetching, or sometimes vertex pulling, is run(在vertex shader执行之前,会执行一个叫做vertex fetching或者叫做vertex pulling的操作). This automatically provides inputs to the vertex shader.(这个操作自动的把输入数据输送给vertex shader)

Vertex Attributes(顶点属性,实际上有些名词你可以不用翻译,老外怎么叫你就怎么叫就得了,翻译出来还别扭,就像这个单词,纯属直译)

In GLSL, the mechanism for getting data in and out of shaders is to declare global variables with the in and out storage qualifiers(在GLSL中,往shader中传入或者从shader中获取数据的方法就是定义全局变量,并用in或者out标识符去修饰). You were briefly introduced to the out qualifier in Chapter 2(你已经在第二章中见识到了out修饰符了), “Our First OpenGL Program,” when Listing 2.4 used it to output a color from the fragment shader(在Listing2.4中,它被用来指出从fragment shader中输出一个颜色数据). At the start of the OpenGL pipeline, we use the in keyword to bring inputs into the vertex shader(在OpenGL渲染管线的开始阶段、我们使用in这个关键字来给vertex shader弄点输入数据). Between stages, in and out can be used to form conduits from shader to shader and pass data between them(在渲染管线的各个阶段之间,in和out可以形成一个用于数据传输的管道). We’ll get to that shortly(我们将很快的接触到那一款). For now, consider the input to the vertex shader and what happens if you declare a variable with an in storage qualifier(现在,我们先来看看vertex shader的输入数据以及当你用in去修饰一个变量时,到底会发生什么). This marks the variable as an input to the vertex shader(这个in就标记了这个变量时vertex shader的输入数据), which means that it is essentially an input to the OpenGL graphics pipeline(也就是说,它是一个基本的OpenGL渲染管线的输入数据). It is automatically filled in by the fixed-function vertex fetch stage(这个变量会在vertex fetch阶段自动被赋值). The variable becomes known as a vertex attribute(这个变量通常被称为顶点属性)

Vertex attributes are how vertex data is introduced into the OpenGL pipeline(顶点属性们定义了数据如何被传送给OpenGL渲染管线). To declare a vertex attribute, you declare a variable in the vertex shader using the in storage qualifier(你只需要使用in修饰符去修饰一个vertex shader中的变量,就申明了一个顶点属性). An example of this is shown in Listing 3.1, where we declare thevariable offset as an input attribute(在Listing3.1中,我们申明了变量offset作为一个输入的属性)

#version 450 core
// 'offset' is an input vertex attribute
layout (location = 0) in vec4 offset;
void main(void)
{
const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4(0.25, 0.25, 0.5, 1.0));
// Add 'offset' to our hard-coded vertex position
gl_Position = vertices[gl_VertexID] + offset;
}
Listing 3.1: Declaration of a vertex attribute

In Listing 3.1, we have added the variable offset as an input to the vertex shader(在Listing3.1中我们给vertex shader加了一个输入变量叫offset). As it is an input to the first shader in the pipeline, it will be filled automatically by the vertex fetch stage(它作为渲染管线的第一个阶段,这些输入的数据会被vertex fetch的过程初始化). We can tell this stage what to fill the variable with by using one of the many variants of the vertex attribute functions, glVertexAttrib()(我们可以使用glVertexAttrib系列的API告诉这个阶段,如何去给这些变量赋值). The prototype for glVertexAttrib4fv(), which we use in this example, is(在我们的案例中,我们使用的API的定义是:)

void glVertexAttrib4fv(GLuint index, const GLfloat * v);

Here, the parameter index is used to reference the attribute (这里,index被用于指定属性的索引)and v is a pointer to the new data to put into the attribute(v是一个指针,指向输入的数据). You may have noticed the layout (location = 0) code in the declaration of the offset attribute(你可能已经注意到了location=0这句代码了). This is a layout qualifier, which we have used to set the location of the vertex attribute to zero(这是一个layout的修饰符,这里我们执行了顶点属性的位置为0). This location is the value we’ll pass in index to refer to the attribute(这里的位置就是指我们将会传递的那个index参数)

Each time we call one of the glVertexAttrib() functions (of which there are many), it will update the value of the vertex attribute that is passed to the vertex shader(每一次我们调用glVertexAttrib系列函数,它就会刷新我们传递给vertex shader的那些变量). We can use this approach to animate our one triangle(我们可以通过这种方式,让我们的三角形动起来). Listing 3.2 shows an updated version of our rendering function that updates the value of offset in each frame(Listing3.2展示了我们新版本的代码,新版本的代码会每一帧都去更新offset变量)

// Our rendering function
virtual void render(double currentTime)
{
const GLfloat color[] = {
(float)sin(currentTime) 0.5f + 0.5f,
(float)cos(currentTime)
0.5f + 0.5f,
0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, color);
// Use the program object we created earlier for rendering
glUseProgram(rendering_program);
GLfloat attrib[] = { (float)sin(currentTime) 0.5f,
(float)cos(currentTime)
0.6f,
0.0f, 0.0f };
// Update the value of input attribute 0
glVertexAttrib4fv(0, attrib);
// Draw one triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Listing 3.2: Updating a vertex attribute

When we run the program with the rendering function of Listing 3.2, the triangle will move in a smooth oval shape around the window(当我们执行本程序的时候,我们的三角形就会沿着一个椭圆做运动了)

本日的翻译就到这里,明天见,拜拜~~

第一时间获取最新桥段,请关注东汉书院以及图形之心公众号

东汉书院,等你来玩哦

猜你喜欢

转载自blog.51cto.com/battlefire/2420526