数值条件永远不会为真?

Numerical condition never true?

概览

上周我在 HLSL 中创建了一个基于条件的像素着色器。目标是只为满足特定条件的像素着色。在我的例子中,条件是基于 "time",我说得比较笼统,因为它不是我们认为的传统时间。我在 3D space 中渲染一条线,这是一项微不足道的任务。但是,根据当前用户选择的时间,应该只显示一定百分比的行。

我创建了一个 Line class 并在我的表单中添加了一个 SliderControl 以允许用户控制当前时间点。这很容易完成,就像设置所有底层代码一样。


问题

在创建底层代码时,我在时间类型上犯了一个简单的错误。在当前时间的常量缓冲区中,我使用了 double;在我的 Vertex 结构(任意定义和输入,以及像素着色器输入)中,我使用了 float。这导致我的像素着色器中的条件始终导致 false。差异的原因是原始数据的类型是 double,但我最终选择 float 来匹配代码中的所有其他内容,而且使用 [=14= 存在某种问题] 输入 HLSL.


HLSL

代码非常简单:

cbuffer TimeBuffer : register(b4) {
    double CurrentTime;
}
struct VertexInput {
    float Time;
    //...
}
struct PixelInput {
    float Time;
    //...
}
float4 PSMain(PixelInput input) : SV_Target {
    float4 result = 0;
    if (input.Time < CurrentTime)
        result = input.Diffuse;

    return result;
}

问题

为什么永远不会呈现该行?

这里的问题是由于输入的 cbufferstruct 之间的类型差异造成的。只需使类型匹配:

cbuffer TimeBuffer : register(b4) {
    float CurrentTime;
}
struct VertexInput {
    float Time;
    //...
}
struct PixelInput {
    float Time;
    //...
}
float4 PSMain(PixelInput input) : SV_Target {
    float4 result = 0;
    if (input.Time < CurrentTime)
        result = input.Diffuse;

    return result;
}

只需将 result 的初始赋值更改为 float4(0, 1, 0, 0) 或其他一些纯色即可显示该行确实正在渲染,但条件永远不会评估为 true


可以找到一个很好的彻底回答为什么这是一个这样的问题 here。我最初不明白这是一个问题,因为我假设 doublefloat 可以像任何其他数字类型一样进行比较。但是我错了,正如上面链接的 post 所述:

The important factors under consideration with float or double numbers are:

Precision: The precision of a floating point number is how many digits it can represent without losing any information it contains.

Rounding: There is a non-obvious differences between binary and decimal (base 10) numbers. Consider the fraction 1/10. In decimal, this can be easily represented as 0.1, and 0.1 can be thought of as an easily representable number. However, in binary, 0.1 is represented by the infinite sequence: 0.00011001100110011….


然而,这似乎也与 intfloat 相关,而不是 doublefloat