Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Glsl mod vs Hlsl fmod

I've implemented the spiral GLSL shader described in this question in HLSL, but the results are not the same. I think it's because of the mod function in GLSL that I've translated to fmod in HLSL. I suspect that this problem only happens when we have negative numbers in the input of the fmod function.

I've tried replacing the call to mod by a call to a function that I've made which does what is described in the GLSL documentation and it works:

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

The working code I use instead of fmod is:

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

By contrast to GLSL mod, MSDN says the HLSL fmod function does this:

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.

I've used an HLSL to GLSL converter, and the fmod function is translated as mod. However, I don't know if I can assume that mod translates to fmod.

Questions

  1. What are the differences between GLSL mod and HLSLfmod?
  2. How can I translate MSDN's cryptic description of fmod to a pseudo-code implementation?

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 Shader

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();
    }
}
like image 749
Ivo Leitão Avatar asked Sep 30 '11 12:09

Ivo Leitão


People also ask

What is the difference between HLSL and GLSL?

In GLSL, you apply modifiers (qualifiers) to a global shader variable declaration to give that variable a specific behavior in your shaders. In HLSL, you don't need these modifiers because you define the flow of the shader with the arguments that you pass to your shader and that you return from your shader.

Is Hlsl similar to GLSL?

in HLSL attributes are arguments in the shader functions, in GLSL, they're keywords denoted by attribute and varying. in GLSL output variables are denoted with a gl_ prefix, in HLSL they're explicitly denoted with a out keyword. (GLSL has the out keyword as well, and allows for custom output variable names.

What is mod in GLSL?

The function mod(x,y) computes the modulus, or remainder, when x is divided by y. The return value is computed as x − y*floor(x/y). As with min and max, y can be either a vector or a float. The mod function can be used as a substitute for the % operator, which is not supported in GLSL ES 1.00.


Video Answer


1 Answers

As you've noted, they're different. The GLSL mod will always have the same sign as y rather than x. Otherwise it's the same -- a value f such that x = i*y + f where i is an integer and |f| < |y|. If you're trying to make a repeating pattern of some kind, the GLSL mod is generally what you want.

For comparison, the HLSL fmod is equivalent to x - y * trunc(x/y). They're the same when x/y is positive, different when x/y is negative.

like image 172
Chris Dodd Avatar answered Oct 09 '22 10:10

Chris Dodd