Вопрос

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

  1. Я могу прикрепить к GL_DEPTH_ATTACHMENT_EXT текстуру только с внутренним типом GL_DEPTH_COMPONENT.
  2. Текстура глубины может быть только 1D или 2D.
  3. Если я хочу прикрепить карту куба, все остальные прикрепленные текстуры также должны быть картами куба.

Похоже, я не могу использовать какое-либо тестирование глубины, когда хочу выполнить рендеринг в карту куба.Или что именно мне здесь не хватает?

РЕДАКТИРОВАТЬ: Похоже, что более новые драйверы Nvidia (180.48) поддерживают карты кубов глубины.

Это было полезно?

Решение

Хорошо, ответим на другие вопросы здесь:

Конечно, можно использовать 6 FBO, по одному на каждую грань.Или использовать один FBO и прикреплять каждую грань, прежде чем рисовать на ней.В обоих случаях грань карты куба будет обрабатываться как любая другая 2D-текстура, и вы сможете использовать ее вместе с обычными 2D-текстурами или буферами рендеринга.И, вероятно, разница между всеми возможными способами (если оборудование их поддерживает) невелика.

Однако также возможно нарисовать все за один шаг, и поскольку мне было любопытно, как это делается, я провел небольшое исследование.

Чтобы создать FBO со всеми гранями карты куба, прикрепленными к одной точке присоединения, я использовал этот код (написанный на D):

// depth cube map
glGenTextures(1, &tDepthCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, tDepthCubeMap);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (uint face = 0; face < 6; face++) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT24,
        width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
}

// color cube map
glGenTextures(1, &tColorCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, tColorCubeMap);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (uint face = 0; face < 6; face++) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA,
        width, height, 0, GL_RGBA, GL_FLOAT, null);
}

// framebuffer object
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, tDepthCubeMap, 0);
glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, tColorCubeMap, 0);

glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);

if (!isValidFBO()) {
    glDeleteFramebuffersEXT(1, &fbo);
    fbo = 0;
}
  • Если вы хотите иметь только карту глубины, вам придется изменить glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); к glDrawBuffer (GL_NONE); перед его проверкой (и перед тем, как к нему обратиться)
  • Для фильтров MIN и MAG должно быть установлено что-то допустимое (по умолчанию — GL_NEAREST_MIPMAP_LINEAR).
  • ширина и высота всех текстур должны быть одинаковыми

Для рендеринга граней кубической карты вам понадобится геометрический шейдер.Следующий шейдер пропускает некоторые вращения, но должно быть понятно, что он делает.gl_Layer используется для направления примитива на правильную грань (0 = +X, 1 = -X, ...).

#version 120
#extension GL_EXT_geometry_shader4 : enable

void main(void) {
    int i, layer;
    for (layer = 0; layer < 6; layer++) {
        gl_Layer = layer;
        for (i = 0; i < 3; i++) {
            gl_Position = gl_PositionIn[i];
            EmitVertex();
        }
        EndPrimitive();
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top