Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.12.2010, 13:53   #1
nXs
Форумчанин
 
Регистрация: 26.02.2010
Сообщений: 126
По умолчанию Ландшафт OpenGL

Здравствуйте ув. форумчане. У меня такой вопрос, рисую ландшафт посредством OpenGL, на него накладывается текстура размером 1024х1024, ландшафт размером 256х256 клеток каждая с которых имеет размер 2х2. Вопрос, почему текстура имеет очень страшный вид, ведь по идее на квадрат ландшафта 2х2 приходится квадрат текстуры 4х4 и качество не должно страдать... Собственно код отрисовки:
Код:
glEnable(GL_TEXTURE_2D);

for i:=0 to 254 do
for j:=0 to 254 do
begin
if Textured then
glBegin(GL_QUADS)
else
glBegin(GL_LINE_STRIP);

glTexCoord2f(i*4*0.001,j*4*0.001);
glVertex3F(i*2,Land[i,j],j*2);
glTexCoord2f((i+1)*4*0.001,j*4*0.001);
glvertex3f((i+1)*2,Land[i+1,j],j*2);
glTexCoord2f((i+1)*4*0.001,(j+1)*4*0.001);
glVertex3F((i+1)*2,Land[i+1,j+1],(j+1)*2);
glTexCoord2f(i*4*0.001,(j+1)*4*0.001);
glvertex3F(i*2,Land[i,j+1],(j+1)*2);
glEnd;
end;

glDisable(GL_TEXTURE_2D);
И еще, почему при загрузке данного ландшафта с текстурой и одной модельки (примерно 15000 полигонов), фпс падает до 10-15, хотя при этом же ландшафте без текстуры и модели фпс=30.

Скрин картинки:

Последний раз редактировалось nXs; 18.12.2010 в 13:58.
nXs вне форума Ответить с цитированием
Старый 18.12.2010, 17:32   #2
.pixel
c++, dx/ogl
Форумчанин
 
Аватар для .pixel
 
Регистрация: 10.11.2008
Сообщений: 131
По умолчанию

Цитата:
по идее на квадрат ландшафта 2х2 приходится квадрат текстуры 4х4 и качество не должно страдать...
“4х4” пикселя чель, на квад?))

Попробуйте так может получше будет.

Код:
glTexCoord2f (0, 0);
glVertex3F( i*2, Land[i,j], j*2);

glTexCoord2f (2, 0);
glvertex3f( (i+1)*2, Land[i+1,j], j*2 );

glTexCoord2f (2, 2);
glVertex3F( (i+1)*2, Land[i+1,j+1], (j+1)*2 );

glTexCoord2f (0, 2);
glvertex3F ( i*2, Land[i,j+1], (j+1)*2 );
Immediate mode – он хорошо когда, надо что-то простое быстро нарисовать. Но когда дело касается сложных сцен то он мало эффективен и показывает сравнительно малую скорость прорисовки.

Мой вам совет, если вы решили уйти дальше кубика, в своем поиске)
Забудьте про весь GL Immediate mode функционал.

Изучите и используйте. VBO, IBO, VAO, Шейдерные программы.
По крайней мере, VBO бы вам точно помог поднять скорость отрисовки примитивов.

Еще можно поинтересоваться что такое - glEnable(GL_CULL_FACE); и glEnable(GL_DEPTH_TEST); и с чем их едят))

да и еще текстуру пробуйте по разному подгрузить с оборачиванием и без... где она у вас там грузится)
Код:
	// установим параметры "оборачивания" текстуры - отсутствие оборачивания
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	// есть оборачивание
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
“Batch, Batch, Batch:” What Does It Really Mean?
I am a donut! Ask not how many tris/batch, but
rather how many batches/frame!

Последний раз редактировалось .pixel; 18.12.2010 в 17:37. Причина: время
.pixel вне форума Ответить с цитированием
Старый 19.12.2010, 13:18   #3
nXs
Форумчанин
 
Регистрация: 26.02.2010
Сообщений: 126
По умолчанию

Спасибо за советы, с текстурой эт я протупил.....
В общем я так понял что для больших сцен нужно использовать glDrawElements(). Попробовал, вот так:
Код:
...
Type TLаnd=array[0..65535,0..2] of GLFloat;  //я так понял нужно задавать двухмерные массивы
Type TFaces=array[0..16383,0..3] of GLFloat;
...
Land:TLаnd;
Faces:TFaces;
...   //отрисовка
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, @Land);
glDrawElements(GL_POLYGON, 16383, GL_UNSIGNED_BYTE, @Faces);
glDisableClientState(GL_VERTEX_ARRAY);
но оно мне рисует только линию из точек, где я не прав?

UPD:В общем я подозреваю что лаг в расчете координат вертексов и фейсов. Вертексы считаю так(по карте высот):
Код:
n:=0;
for i:=0 to 255 do
for j:=0 to 255 do
begin
Land[n,0]:=i*2;
Land[n,1]:=B.Canvas.Pixels[i*4,j*4]/100000;
Land[n,2]:=j*2;
n:=n+1;
end;
а фейсы так:
Код:
n:=0;
for i:=0 to 127 do
for j:=0 to 127 do
begin
faces[n,0]:=n*i;
faces[n,1]:=n*(i+1);
faces[n,2]:=n*j;
faces[n,3]:=n*(j+1);
n:=n+1;
end;
Но как их правильно рассчитать для карты 256х256?

Последний раз редактировалось nXs; 19.12.2010 в 15:17.
nXs вне форума Ответить с цитированием
Старый 19.12.2010, 22:27   #4
.pixel
c++, dx/ogl
Форумчанин
 
Аватар для .pixel
 
Регистрация: 10.11.2008
Сообщений: 131
По умолчанию

glDrawElements() – рисует геометрию из индексного буфера(проиндексированного списка) по данным вершинного буфера (буфер вершин).
Каждый элемент индексного буфера – без знаковое целочисленное.
Это число – индекс (позиция) вершины в буфере вершин (вершинных данных).


Код:
glDrawElements(GL_POLYGON, 16383, GL_UNSIGNED_BYTE, @Faces);
Цитата:
но оно мне рисует только линию из точек, где я не прав?
Возможно, рисовать все-таки лучше GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_QUADS, GL_QUAD_STRIP а не… полигон)

«Faces»? Это что индексы? Indexes – смотрелось бы понятнее.

glDrawElements – нарисует все как надо, если есть привязанные данные на вершины и вершины правильно сгенерированны для геометрии, а индексы на те вершины правильно расставлены.

Гляньте что показывает…

Код:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, @Land);
glDrawArrays( GL_QUADS, 0, 65535);
glDisableClientState(GL_VERTEX_ARRAY);
Рисуйте пока без индексов, сами вершинные данные.
И засуньте вершинные данные в VBO.
Когда все будет рисоваться начнете прикручивать индексы на данную геометрию.

Тут участок кода может чего и подскажет в часности с VBO…
http://paste.org.ru/?iz64s8
“Batch, Batch, Batch:” What Does It Really Mean?
I am a donut! Ask not how many tris/batch, but
rather how many batches/frame!
.pixel вне форума Ответить с цитированием
Старый 21.12.2010, 10:58   #5
nXs
Форумчанин
 
Регистрация: 26.02.2010
Сообщений: 126
По умолчанию

Спасибо огромное, пересмотрев код, понял что массив индексов неправильно генерируется(пока не придумал как сделать правильно...), ваш код работает. Я так понял с помощью vbo можна загнать массивы в память видеокарты и брать их оттуда не передавая каждый раз из системной памяти,хотелось бы еще знать есть ли какие то ограничения на количество таких массивов в памяти карты?

UPD: Я наверное вообще тупой, никак не получается рассчитать индексы, посмотрите пожалуйста что не так
Код:
for i:=0 to 255 do
for j:=0 to 255 do
begin
Land[n,0]:=i*2;
Land[n,1]:=B.Canvas.Pixels[i*4,j*4]/100000;
Land[n,2]:=j*2;

F[i,j]:=n;  <--дополнительный массив
n:=n+1;
end;

n:=0;

for i:=0 to 254 do
for j:=0 to 254 do
begin
Index[n,0]:=F[i,j];
Index[n,1]:=F[i+1,j];
Index[n,2]:=F[i+1,j+1];
Index[n,3]:=F[i,j+1];


n:=n+1;
end;
Последовательность индексов получается 0, 256, 257, 1 , вроде правильно, по координатам это (0, 0, 0; 2, 0, 0; 2, 0, 2; 0, 0, 2), рисую
Код:
glDrawElements(GL_LINE_STRIP, 65024*4, GL_UNSIGNED_INT, @Index[0]);
рисует площадь правильных размеров, но, с помощью glBegin/glEnd намного быстрее получается, и плюс рисует сплошной квадрат, а не набор квадов, понимаю что не так что то считаю, но что не пойму...

Последний раз редактировалось nXs; 21.12.2010 в 11:47.
nXs вне форума Ответить с цитированием
Старый 22.12.2010, 11:25   #6
nXs
Форумчанин
 
Регистрация: 26.02.2010
Сообщений: 126
По умолчанию

Пытаюсь подключить расширения VBO,написал специально модуль типа:
Код:
unit VBO;

interface

uses OpenGL,Windows;

type
 PGLHandleARB = ^GLHandleARB;
 GLHandleARB = integer;
 PPGLCharARB  = ^PGLCharARB;
 PGLCharARB   = ^GLCharARB;
 GLCharARB    = Char;

 TglBufferDataARB= procedure(target: GLenum; size: GLsizei; const data: Pointer; usage: GLenum);stdcall;
 TglBufferSubDataARB=procedure (target: GLenum; offset: GLsizei; size: GLsizei; const data: pointer);stdcall;
 TglBindBufferARB=procedure (target: GLenum; buffer: GLenum);stdcall;
 TglDeleteBuffersARB=procedure (n: GLsizei; buffers: PGLuint);stdcall;
 TglGenBuffersARB=procedure (n: GLsizei; buffers: PGLuint); stdcall;


 procedure glVertexPointer(size:GLint; atype:GLenum; stride:GLsizei; data:pointer); stdcall; external 'OpenGL32';
 procedure glColorPointer(size:GLint; atype:GLenum; stride:GLsizei; data:pointer); stdcall; external 'OpenGL32';
 procedure glNormalPointer(atype:GLenum; stride:GLsizei; data:pointer); stdcall; external 'OpenGL32';
 procedure glTexCoordPointer(size: GLint; atype: GLEnum; stride: GLsizei; data: pointer); stdcall; external 'OpenGL32';
 procedure glDrawArrays(mode:GLenum; first:GLint; count:GLsizei); stdcall; external 'OpenGL32';
 procedure glDrawElements(mode: GLEnum; count: GLsizei; atype: GLEnum; indices: Pointer); stdcall; external 'OpenGL32';
 procedure glEnableClientState(aarray:GLenum); stdcall; external 'OpenGL32';
 procedure glDisableClientState(aarray:GLenum); stdcall; external 'OpenGL32';




const
 GL_VERTEX_ARRAY                                    = $8074;
 GL_NORMAL_ARRAY                                    = $8075;
 GL_COLOR_ARRAY                                     = $8076;
 GL_TEXTURE_COORD_ARRAY                             = $8078;
 GL_ARRAY_BUFFER_ARB         = $8892;
 GL_ELEMENT_ARRAY_BUFFER_ARB = $8893;
 GL_STATIC_DRAW_ARB          = $88E4;

var
{*************************VBO********************************}

 glBufferDataARB: TglBufferDataARB;
 glBufferSubDataARB:TglBufferSubDataARB;
 glBindBufferARB:TglBindBufferARB;
 glDeleteBuffersARB:TglDeleteBuffersARB;
 glGenBuffersARB:TglGenBuffersARB;

procedure InitExtentions;

implementation

var
LibraryOGL:THandle;

function gloadLibrary:boolean;
begin
LibraryOGL:=loadlibrary('OpenGL32.dll');
end;

function gFreeLibrary:boolean;
begin
Result := FreeLibrary(HMODULE(LibraryOGL));
end;


procedure InitExtentions;
begin
if not gloadLibrary then
exit;

 glBufferDataARB       := GetProcAddress(HMODULE(LibraryOGL), 'glBufferDataARB');
 glBufferSubDataARB    := GetProcAddress(HMODULE(LibraryOGL), 'glBufferSubDataARB');
 glBindBufferARB       := GetProcAddress(HMODULE(LibraryOGL), 'glBindBufferARB');
 glGenBuffersARB       := GetProcAddress(HMODULE(LibraryOGL), 'glGenBuffersARB');
 glDeleteBuffersARB       := GetProcAddress(HMODULE(LibraryOGL), 'glDeleteBuffersARB');

 if @glBufferDataARB=nil then
  glBufferDataARB:=wglGetProcAddress('glBufferSubDataARB');
 if @glBufferSubDataARB=nil then
   glBufferSubDataARB    :=wglGetProcAddress('glBufferSubDataARB');
 if @glBindBufferARB=nil then
   glBindBufferARB    :=wglGetProcAddress('glBindBufferARB');
 if @glGenBuffersARB=nil then
   glGenBuffersARB    :=wglGetProcAddress('glGenBuffersARB');
 if @glDeleteBuffersARB=nil then
   glDeleteBuffersARB    :=wglGetProcAddress('glDeleteBuffersARB');


end;

end.
При первом же обращении к функциям из данного модуля программа падает с сообщением "Acces violation at adress 000000...". Подумал что это я накосячил, подключил модуль dglOpenGL вместо самописного , и то же самое, подключил модуль glext, то же самое. И что самое странное, у меня был исходник XTropper который строит ландшафт, и использует VBO, который раньше работал и компилился на ура, сейчас при запуске выдает "Runtime error 3", при чем такая ситуация и на работе и дома! Подскажите что я поломал и как исправить, а то я за два дня всю голову сломал...

Последний раз редактировалось nXs; 22.12.2010 в 11:28.
nXs вне форума Ответить с цитированием
Старый 22.12.2010, 14:24   #7
nXs
Форумчанин
 
Регистрация: 26.02.2010
Сообщений: 126
По умолчанию

В общем решил проблему, обновил драйвер и прописал InitExtentions после получения контекста воспроизведения.
nXs вне форума Ответить с цитированием
Старый 22.12.2010, 17:16   #8
.pixel
c++, dx/ogl
Форумчанин
 
Аватар для .pixel
 
Регистрация: 10.11.2008
Сообщений: 131
По умолчанию

карты высот несколько примеров http://wingman.org.ru/opengl/

Цитата:
никак не получается рассчитать индексы

начните рисовать, отбросьте Z-ось чтобы было проще представить. Z-компоненту потом можно брать из карты высот или монохромного изображения (во время генерации или после, но до того как массив вершин будет отправлен в VBO).

Обрисовал в общих чертах пример того, как можно представить генерацию сетки на основе GL_QUAD.
Это не идеальный вариант но понять суть можно. В качестве текстуры для такой сетки можно использовать тайл (бесшовная текстура). Если вы хотите использовать одну текстуру на всю поверхность (атлас) то UV координаты придется пересчитывать по иному. Там же можно увидеть, что такое индексы вершины и откуда они берутся.
“Batch, Batch, Batch:” What Does It Really Mean?
I am a donut! Ask not how many tris/batch, but
rather how many batches/frame!
.pixel вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
OpenGL bigory Общие вопросы C/C++ 8 24.06.2010 14:26
OpenGL Paul_AG Общие вопросы C/C++ 3 02.02.2010 20:28
Opengl Алексадр Компоненты Delphi 4 29.09.2009 17:23
3d Ландшафт Flinka Помощь студентам 1 28.04.2009 12:19
Трехмерный (3D) ландшафт. OpenGL Flinka Помощь студентам 1 27.04.2009 14:45