2011-09-30 63 views
11

我已經在HLSL的stackoverflow線程How to implement this rotating spiral in WebGL?中實現了螺旋GLSL着色器,但結果並不相同,我認爲這是因爲GLSL中的mod函數已轉換爲fmod在HLSL。我嘗試通過自定義調用函數來取代對mod的調用,該函數執行GSLS文檔(http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml)中描述的功能並且它可以工作:Glsl mod vs Hlsl fmod

mod返回x模y的值。這被計算爲x-y * floor(x/y)。

根據MSDN文檔http://msdn.microsoft.com/en-us/library/windows/desktop/bb509601(v=vs.85).aspx fmod函數,表示如下:

浮點餘被計算,使得X = I * Y + f,其中i是整數,f有相同的符號x,並且f的絕對值小於y的絕對值。

我已經使用了HLSL到GLSL轉換器託管在http://sourceforge.net/projects/hlsl2glsl和fmod函數被翻譯爲mod,但我不知道我是否可以假設mod轉換爲fmod。

我的問題是,這兩個函數之間有什麼區別,以及如何將fmod的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(); 
    } 
} 

我已經沒有問題,如果不是fmod,我稱之爲以下功能(根據GLSL mod的定義)

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

我想你可以在HLSL中使用%作爲mod。 – Robinson

+0

是的,我試過,但%給出完全相同的問題。螺旋不正確代表。它的1/4被剪切 –

+0

看到兩個着色器都可以幫助我們比較它們。 – kvark

回答

13

正如你所指出的,它們是不同的。 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是負數時它們是不同的。

+0

謝謝你正是這樣。謝謝 –