Zaimplementowałem spiralny shader GLSL opisany w wątku stackoverflow How to implement this rotating spiral in WebGL? w HLSL, ale wyniki nie są takie same i myślę, że jest to spowodowane funkcją mod w GLSL, którą przetłumaczyłem na fmod w HLSL. Próbowałem zastąpić wywołanie mod przez wywołanie niestandardowe do funkcji, którą zrobiłem, co robi to, co jest opisane w dokumentacji GSLS (http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml) i działa:Glsl mod vs Hlsl fmod
mod zwraca wartość x modulo y . Jest to obliczane jako x - y * floor (x/y).
Funkcja FMOD według dokumentacji msdn http://msdn.microsoft.com/en-us/library/windows/desktop/bb509601(v=vs.85).aspx mówi następujące:
pływający punkt pozostała część jest tak obliczona, że x = i * y + f, gdzie i jest liczbą całkowitą, f ma taki sam znak, jak x, a wartość bezwzględna f jest mniejsza niż bezwzględna wartość y.
Użyłem konwertera HLSL do GLSL hostowanego w http://sourceforge.net/projects/hlsl2glsl, a funkcja fmod jest tłumaczona jako mod, jednak nie wiem, czy mogę założyć, że mod tłumaczy na fmod.
Moje pytanie brzmi, jakie są różnice między tymi dwiema funkcjami i jak mogę przetłumaczyć tajemniczy opis fmod msdn na implementację pseudokodu.
Podejrzewam, że ten problem występuje tylko wtedy, gdy mamy liczb ujemnych na wejściu funkcji 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 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();
}
}
mam nie ma problemu, jeśli zamiast fmod wywołać następującą funkcję (zgodnie z definicją mod GLSL)
float mod(float x, float y)
{
return x - y * floor(x/y)
}
Myślę, że możesz użyć% dla mod w HLSL. – Robinson
Tak, próbowałem, ale% daje dokładnie ten sam problem. Spirala nie jest poprawnie przedstawiona. 1/4 tego jest wycinane –
Byłoby pomocne zobaczyć oba shadery, abyśmy mogli je porównać. – kvark