Урок 6 - Наложение текстур

  Текстура в OpenGL – это простой графический файл, который отображается на полигоне.
В этом уроке мы рассмотрим 2 вида текстур: простые и с альфа-каналом (прозрачностью).

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

  Текстуру мы будем накладывать на куб.
Его надо нарисовать вручную, чтобы не загромождать код, создайте новый юнит и процедуру RenderBox:

Procedure RenderBox();
begin
glBegin(GL_QUADS);
    glNormal3f( 0.0, 0.0, 1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
   glEnd;
   glBegin(GL_QUADS);
    glNormal3f( 0.0, 0.0,-1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
   glEnd;
   glBegin(GL_QUADS);
    glNormal3f( 0.0, 1.0, 0.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
   glEnd();
   glBegin(GL_QUADS);
    glNormal3f( 0.0,-1.0, 0.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
   glEnd();
   glBegin(GL_QUADS);
    glNormal3f( 1.0, 0.0, 0.0);
    glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0);
   glEnd();
   glBegin(GL_QUADS);
    glNormal3f(-1.0, 0.0, 0.0);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
    glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0);
    glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0,  1.0);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0);
  glEnd();
end;  
Эту процедуру мы будем использовать 2 раза.

  Позиции для текстуры задаются функцией glTexCoord2f(s,t : single). Она задаёт позицию X, Y координаты на полигоне. Вызывать её следует перед заданием позиции каждой точки полигона.

  Для правильного отображения текстуры, надо задать параметры отображения, при помощи функции glTexParameter(тип текстуры, тип фильтра, тип фильтрации) в FormCreate:
glTexParameter (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameter (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
Ну и разрешить режим наложения текстуры в FormCreate:
glEnable(GL_TEXTURE_2D);
  После ключевого слова implementation необходимо записать процедуру самого наложения, потому что её нет в стандартной библиотеке OpenGL.pas поставляемой с Delphi 7.
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32; 
В OpenGL есть специальный тип данных «Uint». Он хранит индекс загруженной текстуры в памяти.

  Теперь нужно загрузить нашу текстуру при старте программы. Для этого создайте глобальную переменную Tex типа Uint и запишите следующий код в FormCreate:
Loadtexture('Tex.tga',Tex,false);
Файлы текстур уже готовы и находится в папке с исходником.
Здесь мы загружаем текстуру в память и присваиваем индекс этой текстуры переменной Tex.

Подготовка закончена.

  Нарисуем наш кубик:
procedure TForm1.FormPaint(Sender: TObject);
  begin
…
    RenderBox();	//рисуем куб
…
  End; 


И наложим текстуру:
procedure TForm1.FormPaint(Sender: TObject);
  begin
…
   glBindTexture(GL_TEXTURE_2D, Tex); // накладываем текстуру
    RenderBox();	//рисуем куб
…
  End; 


  Вызвав один раз glBindTexture, текстура будет накладываться на все полигоны, нарисованные после вызова. Для того, чтобы текстура не накладывалась можно запретить режим наложения glDisable(GL_TEXTURE_2D), а потом разрешить или наложить нулевую текстуру, то есть ничего glBindTexture(GL_TEXTURE_2D, 0).
Готово!!!

Перейдём к текстуре с прозрачностью.
Для того, чтобы текстура имела прозрачные места, необходимо разрешить альфа-тест и задать его параметры в FormCreate:
 glEnable(GL_ALPHA_TEST);     //разрешаем альфа-тест 
 glAlphaFunc(GL_GREATER,0.0);  // устанавливаем параметры
для того чтоб не было резких границ между прозрачным местом и текстурой:
 glEnable (GL_BLEND);         //Включаем режим смешивания цветов
 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; //параметры смешивания 
Загрузим текстуру в созданную переменную Glass в FormCreate:
Loadtexture('Tex.tga',Glass,false);
Теперь наложим заранее созданную текстуру с альфа каналом:
procedure TForm1.FormPaint(Sender: TObject);
  begin
…
   glBindTexture(GL_TEXTURE_2D, Glass); // накладываем текстуру
    RenderBox();	//рисуем куб
…
  End; 


Ну и наконец, отобразим два куба с разными текстурами.
procedure TForm1.FormPaint(Sender: TObject);
  begin
…
glBindTexture(GL_TEXTURE_2D, Glass);
   glPushMatrix();
   glTranslatef(0,1.5,0);
   glRotatef(angle,0,0,1);
   glRotatef(angle1,0,1,0);
    RenderBox();
 glPopMatrix;

 glBindTexture(GL_TEXTURE_2D, Tex);
  glPushMatrix();
  glTranslatef(0,-1.5,0);
  glRotatef(angle,0,0,1);
  glRotatef(angle1,0,1,0);
   RenderBox();
 glPopMatrix;
…
  End; 


В следующем уроке мы узнаем, как сделать туман (дым) в OpenGL.



Добавил(а): катари Дата: 2012-12-18
а можно сделать так чтобы пользователь мог менять цвет текстуры? хотя бы, чтобы мог менять цвет от светлого к темному подскажите пожалуйста как это реализовать



Добавил(а): Admin Дата: 2012-12-19
Я не уверен, но думаю, что скорее всего цвет нужно менять через пиксельный шейдер. Автор уроков подробнее ответить тебе в течении дня.



Добавил(а): Klesh Дата: 2012-12-19
Никаких шейдеров тут не надо. Всё можно сделать ,вписав одну строку перед отрисовкой, glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, @dif); где dif - массив с 4 значениями типа GLFloat (R,G,B,A). Если задать значения к примеру (1,1,1,1) то будет максимальная яркость, а если (0.2,0.2,0.2,1) то будет темный цвет.



Добавил(а): HALF-LIFE Дата: 2013-03-06
Как нанести одно и тоже изображение несколько раз не растягивая её на поверхность?



Добавил(а): juzhnij Дата: 2013-05-29
Ставлю любую свою текстуру без фона и куб уже не прозрачный, таким образом урок ничего не обьясняет, а просто кывидывает информацию как кость собаке.



Добавил(а): Klesh Дата: 2013-05-29
В каком редакторе вы работаете? Я работал в фотошопе и сохранял текстуру с включенной маской, все что было под маской становилось прозрачным. Это уже вопрос редактора и устройства формата TGA, выходящий за рамки этого урока.



Добавил(а): dmch_d Дата: 2014-05-25
В примере добавлен DGLUT. Разве он используется?



Добавил(а): Den1k Дата: 2017-12-25
Скажите пожалуйста, почему, когда вместо куба из примера я рисую сферу с помощью glutSolidSphere, то текстура на нее не накладывается?



Добавил(а): ufo26 Дата: 2018-06-25
подскажите, как использовать файл "textures.pas"? Куда его сохранять и как прописывать вызов в коде?



Добавил(а): ufo26 Дата: 2018-06-25
разобрался. нужно сохранить файл к себе в проект, а в разделе Uses указать имя файла без расширения.


  1. Олег
    Олег 2 years ago
    выбивает ошибку что file tex.tga найдено.
  2. Олег
    Олег 2 years ago
    * не найдено. кто знает что делать?
Отменить.