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

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

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 13.01.2012, 13:37   #51
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,690
По умолчанию

Глянь вот эту статью
http://www.gamedev.ru/code/articles/..._object_system
И для конкретных манипуляций объектами стоит подумать в сторону использования скриптов. Т.е. разрабатывать двиг отдельно, а приложение скриптами.
Kostia вне форума Ответить с цитированием
Старый 16.01.2012, 19:05   #52
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Kostia похоже, что у меня первый вариант получился, т.е. - God game object.

Код:
{/* Визуальный объект*/}
type CSceneObject = class
  public
    LocalObjectSpace : mat4;
    WorldObjectSpace : mat4;
    position : vec3;
    rotation : vec3;
    scale    : vec3;

    refGeometry   : CMesh;
    refMaterial	: CMaterial;

    RenderStage : Integer;

    Parent    : CSceneObject;
    Child     : array[0..MAX_CHILD_OBJECTS] of CSceneObject;
    ChildCount    : integer;

    FrustumCheckResult	: boolean;
    FrustumTypeCheck	: integer;
    FructumSphereRadius : single;
    FrustumCheckAlwaysPass	: boolean;

    HitDepthSortAlwaysBackground : boolean;


    function  CreateChildObject(const RenderStage:integer = RenderStage0Solid): CSceneObject;
    procedure DeleteChildObject(var ob:CSceneObject);
    procedure Draw(const ds: integer = 0);

    procedure UpdateMatrixes();

    constructor Create();
    destructor  Destroy(); override;

end;
  PSceneObject = ^CSceneObject;


{/* Сцена контейнер */}
type CScene = class
  private
    SceneCamera : CCamera;

  public
    World : CSceneObject;

    RS0Objects : array[0..MAX_RENDER_OBJECTS_PER_STAGE] of CSceneObject;
    RS0Count : integer;
    //RS0StageShader : CShader;

    RS1Objects : array[0..MAX_RENDER_OBJECTS_PER_STAGE] of CSceneObject;
    RS1Count : integer;

    RS2Objects : array[0..MAX_RENDER_OBJECTS_PER_STAGE] of CSceneObject;
    RS2Count : integer;

    InFrustrumObjects : array[0..MAX_RENDER_OBJECTS_PER_STAGE] of CSceneObject;
    InFrustrumObjectsCount : integer;

    procedure SetCamera(var camera : CCamera);
    procedure DrawAllSceneStages();
    procedure AddObjectToRenderStage(const RenderStage:integer; var obj:CSceneObject);
    procedure DeleteObjectFromRenderStage(const RenderStage:integer; var obj:CSceneObject);
    procedure SortByDepth(var RenderStageList: array of CSceneObject; const FromFrontToBack: Boolean);
    procedure SortByDepth2(var RenderStageList: array of CSceneObject; const FromFrontToBack: Boolean);


    procedure FrustumCheck(var RenderStageList: array of CSceneObject);
    procedure FrustumCheck2(var RenderStageList: array of CSceneObject; var IFO : array of CSceneObject; var IFOCount : Integer);

    constructor Create();
    destructor Destroy();override;
end;
  PScene = ^CScene;

Ну да и ладно, меня это пока не особо заботит, главное то что я таки написал простецкий граф сцены) Ну а дальше буду совершенствовать его, рефакторить).

В главном цикле
Отсекаю по фрустуму в список для рендеринга попадают отбьекты которые в пирамиде видимости камеры.
Далее этот список сортирую, для solid – front- to – back, а для прочих c альфой – back – to - front
И вывожу в цикле.

Код:
procedure CScene.DrawAllSceneStages();
  // Stage 0 ************************************************
  FrustumCheck2(RS0Objects, InFrustrumObjects, InFrustrumObjectsCount );
  // Сортируем обьекты в списке по расстоянию от камеры, от ближних к дальним
  SortByDepth2(InFrustrumObjects, True);
  // Включаем запись в Z
  glDepthMask(TRUE);
  //glDepthMask(FALSE);
  // Включаем отсечение невидимых треугольников
  glEnable(GL_CULL_FACE);
  // Включаем отсечение задних граней
  glCullFace(GL_BACK);

  for i := 0 to InFrustrumObjectsCount do begin
    if InFrustrumObjects[i] <> nil then begin

      glUseProgram(InFrustrumObjects[i].refMaterial.refShader.ShaderProgram);

      glUniform1i(InFrustrumObjects[i].refMaterial.refShader.Uniforms.forceAlphaTest, 0);

      SceneCamera.SendTransforms(InFrustrumObjects[i].refMaterial.refShader, InFrustrumObjects[i].WorldObjectSpace);

      InFrustrumObjects[i].Draw();

      glUseProgram(0);

    end;
  end;
...
Этот код пример - только для solid фазы, а таких фазы у меня 3-и и остальные 2-е несколько сложней будут, т.е. каждая в два прохода.

Сейчас думаю, как бы мне батчи собирать на прорисовку? А не в лоб в цикле рисовать, как выше показано.

Последний раз редактировалось Warn; 17.01.2012 в 10:15.
Warn вне форума Ответить с цитированием
Старый 17.01.2012, 07:30   #53
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,690
По умолчанию

По прежнему точно также отсылай на прорисовку объекты, у которох желательно чтобы были данных о их сложности(кол-во треугольников например) и если сложность сцены переваливает определенный порог, то делать glFlush, сбрасывать счетчик сложности и продолжать цикл дальше.(Хотя думаю не лучший вариант)

Еще как вариант построить программу следующим образом. Сначала делать вывод графики, потом glFlush(); и пока видеокарта будет строить кадр можно заняться расчетом физики, выполнением скриптов и т.д.
Kostia вне форума Ответить с цитированием
Старый 17.01.2012, 10:40   #54
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Kostia
Цитата:
делать glFlush
Ну да это идея.
У меня пока в сцене около ~60 коробок. нагрузка не такая большая.
И потом читал где-то что отправка буфера команд на прорисовку в конце кадра не имеет большого смысла. Т.е.


Код:
// Прорисовка обьектов сцены
function MyGLApp.OnRendering():GLBoolean;
begin
  // Очистка буфера цвета и глубины
	glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  Camera.Update();

  Scene.DrawAllSceneStages();
  glFlush();
  Result := SwapBuffers(WindowDC);
  //Sleep(0);
end;
Поскольку SwapBuffers и так заставляет драйвер рисовать все (исполнить весь накопленный буфер команд).

Но про glFlush в середине прорисовки ничего не видел, может это и действенно.

Kostia
Цитата:
Еще как вариант построить программу следующим образом. Сначала делать вывод графики, потом glFlush(); и пока видеокарта будет строить кадр можно заняться расчетом физики, выполнением скриптов и т.д
А если идет UpdateScene() и затем RenderScene() - это то же самое? Пока карта рисует предыдущий кадр мы делаем UpdateScene().

Сделал небольшую оптимизацию по установке шейдеров и геометрии и это существенно подняло скорость прорисовки, поскольку минимизировало переключение шейдеров, геометрии и текстур если в списке подряд идут одинаковые объекты.


Код:
procedure CScene.DrawAllSceneStages();
var
  i : integer;
  prevMaterial : CMaterial;
  prevMesh : CMesh;

begin

  // Stage 0 ************************************************
  FrustumCheck2(RS0Objects, RS0IFO, RS0IFOCount );
  // Сортируем обьекты в списке по расстоянию от камеры, от ближних к дальним
  SortByDepth2(RS0IFO, True);
  // Включаем запись в Z
  glDepthMask(TRUE);
  //glDepthMask(FALSE);
  // Включаем отсечение невидимых треугольников
  glEnable(GL_CULL_FACE);
  // Включаем отсечение задних граней
  glCullFace(GL_BACK);
  prevMaterial := nil;
  prevMesh := nil;
  trisCount := 0;
  for i := 0 to RS0IFOCount do begin
    if RS0IFO[i] <> nil then begin
    	// Если материал отличается от прошлого устанавливаем его
      if (prevMaterial <> RS0IFO[i].refMaterial)  then begin
      	glUseProgram(RS0IFO[i].refMaterial.refShader.ShaderProgram);
      	glUniform1i(RS0IFO[i].refMaterial.refShader.Uniforms.forceAlphaTest, 0);
      	glUniform1f(RS0IFO[i].refMaterial.refShader.Uniforms.colorTexture,RS0IFO[i].refMaterial.refTexture.ID);
  			glBindTexture(GL_TEXTURE_2D, RS0IFO[i].refMaterial.refTexture.ID);
      end;
      SceneCamera.SendTransforms(RS0IFO[i].refMaterial.refShader, RS0IFO[i].WorldObjectSpace);
      // Если  геометрия отличается от прошлой установим новую
      if (prevMesh <> RS0IFO[i].refGeometry) then begin
          glBindVertexArray (RS0IFO[i].refGeometry.buff_vao);
      end;

      glDrawArrays (GL_TRIANGLES, 0, RS0IFO[i].refGeometry.vertexes_count);

      // Сохраним материал и геометрию для проверки в цикле на следующей итерации
      prevMaterial := RS0IFO[i].refMaterial;
      prevMesh := RS0IFO[i].refGeometry;
      trisCount := trisCount + RS0IFO[i].refGeometry.triangles_count;
    end;
  end;
Но все-таки это не batch :/ И я все думаю по этому поводу как бы мне прорисовать 60 одинаковых коробок за один вызов glDrawArrays? Т.е. рендер должен быть на столько умным, чтобы паковать одинаковую геометрию в один вызов glDraw… но каким образом это сделать?

Тут у меня кроме того возникает дилемма сортировать ли объекты по удаленности от камеры или же первоочередное действие - это сортировка по геометрии и материалам шейдерам в пачки для рендеринга - батчи?

В первом случае мы так сказать экономим на филрейте получаем меньшую нагрузку на пиксельный конвеер, поскольку рисуем ближайшую геометрию, а все последующие если они не проходят теста Z буфера т.е. находятся за уже отрисованной геометрией отбрасываются и не проходят вычислений в тяжелых пиксельных шейдерах.

Во втором случае мы получаем список практически отсортированный для быстрого вывода пачками – батчами, что несомненный плюс. Однако геометрия из таких батчей может находиться на разном удалении от камеры, - лишние вычисления в пиксельных шейдерах если составляющие батча не отсортирован в пределах своей группы.

Суммируя выше описанное. Можно предположить, что нужно сортировать геометрию по пачкам – батчам для быстрого рендеринга, сортировать как порядок прорисовки самих групп батчей, так и внутренний порядок прорисовки каждого из батчей. Так ли это?

Последний раз редактировалось Warn; 17.01.2012 в 13:27.
Warn вне форума Ответить с цитированием
Старый 17.01.2012, 15:48   #55
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,690
По умолчанию

Тут нужны тесты. Хотя смею предположить, что сортировка по удаленности в приоритет, а затем текстуры и шейдеры. А про батчи забыть, от них толк появится только при отрисовки данных пересылаемых между оперативкой и видеокартой. Т.е. пока мы формируем новый массив вершин, другой успевает попасть в видеокарту и нарисоваться. А если данные геометрии уже лежат на видеокарте(VBO, VAO, текстуры...) то толку не будет.
Поэтому лучше делать как я писал выше, сначала сформировать очередь для рисования, выполнить glFlush() после чего делать дургие расчеты, пока строится кадр в видеокарте и в конце swap. Так асинхронно будут работать и процессор и видеокарта.

Последний раз редактировалось Kostia; 17.01.2012 в 15:55.
Kostia вне форума Ответить с цитированием
Старый 17.01.2012, 16:45   #56
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Цитата:
Хотя смею предположить, что сортировка по удаленности в приоритет.
Возможно, даже Early Z Pass будет полезным сделать, перед прорисовкой сцены.
По крайней мере, в классическом Forward Render рендере(ни DS) может оказаться полезным, экономим на филрейте и тяжелых шейдерах, отсекая ненужные расчеты.

Цитата:
А про батчи забыть, от них толк появится только при отрисовки данных пересылаемых между оперативкой и видеокартой. Т.е. пока мы формируем новый массив вершин, другой успевает попасть в видеокарту и нарисоваться. А если данные геометрии уже лежат на видеокарте(VBO, VAO, текстуры...) то толку не будет.
Почему не будет?)
А, вызывать 100500 раз, все ту же
Код:
glDrawArrays (GL_TRIANGLES, 0, RS0IFO[i].refGeometry.vertexes_count);
для отрисовки однотипных объектов со стороны программы это же не нормально, тут и ненужная нагрузка на ЦП, и видеокарта простаивает. Однотипные данные где бы они ни были размещены просто нужно группировать в батч\дип, это не обязательно но желательно.


Цитата:
Поэтому лучше делать как я писал выше, сначала сформировать очередь для рисования, выполнить glFlush() после чего делать дургие расчеты, пока строится кадр в видеокарте и в конце swap. Так асинхронно будут работать и процессор и видеокарта.
Т.е. логика приложения будет такой?

1. Очистка экрана
2. Рисуем сцену
3. glFlush () //тут мы озадачиваем видеокарту и она начинает рисовать
// тем временем мы…
4. Обновляем логику приложения.
5. И выполняем другие действия с нагрузкой только на ЦПУ.
6. SwapBuffers()
Warn вне форума Ответить с цитированием
Старый 18.01.2012, 17:23   #57
Kostia
Участник клуба
 
Аватар для Kostia
 
Регистрация: 21.11.2007
Сообщений: 1,690
По умолчанию

Цитата:
Почему не будет?)
А, вызывать 100500 раз, все ту же
Код:

glDrawArrays (GL_TRIANGLES, 0, RS0IFO[i].refGeometry.vertexes_count);

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

Правда статичные объекта, как ваш островок например, можно засунуть в список отображения.

В принципе оптимизация есть игры есть процесс решения многокритериальной задачи. И тут есть 2 основных критерия, это нижний и верхний FPS. Как я понял вы гонитесь за верхним, что есть не правильно, важно стабилизация минимально FSP до тех пор, пока максимальный выше какого либо заданного предела. Почему это важно, понять просто, минимальные FPS это есть лаги(тормоза), даже если у вас в сцене в основном 1000 FSP, но время от времени он падает до 10 а потом опять 1000, в помойку такую игру. Приятнее играть в стабильную игру, пусть и с не очень большим FPS ~30-50 вполне достаточно.
А все этих ухищрения с объединениями в батчи как раз могут время от времени просаживать минимальный фпс.

Цитата:
Т.е. логика приложения будет такой?

1. Очистка экрана
2. Рисуем сцену
3. glFlush () //тут мы озадачиваем видеокарту и она начинает рисовать
// тем временем мы…
4. Обновляем логику приложения.
5. И выполняем другие действия с нагрузкой только на ЦПУ.
6. SwapBuffers()
Да, такая логика будет наиболее оптимальной.(IMHO + здравый смысл и опыт)
Kostia вне форума Ответить с цитированием
Старый 18.01.2012, 21:52   #58
Warn
Форумчанин
 
Аватар для Warn
 
Регистрация: 03.11.2011
Сообщений: 230
По умолчанию

Kostia
Цитата:
(хотя я не представляю как вы собираетесь делать это для данных лежащих в видеопамяти)
Есть одна мысль, как это сделать. Инстансинг. Но пока его оставляю на потом.

Цитата:
Правда статичные объекта, как ваш островок например, можно засунуть в список отображения.
Списков вроде бы нету с недавних пор в новом gl. Это пережиток прошлого)

Так или иначе ФПСом я пока доволен как нижним так и вышним, сцена то пустая практически)

Сейчас взялся за загрузку DDS Текстур. Поскольку TGA несмотря на свою простоту довольно таки толстые.

А DDS дают компрессию в размере от оригинала RGB в 4-е раза (DXT5) и (DXT1) в 8-мь раз.
С небольшим шумом в изображении, которым можно пренебречь.
Ну и поскольку они меньше нагрузка при выборке пикселей на видеопамять меньше = больше fps))
И пока все плохо. Вроде все грузится, но вижу черный цвет на объектах, бида(

Загрузку DDS Текстур разбираю по этим докам и примерам.
Вложения
Тип файла: pdf Using Texture Compression in OpenGL.pdf (247.7 Кб, 11 просмотров)
Тип файла: zip ogl_dds_texture_loader.zip (1.63 Мб, 9 просмотров)
Warn вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Программа для проверки (правильности кода). Контекст. AmbaQ Софт 4 14.11.2010 16:50
Контекст устройства. Основы работы с изображением Claster Win Api 1 03.04.2010 00:26
BitBlt на контекст DC и его альтернатива notHaker Мультимедиа в Delphi 7 03.12.2009 01:04
Контекст воспроизведения OpenGL Gerzs Мультимедиа в Delphi 5 23.11.2009 11:33
Контекст воспроизведения OpenGL Sergeevich Gamedev - cоздание игр: Unity, OpenGL, DirectX 6 08.11.2009 21:50