Glsl mod vs Hlsl fmod

Я реализовал спиральный GLSL-шейдер, описанный в потоке stackoverflow Как реализовать эту вращающуюся спираль в WebGL? в HLSL, но результаты не совпадают и Я думаю, это из-за функции мод в GLSL, которую я перевел на fmod в HLSL. Я попытался заменить вызов мод специальным вызовом на функцию, которую я создал, которая выполняет то, что описано в документации GSLS (http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml), и он работает:

mod возвращает значение x по модулю y. Это вычисляется как x - y * floor (x/y).

Функция fmod согласно документации msdn http://msdn.microsoft.com/en-us/library/windows/desktop/bb509601(v=vs.85).aspx говорит следующее:

Остаток с плавающей запятой вычисляется так, что x = я * y + f, где я - целое число, f имеет тот же знак, что и x, а абсолютное значение f меньше, чем абсолютное значение y.

Я использовал конвертер HLSL в GLSL, размещенный в http://sourceforge.net/projects/hlsl2glsl, а функция fmod переводится как мода, однако я не знаю, t знаю, могу ли я предположить, что мода переводится в fmod.

Мой вопрос в том, каковы различия между этими двумя функциями и как я могу перевести шифрованное описание fmod в msdn на реализацию псевдокода.

Я подозреваю, что эта проблема возникает только тогда, когда у нас есть отрицательные числа во входе функции fmod

GLSL Shader:

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

У меня нет проблем, если вместо fmod я вызываю следующую функцию (по определению мода GLSL)

float mod(float x, float y)
{
  return x - y * floor(x/y)
}

Ответ 1

Как вы уже отметили, они разные. Модификация GLSL всегда будет иметь тот же знак, что и y, а не x. В противном случае это то же самое - значение f такое, что x = я * y + f, где я - целое число и | f | < | У |. Если вы пытаетесь сделать повторяющийся шаблон какого-то типа, то, как правило, вы хотите, чтобы мода GLSL была вам нужна.

Для сравнения, fmod HLSL эквивалентен x - y * trunc (x/y). Они одинаковы, когда x/y положителен, отличается, когда x/y отрицателен.