【发布时间】:2025-12-06 06:30:03
【问题描述】:
使用 Unity3D 游戏引擎中的 C# 脚本来控制 HLSL 计算着色器,我试图在 GPU 上生成伪随机数并将它们存储在 Texture2D 中。跟着一起 GPU Gems 3 Hybrid Tausworthe method 和另一个线程Pseudo Random Number Generation on the GPU,我遇到了一个问题。
问题:
生成的纹理看起来是一种纯色。如果我多次运行着色器,每次都会得到不同的纯色纹理结果,但整个纹理是一种颜色。
计算着色器代码
#pragma kernel CSMain
RWTexture2D<float4> result; // 256 resolution texture to write to
uint4 seed; //four uniform random numbers generated on the CPU in a C# script
struct RandomResult
{
uint4 state;
float value;
};
uint TausStep(uint z, int S1, int S2, int S3, uint M)
{
uint b = (((z << S1) ^ z) >> S2);
return ((z & M) << S3) ^ b;
}
uint LCGStep(uint z, uint A, uint C)
{
return A * z + C;
}
RandomResult HybridTaus(uint4 state)
{
state.x = TausStep(state.x, 13, 19, 12, 4294967294);
state.y = TausStep(state.y, 2, 25, 4, 4294967288);
state.z = TausStep(state.z, 3, 11, 17, 4294967280);
state.w = LCGStep(state.w, 1664525, 1013904223);
RandomResult rand;
rand.state = state;
rand.value = 2.3283064365387e-10 * (state.x ^ state.y ^ state.z ^ state.w);
return rand;
}
[numthreads(8, 8, 1)]
void CSMain(uint3 id)
{
result[id.xy] = HybridTaus(seed).value;
}
我需要将状态保存在 gpu 上吗?如果是这样,我该怎么做?之后需要释放内存吗?
我尝试将 HybridTaus() 函数的结果分配给 seed,希望它会在接下来的 HybridTaus(seed) 调用中使用新值,看看这是否会有所作为。我还尝试根据线程 ID(id 参数)添加唯一的任意数字。这给出了一些改进的结果,但我怀疑随机性只有我能做到的那样好,来自对线程 ID 执行的数学运算,而不是有效地来自随机数生成器。
[numthreads(8, 8, 1)]
void CSMain(uint3 id)
{
//first thing I tried
//RandomResult rand = HybridTaus(seed);
//seed = rand.state; // re-assign seed with the new state
//result[id.xy] = rand.value;
//second thing I tried
RandResult rand = HybridTaus(seed * uint4(id.x*id.y*id.x*id.y,
id.x*id.y/id.x*id.y,
id.x*id.y+id.x*id.y,
id.x*id.y-id.x*id.y));
result[id.xy] = rand.value;
}
【问题讨论】:
标签: random gpu compute-shader