开发者

Glsl mod vs Hlsl fmod

开发者 https://www.devze.com 2023-04-09 07:41 出处:网络
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

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_Ve开发者_开发知识库rtexShaderFunction(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();
    }
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号