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();
}

这里是渲染函数,以及其他一些与绘图相关的函数。请注意,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

你可能应该加强你的错误检查(你不经常这样做)。

一方面,调用块是非法glBindTextureglBegin/glEnd(它需要在 glBegin 之前进行)。修复这些非法调用,在渲染循环中添加一些额外的错误检查,看看是否能解决您的问题。

另外,不要这样做: while(glGetError());

如果您有错误,您至少应该抛出异常或记录它们,仅仅丢弃任何未解决的 OpenGL 错误并不是很聪明。一般来说,他们试图告诉你一些重要的事情。

于 2012-09-25T18:28:41.200 回答