Мы не делаем игры :)
Главная  Статьи  Проекты  Загрузки  Ссылки  Гостевая  О нас 
Рендинг в текстуру

Ну, начнем. Рендинг в текстуру - это обычный рендинг с последующей передачей нарисованного в текстуру. Потом с ней можно делать все чего вам хочеться. Начнем рассматривать все по шагам. Шаг первый - создаем текстуру для рендинга:

procedure glBindTexture(Target, Texture: Cardinal); stdcall; external opengl32;
procedure glGenTextures(n: GLsizei; textures: PGLuint); stdcall; external opengl32;

const
  TEX_WIDTH = 128;
  TEX_HEIGHT = 128;

var
  Texture: Cardinal;

glEnable(GL_TEXTURE_2D);

glGenTextures(1, @Texture);
glBindTexture(GL_TEXTURE_2D, Texture);

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

glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, nil);

Константы я ввел для наглядности. Я думаю здесь все понятно: генерируем новую текстуру, натягиваем ее, выбираем режим фильтрации и аплодим. Шаг второй - приготовим все к рендингу в текстуру:

glViewport(0, 0, TEX_WIDTH, TEX_HEIGHT);

glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

Ставим размер вьюпорта таким же как и размер текстуры, а потом очищаем экран (не обязательно менять clear color). Теперь переходим к шагу третьему - рисуем:

glPushMatrix;
glLoadIdentity;
glTranslatef(0,0,-5);

glRotatef(Angle,0,0,1);

glBegin(GL_TRIANGLES);
  glColor3ub(255,0,0);
  glVertex3f(-0.8, -0.8, 0);
  glVertex3f( 0.8, -0.8, 0);
  glVertex3f( 0.8, 0.8, 0);

  glColor3ub(0,255,0);
  glVertex3f( 0.8, 0.8, 0);
  glVertex3f(-0.8, 0.8, 0);
  glVertex3f( 0.8, -0.8, 0);
glEnd;

glPopMatrix;

Рисуем два треугольника - красный и зеленый. Поворачиваем их чтобы было интересней. Я не убирал текстуру (glBindTexture(GL_TEXTURE_2D, 0);) т.к. при рисовании я не ставил текстурные координаты и текстура на выввод треугольников не повлияет. А теперь изображение на экране скопируем в текстуру, это четвертый шаг:

procedure glCopyTexImage2D(target: GLenum; level: GLint; internalFormat: GLenum; x, y, width, height, border: GLint); stdcall; external opengl32;

glBindTexture(GL_TEXTURE_2D, Texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, TEX_WIDTH, TEX_HEIGHT, 0);

Теперь устанавливаем старый размер вьюпорта и просто рисуем текущий кадр, это пятый шаг:

GetClientRect(Handle, Rect);
glViewport(0, 0, Rect.Right - Rect.Left, Rect.Bottom- Rect.Top);

glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;

glTranslatef(0,0,-5);
glRotatef(Angle,0,1,0);

glBindTexture(GL_TEXTURE_2D, Texture);
glBegin(GL_QUADS);
  glColor3ub(255,255,255);
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);
  glTexCoord2f(1,0); glVertex3f( 1,-1,0);
  glTexCoord2f(1,1); glVertex3f( 1, 1,0);
  glTexCoord2f(0,1); glVertex3f(-1, 1,0);
glEnd;

Для того чтобы вернуть первоначальный размер вьюпорта в коде мы используем функцию из Win32 API, можно обойтись без нее вот так:

var
  Viewport: Array[0..3] Of Integer; //GLint,GLsizei...

glGetIntegerv(GL_VIEWPORT, @Viewport);
//рендинг в текстуру
glViewport(Viewport[0], Viewport[1], Viewport[2], Viewport[3]);

Или вот так:

glPushAttrib(GL_VIEWPORT_BIT);
//рендинг в текстуру
glPopAttrib;

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

Автор: Sokal

(c) GameDev 32, 2007-2008
Сайт управляется системой uCoz