天天看点

总结 :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是方法。