2014-11-03 75 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