Глсл мод против Хлсл фмод
Я реализовал спиральный шейдер GLSL, описанный в этом вопросе, в HLSL, но результаты не совпадают. Я думаю, что это из-за mod
функция в GLSL, что я перевел на fmod
в HLSL. Я подозреваю, что эта проблема возникает только тогда, когда у нас есть отрицательные числа на входе 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
является целым числом,f
имеет тот же знак, что иx
и абсолютное значениеf
меньше абсолютного значенияy
,
Я использовал преобразователь HLSL в GLSL, и fmod
функция переводится как mod
, Тем не менее, я не знаю, могу ли я предположить, что mod
переводит на fmod
,
Вопросы
- Каковы различия между GLSL
mod
и HLSLfmod
? - Как я могу перевести загадочное описание MSDN
fmod
к реализации псевдокода?
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();
}
}
1 ответ
Как вы заметили, они разные. 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
отрицательно.