之前我们学习了如何声明顶点着色器、如何设置常量寄存器中的常量。接下来我们学习如何写和编译一个顶点着色器程序。

在我们编译一个顶点着色器之前,首先需要写一个。

有17种不同的指令(instruction),它们的句法如下:
1. add
参数:dest,src1,src2
作用:src1+src2
2. dp3
参数:dest,src1,src2
作用:三个分量的点积(three-component dot product)。dest.x = dest.y = dest.z = dest.w = (src1.x*src2.x)+(src1.y*src2.y)+(src1.z*src2.z)
3. dp4
参数:dest,src1,src2
作用:四个分量的点积。(four-component dot product)dest.w = (src1.x*src2.x)+(src1.y*src2.y)+(src1.z*src2.z)+(src1.w*src2.w);
dest.x = dest.y = dest.z = dp4结果的标量
和mul的不同点:dp4产生的积是标量。mul是一个向量积(component by component vector product)。
4. dst
参数:dest,src1,src2
作用:dst这样计算:第一个源操作数(src1)被假定为vector(ignored,d*d,d*d,ignored),
第二个源操作数(src2)被假定为vector(ignored,1/d,ignored,1/d).
Calculate distance vector:
dest.x = 1
dest.y = src1.y*src2.y
dest.z = src1.z
dest.w = src2.w
dst在计算标准衰减(standard attenuation)是很有用的。
5. expp
参数:dest,src.w
作用:Exponential 10-bit precision
6. lit
参数:dest,src
作用:Calculate lighting coefficients from two dot products and a power.
7. logp
参数:dest,src.w
作用:Logarithm 10-bit precision
8. mad
参数:dest,src1,src2,src3
作用:dest = (src1*src2)+src3
9. max
参数:dest,src1,src2
作用:dest = (src1>=src2)?src1:src2)
10. min
参数:dest,src1,src2
作用:dest = (src1<src2)?src1:src2
11. mov
参数:dest,src
作用:
12. mul
参数:dest,src1,src2
作用:计算叉乘
13. nop
参数:none
作用:do nothing.
14. rcp
参数:dest,src.w
作用:
15. rsq
参数:dest,src
作用:
16. sge
参数:dest,src1,src2
作用:dest = (src1>=src2) ? 1 : 0
17. slt
参数:dest,src1,src2
作用:dest = (src1<src2) ? 1 : 0

ALU顶点着色器是一个操作quad-float data的多线程的向量处理器,它由两个功能单元组成。SIMD Vector Unit负责mov,mul,add,mad,dp3,dp4,dst,min,max,
slt,sge指令。 Special Function Unit负责rcp,rsq,lgp,expp,lit指令。大多数指令执行一个循环,在特殊环境下,rcp,rsq执行超过一个循环。They take only one slot in the vertex shader, but they actually take longer than one cycle to
execute when the result is used immediately because that leads to a register stall.

rsq被用在光照方程中规范化(normalize)向量。expp可以用于雾特效,处理噪音生成和粒子系统中粒子的行为,或者to implement a system for how
objects in a game are damaged.
lit指令被默认处理方向光(directional lights)。它计算漫反射和高光元素,基于N*L、N*H和specular power。 you can use an attenuation level separately with the result of lit by
using the dst instruction. This is useful for constructing attenuation factors for point and spot lights.

也有复杂的指令被顶点着色器支持,不应该用“宏”指这些复杂指令,因为它们不能被“C预处理宏”简单地代替。在使用这些指令前,你应该认真考虑。如果你使用它们,
你可能会丢失128-instructions和优化路径的控制。另一方面,Intel和AMD为它们的处理器提供软件效仿模式(software emulation mode),这可以优化一个m4x4复杂指令,
一些图形硬件也打开了优化m4x4的大门。所以,用在你的顶点着色器里,用m4x4代替调用dp4。如果你决定在你的着色器中使用m4x4指令,在那之后,你不应该在相同的数据上调用dp4,
因为这会在变换后的结果上有稍微不同。
-----------------------------------------------------------------------------------------------------
宏   |  参数                 | 作用                                                                                | Clocks |
expp | dest, src1         | Provides exponential with full precision to at least 1/220     | 12 |
frc  | dest, src1         | Returns fractional portion of each input component             | 3 |
log     | dest, src1         | Provides log2(x) with full float precision of at least 1/220     | 12 |
m3x2 | dest, src1, src2 | Computes the product of the input vector and a 3x2 matrix | 2 |
m3x3 | dest, src1, src2 | Computes the product of the input vector and a 3x3 matrix | 3 |
m3x4 | dest, src1, src2 | Computes the product of the input vector and a 3x4 matrix | 4 |
m4x3 | dest, src1, src2 | Computes the product of the input vector and a 4x3 matrix | 3 |
m4x4 | dest, src1, src2 | Computes the product of the input vector and a 4x4 matrix | 4 |
-----------------------------------------------------------------------------------------------------

你可以用这些指令执行所有变换和灯光操作。

现在,让我们来看看这些寄存器和指令如何运用在ALU顶点着色器中。在版本vs.1.1中,每个rasterizer(光栅)有16个输入寄存器,96个常量寄存器,12个临时寄存器(temporary),一个地址寄存器(address),13个输出寄存器。
每个寄存器可以处理4x32-bit值。每个32-bit值可以通过脚注x,y,z,w取得。为了访问这些寄存器分量,你必须在寄存器名字的后面添加.x,.y,.z,.w。

【使用输入寄存器】
你可以通过它们的名字v0-v15来访问这16个输入寄存器。
输入寄存器中一般提供的值有:
Position (x,y,z,w)
Diffuse color (r,g,b,a) — 0.0 到 1.0
Specular color (r,g,b,a) — 0.0 到 1.0
可达8个texture coordinates (each as s, t, r, q or u, v, w, q) 但一般是4个或者6个,取决于硬件的支持
Fog (f,*,*,*) — 用在雾方程的值
Point size (p,*,*,*)

你可以通过v0.x访问position的x分量。如果你需要知道RGBA diffuse color 的表示绿色的分量,你可以查看v1.y。你可以通过v7.x设置雾的值。其他分量,v7.y,v7.z,v7.w不被使用。
输入寄存器是只读的,每个指令只能访问(access)一个顶点输入寄存器。在输入寄存器中,未被特殊化的(即未被赋值)分量x,y,z设为0.0,w设为1.0。
下面的例子中,c0-c3和v0之间的点乘被存储在oPos中:
dp4 oPos.x , v0 , c0
dp4 oPos.y , v0 , c1
dp4 oPos.z , v0 , c2
dp4 oPos.w , v0 , c3

这个代码片段通常用在在World、View、Projection矩阵的结合体的帮助下,从 projection space 映射到 clip space。
因为给定的是单位向量,而两个单位向量的点积范围为[-1,1],所以oPos得到的值总在[-1,1]内。
你也可以使用: m4x4 oPos, v0, c0
不要忘记这个事实,你要至始至终的在你的顶点着色器中使用m4x4 或者 dp4, 不能既使用m4x4又使用dp4,根据前面讨论过的,dp4和m4x4作用的结果是有稍微区别的!
你也一定不要忘了每条指令只能使用一个输入寄存器。
所有在输入寄存器中的数据将贯穿顶点着色器程序的执行(即程序没结束前一直存在),甚至存在的时间更长,这意味着这些数据的生命周期甚至比顶点着色器的生命都长。
所以在下一个顶点着色器中reuse这些数据是可能的。

【使用常量寄存器】

常量寄存器中的数据一般包括:Matrix data、光照特性(如位置、衰减因子等)、当前时间、顶点插值数据、程序数据。有96个常量寄存器(or in the case of theRADEON 8500, 192个),所以可以存储96个quad-floats。

常量寄存器于顶点着色器是只读的,然而,应用程序可以对顶点着色器进行读写。常量寄存器保存它的数据的时间超过顶点着色器的生命周期,所以可以在下一个顶点着色器中reuse数据。所以app可以避免多余的SetVertexShaderConstant()的调用。读取过程中如果超过常量寄存器的range,将返回(0,0,0,0)。

你只能每个指令用一个常量寄存器,但你可以多次使用它。例如:

下面的指令是合法的:mul r5, c11, c11  // 表示c11和c11的积被存储在r5中
这条是非法的:add v0, c4, c3  //因为它一条指令使用了两个不同的寄存器

【使用寻址寄存器】

你可以用a0-an来访问寻址寄存器(如果着色器版本高于1.1,多个寻址寄存器可用)。在版本1.1中,只能使用a0来执行间接寻址操作,用来offset常量寄存器(也就是constant memory)。如:c[a0.x + n] ; // n表示基地址(base address),a0.x是地址偏移量(address offset)。

这儿是一个使用寻址寄存器的例子:

mov a0.x,r1.x
m4x3 r4,v0,c[a0.x + 9];
m3x3 r5,v3,c[a0.x + 9];
...
根据储存在临时寄存器r1.x的值,在指令m4x4,m3x3中使用不同的常量寄存器。记住,a0只存储整数,没有分数。而且,一个顶点着色器只能通过mov指令write to a0.x。

【使用临时寄存器】

你可以用r0-r11来访问12个临时寄存器。每个临时寄存器可以写一次读三次,因此,一个指令可以使用相同的临时寄存器三次。在写入临时寄存器之前,顶点着色器不能尝试从临时寄存器读取一个值。如果你尝试从一个尚未写入值的临时寄存器读取数据,当创建顶点着色器的时候(调用CreateVertexShader()),API将给你一个错误信息。

【使用输出寄存器】

你可以通过下面的寄存器名字访问13个只写输出寄存器。

一个例子:

dp4 oPos.x , v0 , c4 ; emit projected x position
dp4 oPos.y , v0 , c5 ; emit projected y position
dp4 oPos.z , v0 , c6 ; emit projected z position
dp4 oPos.w , v0 , c7 ; emit projected w position
mov oD0, v5 ; set the diffuse color
mov oT0, v2 ; outputs the texture coordinates to oT0 from input register v2

vertex shader(3)的更多相关文章

  1. vertex shader(4)

    Swizzling and Masking 如果你使用输入.常量.临时寄存器作为源寄存器,你可以彼此独立地swizzle .x,.y,.z,.w值.如果你使用输出.临时寄存器作为目标寄存器,你可以把. ...

  2. vertex shader(2)

    一次只有一个vertex shader是活跃的.你可以有多个vertex shader,如果一个物体特殊的变换或者灯光,你可以选择合适的vertex shader来完成这个任务. 你可能想使用vert ...

  3. vertex shader(1)

    Vertex shader Architecture: 所有在vertex shader中的数据都用128-bit的quad-floats表示(4x32-bit). vertex shader线性地执 ...

  4. 【Unity Shader实战】卡通风格的Shader(二)

    写在前面 本系列其他文章: 卡通风格的Shader(一) 好久没写博客了,一定是因为课程作业比较多,一定不是因为我懒,恩恩. 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface ...

  5. 【Unity Shader实战】卡通风格的Shader(一)

    写在前面 本系列其他文章: 卡通风格的Shader(二) 呜,其实很早就看到了这类Shader,实现方法很多,效果也有些许不一样.从这篇开始,陆续学习一下接触到的卡通类型Shader的编写. 本篇的最 ...

  6. 学习笔记:GLSL Core Tutorial – Vertex Shader(内置变量说明)

    1.每个Vertex Shader都有用户定义的输入属性,例如:位置,法线向量和纹理坐标等.Vertex Shaders也接收一致变量(uniform variables). uniform vari ...

  7. 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)

    在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时, ...

  8. Unity Shader (三)Surface Shader机制

    转自:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的机制一直是 ...

  9. Unity Shader (一)ShaderLab 语法

    一.什么是Shader Shader(着色器):是可以在GPU上运行的一段程序,通过Shader可以进行一些渲染相关的设置. 二.什么是ShaderLab 目前面向GPU的编程有三种高级图像语言:HL ...

随机推荐

  1. 使用Postman对Restful接口进行测试

    趁着项目需要,花了两天时间对postman进行了一下学习,因为看到各大测试群,各个初入测试的孩子们都在问postman,但其实网上也有很多的教程,这里我就再来发一篇. 1. Http协议 要对接口进行 ...

  2. RabbitMQ介绍及windows下安装使用

    RebbitMQ介绍 RabbitMQ是一个由 Erlang (一种通用的面向并发的编程语言)开发的AMQP(Advanced Message Queue )的开源实现,Rabbit MQ 是建立在E ...

  3. WCF常用绑定选择

    一.五种常用绑定常用绑定的传输协议以及编码格式 名称 传输协议 编码格式 互操作性 BasicHttpBinding HTTP/HTTPS Text,MTOM Yes NetTcpBinding TC ...

  4. crm2013js弹出窗口

  5. 制作Windows XP万能克隆镜像

    制作Windows XP万能克隆镜像 战前分析:对于Windows XP,制作万能克隆时的一个重要问题就是系统激活,因为Windows XP为了防止盗版,采取了激活机制,当硬件发生改变时,系统就会要求 ...

  6. 怎么安装Docker CE 17( Centos 7)

    Docker CE for Centos 7 yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manage ...

  7. 嵌入式linux问题杂锦

    tftp 在开发板上不能获取共享文件,出现: Permission denied tftp: can't open 'myTcpTest': Permission denied 是因为,我在/sys目 ...

  8. 从wiresharp看tcp三次握手

    我们知道,传输层是OSI模型中用户进行数据传输的分层,目前仅有TCP和UDP两种协议可用.TCP为了进行传输控制,引入了三次握手机制,以确保通信连接的建立.道理很简单,我们跟别人打电话聊天时,对方拿起 ...

  9. error: device not found

    C:\Users\Administrator>adb shell error: device not found    出现上面情况,首先检查设备管理器中,安卓的驱动是否安装OK?   如果驱动 ...

  10. golang调用动态库

    测试动态库 test_so.h int test_so_func(int a,int b); test_so.c #include "test_so.h" int test_so_ ...