Shader学习之Cg语言四(输入\输出与语义绑定)

来源:互联网 发布:甘肃干部网络考试答案 编辑:程序博客网 时间:2024/06/06 03:42

第一次在candycat博客中看到语义和语义绑定时完全不懂说的什么,这次在《GPU编程与CG语言之阳春白雪下里巴人》再次看到,将自己的理解记录下来,方便自己查阅与理解。

首先回顾一下GPU图形绘制管线原理
应用程序阶段:应用程序(宿主程序)将图元信息(顶点位置、法向量、 纹理坐标等)传递给顶点着色程序。
几何阶段:顶点着色程序基于图元信息进行坐标空间转 换,运算得到的数据传递到片段着色程序中。
光栅化阶段:片段着色程序接收来之顶点着色程序的输入数据,并且接受从应用程 序中传递的纹理信息,将这些信息综合起来计算每个片段的颜色值,最后将这些 颜色值输送到帧缓冲区(或颜色缓冲区)中。

这些是顶点着色程序和片段着色程序的基本功能和数据输入输出,着色程序接受多种数据类型,并灵活的进行各种算法的处理,如, 可以接受光源信息(光源位置、强度等)、材质信息(反射系数、折射系数等)、 运动控制信息(纹理投影矩阵、顶点运动矩阵等),可以在顶点程序中计算光线 的折射方向,并传递到片段程序中进行光照计算。

在这个过程中语义绑定确定了数据类型和传递形式。同时解决了下面一些问题
1、从应用程序传递到GPU的数据,分为图元信息数据(在GPU处理的基本数 据如顶点位置信息等)和其他的离散数据(在GPU运行流程中不会发生变化, 如材质对光的反射、折射信息),这两种输入数据如何区分?
2、从应用程序传递到GPU中的图元信息如何区分类型,即,顶点程序怎么知 道一个数据是位置数据,而不是法向量数据?
3、顶点着色程序与片段着色程序之间的数据传递如何进行?

Cg关键字:int、float等数据类型,Cg语义词 (位置信息,法向量信息,寄存器,纹理等),in,out,inout,uniform,const
其中比较不好理解的是uniform,书中对uniform的解释如下:
Cg 语言将输入数据流分为两类:
1. Varying inputs:即数据流输入图元信息的各种组成要素。从应用程序输入 到 GPU 的数据除了顶点位置数据,还有顶点的法向量数据,纹理坐标数据 等。Cg 语言 供了一组语义词,用以表明参数是由顶点的哪些数据初始化 的。
2. Uniform inputs:表示一些与三维渲染有关的离散信息数据,这些数据通常由应用程序传入,并通常不会随着图元信息的变化而变化,如材质对光的反射信息、运动矩阵等。Uniform 修辞一个参数,表示该参数的值由外部应 用程序初始化并传入;例如在参数列表中写:

uniform float brightness,uniform float4x4 modleWorldProject

表示从“外部”传入一个 float 类型数据,和一个 4 阶矩阵。“外部”的含义 通常是用 OpenGL 或者 DirectX 所编写的应用程序。使用 Uniform 修辞的变量,除了数据来源不同外,与其他变量是完全一样的。
需要注意的一点是:uniform 修辞的变量的值是从外部传入的,所以在 Cg 程 序(顶点程序和片段程序)中通常使用 uniform 参数修辞函数形参,不容许声明 一个用 uniform 修辞的局部变量!否则编译时会出现错误 示信息:
Error C5056:’uniform’not allowed on local variable

语义绑定
语义词,表示输入图元的数据含义(是位置信息,还是法向量信息),也表明这些图元数据存放的硬件资源(寄存器或者纹理缓冲区)。顶点着色程序和片段着色程序中 Varying inputs 类型的输入,必须和一个语义词相绑定,这称之为 绑定语义(binding semantics)。
语义,是两个处理阶段(顶点程序、片段程序)之间的输入\ 输出数据和寄存器之间的桥梁,同时语义通常也表示数据的含义,如 POSITION 一般表示参数种存放的数据是顶点位置。

顶点着色程序的输入语义

POSITION NORMAL BINORMAL BLENDWEIGHT TANGENT PSIZE BLENDINDICES TEXCOORD0---TEXCOORD7

语义词 POSITION0 等价于 POSITION,其他的语义词也有类似的等价关系。为了说明语义词的含义,举例如下:

in float4 modelPos: POSITION

表示该参数中的数据是的顶点位置坐标(通常位于模型空间),属于输入参数,语义词 POSITION 是输入语义,如果在 OpenGL 中则对应为接受应用程序传递的顶点数据的寄存器(图形硬件上)。

in float4 modelNormal: NORMAL

表示该参数中的数据是顶点法向量坐标(通常位于模型空间),属于输入参 数,语义词 NORMAL 是输入语义,如果在 OpenGL 中则对应为接受应用程序传 递的顶点法向量的寄存器(图形硬件上)。
注意,上面的参数都被声明为四元向量,通常我们在应用程序涉及的顶点位 置和法向量都是三元向量,至于为什么要将三元向量便为四元向量,又称齐次坐 标,具体请看附录 A。顶点位置坐标传入顶点着色程序中转化为四元向量,最后 一元数据为 1,而顶点法向量传入顶点着色程序中转化为四元向量,最后一元数 据为 0。

顶点着色程序的输出语义&片段着色程序的输入语义
下面这些语义词适用于所有的Cg vertex profiles作为输出语义和Cg fragment profiles的输入语义:
POSITION,PSIZE,FOG, COLOR0-COLOR1, TEXCOORD0-TEXCOORD7。
为了保持顶点程序输出语义和片段程序输入语义的一致性,通常使用相同的 struct类型数据作为两者之间的传递。例 如:

struct VertexIn {    float4 position : POSITION;     float4 normal : NORMAL;};struct VertexScreen {    float4 oPosition : POSITION;    float4 objectPos : TEXCOORD0;     float4 objectNormal : TEXCOORD1;};

注意:当使用struct结构中的成员变量绑定语义时,需要注意到顶点着色程 序中使用的POSITION语义词,是不会被片段程序所使用的。
如果需要从顶点着色程序向片段程序传递数据,例如顶点投影坐标、光照信 息等,则可以声明另外的参数,绑定到TEXCOORD系列的语义词进行数据传递, 实际上TEXCOORD系列的语义词通常都被用于从顶点程序向片段程序之间传递 数据

片段着色程序的输出语义
片段着色程序的输出语义词较少,通常是COLOR。这是因为片段着色程序 运行完毕后,就基本到了GPU流水线的末端了。 片段程序必须声明一个out向量 (三元或四元),绑定语义词COLOR,这个值将被用作该片断的最终颜色值。 例如:

void main_f(out float4 color : COLOR){    color.xyz = float3(1.0,1.0,1.0);    color.w = 1.0; }

一些fragment profile支持输出语义词DEPTH,与它绑定的输出变量会设置片 断的深度值;还有一些支持额外的颜色输出,可以用于多渲染目标(multiple render targets , MRTs)。

语义绑定方法
1. 绑定语义放在函数的参数列表的参数声明后面中:

[const] [in | out | inout]<type><identifier> [ :<binding-semantic>][=<initializer>]

其中,const 作为可选项,修辞形参数据;in、out、inout 作为可选项,说 明数据的调用方式;type 是必选项,声明数据的类型;identifier 是必选项, 形参变量名;一个冒号“:”加上一个绑定语义,是可选项;最后是初始化 参数,是可选项。如下代码所示。形参列表中的参数一、参数二绑定到输 入语义;参数三、参数四绑定到输出语义;尽管参数一和参数 3 的绑定语 义词一样,但前者是输入语义,后者是输出语义,所以这两个参数数据所 对应的硬件位置是不一样的。

void mian_v(float4 position_obj : POSITION,             float3 normal_obj : NORMAL,            out float4 oPosition : POSITION,             out float4 oColor : COLOR,            uniform float4x4 modelViewProj){..................}

2.绑定语义可以放在结构体(struct)的成员变量后面:

struct <struct-tag> {    <type><identifier> [:<binding-semantic >]; };

举例如下,结构 C2E1v_Outpu 中的 2 个成员变量分别绑定到语义 POSITION 和 COLOR,然后在 C2E1v_green 顶点程序入口函数中输出,所以C2E1v_Outpu 中的语义是输出语义。

struct C2E1v_Output {    float4 position : POSITION;     float3 color : COLOR;};C2E1v_Output C2E1v_green(float2 position : POSITION) {    C2E1v_Output OUT;    OUT.position = float4(position,0,1);     OUT.color = float3(0,1,0);    return OUT; }

3.绑定语义词可以放在函数声明的后面,其形式为:

<type> <identifier> (<parameter-list>) [:<binding-semantic] {    <body>}

如下代码所示,顶点入口函数的声明后带有“COLOR”语义词,表示该函 数需要反馈一个颜色值,所以函数的返回类型为 float4,函数体也必须以 return 语句结束。

float4 main_v(float4 position: POSITION,                 out float4 oposition : POSITION,                uniform float4x4 modelViewProj):COLOR{    oposition = mul(modelViewProj,position);    float4 ocolor = float4(1.0,0,0,0);    return ocolor; }

4.最后一种语义绑定的方法是,将绑定语义词放在全局非静态变量的声明后 面。其形式为:

<type> <identifier> [:<binding-semantic>][=<initializer>];
阅读全文
0 0
原创粉丝点击