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 ofx
moduloy
. This is computed asx - 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
, wherei
is an integer,f
has the same sign asx
, and the absolute value off
is less than the absolute value ofy
.
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
.
mod
and HLSLfmod
? fmod
to a pseudo-code implementation?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 );
}
}
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();
}
}
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With