Thinking in Shader(3)
Window7
CgToolkit
羽化的第十九篇博客,隔了一个星期才出现,也许就是所谓惰性吧,工作开始忙起来了,所以可能有时候不能达到一星期一篇的目标了,但研究还在继续,因为羽化是个不喜欢半途而废的人,首先是听说的弟弟要去参军了,真是一个好消息,对于他来说进入军队也是个很好的锻炼,回想小时候弟弟妹妹围着两个哥哥打转的日子已经一去不复返了,我们都在慢慢长大,价值观和人生观在慢慢出现了很大的差异,联系也越来越少,也许现在羽化不是一个称职的兄长,在弟弟妹妹面对人生的艰难时刻没有站出来鼓励他们,也没给予作为哥哥应有的可靠和关爱才会导致他们慢慢荒废了学业,但羽化知道,他们都是善良的人,这是最好的,也是用什么都无法换来的,希望他们弟弟妹妹们能在未来的路上走得开心,顺利~ ~ 最近闲来和飞噶去上海动物园一趟,里面动物如人各种众生相,总的来说,其实我们所处的社会就是一个巨大动物园,都谈不上真正的自由。。。话说今天帮飞噶女朋友搬家,在普陀附近居然半天找不到吃的地方。。。
好吧~ ~继续开始Cg的学习。
绑定语义
这里是个顶点数据绑定的语义的例子
- struct myinputs {
- float3 myPosition : POSITION;
- float3 myNormal : NORMAL;
- float3 myTangent : TANGENT;
- float refractive_index : TEXCOORD3;
- };
- outdata foo(myinputs indata)
- {
- /* ... */
- // Within the program, the parameters are referred to as
- // “indata.myPosition”, “indata.myNormal”, and so on.
- /* ... */
- }
- /*还可以写成*/
- outdata foo(float3 myPosition : POSITION,
- float3 myNormal : NORMAL,
- float3 myTangent : TANGENT,
- float refractive_index : TEXCOORD3) {
- /* ... */
- // Within the program, the parameters are referred to by
- // their variable names: “myPosition”, “myNormal”,
- // “myTangent”, and “refractive_index”.
- /* ... */
- }
struct myinputs {
float3 myPosition : POSITION;
float3 myNormal : NORMAL;
float3 myTangent : TANGENT;
float refractive_index : TEXCOORD3;
};
outdata foo(myinputs indata)
{
/* ... */
// Within the program, the parameters are referred to as
// “indata.myPosition”, “indata.myNormal”, and so on.
/* ... */
}
/*还可以写成*/
outdata foo(float3 myPosition : POSITION,
float3 myNormal : NORMAL,
float3 myTangent : TANGENT,
float refractive_index : TEXCOORD3) {
/* ... */
// Within the program, the parameters are referred to by
// their variable names: “myPosition”, “myNormal”,
// “myTangent”, and “refractive_index”.
/* ... */
}
绑定语义的概念和普通语言中基本类似,Cg中提供的几种语义有:
POSITION
BLENDWEIGHT
NORMAL
TANGENT
BINORMAL
PSIZE
BLENDINDICES
TEXCOORD0—TEXCOORD7
COLOR0–COLOR1
顶点程序输出通过光栅和可用的Varying Outputs片段程序,作为顶点和片段程序的交互,他们必须保证数据能在彼此间传输通过,作为应用与顶点程序传输的数据流,Cg使用绑定语义指明了顶点程序与片段程序。
下面的程序是对应顶点输出:
- // Vertex program
- struct myvf
- {
- float4 pout : POSITION; // Used for rasterization
- float4 diffusecolor : COLOR0;
- float4 uv0 : TEXCOORD0;
- float4 uv1 : TEXCOORD1;
- };
- myvf foo(/* ... */)
- {
- myvf outstuff;
- /* ... */
- return outstuff;
- }
// Vertex program
struct myvf
{
float4 pout : POSITION; // Used for rasterization
float4 diffusecolor : COLOR0;
float4 uv0 : TEXCOORD0;
float4 uv1 : TEXCOORD1;
};
myvf foo(/* ... */)
{
myvf outstuff;
/* ... */
return outstuff;
}
再者,下面的是另一个例子展示如何应用相同数据作为片段程序输入:
- // Fragment program
- struct myvf
- {
- float4 diffusecolor : COLOR0;
- float4 uv0 : TEXCOORD0;
- float4 uv1 : TEXCOORD1;
- };
- fragout bar(myvf indata)
- {
- float4 x = indata.uv0;
- /* ... */
- }
// Fragment program
struct myvf
{
float4 diffusecolor : COLOR0;
float4 uv0 : TEXCOORD0;
float4 uv1 : TEXCOORD1;
};
fragout bar(myvf indata)
{
float4 x = indata.uv0;
/* ... */
}
所有顶点程序必须声明和设置一个顶点输出通过POSITOIN,这个值是光栅需要的。
为了确保顶点程序和片段程序的互通,双方必须使用相同的结构对应各自的输入和输出,如下面的程序:
- struct myvert2frag
- {
- float4 pos : POSITION;
- float4 uv0 : TEXCOORD0;
- float4 uv1 : TEXCOORD1;
- };
- // Vertex program
- myvert2frag vertmain(...)
- {
- myvert2frag outdata;
- /* ... */
- return outdata;
- }
- // Fragment program
- void fragmain(myvert2frag indata )
- {
- float4 tcoord = indata.uv0;
- /* ... */
- }
struct myvert2frag
{
float4 pos : POSITION;
float4 uv0 : TEXCOORD0;
float4 uv1 : TEXCOORD1;
};
// Vertex program
myvert2frag vertmain(...)
{
myvert2frag outdata;
/* ... */
return outdata;
}
// Fragment program
void fragmain(myvert2frag indata )
{
float4 tcoord = indata.uv0;
/* ... */
}
注意:一些顶点输出的语义是针对光栅,这些值实际上不能用在片段程序,即使他们出现在输入的结构中,例如indata.pos值是连接POSITION片段语义却不能在fragmain的shader中识别出来。
Arrays数组
这里说说Cg中的数组,因为Cg不支持指针,所以用数组的情况很多。其实用法都类似,在书中有个地方羽化觉得比较诡异,就是Unsized Arrays,原来是一个很简单的调用,而官方貌似把这个当成一种特性,貌似这只是种技巧。。。具体实例如下:
- float myfunc(float vals[])
- {
- float sum = 0;
- for (int i = 0; i < vals.length; i++)
- {
- sum += vals[i];
- }
- return sum;
- }
- float4 main(...)
- {
- float vals1[2];
- float vals2[76];
- ...
- float myval1 = myfunc(vals1); // match
- float myval2 = myfunc(vals2); // match
- ...
- }
float myfunc(float vals[])
{
float sum = 0;
for (int i = 0; i < vals.length; i++)
{
sum += vals[i];
}
return sum;
}
float4 main(...)
{
float vals1[2];
float vals2[76];
...
float myval1 = myfunc(vals1); // match
float myval2 = myfunc(vals2); // match
...
}
运算符
Cg支持普通的运算符(+,-,*,/)同样支持矢量运算,例如:
float3(a, b, c) * float3(A, B, C) equals float3(a*A,b*B, c*C)
a * float3(A, B, C) is equal to float3(a*A, a*B, a*C)
Advanced Fragment Profiles先进的片段配置
Cg提供了先进的片段配置方便纹理的查找,通常情况下需要两个参数:
Texturesampler纹理采样器---通常类型为sampler, sampler1D,sampler2D,sampler3D, samplerCUBE, samplerRECT和通过a filter,clamp, wrap,similar configuration结合一张纹理图片,注意不能直接用在Cg语言中,通常是通过应用作为统一参数提供个程序。
Texturecoordinate纹理坐标---根据纹理的类型来查找,通常这个坐标可能是scalar,a two‐vector, athree‐vector, or a four‐vector.
下面是一个使用tex2D()功能来执行纹理查找确定这个片段的RGBA颜色的例子:
- void applytex(uniform sampler2D mytexture,
- float2 uv : TEXCOORD0,
- out float4 outcolor : COLOR)
- {
- outcolor = tex2D(mytexture, uv);
- }
void applytex(uniform sampler2D mytexture,
float2 uv : TEXCOORD0,
out float4 outcolor : COLOR)
{
outcolor = tex2D(mytexture, uv);
}
Cg提供了一个多样性的纹理查找功能,具体可以翻手册。
CgFX
CgFX是一种强大的通用的着色器规范和交换格式。对于实时图像艺术家和开发者来说,这种格式提供了几个好处:
2.支持Cg、汇编和固定功能Shader
3.可编辑参数和嵌入式GUI
4.多通道Shader
5.渲染状态和纹理状态规范
羽化个人认为CgFX就像一个IDE和SDK的结合-0-
Techniques方法和Passes传递
CgFX文件包含一个或者多个方法,这些方法通过GPU硬件判断提供适应,同样可以用于提供细节层、功能、性能的回调。例如:
- technique PixelShaderVersion
- {…};
- technique FixedFunctionVersion
- {…};
- technique LowDetailVersion
- {…};
technique PixelShaderVersion
{…};
technique FixedFunctionVersion
{…};
technique LowDetailVersion
{…};
一个方法都包含一个或者多个传递,每一个传递代表一套渲染状态和Shaders来申请一次单一的渲染通过。
下期预告:
Thinking in Shader(4)