在CPU上执行的数学在GPU上有不同的结果

时间:2014-11-03 05:07:38

标签: opengl glsl

我试图让GLSL片段着色器根据纹理坐标将传入的片段扭曲为poorly simulate a CRT

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值除以x而不是y。这已经修复了new output is the same,因为分母值非常接近。

2 个答案:

答案 0 :(得分: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版本。

答案 1 :(得分:0)

使用的公式仅支持从0到1的UV值。如果使用该范围之外的值,则公式会崩溃。