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 に答える