BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

顶点和片段着色器

| 作者 Marco Scabia 关注 0 他的粉丝 发布于 2011年11月4日. 估计阅读时间: 11 分钟 | Google、Facebook、Pinterest、阿里、腾讯 等顶尖技术团队的上百个可供参考的架构实例!

目录

需求

预备知识

最好对Stage3D API有基本的了解。最好拥有使用VertexBuffer的经验。在完成本教程之前,一定要阅读这个关于Stage3D的系列的上一篇教程(Stage3D的工作原理)。

用户水平

中级

需要的产品

本教程将介绍着色器。着色器是Stage3D呈现管道的核心。您将学习什么是顶点着色器和片段着色器,它们如何适合3D呈现管道,以及为什么需要它们。

使用着色器

在本系列的上一篇介绍Stage3D工作原理的文章中,您已知道Stage3D基于一种可编程图形管道。

Stage3D的可编程图形管道非常有用,因为您可以对呈现行为进行编程。这是对旧有的固定函数图形管道的一项重大改进,涉及到向GPU提供数据,以便它可以在无需任何控件的情况下呈现。

但是,它还意味着为了使用Stage3D,您需要负责编写这些实际使管道可编程的可编程代码。

图形管道中的可编程代码是一些称为着色器的程序。着色器有两种工作方式:顶点着色器和片段着色器(也称为像素着色器)。要完全使用Stage3D呈现所有内容,您需要编写至少1个顶点着色器和1个片段着色器,否则您的图形管道将无法编程,也不会生效。

着色器是一些在您的图形硬件GPU上运行的小程序,不会像正常的ActionScript代码一样由CPU执行。这是着色器程序与常规代码之间最重要的区别。

着色器就是GPU程序。

在Stage3D内,着色器使用一个名为Program3D的特殊的Stage3D API类包装。Program3D提供了创建着色器实例并将它上传到GPU所需的功能。着色器程序然后即可执行,Stage3D API允许在您的主要ActionScript代码与着色器程序之间通信。

着色器运行速度很快。但请注意,ActionScript是一种较慢的语言。但是当运行ActionScript时,因为您是在一个虚拟机内执行代码,所以该语言的运行速度比C++等原生语言更慢。这就是如今的许多AAA游戏仍然使用C++编写的原因。

在首次使用Flash时,您可以创建GPU原生的着色器程序——以便它们可以完整的(GPU)原生速度运行。

理解着色器如何适合可编程图形管道

可编程图形管道描述了Stage3D内容呈现的方式(参见图1)。

图1. 可编程图形管道结构图。

查看上图,留意顶点着色器和片段着色器是如何构成管道中的重要部分的。

当呈现一个几何形状时,您将有一个称为VertexBuffer的顶点流,它生成几何三角形。这个来自顶点缓冲区的顶点流提供作为顶点着色器的输入,它可以以可编程的方式处理顶点数据。顶点着色器输出供GPU用于组装三角形。这些三角形然后在视口中经过恰当地切分和剔除,随后发送到Rasterizer块中,该块生成一个新的输出流,其中包含所谓的片段:微型的数据结构,每个片段与屏幕上出现的一个三角形像素相对应。

片段的数据内容主要有顶点着色器确定。事实上,顶点着色器有能力将顶点属性参数作为它的输出传递。Rasterizer所做的是将顶点着色器输出的针对每个顶点的数据插入到三角形中,使屏幕上的每个片段(三角形像素)获得这个特定像素的正确值。

例如,想象您的顶点缓冲区指定了一种顶点颜色作为顶点属性,您的三角形有两个顶点指定为白色,一个顶点指定为黑色。顶点着色器将把这些顶点颜色传递到它的输出,传递到管道中的以下块中。然后,一个与三角形中某个位置相对应的片段将收到一个具有一定灰度的颜色:白色顶点和黑色顶点颜色的插值。这种灰度对于接近白色顶点的片段会更亮,对于接近黑色顶点的片段会更黑。

这些插入的未处理的片段然后作为输入发送到片段着色器,后者使用该数据建立最终的像素颜色。

除了它作为输入收到的这些片段,您也可以使用ActionScript代码向片段着色器发送一个或多个输入纹理,片段着色器可对这些纹理进行采样。

使用顶点着色器

顶点着色器是在GPU上运行的小程序。从名称可以看出,可通过处理它们来处理顶点。顶点着色器是处理顶点的微型程序。

一般而言,您将使用您的几何信息创建一个VertexBuffer并将它传递给GPU。然后您将使用一种着色语言(比如AGAL)编写一个顶点着色器。会为您的VertexBuffer中的每个顶点调用顶点着色器程序。

这就像有一个围绕顶点程序,执行以下任务的for循环:

for (var i:int = 0; i < vertexBuffer.length; i++)
{
    executeVertexShader(vertexBuffer[i]);
}

即使您没有看到for循环。所以会处理VertexBuffer中的所有顶点。

您也可以将常量值以常量寄存器的形式从ActionScript传递到VertexShader。每次您希望运行着色器(每次您调用Context3D::drawTriangles方法来呈现一个结构),您都可以传入一个不同的值。着色器可以处理这个常量值,以调整它的算法和输出。

顶点着色器的输入是一个VertexBuffer,它由一个或多个顶点属性流组成。在最低限度,一个顶点缓冲区必须包含顶点位置。这些顶点位置通常指一个位于每个3D模型本地的坐标系统(每个模型拥有自己的原点)。顶点着色器将位置传输到屏幕空间,以便它们可以正确地显示。顶点缓冲区可能还包含其他顶点属性,比如顶点颜色或纹理UV坐标。顶点着色器通常传递这些值作为输出(最终在处理它们之后),以便它们可以由Rasterizer插入并作为输入传入到片段着色器中。

顶点着色器最明显和自然的用途是对屏幕中的几何形状执行矩阵变换。您会获得本地空间中的所有顶点。并将变换矩阵传递给顶点着色器。顶点着色器将使用矩阵转换VertexBuffer中的所有顶点。它会非常块地执行此任务。比您在ActionScript中编写代码要快得多,因为它是硬件加速的。

有趣的是,顶点着色器完全是可编程的。您可通过您喜欢的任何方式修改您的几何形状。例如,一个修改顶点位置的典型应用是骨头的创建:您可以定义一组骨头、您的几何形状的一个框架,以及一个皮肤(网格)。当骨头旋转时,它们位于一个层次结构中,它们修改其皮肤的形状。这正是创建手指动画的方式。这么做的最佳方式是将骨头的旋转(转换)传递给一个顶点着色器,让顶点着色器修改皮肤,以便它看起来得到了恰当的绘制和变形。

顶点着色器还有许多其他的应用:模拟软布的外观,或者变形物体。创建两个网格,它们具有相同数量的顶点,让顶点着色器依据变形参数将网格1变形为网格2。

使用片段着色器

像顶点着色器一样,片段着色器也是在GPU上运行的小程序。从名称可以看出,片段着色器处理片段——它们负责输出每个呈现的三角形像素的最终像素颜色。

基本而言,它的工作原理如下:片段着色器以输入的形式收到顶点着色器通过管道传递的所有这些片段。如上所述,到达片段着色器的片段是顶点着色器的顶点属性输出的插入版本。

片段着色器执行流程在本质上就像一个隐藏的循环。如果您想象将您未处理的片段添加到某种称为的fragmentStream的流中,那么片段着色器的执行将等效于以下代码:

for (var i:int = 0; i < fragmentStream.length; i++)
{
    executeFragmentShader(fragmentStream[i]);
}

可以说,输入fragmentStream是未处理的。这意味着片段着色器可以处理它,计算该三角形屏幕像素的最终颜色。

片段着色器真正位于可编程图形管道的核心。片段着色器的最常见用途是计算从顶点属性颜色(用于顶点着色几何体)或从纹理和相关的顶点属性UV纹理坐标(用于纹理几何体)开始的各种三角形像素颜色。

但片段着色器并不仅限于创建这些简单效果,实际上,片段着色器可用于创建您在现代3D游戏中看到的所有令人惊艳的3D效果。例如,动态光线效果大部分都是使用片段着色器完成的。可以想象,动态光线意味着依据场景中存在的光线、它们相对于我们的几何体的位置,以及几何体的材质来计算像素颜色。这正是动态光线最常使用片段着色器创建的原因。

反射效果,比如水或环境映射,都是使用片段着色器创建的。可使用片段着色器创建的效果非常丰富,这些基本效果仅仅是所有可能性的冰山一角。

最后,您在屏幕上看到效果取决于片段着色器。所以片段着色器是管理实际呈现的内容的代码。

延伸阅读

在本教程中,您学习了使用顶点着色器和片段着色器的概念。这些着色器构成了Stage3D API中的呈现管道的核心。着色器可用于创建所有类型的3D图形效果,有大量在线文献介绍了基于着色器的技术。请继续阅读这个Stage3D系列中的下一篇教程,了解着色语言,专门学习一下AGAL (Adobe Graphics Assembly Language)。

要更详细地研究着色器,我建议阅读nVidia所编写的流行的“GPU Gems”图书,它们已免费在线发布。它们没有专门介绍使用Flash和Stage3D,但提供了对您可以使用着色器创建的效果的有用概述:

查看原文:Vertex and Fragment Shaders

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT