您的位置:首页 > 运维架构

OpenGL学习 Following the Pipeline

2014-08-19 23:23 197 查看
Passing Data to the Vertex Shader

Vertex Attributes

At the start of the OpenGL pipeline,we use the in keyword to bring inputs into the vertex shader.

Between stages,in and out can be used to form conduits from shader to shader and pass data
between them.

For now, consider the input to the vertex shader
and what happens if you declare a variable with an in storage qualifier. This
marks the variable as an input to the vertex shader, which means that it is
automatically filled in by the fixed-function vertex fetch stage. The variable
becomes known as a vertex attribute.

Vertex attributes are how vertex data is
introduced into the OpenGL pipeline. To declare a vertex attribute, declare a
variable in the vertex shader using the in storage qualifier.

#version 430 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;
}


We can tell this stage what to fill the variable
with by using one of the many variants of the vertex attribute functions,
glVertexAttrib*(). The prototype for glVertexAttrib4fv(),
which we use in
this example, is

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

index is used to reference the
attribute and v is a pointer to the new data to put into the
attribute.

The layout (location = 0) code in the declaration
of the offset attribute.This is a layout qualifier, and we have used it to set
the location of the vertex attribute to zero. This location is the value we’ll
pass in index to refer to the attribute.

Passing Data from Stage to
Stage


built-in variables such as gl_VertexID and
gl_Position.

We use in and out to pass data from a stage to
another.

Interface Blocks

Declare interface variables to communicate a
number of different pieces of data between stages, and these may include arrays,
structures, and other complex arrangements of variables.To achieve this, we can
group together a number of variables into an interface block. The declaration of
an interface block looks a lot like a structure declaration, except that it is
declared using the in or out keyword depending on whether it is an input to or
output from the shader.

Interface blocks are matched between stages using
the block name (VS_OUT in this case), but are referenced in shaders using the
instance name.

Matching interface blocks by block name but
allowing block instances to have different names in each shader stage serves two
important purposes:

First, it allows the name by which you refer to
the block to be different in each stage, avoiding confusing things such as
having to use vs_out in a fragment shader;

Second, it allows interfaces to go from being
single items to arrays when crossing between certain shader stages, such as the
vertex and tessellation or geometry shader stages as we will see in a short
while.

Note that interface blocks are only for moving
data from shader stage to shader stage — you can’t use them to group together
inputs to the vertex shader or outputs from the fragment shader.

Tessellation

Tessellation is the process of breaking a
high-order primitive (which is known as a patch in OpenGL) into many smaller,
simpler primitives such as triangles for rendering.

OpenGL includes a fixed-function, configurable
tessellation engine that is able to break up quadrilaterals, triangles, and
lines into a potentially large number of smaller points, lines, or triangles
that can be directly consumed by the normal rasterization hardware further down
the pipeline.

Logically, the tessellation phase sits directly
after the vertex shading stage in the OpenGL pipeline and is made up of three
parts: the tessellation control shader, the fixed-function tessellation engine,
and the tessellation evaluation shader.

Tessellation Control
Shaders


Each patch is formed from a number of control
points. The number of control points per patch is configurable and set by
calling glPatchParameteri() with pname set to GL_PATCH_VERTICES and value set to
the number of control points that will be used to construct each patch. The
prototype of glPatchParameteri() is

void glPatchParameteri(GLenum pname, GLint
value);

By default, the number of control points per patch
is three.

If this is what you want (as in our example
application), you don’t need to call it at all.

The vertex shader runs once per control point
whilst the tessellation control shader runs in batches on groups of control
points where the size of each batch is the same as the number of vertices per
patch.

Vertices are used as control points, and the
result of the vertex shader is passed in batches to the tessellation control
shader as its input. The number of control points per patch can be changed such
that the number of control points that is output by the tessellation control
shader can be different from the number of control points that it consumes. The
number of control points produced by the control shader is set using an output
layout qualifier in the control shader’s source code. Such a layout qualifier
looks like: layout (vertices = N) out; Here, N is the number of control points
per patch.

The control shader is responsible for calculating
the values of the output control points and for setting the tessellation factors
for the resulting patch that will be sent to the fixed-function tessellation
engine. The output tessellation factors are written to the gl_TessLevelInner and
gl_TessLevelOuter built-in output variables, whereas any other data that is
passed down the pipeline is written to user-defined output variables (those
declared using the out keyword, or the special built-in gl_out array) as
normal.

Listing 3.7 shows a simple tessellation control
shader. It sets the number of output control points to three (the same as the
default number of input control points) using the layout (vertices = 3) out;
layout qualifier, copies its input to its output (using the built-in variables
gl_in and gl_out), and sets the inner and outer tessellation level to 5. The
built-in input variable gl_InvocationID is used to index into the gl_in and
gl_out arrays. This variable contains the zero-based index of the control point
within the patch being processed by the current invocation of the tessellation
control shader:

#version 430 core

ayout (vertices = 3) out;

void main(void)

{

if (gl_InvocationID == 0)

{
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}

gl_out[gl_InvocationID].gl_Position =         gl_in[gl_InvocationID].gl_Position;

}


The tessellation engine


The tessellation engine is a
fixed-function part of the OpenGL pipeline that takes high-order surfaces
represented as patches and breaks them down into simpler primitives such as
points, lines, or triangles. Before the tessellation engine receives a patch,
the tessellation control shader processes the incoming control points and sets
tessellation factors that are used to break down the patch. After the
tessellation engine produces the output primitives, the vertices representing
them are picked up by the tessellation evaluation shader. The tessellation
engine is responsible for producing the parameters that are fed to the
invocations of the tessellation evaluation shader, which it then uses to
transform the resulting primitives and get them ready for
rasterization.

Tessellation Evaluation
Shaders


【To be continue...】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: