简体   繁体   English

SDL 3d OpenGL:多维数据集上的纹理产生空白屏幕

[英]SDL 3d OpenGL: texture on cube produces blank screen

I have been trying to load a texture on to a cube using SDL_image and OpenGL. 我一直在尝试使用SDL_image和OpenGL将纹理加载到多维数据集。 For some reason, the entire window remains blank when I attempt to use textures. 由于某些原因,当我尝试使用纹理时,整个窗口保持空白。 By commenting out my texture initialisation call, the window renders as it should, except with a white texture. 通过注释掉我的纹理初始化调用,窗口将呈现应有的渲染效果,但白色纹理除外。 The same applies when my call to glEnable(GL_TEXTURE_2D) gets commented out. 当我对glEnable(GL_TEXTURE_2D)的调用被注释掉时,也是如此。 I have been trying for several hours now to fix this, and have spent most of those looking online for whether anyone has come up with a solution, but nothing I tried worked. 我已经尝试了几个小时来解决此问题,并且花了很多时间在网上寻找是否有人提出了解决方案,但是我没有尝试过。 I have posted only sections of my code below, if more is required, please let me know. 我仅在下面发布了我的代码的各个部分,如果需要更多内容,请告诉我。

OpenGL initialisation (The order for glEnable(GL_TEXTURE_2D) may be incorrect): 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;
}

Here my loadTexture function (errorCode remains 0 through the entire function, and nothing is printed to stderr): 这是我的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;
}

Finally, my actual render code. 最后,我的实际渲染代码。 Note that the return value for the loadTexture function is copied into all elements of the texture array (right, left, top, bottom, front, back (enums)). 请注意,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();
}

And here the render function, along with some other drawing-related functions. 这里是render函数,以及其他一些与绘图相关的函数。 Note that initDisplayLists() is called in initialisation. 请注意,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;
}

You should probably beef up your error checking a bit (you're not doing it very often). 您可能应该加强您的错误检查(您不经常这样做)。

For one thing, it's illegal to call glBindTexture in a glBegin/glEnd block (it needs to go before glBegin). 一方面,在glBegin/glEnd块中调用glBindTexture是非法的(它必须在glBegin之前)。 Fix these illegal calls, add some extra error checking in your render loop, and see if that solves your problem. 修复这些非法调用,在渲染循环中添加一些额外的错误检查,看看是否能解决您的问题。

Also, don't do this: while(glGetError()); 另外,不要这样做: while(glGetError());

If you have errors you should be throwing exceptions or logging them at the very least, it's not very smart to just throw away any outstanding OpenGL errors. 如果您有错误,则应该抛出异常或至少记录异常,仅丢弃所有未解决的OpenGL错误并不是很明智。 Generally they are trying to tell you something important. 通常,他们试图告诉您一些重要的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM