2

SDL_image と OpenGL を使用してキューブにテクスチャをロードしようとしています。テクスチャを使用しようとすると、何らかの理由でウィンドウ全体が空白のままになります。テクスチャの初期化呼び出しをコメント アウトすることで、白いテクスチャを除いて、ウィンドウは正常にレンダリングされます。glEnable(GL_TEXTURE_2D) への呼び出しがコメントアウトされた場合も同様です。私はこれを修正するために数時間試行しており、オンラインで誰かが解決策を思いついたかどうかを探すのにほとんどの時間を費やしましたが、私が試したものは何もうまくいきませんでした. 以下にコードのセクションのみを投稿しました。さらに必要な場合はお知らせください。

OpenGL の初期化 (glEnable(GL_TEXTURE_2D) の順序が間違っている可能性があります):

//Configures OpenGL for 3d rendering
//Needs to know the window height and width
void setUpOpenGL(int width, int height)
{
//Enable depth testing, necessary for 3d worlds
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

//Set the background colour to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//Set the clear depth at 1m?
glClearDepth(1.0f);

//Configure the viewport, giving height and width
glViewport(0, 0, width, height);

//Clear the colour buffer
glClear(GL_COLOR_BUFFER_BIT);

//Initiate OpenGL for projection drawing
glMatrixMode(GL_PROJECTION);
//Load identity, purpose still unknown
glLoadIdentity();

//Initiate viewport as perspective, give the field of view, aspect ratio (width/height), minimum distance and maximum distance
gluPerspective(45.0f, (float)width / (float)height, 0.01f, 500.0f);

//Initiate OpenGL for model drawing, preparation for frame rendering
glMatrixMode(GL_MODELVIEW);
//Load identity again (identity matrix?)
glLoadIdentity();

//Set the shading model to smooth.  Other options feasable, but don't look as good
glShadeModel(GL_SMOOTH);
//For whatever reason, we need to state how to calculate depth.  Grouped under "Alpha Function"
glDepthFunc(GL_LEQUAL);

//Calculate perspective as "nicest"; "don't care" and "fastest" are other options
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//Finished configuring OpenGL
return;
}

ここで私の loadTexture 関数 (errorCode は関数全体で 0 のままで、stderr には何も出力されません):

//Function to load textures from file.  Needs to know the filename / relative location.
//Load textures from file
int loadTexture(char *filename)
{
GLuint returnValue = -1;
SDL_Surface *image;
void *raw;
int width, height, bpp;
Uint8 *srcPixel, *dstPixel;
Uint32 truePixel;
GLenum errorCode;

image = IMG_Load(filename);

if(!image)
{
    fprintf(stderr, "Warning: Error loading image %s: %s\n", filename, IMG_GetError());
    return -2;
}

if(image->format->BytesPerPixel < 2)
{
    fprintf(stderr, "Warning: %s is a bad image, not true colour\n", filename);
    return -3;
}

width = image->w;
height = image->h;

raw = (void *)malloc(width * height * 4);
dstPixel = (Uint8 *)raw;

SDL_LockSurface(image);

bpp = image->format->BytesPerPixel;

for(int i = height - 1; i >= 0; i--)
{
    for(int j = 0; j < width; j++)
    {
        srcPixel = (Uint8 *)image->pixels + i * image->pitch + j * bpp;

        switch(bpp)
        {
        case 1:
            truePixel = *srcPixel;
            break;
        case 2:
            truePixel = *(Uint16 *)srcPixel;
            break;
        case 3:
            if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
                truePixel = srcPixel[0] << 16 | srcPixel[1] << 8 | srcPixel[2];
            else
                truePixel = srcPixel[0] | srcPixel[1] << 8 | srcPixel[2] << 16;
            break;
        case 4:
            truePixel = *(Uint32 *)srcPixel;
            break;
        default:
            fprintf(stderr, "Warning: image BPP of %d in image %s unuseable\n", bpp, filename);
            SDL_UnlockSurface(image);
            SDL_FreeSurface(image);
            free(raw);
            return -4;
        }

        SDL_GetRGBA(truePixel, image->format, &(dstPixel[0]), &(dstPixel[1]), &(dstPixel[2]), &(dstPixel[3]));
        dstPixel++;
        dstPixel++;
        dstPixel++;
        dstPixel++;
    }
}

SDL_UnlockSurface(image);
SDL_FreeSurface(image);

while(glGetError());

glGenTextures(1, &returnValue);
glBindTexture(GL_TEXTURE_2D, returnValue);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (Uint8 *)raw);

errorCode = glGetError();
if(errorCode)
{
    if(errorCode == GL_OUT_OF_MEMORY)
        fprintf(stderr, "Warning: Texture memory full while binding texture from image %s\n", filename);
    else
        fprintf(stderr, "OpenGL error while creating texture: %d", (int)errorCode);

    glDeleteTextures(1, &returnValue);
    free(raw);
    return -5;
}

//gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (Uint8 *)raw);

errorCode = glGetError();
if(errorCode)
{
    if(errorCode == GL_OUT_OF_MEMORY)
        fprintf(stderr, "Warning: Texture memory full while building texture from image %s\n", filename);
    else
        fprintf(stderr, "OpenGL error while creating texture: %s", (int)errorCode);

    glDeleteTextures(1, &returnValue);
    free(raw);
    return -6;
}

return returnValue;
}

最後に、実際のレンダリング コードです。loadTexture 関数の戻り値は、テクスチャ配列のすべての要素 (右、左、上、下、前、後 (列挙型)) にコピーされることに注意してください。

void cube::render(void)
{
float xMinOffset, xMaxOffset, yMinOffset, yMaxOffset, zMinOffset, zMaxOffset;
//getoffset(xMinOffset, xMaxOffset, yMinOffset, yMaxOffset, zMinOffset, zMaxOffset);

xMinOffset = yMinOffset = zMinOffset = 0.0f;
xMaxOffset = yMaxOffset = zMaxOffset = 1.0f;

//Positive x, or right
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(1.0f, 0.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, texture[right]);

    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
}
glEnd();

//Negative x, or left
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(-1.0f, 0.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, texture[left]);

    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMinOffset, yMinOffset, zMinOffset);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
}
glEnd();

//Positive y, or top
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(0.0f, 1.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, texture[top]);

    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
}
glEnd();

//Negative y, or bottom
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(0.0f, -1.0f, 0.0f);
    glBindTexture(GL_TEXTURE_2D, texture[bottom]);

    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMinOffset, yMinOffset, zMinOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
}
glEnd();

//Positive z, or front
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(0.0f, 0.0f, 1.0f);
    glBindTexture(GL_TEXTURE_2D, texture[front]);

    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMinOffset, yMinOffset, zMaxOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMaxOffset);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMaxOffset);
}
glEnd();

//Negative z, or back
glBegin(GL_QUADS);
{
    glColor3f(1.0f, 1.0f, 1.0f);
    glNormal3f(0.0f, 0.0f, -1.0f);
    glBindTexture(GL_TEXTURE_2D, texture[back]);

    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(xMinOffset, yMinOffset, zMinOffset);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(xMinOffset, yMaxOffset, zMinOffset);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(xMaxOffset, yMaxOffset, zMinOffset);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(xMaxOffset, yMinOffset, zMinOffset);
}
glEnd();
}

ここでは render 関数とその他の描画関連の関数を示します。initDisplayLists() は初期化で呼び出されることに注意してください。

void redraw(void)
{
//Still has the data from the previous frame
//Clear the colour and depth buffers before rendering
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Load identity, purpose unknown
glLoadIdentity();

//Draw horizontal crosshair
glBegin(GL_LINES);
{
    //White colour
    glColor3f(1.0f, 1.0f, 1.0f);
    //x, y, z
    //Vertex2f would be ideal, but doesn't appear (min view distance for perspective?)
    glVertex3f(-0.0001f, 0.0f, -0.01f);
    glVertex3f(0.0001f, 0.0f, -0.01f);
}
glEnd();
//Draw vertical crosshair
glBegin(GL_LINES);
{
    //Also white
    glColor3f(1.0f, 1.0f, 1.0f);
    //Again: x, y, z
    glVertex3f(0.0f, -0.0001f, -0.01f);
    glVertex3f(0.0f, 0.0001f, -0.01f);
}
glEnd();

//Rotate on the x axis (pitch)
glRotatef(se::pl0.rX, 1.0f, 0.0f, 0.0f);
//Rotate viewport on the y axis (yaw)
glRotatef(se::pl0.rY, 0.0f, 1.0f, 0.0f);
//Translate the world by the negative of our coordinates
//Camera one way = objects the other...
glTranslatef(-se::pl0.x, -se::pl0.y, -se::pl0.z);

glCallList(1);

//Show the screen we have been calculating, preparing the screen we were showing for drawing
SDL_GL_SwapBuffers();
return;
}

void initDisplayLists(void)
{
glGenLists(1);

cube block = cube();

glNewList(1, GL_COMPILE);
{
    block.render();
}
glEndList();

return;
}
4

1 に答える 1

0

おそらく、エラー チェックを少し強化する必要があります (頻繁に行うわけではありません)。

glBindTexture1 つには、ブロック内での呼び出しは違法glBegin/glEndです (glBegin の前に移動する必要があります)。これらの不正な呼び出しを修正し、レンダリング ループにエラー チェックを追加して、問題が解決するかどうかを確認してください。

また、これをしないでください: while(glGetError());

エラーが発生した場合は、少なくとも例外をスローするかログに記録する必要があります。未解決の OpenGL エラーを単に破棄するのは賢明ではありません。一般的に、彼らはあなたに何か重要なことを伝えようとしています。

于 2012-09-25T18:28:41.200 に答える