Проблемы с отображением текстур OpenGL ES 1.1 - PullRequest
1 голос
/ 08 ноября 2011

Я работаю над простой маленькой игрой для iPhone, и я хотел бы использовать текстуры, однако я не могу заставить ее работать ...

После некоторых исследований я нашел эту страницу и этот сайт . Оба являются отличными ссылками и научили меня немного о текстурах, однако после загрузки текстуры с использованием любой функции я не могу отобразить текстуру, вот как выглядит мой код:

Очень простая функция отображения текстуры (не работает)

void drawTexture(GLuint texture, float x, float y, float w, float h)
{
   glBindTexture(GL_TEXTURE_2D,texture);

   GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
   GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};

   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);

   glVertexPointer(2, GL_FLOAT, 0,box);
   glTexCoordPointer(2, GL_FLOAT, 0, tex);

   glDrawArrays(GL_TRIANGLE_STRIP,0,4);

   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

Обычно я бы не создавал массив каждый кадр только для отображения изображения, но это всего лишь пример. Когда я запускаю эту функцию, я ничего не получаю. Пусто - нет изображения, ничего (если, конечно, я ранее не включил массив цветов и не отключил его впоследствии)

Вторая простая функция отображения (в ней используется быстрый маленький класс)

void draw_rect(RectObject* robj){
    glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
    glEnableClientState(GL_VERTEX_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
    glEnableClientState(GL_COLOR_ARRAY);

    if ([robj texture] != -1){
        glEnable(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_TEXTURE_2D);
        glClientActiveTexture([robj texture]);

        glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
        glBindTexture(GL_TEXTURE_2D, [robj texture]);
    }

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_TEXTURE_COORD_ARRAY);
}

С другой стороны, эта функция изменяет отображение вместо вывода текстуры, однако выводит черный квадрат ...

Настройка фона

В моей функции инициализации я звоню

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);

Две длинные функции загрузки текстур

struct Texture2D LoadImage(NSString* path)
{
    struct Texture2D tex;
    tex.texture = -1;

    // Id for texture 
    GLuint texture;
    // Generate textures
    glGenTextures(1, &texture);
    // Bind it
    glBindTexture(GL_TEXTURE_2D, texture);
    // Set a few parameters to handle drawing the image
    // at lower and higher sizes than original
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

    //NSString *path = [[NSString alloc] initWithUTF8String:imagefile.c_str()];
    path = [[NSBundle mainBundle] pathForResource:path ofType:@""];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:texData];
    if (image == nil)
        return tex;
    // Get Image size
    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    // Allocate memory for image
    void *imageData = malloc( height * width * 4 );
    CGContextRef imgcontext = CGBitmapContextCreate(
                                                imageData, width, height, 8, 4 * width, colorSpace,
                                                kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
    CGColorSpaceRelease( colorSpace );
    CGContextClearRect( imgcontext,
                   CGRectMake( 0, 0, width, height ) );
    CGContextTranslateCTM( imgcontext, 0, height - height );
    CGContextDrawImage( imgcontext,
                   CGRectMake( 0, 0, width, height ), image.CGImage );

    // Generate texture in opengl
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
             0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
    // Release context
    CGContextRelease(imgcontext);
    // Free Stuff
    free(imageData);
    [image release];
    [texData release];

    // Create and return texture

    tex.texture=texture;
    tex.width=width;
    tex.height=height;
    return tex;
}



GLuint makeTexture(NSString* path){
    GLuint texture[1]={-1};
    glGenTextures(1, texture);
    glBindTexture(GL_TEXTURE_2D, texture[0]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);



    path = [[NSBundle mainBundle] pathForResource:path ofType:@"png"];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:texData];
    if (image == nil)
        NSLog(@"Do real error checking here");

    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    void *imageData = malloc( height * width * 4 );
    CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
    CGColorSpaceRelease( colorSpace );
    CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
    CGContextTranslateCTM( context, 0, height - height );
    CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    CGContextRelease(context);

    free(imageData);
    [image release];
    [texData release];

    return texture[0];
}

Если бы вы указали мне правильное направление, это было бы очень признательно.

Ответы [ 3 ]

4 голосов
/ 08 ноября 2011

Прежде всего, ваша функция draw_rect имеет ошибку.Не звоните glClientActiveTexture, он используется для мультитекстурирования, и он вам не нужен.Вызов его с помощью текстурного объекта либо свяжет какой-то действительно странный текстурный блок, либо, скорее всего, приведет к ошибке.

А в функции drawTexture вы фактически рисуете треугольники по часовой стрелке.Предполагая, что вы не перевернули направление y в матрице проекции или что-то в этом роде, если у вас включен выбор задней поверхности, вся ваша геометрия будет отброшена.Попробуйте позвонить glDisable(GL_CULL_FACE), хотя выборка на задней панели должна быть отключена по умолчанию.Или, что еще лучше, измените порядок вершин против часовой стрелки:

box[] = { x,y+h, x,y, x+w,y+h, x+w,y };

У вас также есть несоответствие координат текстуры вершинам в вашей функции drawTexture, но это не должно приводить к тому, что текстура не будетнарисовано, а точнее просто выглядит немного странно.Учитывая изменения в порядке против часовой стрелки из последнего абзаца, координаты текстуры должны быть:

tex[] = { 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f };

РЕДАКТИРОВАТЬ: Ваша функция draw_rect также портит состояние, потому что вывключите вершины и цветовые массивы, но не отключайте их снова, когда закончите рендеринг.Когда вы теперь хотите нарисовать что-то другое без цветового массива (как в drawTexture), цветовой массив все еще включен и использует некоторые произвольные данные.Поэтому вы должны добавить

glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

сразу после

glDisableClientState(GL_TEXTURE_COORD_ARRAY);

в draw_rect.

РЕДАКТИРОВАТЬ: И вы также должны обернуть drawTextureфункция в паре glEnable(GL_TEXTURE_2D) и glDisable(GL_TEXTURE_2D).Вы включаете текстурирование в коде инициализации, что неправильно.Вы должны установить все необходимые состояния непосредственно перед рендерингом, особенно такое сильно зависящее от объекта состояние, как текстурирование.Например, когда вы вызываете draw_rect до drawTexture, вы в конечном итоге отключаете текстурирование, хотя вы включили его в код инициализации и думали, что оно всегда включено.Вы видите, что это не очень хорошая идея?

РЕДАКТИРОВАТЬ: Я только что заметил еще одну ошибку.В draw_rect вы звоните glEnable и glDisable с GL_TEXTURE_COORD_ARRAY, что неправильно.Вы должны использовать glEnableClientState и glDisableClientState для включения / отключения массивов вершин, как вы делали int drawTexture.

Так что в качестве небольшого промежуточного вывода ваши функции должны выглядеть примерно так:

void drawTexture(GLuint texture, float x, float y, float w, float h)
{
    glBindTexture(GL_TEXTURE_2D,texture);
    glEnable(GL_TEXTURE_2D);

    GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
    GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};

    glTexCoordPointer(2, GL_FLOAT, 0, tex);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, box);
    glEnableClientState(GL_VERTEX_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP,0,4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glDisable(GL_TEXTURE_2D);
}

void draw_rect(RectObject* robj)
{
    if ([robj texture] != -1)
    {
        glBindTexture(GL_TEXTURE_2D, [robj texture]);
        glEnable(GL_TEXTURE_2D);

        glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    }

    glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
    glEnableClientState(GL_VERTEX_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    if ([robj texture] != -1)
    {
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisable(GL_TEXTURE_2D);
    }
}
1 голос
/ 09 ноября 2011

Если одна из текстур работает, а другая нет, может ли это быть проблемой с файлом текстур?Размеры иногда могут вас обмануть, попробуйте использовать один и тот же файл (тот, который работает) на обеих текстурах и посмотрите, решено ли это.Если это так, то это проблема с файлом текстуры.

0 голосов
/ 18 января 2016

Веселье работает.

void drawTexture(GLuint texture, float x, float y, float w, float h)
{
    glBindTexture(GL_TEXTURE_2D,texture);
    glEnable(GL_TEXTURE_2D);

    GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
    GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};

    glTexCoordPointer(2, GL_FLOAT, 0, tex);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, box);
    glEnableClientState(GL_VERTEX_ARRAY);

    glDrawArrays(GL_TRIANGLE_STRIP,0,4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glDisable(GL_TEXTURE_2D);
}

, но мы должны относиться к правильной координате для текстуры.wo должен изменить код

форма

GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};

на

GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = { 0.0f,1.0f,  1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f };

Спасибо stackoverflow.Спасибо за вашу помощь.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...