[译]Vulkan教程(12)图形管道基础之入门
Introduction 入门
Over the course of the next few chapters we'll be setting up a graphics pipeline that is configured to draw our first triangle. The graphics pipeline is the sequence of operations that take the vertices and textures of your meshes all the way to the pixels in the render targets. A simplified overview is displayed below:
接下来的几个章节里,我们将设置图形管道,以绘制第一个三角形。图形管道是一系列的操作,它接收网格的顶点和纹理,(处理之)一直到渲染目标的像素上。一个简化的概览图如下所示:
The input assembler collects the raw vertex data from the buffers you specify and may also use an index buffer to repeat certain elements without having to duplicate the vertex data itself.
input assembler 收集原始顶点数据from你指定的buffer,还可能使用一个index buffer to重复某些元素without必须重复顶点数据本身。
The vertex shader is run for every vertex and generally applies transformations to turn vertex positions from model space to screen space. It also passes per-vertex data down the pipeline.
vertex shader 运行for每个顶点,一般施展变换to变换顶点位置from模型空间to屏幕空间。它也传递逐顶点的数据down到pipeline(的后续阶段)。
The tessellation shaders allow you to subdivide geometry based on certain rules to increase the mesh quality. This is often used to make surfaces like brick walls and staircases look less flat when they are nearby.
tessellation shaders 允许你细分几何体 基于某种规则to增加网格质量。这常用于让表面例如砖墙和楼梯看起来不那么平坦when它们靠近(摄像机)。
The geometry shader is run on every primitive (triangle, line, point) and can discard it or output more primitives than came in. This is similar to the tessellation shader, but much more flexible. However, it is not used much in today's applications because the performance is not that good on most graphics cards except for Intel's integrated GPUs.
geometry shader 运行on每个图元(三角形、线、点)and能忽略图元或产生更多图元。这与tessellation shader相似,但是更加可扩展。但是,它在现在的app里应用并不多,因为性能不怎么好on大多数图形卡上,除了Intel的集成GPU。
The rasterization stage discretizes the primitives into fragments. These are the pixel elements that they fill on the framebuffer. Any fragments that fall outside the screen are discarded and the attributes outputted by the vertex shader are interpolated across the fragments, as shown in the figure. Usually the fragments that are behind other primitive fragments are also discarded here because of depth testing.
rasterization 阶段将图元分解为fragment。这是要填入帧缓存的像素候选人。任何落到屏幕外的Fragment都会被忽略,顶点shader输出的属性被插值到Fragment上,如图所示。通常,在其他Fragment后面的Fragment也会被忽略-由于深度测试。
The fragment shader is invoked for every fragment that survives and determines which framebuffer(s) the fragments are written to and with which color and depth values. It can do this using the interpolated data from the vertex shader, which can include things like texture coordinates and normals for lighting.
fragment shader 被调用for每个幸存的Fragment-and决定了Fragment写入哪个帧缓存,写入什么颜色,什么深度值。它可以用插值的数据from顶点shader-which可能包含例如纹理坐标和法线for光照之类的东西。
The color blending stage applies operations to mix different fragments that map to the same pixel in the framebuffer. Fragments can simply overwrite each other, add up or be mixed based upon transparency.
color blending 阶段试试操作to混合不同的Fragment-that映射到帧缓存的同一像素上。Fragment可以简单地覆盖另一个Fragment,加起来or基于透明度来混合。
Stages with a green color are known as fixed-function stages. These stages allow you to tweak their operations using parameters, but the way they work is predefined.
绿色的阶段被称为固定功能阶段。这些阶段允许你用参数修改其操作,但是它们的工作方式是预定义了的。
Stages with an orange color on the other hand are programmable
, which means that you can upload your own code to the graphics card to apply exactly the operations you want. This allows you to use fragment shaders, for example, to implement anything from texturing and lighting to ray tracers. These programs run on many GPU cores simultaneously to process many objects, like vertices and fragments in parallel.
橙色的阶段是programmable
(可编程的)
,which意味着你可以上传自己的代码to图形卡to实施你想要的操作。例如,这允许你使用Fragment shader-to实现任何事from纹理贴图和光照to光线追踪。这些程序同时运行在许多GPU核心上to并行处理大量对象,例如顶点和Fragment。
If you've used older APIs like OpenGL and Direct3D before, then you'll be used to being able to change any pipeline settings at will with calls like glBlendFunc
and OMSetBlendState
. The graphics pipeline in Vulkan is almost completely immutable, so you must recreate the pipeline from scratch if you want to change shaders, bind different framebuffers or change the blend function. The disadvantage is that you'll have to create a number of pipelines that represent all of the different combinations of states you want to use in your rendering operations. However, because all of the operations you'll be doing in the pipeline are known in advance, the driver can optimize for it much better.
如果你用过旧API例如OpenGL和Direct3D,那么你将习惯于能够修改任何管道配置with调用例如glBlendFunc
和OMSetBlendState
。在Vulkan中的图形管道几乎是不可变的,所以你必须重建管道if你想替换shader,绑定不同的帧缓存or修改混合功能。缺点是,你必须创建很多管道that代表所有这些不同的状态组合that你想在你的app中用的。但是,由于你在管道中所有要做的操作都已经提前知道了,驱动可以优化得好的多。
Some of the programmable stages are optional based on what you intend to do. For example, the tessellation and geometry stages can be disabled if you are just drawing simple geometry. If you are only interested in depth values then you can disable the fragment shader stage, which is useful for shadow map generation.
有的可编程阶段是可选的-基于你想做什么。例如,tessellation和geometry阶段可以被忽略if你只想绘制简单的几何体。If你只对深度值感兴趣,那么你可以禁用Fragment sader阶段,which对阴影映射生成有用。
In the next chapter we'll first create the two programmable stages required to put a triangle onto the screen: the vertex shader and fragment shader. The fixed-function configuration like blending mode, viewport, rasterization will be set up in the chapter after that. The final part of setting up the graphics pipeline in Vulkan involves the specification of input and output framebuffers.
下一章,我们将创建2个可编程阶段-用于将三角形显示到屏幕上:顶点shader和Fragment shader。固定功能配置例如混合模式、视口、光栅化会在之后的章节配置。设置Vulkan图形管道的最后部分涉及到对帧缓存input和output的说明。
Create a createGraphicsPipeline
function that is called right after createImageViews
in initVulkan
. We'll work on this function throughout the following chapters.
创建createGraphicsPipeline
函数that在initVulkan
函数的createImageViews
之后调用。我们将编写这个函数-在后续几章里。
1 void initVulkan() { 2 createInstance(); 3 setupDebugCallback(); 4 createSurface(); 5 pickPhysicalDevice(); 6 createLogicalDevice(); 7 createSwapChain(); 8 createImageViews(); 9 createGraphicsPipeline(); 10 } 11 12 ... 13 14 void createGraphicsPipeline() { 15 16 }