2014-11-03 74 views
0

我試圖讓GLSL片段着色器將基於它們的紋理座標的傳入片段扭曲到poorly simulate a CRT在GPU上執行的數學在GPU上有不同的結果

After the code failed to work,我將它移植到C++來修改紋理的RGB值。代碼worked as expected

這讓我相信我的GLSL代碼有些問題,儘管它是用C++鏡像的,並且完美地工作。

有什麼我不知道GLSL數學可能導致這種情況嗎?

C++代碼

const unsigned int RED = 0xFFFF0000; 
const unsigned int BLUE = 0xFF0000FF; 
const float X_MAX = 429.0f/448.0f; 
const float Y_MAX = 320.0f/336.0f; 
const float X_CORNER = 410.0f/448.0f; 
const float Y_CORNER = 306.0f/336.0f; 
const float X_COEF = (X_MAX-X_CORNER)/(Y_CORNER * Y_CORNER); 
const float Y_COEF = (Y_MAX-Y_CORNER)/(X_CORNER * X_CORNER); 
float FUNCX(float y) 
{ 
    return X_MAX-X_COEF*y*y; 
} 
float FUNCY(float x) 
{ 
    return Y_MAX-Y_COEF*x*x; 
} 

unsigned int get(glm::vec2 intex) 
{ 
    intex *= 2.0;  // Transform the texture rectangle from 0..1 
    intex.x -= 1.0;  //     to 
    intex.y -= 1.0;  //    -1 .. 1 
    glm::vec2 d = glm::vec2(0.0,0.0); 
    d.x = FUNCX(intex.y); // get the curve amount for X values based on Y input 
    d.y = FUNCY(intex.x); // get the curve amount for Y values based on X input 
    if (abs(intex.x/d.x) > 1.0) // if the X value is outside of the curve 
     return RED;    // draw RED for debugging 
    if (abs(intex.y/d.y) > 1.0) // if the Y value is outside of the curve 
     return BLUE;   // draw BLUE for debugging 
    glm::vec2 outtex = glm::vec2(0.0f,0.0f); 
    outtex.x = 1.0 + intex.x/d.x; // Now the -1 .. 1 values get shifted back 
    outtex.y = 1.0 + intex.y/d.y; //    to 
    outtex /= 2.0;    //    0 .. 1 
    return texture.get(512*outtex.x,512*outtex.y); 
} 

GLSL片段着色器

const vec4 RED = vec4(1.0,0.0,0.0,1.0); 
const vec4 BLUE = vec4(0.0,0.0,1.0,1.0); 
const float X_MAX = 429.0/448.0; 
const float Y_MAX = 320.0/336.0; 
const float X_CORNER = 410.0/448.0; 
const float Y_CORNER = 306.0/336.0; 
const float X_COEF = (X_MAX-X_CORNER)/(Y_CORNER * Y_CORNER); 
const float Y_COEF = (Y_MAX-Y_CORNER)/(X_CORNER * X_CORNER); 
float FUNCX(float y) 
{ 
    return X_MAX-X_COEF*y*y; 
} 
float FUNCY(float x) 
{ 
    return Y_MAX-Y_COEF*x*x; 
} 

vec4 get(vec2 intex) 
{ 
    intex *= 2.0;  // Transform the texture rectangle from 0..1 
    intex.x -= 1.0;  //     to 
    intex.y -= 1.0;  //    -1 .. 1 
    vec2 d = vec2(0.0,0.0); 
    d.x = FUNCX(intex.y); // get the curve amount for X values based on Y input 
    d.y = FUNCY(intex.x); // get the curve amount for Y values based on X input 
    if (abs(intex.x/d.x) > 1.0) // if the X value is outside of the curve 
     return RED;    // draw RED for debugging 
    if (abs(intex.y/d.y) > 1.0) // if the Y value is outside of the curve 
     return BLUE;   // draw BLUE for debugging 
    vec2 outtex = vec2(0.0,0.0); 
    outtex.x = 1.0 + intex.x/d.x; // Now the -1 .. 1 values get shifted back 
    outtex.y = 1.0 + intex.y/d.y; //    to 
    outtex /= 2.0;    //    0 .. 1 
    return texture2D(texture,outtex); 
} 

注:超級馬里奧世界的圖像僅用於測試目的。 注2:C++代碼中的512個值是所用紋理的大小。

編輯:GLSL代碼中存在一個輸入錯誤,其中y值除以y而不是y。這已被修復,並且new output is the same因爲分母值非常接近。

+0

我已經看到了不同Nvidia GPU之間浮點結果的差異(小舍入差異)。 – jozxyqk 2014-11-04 11:05:59

回答

0

該公式僅用於支持從0到1的UV值。如果使用該範圍之外的值,則公式將失效。

2

代碼是不一樣的。在C++代碼:

if (abs(intex.y/d.y) > 1.0) // if the Y value is outside of the curve 
    return BLUE;   // draw BLUE for debugging 

在GLSL代碼:

if (abs(intex.y/d.x) > 1.0) // if the Y value is outside of the curve 
    return BLUE;   // draw BLUE for debugging 

的C++版本由d.y劃分,通過d.x的GLSL版本。

+0

謝謝。我做了改變,結果與之前一樣,因爲數值幾乎相等。 – 2014-11-03 12:25:52