Рендинг в текстуру (FBO)
В статье Рендинг в текстуру мы рассмотрели самую простую реализацию рендинга в текстуру.
В этой статье, для выполнения этой задачи мы воспользуемся еще и расширением GL_EXT_framebuffer_object.
Итак, инициализация расширения:
const
GL_FRAMEBUFFER_EXT = $8D40;
GL_COLOR_ATTACHMENT0_EXT = $8CE0;
GL_FRAMEBUFFER_COMPLETE_EXT = $8CD5;
var
GL_EXT_framebuffer_object: Boolean;
glGenFramebuffersEXT: procedure(n: GLsizei; FrameBuffers: PGLuint); stdcall;
glBindFramebufferEXT: procedure(Target, FrameBuffer: GLuint); stdcall;
glFramebufferTexture2DEXT: procedure(Target, Attachment, TexTarget, Texture: GLuint; Level: GLint); stdcall;
glCheckFramebufferStatusEXT: function(Target: GLenum): GLenum; stdcall;
var
Extensions: String;
begin
Extensions := glGetString(GL_EXTENSIONS);
GL_EXT_framebuffer_object := Pos('GL_EXT_framebuffer_object', Extensions) <> 0;
if GL_EXT_framebuffer_object then
begin
glGenFramebuffersEXT := wglGetProcAddress('glGenFramebuffersEXT');
glBindFramebufferEXT := wglGetProcAddress('glBindFramebufferEXT');
glFramebufferTexture2DEXT := wglGetProcAddress('glFramebufferTexture2DEXT');
glCheckFramebufferStatusEXT := wglGetProcAddress('glCheckFramebufferStatusEXT');
end
else
PostQuitMessage(0);
|
Это не все функции (константы), а только те которыми мы будем пользоваться, полный список
функций (констант) вы можете увидеть на opengl.org/registry/ выбрав расширение GL_EXT_framebuffer_object.
Теперь алгоритм. Первое - инициализируем текстуру и обьект кадрового буфера (Frame Buffer Object - FBO):
var
Texture: Cardinal;
FrameBuffer: 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);
//создаем кадровый буфер
glGenFramebuffersEXT(1, @FrameBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FrameBuffer);
//прикрепим текстуру к кадровому буферу (содержимое буфера будет "на ней")
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, Texture, 0);
//проверяем на наличие ошибок
if glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) <>
GL_FRAMEBUFFER_COMPLETE_EXT then
begin
PostQuitMessage(0);
end;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
Теперь можем использовать наш буфер, рисуем на буфере:
//активируем буфер
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FrameBuffer);
//запоминаем вьюпорт
glPushAttrib(GL_VIEWPORT_BIT);
//устанавливаем размер вьюпорта, очищаем экран
glViewport(0, 0, TEX_WIDTH, TEX_HEIGHT);
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
//рисуем наши треугольники
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;
//восстанавливаем все
glPopAttrib;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
Теперь все что мы нарисовали на нашей текстуре можно показывать:
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;
|
Как вы видите основные моменты не отличаются от простого рендинга в текстуру представленного
в предыдущей статье, мы просто добавили работу с обьектом кадрового буфера.
Кроме более высокой скорости у этого метода есть еще одно преимущество, размер текстуры для рендинга
ограничивается только возможностями вашей видеокарты. Вот пример,
приятного вам кодинга.
Автор: Sokal
(c) GameDev 32, 2007-2008
|
|