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