Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Текстуры в OpenGL  (Прочитано 3430 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Текстуры в OpenGL
« : 17 Июня 2015, 20:41:46 »
Итак, вопрос : как в OpenGL можно наложить текстуру на двухмерный прямоугольник без библиотеки <GL/glaux.h> так как она сделана чисто под винду?
« Последнее редактирование: 17 Июня 2015, 21:25:22 от Гриб_под_зонтом »
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн SkinnyJack

  • Любитель
  • *
  • Сообщений: 53
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #1 : 18 Июня 2015, 09:00:53 »
glaux используется, как я понимаю, для работы с разными форматами графических файлов, распаковывая их в rgb/rgba массивы(каждому пикселю изображения соответствуют три байта цвета, либо три байта цвета + один байт альфа канала соответственно). Для bmp такое не трудно написать самому, для других форматов можно поискать соответствующую библиотеку(libpng, например).
В остальном, всё как тут, там даже внизу есть примеры под glx/sdl.


Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #2 : 19 Июня 2015, 22:41:14 »
SkinnyJack,
Библиотеки искал, но ничего полезного не нашёл. Ссылку?
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #3 : 19 Июня 2015, 23:29:34 »
« Последнее редактирование: 19 Июня 2015, 23:55:49 от unimix »

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #4 : 20 Июня 2015, 15:40:13 »
unimix, При попытки загрузить такую текстуру:

Загружает такую:

А вообще способ походу реально работает, нужно только с мелочами разобраться
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #5 : 22 Июня 2015, 22:56:47 »
Помогите пожалуйста, очень интересна данная тема  :-[
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн Delit

  • Новичок
  • *
  • Сообщений: 18
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #6 : 23 Июня 2015, 18:05:07 »
Сначало попробуй стандартную текстуру (квадратную со стороной кратной степени двойки).
Судя по картинке где то перепутаны форматы пикселей. Без кода сказать что то конкретно трудно.
« Последнее редактирование: 23 Июня 2015, 18:47:16 от Delit »

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #7 : 23 Июня 2015, 21:11:19 »
unimix, При попытки загрузить такую текстуру:

Загружает такую:

А вообще способ походу реально работает, нужно только с мелочами разобраться
Тут скорее всего дело в самой текстуре. У меня ваша текстура загружается также как и у вас. Попробуйте вашим проектом загрузить эту текстуру:



Вот пример кода, которым я пытался загрузить текстуры:
#include <GL/gl.h>
 #include <GL/glu.h>
 #include <GL/freeglut.h>
 #include <png.h>
 #include <cstdio>
 #include <string>

 #define TEXTURE_LOAD_ERROR 0

 using namespace std;

 GLuint loadTexture(const string filename, int &width, int &height);

 static GLuint texture;

  /** loadTexture
  * loads a png file into an opengl texture object, using cstdio , libpng, and opengl.
  *
  * \param filename : the png file to be loaded
  * \param width : width of png, to be updated as a side effect of this function
  * \param height : height of png, to be updated as a side effect of this function
  *
  * \return GLuint : an opengl texture id.  Will be 0 if there is a major error,
  * should be validated by the client of this function.
  *
  */
 GLuint loadTexture(const string filename, int &width, int &height)
 {
   //header for testing if it is a png
   png_byte header[8];

   //open file as binary
   FILE *fp = fopen(filename.c_str(), "rb");
   if (!fp) {
     return TEXTURE_LOAD_ERROR;
   }

   //read the header
   fread(header, 1, 8, fp);

   //test if png
   int is_png = !png_sig_cmp(header, 0, 8);
   if (!is_png) {
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }

   //create png struct
   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
       NULL, NULL);
   if (!png_ptr) {
     fclose(fp);
     return (TEXTURE_LOAD_ERROR);
   }

   //create png info struct
   png_infop info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) {
     png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
     fclose(fp);
     return (TEXTURE_LOAD_ERROR);
   }

   //create png info struct
   png_infop end_info = png_create_info_struct(png_ptr);
   if (!end_info) {
     png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
     fclose(fp);
     return (TEXTURE_LOAD_ERROR);
   }

   //png error stuff, not sure libpng man suggests this.
   if (setjmp(png_jmpbuf(png_ptr))) {
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     fclose(fp);
     return (TEXTURE_LOAD_ERROR);
   }

   //init png reading
   png_init_io(png_ptr, fp);

   //let libpng know you already read the first 8 bytes
   png_set_sig_bytes(png_ptr, 8);

   // read all the info up to the image data
   png_read_info(png_ptr, info_ptr);

   //variables to pass to get info
   int bit_depth, color_type;
   png_uint_32 twidth, theight;

   // get info about png
   png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
       NULL, NULL, NULL);

   //update width and height based on png info
   width = twidth;
   height = theight;

   // Update the png info struct.
   png_read_update_info(png_ptr, info_ptr);

   // Row size in bytes.
   int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

   // Allocate the image_data as a big block, to be given to opengl
   png_byte *image_data = new png_byte[rowbytes * height];
   if (!image_data) {
     //clean up memory and close stuff
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }

   //row_pointers is for pointing to image_data for reading the png with libpng
   png_bytep *row_pointers = new png_bytep[height];
   if (!row_pointers) {
     //clean up memory and close stuff
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     delete[] image_data;
     fclose(fp);
     return TEXTURE_LOAD_ERROR;
   }
   // set the individual row_pointers to point at the correct offsets of image_data
   for (int i = 0; i < height; ++i)
     row_pointers[height - 1 - i] = image_data + i * rowbytes;

   //read the png into image_data through row_pointers
   png_read_image(png_ptr, row_pointers);

   //Now generate the OpenGL texture object
   GLuint texture;
   glGenTextures(1, &texture);
   glBindTexture(GL_TEXTURE_2D, texture);
   glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, width, height, 0,
       GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

   //clean up memory and close stuff
   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
   delete[] image_data;
   delete[] row_pointers;
   fclose(fp);

   return texture;
 }

 void render()
 {
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     /* fov, aspect, near, far */
     gluPerspective(60, 1, 1, 10);
     gluLookAt(0, 0, -2, /* eye */
               0, 0, 2, /* center */
               0, 1, 0); /* up */
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glEnable(GL_TEXTURE_2D);

         /* create a square on the XY
            note that OpenGL origin is at the lower left
            but texture origin is at upper left
            => it has to be mirrored
            (gasman knows why i have to mirror X as well) */
         glBegin(GL_QUADS);
         glNormal3f(0.0, 0.0, 1.0);
         glTexCoord2d(1, 1); glVertex3f(0.0, 0.0, 0.0);
         glTexCoord2d(1, 0); glVertex3f(0.0, 1.0, 0.0);
         glTexCoord2d(0, 0); glVertex3f(1.0, 1.0, 0.0);
         glTexCoord2d(0, 1); glVertex3f(1.0, 0.0, 0.0);
         glEnd();

         glDisable(GL_TEXTURE_2D);
     glPopAttrib();

     glFlush();

     glutSwapBuffers();
 }

 void init()
 {
     glClearColor(0.0, 0.0, 0.0, 0.0);
     glShadeModel(GL_SMOOTH);

     glEnable(GL_LIGHTING);
     glEnable(GL_LIGHT0);
     glEnable(GL_DEPTH_TEST);

     GLfloat light0_position[] = {2.0, 2.0, 2.0, 0.0};
     GLfloat light0_ambient[] = {1.0, 1.0, 1.0, 0.0};

     glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
     glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
     int width, height;

     texture = loadTexture("opengl.png", width, height);
 }

 #if STUFF_IS_MOVING
 void idle()
 {
     render();
     usleep((1 / 50.0) * 1000000);
 }
 #endif

 void resize(int w, int h)
 {
     glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 }

 void key(unsigned char key, int x, int y)
 {
     if (key == 'q') exit(0);
 }

 int main(int argc, char *argv[])
 {
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
     glutInitWindowSize(640, 480);
     glutCreateWindow("Texture demo - [q]uit");

     init();
     glutDisplayFunc(render);
     glutReshapeFunc(resize);
     #if STUFF_IS_MOVING
         glutIdleFunc(idle);
     #endif
     glutKeyboardFunc(key);

     glutMainLoop();

     return 0;
 }

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #8 : 24 Июня 2015, 17:10:14 »
qub,
Загружает нормально. А от чего это зависит?
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #9 : 24 Июня 2015, 20:30:49 »
qub,
Загружает нормально. А от чего это зависит?

Вот пример кода который загружает вашу текстуру, у меня он работает. Прошу проверить работает ли у вас.

#ifdef _WIN32
#include <GL/glut.h>
#else
#include <GL/freeglut.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <png.h>
#include <iostream>
#include <math.h>

GLubyte *textureImage;
float rotateX = 0;
float rotateY = 0;

int mouseX;
int mouseY;

int next_power_of_two(int n)
{
    double logbase2 = log((double) n) / log(2.0);
    return (int) (pow(2, ceil(logbase2)) + 0.5);
}

bool loadPngImage(char *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;

    if ((fp = fopen(name, "rb")) == NULL)
        return false;

    /* Create and initialize the png_struct
     * with the desired error handler
     * functions.  If you want to use the
     * default stderr and longjump method,
     * you can supply NULL for the last
     * three parameters.  We also supply the
     * the compiler header file version, so
     * that we know if the application
     * was compiled with a compatible version
     * of the library.  REQUIRED
     */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                     NULL, NULL, NULL);

    if (png_ptr == NULL) {
        fclose(fp);
        return false;
    }

    /* Allocate/initialize the memory
     * for image information.  REQUIRED. */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return false;
    }

    /* Set error handling if you are
     * using the setjmp/longjmp method
     * (this is the normal method of
     * doing things with libpng).
     * REQUIRED unless you  set up
     * your own error handlers in
     * the png_create_read_struct()
     * earlier.
     */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated
         * with the png_ptr and info_ptr */
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        /* If we get here, we had a
         * problem reading the file */
        return false;
    }

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);

    /* If we have already
     * read some of the signature */
    png_set_sig_bytes(png_ptr, sig_read);

    /*
     * If you have enough memory to read
     * in the entire image at once, and
     * you need to specify only
     * transforms that can be controlled
     * with one of the PNG_TRANSFORM_*
     * bits (this presently excludes
     * dithering, filling, setting
     * background, and doing gamma
     * adjustment), then you can read the
     * entire image (including pixels)
     * into the info structure with this
     * call
     *
     * PNG_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);

    png_uint_32 width, height;
    int bit_depth;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 &interlace_type, NULL, NULL);
    outWidth = width;
    outHeight = height;

    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        // note that png is ordered top to
        // bottom, but OpenGL expect it bottom to top
        // so the order or swapped
        memcpy(*outData+(row_bytes * (outHeight-1-i)), row_pointers[i], row_bytes);
    }

    /* Clean up after the read,
     * and free any memory allocated */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    /* Close the file */
    fclose(fp);

    /* That's it */
    return true;
}

void init(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    // The following two lines enable semi transparent
    glEnable(GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    int width, height;
    bool hasAlpha;
    char filename[] = "car.png";
    bool success = loadPngImage(filename, width, height, hasAlpha, &textureImage);
    if (!success) {
        std::cout << "Unable to load png file" << std::endl;
        return;
    }
    std::cout << "Image loaded " << width << " " << height << " alpha " << hasAlpha << std::endl;
    int texture_width = next_power_of_two(width);
    int texture_height = next_power_of_two(height);
    std::cout << "Image loaded " << texture_width << " " << texture_height << " alpha " << hasAlpha << std::endl;

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width,
                 height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                 textureImage);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_FLAT);

}

void display(void) {
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.6);
    glRotatef(rotateX, 0,1,0);
    glRotatef(rotateY, 1,0,0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(-2.0, -1.0, 0.0);
    glTexCoord2f(0.0, 1.0);
    glVertex3f(-2.0, 1.0, 0.0);
    glTexCoord2f(1.0, 1.0);
    glVertex3f(0.0, 1.0, 0.0);
    glTexCoord2f(1.0, 0.0);
    glVertex3f(0.0, -1.0, 0.0);

    glEnd();
    glutSwapBuffers();
}

void myReshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, 1.0 * (GLfloat) w / (GLfloat) h, 1.0, 30.0);
    glMatrixMode(GL_MODELVIEW);
}

void mousePassive(int x, int y){
    mouseX = x;
    mouseY = y;
}

void mouseMotion(int x, int y){
    const float SPEED = 2;

    rotateX += (mouseX-x)/SPEED;
    rotateY += (mouseY-y)/SPEED;
    mousePassive(x, y);
    glutPostRedisplay();
}

int
main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("PNG texture");
    glutMotionFunc(mouseMotion);
    glutPassiveMotionFunc(mousePassive);
    init();
    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    std::cout << "Use mouse drag to rotate." << std::endl;
    glutMainLoop();
    return 0;
}
« Последнее редактирование: 24 Июня 2015, 20:42:06 от qub »

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #10 : 24 Июня 2015, 23:17:08 »
qub,
спасибо, работает. Такой вопрос: как можно уменьшить и оптимизировать данный код что бы в функции display() вместо прямоугольника выводилась текстура?
Код: (cpp) [Выделить]
#include <GL/freeglut.h>
#include <fstream>
#include <iostream>
#include <cmath>

const int TIME = 50;
const int SIZE = 10;

const int SIZE_X = 24;
const int SIZE_Y = 20;

bool WIN;

int x, y;

int pole[SIZE_X][SIZE_Y];

void poleInit()
{
      std::ifstream fin("map.txt");
     
      for(int m=0; m<SIZE_X; m++)
      {
            for(int n=0; n<SIZE_Y; n++)
            {
                  fin >> pole[m][n];
                 
                  if (pole[m][n]==2)
                  {
                        x = m;
                        y = n;
                  }
            }
      }
      pole[x][y] = 2;
}
void PrintText2D(double x, double y, std::string text)
{
    glRasterPos2f(x, y);
    glutBitmapString(GLUT_BITMAP_9_BY_15, (const unsigned char*)text.c_str());
}
void display()
{
      glClear(GL_COLOR_BUFFER_BIT);
     
      for(int m=0; m<SIZE_X; m++)
      {
            for(int n=0; n<SIZE_Y; n++)
            {
                  switch(pole[m][n])
                  {
                        case 1:
                        glColor3f(0.0, 0.0, 0.6);
                        glRectf(m*SIZE, n*SIZE, m*SIZE+SIZE, n*SIZE+SIZE);
                        break; //стена
                       
                        case 2:
                        glColor3f(0.5, 0.5, 0.5);
                        glRectf(m*SIZE+1, n*SIZE+1, m*SIZE+SIZE-1, n*SIZE+SIZE-1);
                        break; //игрок
                       
                        //case 3:
                        //glColor3f(0.0, 0.00, 0.0);
                        //glRectf(m*SIZE, n*SIZE, m*SIZE+SIZE, n*SIZE+SIZE);
                        //break; //выход
                  }
            }
      }
     
      if (WIN==true)
      {
            glColor3f(1.0, 1.0, 1.0);
            PrintText2D(100, 100, "YOU WIN!");
      }
     
      glFlush();
}
void win()
{
      WIN = true;
}
void Keyboard(unsigned char key, int au, int bu)
{
      if (key == 27) exit(0);
}
void MyKeyboard(int key, int xu, int yu)
{
      pole[x][y] = 0;
      switch(key)
      {
            case GLUT_KEY_UP : if (y != SIZE_Y-1 && pole[x][y+1] != 1) y++; break;
           
            case GLUT_KEY_DOWN : if (y != 0 && pole[x][y-1] != 1) y--; break;
           
            case GLUT_KEY_LEFT : if (x != 0 && pole[x-1][y] != 1) x--; break;
           
            case GLUT_KEY_RIGHT : if (x != SIZE_X-1 && pole[x+1][y] != 1) x++; break;
      }
      if (pole[x][y]==3)win();
      pole[x][y] = 2;
}
void timer(int = 0)
{
      display();
     
      glutTimerFunc(TIME,timer,0);
}
int main(int argc, char **argv)
{
      poleInit();
     
      for (int xx=0; xx<SIZE_X; xx++)
      {
            for (int yy=0; yy<SIZE_Y; yy++)
            {
                  std::cout << pole[xx][yy] << " ";
            }
            std::cout << std::endl;
      }
     
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
      glutInitWindowSize(SIZE*2*SIZE_X, SIZE*2*SIZE_Y);
      glutInitWindowPosition(250, 50);
      glutCreateWindow("Labirint");
     
      glClearColor(0.0, 0.0, 0.0, 0.0); //чёрный
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluOrtho2D(0, SIZE_X*SIZE, 0, SIZE_Y*SIZE);
     
      glutDisplayFunc(display);
      glutTimerFunc(TIME,timer,0);
      glutKeyboardFunc(Keyboard);
      glutSpecialFunc(MyKeyboard);
     
      glutMainLoop();
}
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #11 : 30 Июня 2015, 20:13:15 »
qub,
спасибо, работает. Такой вопрос: как можно уменьшить и оптимизировать данный код что бы в функции display() вместо прямоугольника выводилась текстура?
Код: (cpp) [Выделить]
#include <GL/freeglut.h>
#include <fstream>
#include <iostream>
#include <cmath>

const int TIME = 50;
const int SIZE = 10;

const int SIZE_X = 24;
const int SIZE_Y = 20;

bool WIN;

int x, y;

int pole[SIZE_X][SIZE_Y];

void poleInit()
{
      std::ifstream fin("map.txt");
     
      for(int m=0; m<SIZE_X; m++)
      {
            for(int n=0; n<SIZE_Y; n++)
            {
                  fin >> pole[m][n];
                 
                  if (pole[m][n]==2)
                  {
                        x = m;
                        y = n;
                  }
            }
      }
      pole[x][y] = 2;
}
void PrintText2D(double x, double y, std::string text)
{
    glRasterPos2f(x, y);
    glutBitmapString(GLUT_BITMAP_9_BY_15, (const unsigned char*)text.c_str());
}
void display()
{
      glClear(GL_COLOR_BUFFER_BIT);
     
      for(int m=0; m<SIZE_X; m++)
      {
            for(int n=0; n<SIZE_Y; n++)
            {
                  switch(pole[m][n])
                  {
                        case 1:
                        glColor3f(0.0, 0.0, 0.6);
                        glRectf(m*SIZE, n*SIZE, m*SIZE+SIZE, n*SIZE+SIZE);
                        break; //стена
                       
                        case 2:
                        glColor3f(0.5, 0.5, 0.5);
                        glRectf(m*SIZE+1, n*SIZE+1, m*SIZE+SIZE-1, n*SIZE+SIZE-1);
                        break; //игрок
                       
                        //case 3:
                        //glColor3f(0.0, 0.00, 0.0);
                        //glRectf(m*SIZE, n*SIZE, m*SIZE+SIZE, n*SIZE+SIZE);
                        //break; //выход
                  }
            }
      }
     
      if (WIN==true)
      {
            glColor3f(1.0, 1.0, 1.0);
            PrintText2D(100, 100, "YOU WIN!");
      }
     
      glFlush();
}
void win()
{
      WIN = true;
}
void Keyboard(unsigned char key, int au, int bu)
{
      if (key == 27) exit(0);
}
void MyKeyboard(int key, int xu, int yu)
{
      pole[x][y] = 0;
      switch(key)
      {
            case GLUT_KEY_UP : if (y != SIZE_Y-1 && pole[x][y+1] != 1) y++; break;
           
            case GLUT_KEY_DOWN : if (y != 0 && pole[x][y-1] != 1) y--; break;
           
            case GLUT_KEY_LEFT : if (x != 0 && pole[x-1][y] != 1) x--; break;
           
            case GLUT_KEY_RIGHT : if (x != SIZE_X-1 && pole[x+1][y] != 1) x++; break;
      }
      if (pole[x][y]==3)win();
      pole[x][y] = 2;
}
void timer(int = 0)
{
      display();
     
      glutTimerFunc(TIME,timer,0);
}
int main(int argc, char **argv)
{
      poleInit();
     
      for (int xx=0; xx<SIZE_X; xx++)
      {
            for (int yy=0; yy<SIZE_Y; yy++)
            {
                  std::cout << pole[xx][yy] << " ";
            }
            std::cout << std::endl;
      }
     
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
      glutInitWindowSize(SIZE*2*SIZE_X, SIZE*2*SIZE_Y);
      glutInitWindowPosition(250, 50);
      glutCreateWindow("Labirint");
     
      glClearColor(0.0, 0.0, 0.0, 0.0); //чёрный
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluOrtho2D(0, SIZE_X*SIZE, 0, SIZE_Y*SIZE);
     
      glutDisplayFunc(display);
      glutTimerFunc(TIME,timer,0);
      glutKeyboardFunc(Keyboard);
      glutSpecialFunc(MyKeyboard);
     
      glutMainLoop();
}
Написание такого примера оказалось намного сложней чем я думал. Мой пример создан банальной подгонкой кода и подбором параметров OpenGL функций взятых из разных сайтов с примерами по OpenGL. Как правильно пишутся тайловые движки с использованием OpenGL я мало представляю.

Вот скриншот того, что получилось:



Использованные текстуры:
1) Текстура травы без альфа-канала


2) Текстура грязи с альфа-каналом


Карта уровня map.txt:
(Нажмите, чтобы показать/скрыть)

Вот код того, что получилось:

#include <GL/freeglut.h>
#include <png.h>
#include <iostream>
#include <math.h>
#include <fstream>


GLubyte *textureGrass;
GLubyte *textureDirt;
GLuint texture[2];

int width, height;
bool hasAlpha;

const int SIZE_X = 10;
const int SIZE_Y = 10;
int map_arr[SIZE_X][SIZE_Y];

int x, y;

bool loadPngImage(char *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;

    if ((fp = fopen(name, "rb")) == NULL)
        return false;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                     NULL, NULL, NULL);

    if (png_ptr == NULL) {
        fclose(fp);
        return false;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        return false;
    }

    png_init_io(png_ptr, fp);

    png_set_sig_bytes(png_ptr, sig_read);

    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);

    png_uint_32 width, height;
    int bit_depth;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 &interlace_type, NULL, NULL);
    outWidth = width;
    outHeight = height;

    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        memcpy(*outData+(row_bytes * (outHeight-1-i)), row_pointers[i], row_bytes);
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    fclose(fp);

    return true;
}

void LoadMap()
{
      std::ifstream fin("map.txt");

      for(int m=0; m<SIZE_X; m++)
      {
            for(int n=0; n<SIZE_Y; n++)
            {
                  fin >> map_arr[m][n];
            }
      }
}

void init(void) {

    char grass[] = "grass.png";
    char dirt[] = "dirt.png";

    loadPngImage(grass, width, height, hasAlpha, &textureGrass);
    loadPngImage(dirt, width, height, hasAlpha, &textureDirt);

    glGenTextures(2, &texture[0]);

    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

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

    glBindTexture(GL_TEXTURE_2D, texture[1]);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureGrass);

}

void display(void) {

    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glEnable( GL_TEXTURE_2D );
    glTranslatef(-5, -5, -8.6);

    int tile;

    for(y=0; y<SIZE_Y; y++)
      {
            for(int x=0; x<SIZE_X; x++)
            {

                tile = map_arr[y][x];
                switch(tile)
                {
                        case 0:
                            glBindTexture(GL_TEXTURE_2D, texture[0]);
                        break;

                        case 1:
                            glBindTexture(GL_TEXTURE_2D, texture[1]);
                        break;
                }
                glPushMatrix();
                glBegin(GL_QUADS);
                    glTexCoord2f(0.0f, 0.0f); glVertex3f(float(x), float(y), 0.0);
                    glTexCoord2f(1.0f, 0.0f); glVertex3f(float(x + 1), float(y), 0.0f);
                    glTexCoord2f(1.0f, 1.0f); glVertex3f(float(x + 1), float(y + 1), 0.0f);
                    glTexCoord2f(0.0f, 1.0f); glVertex3f(float(x), float(y + 1), 0.0f);

                glEnd();
                glPopMatrix();
            }
      }

    glutSwapBuffers();
}

void myReshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, 1.0 * (GLfloat) w / (GLfloat) h, 1.0, 30.0);
    glMatrixMode(GL_MODELVIEW);
}

int
main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(512, 512);
    glutCreateWindow("Labirint");
    LoadMap();
    init();
    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4062
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #12 : 30 Июня 2015, 20:36:18 »
qub, а что это диагональ в карте в одну сторону, а на скрине в другую?
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн qub

  • Новичок
  • *
  • Сообщений: 41
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #13 : 30 Июня 2015, 20:42:33 »
qub, а что это диагональ в карте в одну сторону, а на скрине в другую?
Это "зеркалирование" изначально проявляется в примере Гриб_под_зонтом, в сообщение https://forum.ubuntu.ru/index.php?topic=262491.msg2079506#msg2079506, по-этому и в моем примере тоже.

Оффлайн Гриб_под_зонтом

  • Автор темы
  • Активист
  • *
  • Сообщений: 301
    • Просмотр профиля
Re: Текстуры в OpenGL
« Ответ #14 : 01 Июля 2015, 15:08:04 »
qub,
Да есть такая проблема, не знаю пока что с ней делать.
А за пример огромное спасибо, вроде разобрался.
Hp 250 G3: 8Gb RAM, Intel Celeron 2.16-2.58GHz with 2 core, Intel HD Graphics.
Ubuntu 18.04 LTS with GNOME 3.

 

Страница сгенерирована за 0.025 секунд. Запросов: 22.