由于hlsl資料的存儲以及資料格式的多種原因,導緻在計算的時候有很多小規則,如果不注意很容易出問題。
1.變量的初始化:
理論上來說float4 color = 0; 是沒有錯的,但是如果這樣初始化在對其進行計算的時候會出問題,例如簡單的+和*計算都會直接報錯,是以在初始化的時候最好能夠float4 color = float4(0,0,0,0);這樣寫。
重要:HLSL的結構體struct其實并不管你是一個變量還是幾個變量,它就是按照一次放滿一個float4的記憶體長度,多少變量都往一個float4裡面塞,塞滿了再接着塞下一個float4。測試結果顯示:cbuffer的長度必須是float4的整數倍才行,不知道float+float3的這種組合是否可以正常擷取資料,也不清楚float+float+float3+float3這種組合能不能正常配置設定到資料,關鍵取決于GPU的記憶體配置設定規則。
2.加法:x1 + x2 = (x1.x+x2.x,x1.y+x2.y,x1.z+x2.z,x1.w+x2.w)
float4 x1 = float4(0.1,0.1,0,1.0);
float4 x2 = float4(0.2,0.2,0,1.0);
x1 + x2 = (0.3,0.3,0,2.0);
3.乘法:x1 * x2 = (x1.x*x2.x,x1.y*x2.y,x1.z*x2.z,x1.w*x2.w)
x1 * x2 = (0.02,0.02,0,1.0);
4.語義:語義隻不過是C++與hlsl資料映射的一個key,而資料在C++和hlsl裡面表現出的資料類型,并不需要一定相同(包括資料的長度)。此外AI階段輸入的資料,vs并不需要全部使用,它可以根據自己的需求使用其中一部分資料。
需要保證的是:在C++這邊原語的定義要跟AI階段輸入的資料格式一緻,而vs裡面使用的時候也需要跟input對象保持一緻,它們之間的映射是松耦合的。
5.語義的定義:語義的名字不是我們自己随便能取的,是hlsl定義好的,而且vs裡面能用什麼ps裡面能用什麼都是定好了的:詳情
6.一個讓人蛋疼的錯誤:
struct VertexInputType
{
float4 position : POSITION;
float3 normal : NORMAL;
//float3 tangent : TANGENT;
//float3 binormal : BINORMAL;
float2 texture : TEXTURE; //紋理坐标
};
把變量定義為texture的時候vs的編譯失敗,或許這個正好是一個關鍵字什麼的,反正用文本編輯hlsl很蛋疼。但是,現在市面上又沒有DX11支援很好的IDE。悲催以後定義變量的時候加個字首。
7.語義可以使勁的關聯,即使AI的時候空置某些變量的内容,hlsl也能正常運作,因為記憶體空間是在建立vbuffer的時候已經定義好的,而格式也在inputlayout裡面定義好了。到了vs裡面即使某些值為null,也不會打亂整個資料格式,它隻是會讓某些為空。
8.關于SV_POSITION這個系統語義,它是給傳遞給ps的POSITION用的,它是一個float4類型,這是強制的,會引起文法錯誤。(細節害死人啊 - -)
9.渲染到多個目标時,5.0最多可以渲染到8個對象裡面去
10.向量的比較:
float4 x = float4(1.0f,1.0f,1.0f,1.0f);
float4 y = float4(1.0f,1.0f,1.0f,1.0f);
// 正确
float4 n = x < y ? 1.0f : 0.0f;
// 錯誤
if(x<y)
{
int i = 0;
}
對于向量來說,使用三目運算符是可以進行對位運算的,但是使用if語句就不行,因為比較傳回的是一個float4的類型的值,而if需要傳遞的參數是int值,至少你得是一個float值才行,而float4顯然是不行的。
11.由于是用每4個float作為存儲單元的,有時候因為一個常量跨存儲單元存儲而導緻錯誤。為此這裡有一種直接指定存儲位置的解決方案:
cbuffer cbShading : register(b2)
{
// Water-reflected sky color
float3 g_SkyColor : packoffset(c0.x);
// The color of bottomless water body
float3 g_WaterbodyColor : packoffset(c1.x);
// The strength, direction and color of sun streak
float g_Shineness : packoffset(c1.w);
float3 g_SunDir : packoffset(c2.x);
float3 g_SunColor : packoffset(c3.x);
// The parameter is used for fixing an artifact
float3 g_BendParam : packoffset(c4.x);
// Perlin noise for distant wave crest
float g_PerlinSize : packoffset(c4.w);
float3 g_PerlinAmplitude : packoffset(c5.x);
float3 g_PerlinOctave : packoffset(c6.x);
float3 g_PerlinGradient : packoffset(c7.x);
// Constants for calculating texcoord from position
float g_TexelLength_x2 : packoffset(c7.w);
float g_UVScale : packoffset(c8.x);
float g_UVOffset : packoffset(c8.y);
};
如上:cbShading是一個cbuffer,是以需要為它指定的是一個b(n)的buffer寄存器。而因為它是cbuffer,是以裡面的配置設定都是以c開頭的,packoffset是方法。