天天看點

總結 :hlsl的運算

由于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是方法。