Я пытался загрузить текстуру в куб, используя 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;
}
Вам, вероятно, следует немного усилить проверку ошибок (вы делаете это не очень часто).
Во-первых, незаконно звонить glBindTexture
в glBegin/glEnd
блок (он должен идти до glBegin). Исправьте эти недопустимые вызовы, добавьте дополнительную проверку ошибок в цикле рендеринга и посмотрите, решит ли это вашу проблему.
Кроме того, не делайте этого: while(glGetError());
Если у вас есть ошибки, вы должны генерировать исключения или, по крайней мере, регистрировать их, не очень разумно просто отбрасывать все оставшиеся ошибки OpenGL. Обычно они пытаются сказать вам что-то важное.
Других решений пока нет …