#c #opengl #3d #rendering #2d
#c #opengl #3D #рендеринг #2d
Вопрос:
Я знаю, как ускорить рендеринг в 3d, просто сначала отрисовав ближайшие плоскости.
Но как мне воспользоваться этим типом метода в 2d-режиме? Я не могу использовать тестирование глубины, потому что все они находятся на одном z-уровне.
Итак, я подумал, можно ли ускорить это, когда мне не нужно отображать невидимые части слоев «ниже». Возможно ли это?
Обратите внимание, что я выполняю рендеринг в 3D-режиме, могут быть 3D-объекты и 2d-объекты одновременно. Поэтому я не могу переключиться только на 2d-рендеринг, я всегда использую 3D-координаты для всего. И я могу поворачивать камеру по своему усмотрению, поэтому приемы, зависящие от конкретной камеры, неприемлемы.
Редактировать: я попробовал метод, предложенный Вилле:
( http://img815.imageshack.us/img815/7857/zfighting.png )
но, как вы видите, это приведет к z-битве.
Код, который я использовал для рендеринга, находится здесь:
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_POLYGON_OFFSET_FILL);
glColor4f(1,0,0,1);
DrawQuad(0, 0, 10, 10);
glColor4f(0,0,1,1);
DrawQuad(5, 5, 15, 15);
glDepthFunc(GL_LEQUAL);
Комментарии:
1. Тестирование глубины (с режимом по умолчанию GL_LESS) все равно будет работать, даже если все ваши 2d-объекты находятся на одном z-уровне. Пиксели не будут обновляться дважды.
2. @Вилле, это привело бы к z-битве. смотрите изображение, которое я опубликовал.
3. Вы правы, я думал, вы имели в виду 2d-объекты в стиле HUD и не поняли, что вы намеревались вращать камеру вокруг 2d-объектов тоже. Для этого я бы сначала отрисовал текстуру в орторежиме, как предлагает derkyjadex.
4. @Вилле, не будет ли рендеринг в текстуре излишеством …? я специально пытаюсь найти более быстрый метод, чем я использую atm: просто отключаю тестирование глубины. Но я надеялся, что смогу немного оптимизировать это, поскольку на самом деле это отрисовывает несколько бесполезных пикселей, которые никогда не видны…
Ответ №1:
Звучит так, как будто вы визуализируете все свои «2D» объекты на одной плоскости. Вы могли бы отобразить свои 2D-части в закадровый буфер кадров с ортографической проекцией и присвоить им разные значения Z, как предложил datenwolf. Затем отобразите текстуру фреймбуфера в вашей основной 3D-сцене.
Комментарии:
1. Или просто очистите буфер глубины и перерисуйте 2D-плоскости.
2. рендеринг в фреймбуфер выполняется быстрее, чем просто отключение проверки глубины?
3. Возможно, нет, у datenwolf, возможно, есть предложение получше. Но вы не отключаете проверку глубины, вы очищаете буфер глубины, чтобы OpenGL «забыл» об уже отрисованных 3D-объектах. Использование отдельного фреймбуфера эффективно делает то же самое, но вы можете сохранить свой буфер глубины 3D, если некоторые из 3D-объектов должны отображаться перед 2D-объектами.
Ответ №2:
Что вы понимаете под 2D-режимом? Вы имеете в виду ортографическую проекцию? Тогда у меня есть хорошие новости: тестирование глубины работает и там отлично. gluOrtho2D в основном такой же, как glOrtho (…, -1, 1); т. Е. вам нужно потратить диапазон Z -1 … 1.
РЕДАКТИРОВАТЬ из-за комментария:
Вполне возможно объединить рендеринг нескольких проекций в одном кадре:
void render_perspective_scene(void);
void render_ortho_scene(void);
void render_HUD();
void display()
{
float const aspect = (float)win_width/(float)win_height;
glViewport(0,0,win_width,win_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-aspect*near/lens, aspect*near/lens, -near/lens, near/lens, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_perspective_scene();
// just clear the depth buffer, so that everything that's
// drawn next will overlay the previously rendered scene.
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect*scale, aspect*scale, -scale, scale, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_ortho_scene();
// Same for the HUD, only that we render
// that one in pixel coordinates.
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, win_width, 0, win_height, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_HUD();
}
Конечно, если вы повелись на те плохие руководства, которые помещают настройку матрицы проекции в обработчик изменения формы, вы, конечно, не в состоянии увидеть это очевидное решение.
Комментарии:
1. «Обратите внимание, что я выполняю рендеринг в 3D-режиме, могут быть 3D-объекты и 2d-объекты одновременно. Итак, я не могу переключиться только на 2d-рендеринг «вы это читали?
2. Конечно, вы можете переключить это. Как, по-вашему, визуализируются игровые изображения?
3. HUD — это не то, чего я пытаюсь достичь здесь. Представьте, что у вас есть обычный 3D-мир, и затем вы визуализируете 3D-мир в 2D-режиме, если смотреть сверху, а затем поворачиваете камеру и видите, как мир сглаживается.
4. Хорошо, вы страдаете от серьезного заблуждения: OpenGL — это не график сцены. После того, как вы отправили некоторую геометрию в OpenGL, она просто растрирует ее до пикселей, а затем забывает о геометрии. Итак, переход к ортогональному рендерингу чего-либо, а затем поворот / переключение проекции не изменит то, что вы уже нарисовали в фреймбуфере. Итак, что вам на самом деле нужно сделать, это либо выполнить рендеринг текстур, затем нарисовать эти квадратики, либо сотворить какую-нибудь шейдерную магию, чтобы спроецировать геометрию плоско на эти плоскости, но при этом передать значения глубины, пригодные для тестирования глубины.
5. я пробовал с шейдерами, но это также потребовало отключения проверки глубины … я думаю, что для этого нет решения, не то чтобы мне это действительно нужно, но, как помешанный на оптимизации, я хотел бы знать каждый трюк: P