关于数学:Glsl Mod与Hlsl Fmod

Glsl mod vs Hlsl fmod

我已经在HLSL中实现了此问题中描述的螺旋GLSL着色器,但是结果并不相同。我认为这是因为我已将GLSL中的mod函数转换为HLSL中的fmod。我怀疑只有在fmod函数的输入中我们有负数时,才会出现此问题。

我尝试用对我所做的函数的调用替换对mod的调用,该函数执行GLSL文档中描述的功能,并且可以正常工作:

mod returns the value of x modulo y. This is computed as x - y * floor(x/y).

我使用的代替fmod的工作代码是:

1
2
3
4
float mod(float x, float y)
{
  return x - y * floor(x/y)
}

与GLSL mod相比,MSDN说HLSL fmod函数可以做到这一点:

The floating-point remainder is calculated such that x = i * y + f, where i is an integer, f has the same sign as x, and the absolute value of f is less than the absolute value of y.

我已经使用了HLSL到GLSL转换器,并且fmod函数被转换为mod。但是,我不知道是否可以假设mod转换为fmod

问题

  • GLSL mod和HLSL fmod有什么区别?
  • 如何将MSDN fmod的隐式描述转换为伪代码实现?
  • GLSL着色器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    uniform float time;
    uniform vec2 resolution;
    uniform vec2 aspect;

    void main( void ) {
      vec2 position = -aspect.xy + 2.0 * gl_FragCoord.xy / resolution.xy * aspect.xy;
      float angle = 0.0 ;
      float radius = length(position) ;
      if (position.x != 0.0 && position.y != 0.0){
        angle = degrees(atan(position.y,position.x)) ;
      }
      float amod = mod(angle+30.0*time-120.0*log(radius), 30.0) ;
      if (amod<15.0){
        gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
      } else{
        gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );                    
      }
    }

    HLSL着色器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    struct Psl_VertexShaderInput
    {
        float3 pos : POSITION;
    };

    struct Psl_VertexShaderOutput
    {
        float4 pos : POSITION;

    };

    struct Psl_PixelShaderOutput
    {
        float4 Output0 : COLOR0;
    };

    float3 psl_positionOffset;
    float2 psl_dimension;

    Psl_VertexShaderOutput Psl_VertexShaderFunction(Psl_VertexShaderInput psl_input)
    {
        Psl_VertexShaderOutput psl_output = (Psl_VertexShaderOutput)0;

        psl_output.pos = float4(psl_input.pos + psl_positionOffset, 1);


        return psl_output;
    }

    float time : TIME;
    float2 resolution : DIMENSION;


    Psl_PixelShaderOutput Psl_PixelShaderFunction(float2 pos : VPOS)
    {
        Psl_PixelShaderOutput psl_output = (Psl_PixelShaderOutput)0;

        float2 aspect = float2(resolution.x / resolution.y, 1.0);
        float2 position = -aspect.xy + 2.0 * pos.xy / resolution.xy * aspect.xy;
        float angle = 0.0;
        float radius = length(position);
        if (position.x != 0.0 && position.y != 0.0)
        {
            angle = degrees(atan2(position.y, position.x));
        }
        float amod = fmod((angle + 30.0 * time - 120.0 * log(radius)), 30.0);
        if (amod < 15.0)
        {
            psl_output.Output0 = float4(0.0, 0.0, 0.0, 1.0);
            return psl_output;
        }

        else
        {
            psl_output.Output0 = float4(1.0, 1.0, 1.0, 1.0);
            return psl_output;
        }

    }

    technique Default
    {
        pass P0
        {
            VertexShader = compile vs_3_0 Psl_VertexShaderFunction();
            PixelShader = compile ps_3_0 Psl_PixelShaderFunction();
        }
    }


    您已经注意到,它们是不同的。 GLSL mod将始终具有与y相同的符号,而不是与x相同。否则是相同的-值f,例如x = i*y + f,其中i是整数,而|f| < |y|。如果您要制作某种重复图案,则通常需要GLSL mod

    为了进行比较,HLSL fmod等效于x - y * trunc(x/y)。当x/y为正时,它们是相同的,当x/y为负时,它们是不同的。