GLSL中的mod和HLSL中的fmod区别

17
我已经在HLSL中实现了这个问题中描述的螺旋GLSL着色器,但结果并不相同。我认为这是因为我在HLSL中翻译了GLSL中的mod函数成为fmod函数所导致的。我怀疑这个问题只会在fmod函数的输入中有负数时才会出现。
我已经尝试用我自己制作的函数替换mod函数的调用,它实现了GLSL文档中描述的功能,并且能够正常工作:

mod返回x模除y的值。这可以计算为x - y * floor(x/y)

我使用的代替fmod的可工作代码如下:
float mod(float x, float y)
{
  return x - y * floor(x/y)
}

与GLSL的mod函数相比,MSDN说HLSL的fmod函数会这样做:
浮点余数计算如下:x = i * y + f,其中i是整数,fx具有相同的符号,并且f的绝对值小于y的绝对值。
我使用了一个HLSL到GLSL转换器,将fmod函数翻译为mod。但是,我不知道是否可以假设mod翻译成fmod

问题

  1. GLSL mod和HLSL fmod之间有什么区别?
  2. 如何将MSDN的晦涩描述转换为伪代码实现?

GLSL着色器

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着色器

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();
    }
}

我认为在HLSL中可以使用%作为取模运算符。 - Robinson
是的,我尝试过了,但是百分号仍然存在完全相同的问题。 螺旋形图案没有正确地呈现出来。 四分之一的图案被切断了。 - Ivo Leitão
能够看到两个着色器将非常有帮助,这样我们就可以进行比较。 - kvark
好的,你说得对。我会提供给他们。 - Ivo Leitão
1个回答

20

正如你所指出的,它们是不同的。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为负时它们是不同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接