0

C で OpenGL を使用してスカイボックスを作成しようとしています。多くのチュートリアルを表示し、多くの人のコードを調べましたが、何も見逃していないとは思いませんが、黒い画面が表示されます。私はすべて間違っていましたか?

#include <windows.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdio.h>
#include <math.h>

GLuint texture[6];

/**
 * Init function initializing the background to black.
 */
void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();   
    glMatrixMode(GL_MODELVIEW | GL_PROJECTION);
    glEnable(GL_DEPTH_TEST);    
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
   glMatrixMode(GL_MODELVIEW);
}

GLuint LoadTexture(const char * filename, int width, int height)
{
    GLuint texture;
    unsigned char * data;
    FILE * file;

    //Open the image file
    file = fopen(filename, "rb");
    //If it doesn't open just return 0
    if(file == NULL)
    {
        return 0;
    }

    //Allocate space for data and read
    data = (unsigned char *)malloc(width * height * 3);
    fread(data, width * height * 3, 1, file);

    //Close the file
    fclose(file);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );    
    free(data);

    return texture;     
}

void draw()
{
    int width = 512;
    int height = 512;
    int length = 512;

    //start in this coordinates
    int x = 0;
    int y = 0;
    int z = 0;

    //center the square
    x = x - width / 2;
    y = y - height / 2;
    z = z - length / 2;

    // Bind the BACK texture of the sky map to the BACK side of the cube
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glBegin(GL_QUADS);      
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,  z);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, z);
    glEnd();

    //FRONT
    glBindTexture(GL_TEXTURE_2D, texture[1]);
    glBegin(GL_QUADS);  
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z + length);
    glEnd();

    //BOTTOM
    glBindTexture(GL_TEXTURE_2D, texture[4]);
    glBegin(GL_QUADS);      
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y,  z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y,  z + length); 
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z);
    glEnd();

    //TOP
    glBindTexture(GL_TEXTURE_2D, texture[5]);
    glBegin(GL_QUADS);      
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
    glEnd();

    //LEFT
    glBindTexture(GL_TEXTURE_2D, texture[2]);
    glBegin(GL_QUADS);      
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length); 
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,  z + length);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z);     

    glEnd();

    //RIGHT
    glBindTexture(GL_TEXTURE_2D, texture[3]);
    glBegin(GL_QUADS);  
        glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,  z + length);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
        glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
    glEnd();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    texture[0] = LoadTexture("back.bmp", 512, 512);
    /*texture[0] = SOIL_load_OGl_texture
    {
        "back.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_INVERT_Y
    };*/
    texture[1] = LoadTexture("front.bmp", 512, 512);
    texture[2] = LoadTexture("left.bmp", 512, 512);
    texture[3] = LoadTexture("right.bmp", 512, 512);
    texture[4] = LoadTexture("cesped.bmp", 512, 512);
    texture[5] = LoadTexture("top.bmp", 512, 512);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);

    draw();
    glutSwapBuffers();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA);
    glutInitWindowSize(1000, 1000);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("blah");

    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMainLoop();

    return 0;
}
4

2 に答える 2

1

問題は、スカイボックスが可視領域内にないことです。射影行列 の定義をglFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);見ると、z 軸に沿った可視値は 1.5 から 20.0 の間でなければならないことがわかります。しかし、スカイボックスは -256.0 から 256.0 まで描画されます。これはファー プレーン/ニア プレーンの背後にあり、切り取られます。

これには 2 つの解決策があります。1 つは、より小さなスカイボックスを描画するか、可視領域を増やすことです。一般に、結果は両方の場合で同じになります (少なくとも、最初のオブジェクトとして深度テストを行わずにスカイボックスをレンダリングする場合、通常はそうします)。

コメントによると: ピクセル単位のテクスチャのサイズとジオメトリのサイズの間に関係はありません。したがって、一辺の長さが 512 の立方体を描く必要はありません。

于 2015-01-28T10:25:42.640 に答える
0

いくつかのことがおかしいようです:

  • glClear は GL_DEPTH_BUFFER_BIT なしで呼び出されますが、深度テストは有効になっています
  • gluLookAt は、目の位置と関心点の両方に (0,0,0) を使用します。モデルビュー マトリックスは見栄えがよくありません。位置にはボックスの中心を使用し、ターゲットには何でも使用する必要があります。
  • 表示機能が画像をリロードし、フレームごとにテクスチャを再作成しています! これは、init() 関数で、起動時に一度だけ実行する必要があります。
  • テクスチャ座標を提供し いる ため、GL_TEXTURE_GEN_S または GL_TEXTURE_GEN_T を有効にする必要はありません。
  • @BDL の発言: ボックスのサイズ (512.0) を考慮すると、ファー クリッピング プレーンが近すぎます (20.0)。
于 2015-01-28T14:32:44.230 に答える