0

我正在尝试使用 OpenGL 的立方体映射,但由于某种原因,y 图像被反转并且正在搞砸结果,并且正在执行的反射和折射无法正常工作。

这是我的代码。

void initCubeMap()
{
    GLbyte *pBytes;
    GLint eFormat, iComponents;
    GLint width, height;

    // Cull backs of polygons
    glCullFace(GL_BACK);
    glFrontFace(GL_CCW);
    glEnable(GL_CULL_FACE);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

    // Set up texture maps        
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    // Load Cube Map images
    for(int i=0; i<6; i++)
    {        
        // Load this texture map
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
        pBytes = utilities.loadTGA(cubeFaces[i], &width, &height, &iComponents, &eFormat);
        glTexImage2D(cube[i], 0, GL_RGB8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, pBytes);
        free(pBytes);
    }

    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);

    // Enable cube mapping, and set texture environment to decal
    glEnable(GL_TEXTURE_CUBE_MAP);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}

void renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
        camera.RenderCam();
        camera.MoveCamMouse();

        // Sky Box is manually textured
        glDisable(GL_TEXTURE_GEN_S);
        glDisable(GL_TEXTURE_GEN_T);
        glDisable(GL_TEXTURE_GEN_R); 

        drawSkyBox();

        // Use texgen to apply cube map
        glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);
        glEnable(GL_TEXTURE_GEN_R);

        glPushMatrix();
            glMatrixMode(GL_TEXTURE);
            glPushMatrix();
                GLfloat m[16];
                glGetFloatv(GL_MODELVIEW_MATRIX, m);
                camera.getCameraInverse(m);
                glMultMatrixf(m);
                glUseProgram(glassProgram);
                utilities.setUniform("Cubemap", 0);
                glutSolidSphere(5.0, 100, 100);
                glUseProgram(0);
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    glPopMatrix();

    // FPS
    frame++;

    time = glutGet(GLUT_ELAPSED_TIME);
    if (time - timebase > 1000) 
    {
        sprintf(s,"Template | FPS: %4.2f",frame*1000.0/(time-timebase));
        timebase = time;
        frame = 0;
    }

    glutSetWindowTitle((const char*)&s);

    // Swap double buffer for flicker-free animation
    glutSwapBuffers();
}

void Camera::getCameraInverse(GLfloat *result)
{
    GLfloat resultTemp[16];
    float tmp[12];                                              //temporary pair storage
    float det;                                                  //determinant

    //calculate pairs for first 8 elements (cofactors)
    tmp[0] = result[10] * result[15];
    tmp[1] = result[11] * result[14];
    tmp[2] = result[9] * result[15];
    tmp[3] = result[11] * result[13];
    tmp[4] = result[9] * result[14];
    tmp[5] = result[10] * result[13];
    tmp[6] = result[8] * result[15];
    tmp[7] = result[11] * result[12];
    tmp[8] = result[8] * result[14];
    tmp[9] = result[10] * result[12];
    tmp[10] = result[8] * result[13];
    tmp[11] = result[9] * result[12];

    //calculate first 8 elements (cofactors)
    resultTemp[0] = tmp[0]*result[5] + tmp[3]*result[6] + tmp[4]*result[7] -    tmp[1]*result[5] - tmp[2]*result[6] - tmp[5]*result[7];

    resultTemp[1] = tmp[1]*result[4] + tmp[6]*result[6] + tmp[9]*result[7] -    tmp[0]*result[4] - tmp[7]*result[6] - tmp[8]*result[7];

    resultTemp[2] = tmp[2]*result[4] + tmp[7]*result[5] + tmp[10]*result[7] - tmp[3]*result[4] - tmp[6]*result[5] - tmp[11]*result[7];

    resultTemp[3] = tmp[5]*result[4] + tmp[8]*result[5] + tmp[11]*result[6] - tmp[4]*result[4] - tmp[9]*result[5] - tmp[10]*result[6];

    resultTemp[4] = tmp[1]*result[1] + tmp[2]*result[2] + tmp[5]*result[3] -    tmp[0]*result[1] - tmp[3]*result[2] - tmp[4]*result[3];

    resultTemp[5] = tmp[0]*result[0] + tmp[7]*result[2] + tmp[8]*result[3] -    tmp[1]*result[0] - tmp[6]*result[2] - tmp[9]*result[3];

    resultTemp[6] = tmp[3]*result[0] + tmp[6]*result[1] + tmp[11]*result[3] - tmp[2]*result[0] - tmp[7]*result[1] - tmp[10]*result[3];

    resultTemp[7] = tmp[4]*result[0] + tmp[9]*result[1] + tmp[10]*result[2] - tmp[5]*result[0] - tmp[8]*result[1] - tmp[11]*result[2];

    //calculate pairs for second 8 elements (cofactors)
    tmp[0] = result[2]*result[7];
    tmp[1] = result[3]*result[6];
    tmp[2] = result[1]*result[7];
    tmp[3] = result[3]*result[5];
    tmp[4] = result[1]*result[6];
    tmp[5] = result[2]*result[5];
    tmp[6] = result[0]*result[7];
    tmp[7] = result[3]*result[4];
    tmp[8] = result[0]*result[6];
    tmp[9] = result[2]*result[4];
    tmp[10] = result[0]*result[5];
    tmp[11] = result[1]*result[4];

    //calculate second 8 elements (cofactors)
    resultTemp[8] = tmp[0]*result[13] + tmp[3]*result[14] + tmp[4]*result[15] - tmp[1]*result[13] - tmp[2]*result[14] - tmp[5]*result[15];

    resultTemp[9] = tmp[1]*result[12] + tmp[6]*result[14] + tmp[9]*result[15] - tmp[0]*result[12] - tmp[7]*result[14] - tmp[8]*result[15];

    resultTemp[10] = tmp[2]*result[12] + tmp[7]*result[13] + tmp[10]*result[15] - tmp[3]*result[12] - tmp[6]*result[13] - tmp[11]*result[15];

    resultTemp[11] = tmp[5]*result[12] + tmp[8]*result[13] + tmp[11]*result[14] - tmp[4]*result[12] - tmp[9]*result[13] - tmp[10]*result[14];

    resultTemp[12] = tmp[2]*result[10] + tmp[5]*result[11] + tmp[1]*result[9] - tmp[4]*result[11] - tmp[0]*result[9] - tmp[3]*result[10];

    resultTemp[13] = tmp[8]*result[11] + tmp[0]*result[8] + tmp[7]*result[10] - tmp[6]*result[10] - tmp[9]*result[11] - tmp[1]*result[8];

    resultTemp[14] = tmp[6]*result[9] + tmp[11]*result[11] + tmp[3]*result[8] - tmp[10]*result[11] - tmp[2]*result[8] - tmp[7]*result[9];

    resultTemp[15] = tmp[10]*result[10] + tmp[4]*result[8] + tmp[9]*result[9] - tmp[8]*result[9] - tmp[11]*result[10] - tmp[5]*result[8];

    // calculate determinant
    det = result[0]*resultTemp[0] + result[1]*resultTemp[1] + result[2]*resultTemp[2] + result[3]*resultTemp[3];

    resultTemp[0] = resultTemp[0]/det;
    resultTemp[1] = resultTemp[1]/det;
    resultTemp[2] = resultTemp[2]/det;
    resultTemp[3] = resultTemp[3]/det;
    resultTemp[4] = resultTemp[4]/det;
    resultTemp[5] = resultTemp[5]/det;
    resultTemp[6] = resultTemp[6]/det;
    resultTemp[7] = resultTemp[7]/det;
    resultTemp[8] = resultTemp[8]/det;
    resultTemp[9] = resultTemp[9]/det;
    resultTemp[10] = resultTemp[10]/det;
    resultTemp[11] = resultTemp[11]/det;
    resultTemp[12] = resultTemp[12]/det;
    resultTemp[13] = resultTemp[13]/det;
    resultTemp[14] = resultTemp[14]/det;
    resultTemp[15] = resultTemp[15]/det;

    if(det==0.0f)
    {
        result[0] = 1.0;
        result[1] = 0.0;
        result[2] = 0.0;
        result[3] = 0.0;
        result[4] = 0.0;
        result[5] = 1.0;
        result[6] = 0.0;
        result[7] = 0.0;
        result[8] = 0.0;
        result[9] = 0.0;
        result[10] = 1.0;
        result[11] = 0.0;
        result[12] = 0.0;
        result[13] = 0.0;
        result[14] = 0.0;
        result[15] = 1.0;
    }

    result[0] = resultTemp[0];
    result[1] = resultTemp[4];
    result[2] = resultTemp[8];
    result[3] = resultTemp[12];
    result[4] = resultTemp[1];
    result[5] = resultTemp[5];
    result[6] = resultTemp[9];
    result[7] = resultTemp[13];
    result[8] = resultTemp[2];
    result[9] = resultTemp[6];
    result[10] = resultTemp[10];
    result[11] = resultTemp[14];
    result[12] = resultTemp[3];
    result[13] = resultTemp[7];
    result[14] = resultTemp[11];
    result[15] = resultTemp[15];
}

这是我现在的 OpenGL 显示功能。它仍然无法正常工作。

void renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        camera.RenderCam();
        camera.MoveCamMouse();

        // Sky Box is manually textured
        glDisable(GL_TEXTURE_GEN_S);
        glDisable(GL_TEXTURE_GEN_T);
        glDisable(GL_TEXTURE_GEN_R); 

        drawSkyBox();

        // Use texgen to apply cube map
        glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);
        glEnable(GL_TEXTURE_GEN_R);

        glUseProgram(glassProgram);
        utilities.setUniform("Cubemap", 0);
        glPushMatrix();
            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            glScalef(-1, -1, -1);
            glPushMatrix();
                GLfloat m[16];
                glGetFloatv(GL_MODELVIEW_MATRIX, m);
                camera.getCameraInverse(m);
                glMultMatrixf(m);
                glutSolidSphere(5.0, 100, 100);
            glPopMatrix();
            glMatrixMode(GL_TEXTURE);
            glLoadIdentity();
            glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        glUseProgram(0);

    glPopMatrix();
    // FPS
    frame++;

    time = glutGet(GLUT_ELAPSED_TIME);
    if (time - timebase > 1000) 
    {
        sprintf(s,"Texture Mapping | FPS: %4.2f",frame*1000.0/(time-timebase));
        timebase = time;
        frame = 0;
    }

    glutSetWindowTitle((const char*)&s);

    // Swap double buffer for flicker-free animation
    glutSwapBuffers();
}

这是我执行反射和折射的 GLSL 代码。不确定这里是否有问题

// Vertex Shader

const float EtaR = 0.65;
const float EtaG = 0.67;         // Ratio of indices of refraction
const float EtaB = 0.69;
const float FresnelPower = 1.0;

const float F  = ((1.0-EtaG) * (1.0-EtaG)) / ((1.0+EtaG) * (1.0+EtaG));

varying vec3  Reflect;
varying vec3  RefractR;
varying vec3  RefractG;
varying vec3  RefractB;
varying float Ratio;

void main()
{
    vec4 ecPosition  = gl_ModelViewMatrix * gl_Vertex;
    vec3 ecPosition3 = ecPosition.xyz / ecPosition.w;

    vec3 i = normalize(ecPosition3);
    vec3 n = normalize(gl_NormalMatrix * gl_Normal);

    Ratio   = F + (1.0 - F) * pow((1.0 - dot(-i, n)), FresnelPower);

    RefractR = refract(i, n, EtaR);
    RefractR = vec3(gl_TextureMatrix[0] * vec4(RefractR, 1.0));
    RefractG = refract(i, n, EtaG);
    RefractG = vec3(gl_TextureMatrix[0] * vec4(RefractG, 1.0));

    RefractB = refract(i, n, EtaB);
    RefractB = vec3(gl_TextureMatrix[0] * vec4(RefractB, 1.0));

    Reflect  = reflect(i, n);
    Reflect  = vec3(gl_TextureMatrix[0] * vec4(Reflect, 1.0));

    gl_Position = ftransform();
}

// Fragment Shader

varying vec3  Reflect;
varying vec3  RefractR;
varying vec3  RefractG;
varying vec3  RefractB;
varying float Ratio;

uniform samplerCube Cubemap;

void main()
{
    vec3 refractColor, reflectColor;

    refractColor.r = vec3(textureCube(Cubemap, RefractR)).r;
    refractColor.g = vec3(textureCube(Cubemap, RefractG)).g;
    refractColor.b = vec3(textureCube(Cubemap, RefractB)).b;

    reflectColor   = vec3(textureCube(Cubemap, Reflect));

    vec3 color     = mix(refractColor, reflectColor, Ratio);

    gl_FragColor   = vec4(color, 1.0);
}
4

1 回答 1

3

但由于某种原因,y 图像被反转并搞砸了结果

是的,这是很多人遇到的一个相当普遍的问题。原因是 OpenGL 立方体贴图遵循 RenderMan 规范,其中扫描线排序与常规纹理相反。这种不一致是,嗯,不一致。从文件加载图像时,最好通过在加载图像时反转扫描线顺序来解决。在对立方体贴图纹理进行渲染时,应该翻转 Y 轴上的投影。

在您的情况下,一个简单的解决方法是将纹理矩阵在 y 中缩放 -1,即

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScale(1, -1, 1);

并通过交换 GL_TEXTURE_CUBE_MAP_POSITIVE_Y 和 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 图像。

于 2012-10-10T18:08:58.727 回答