Pregunta

Según ARB_geometry_shader4 es posible renderizar una escena en el 6 caras de un mapa de cubo con un sombreador de geometría y el mapa de cubo adjunto a un objeto framebuffer. Quiero crear un mapa de sombras de esta manera. Sin embargo, parece haber un conflicto que no puedo resolver:

  1. Solo puedo adjuntar una textura con GL_DEPTH_COMPONENT como tipo interno a GL_DEPTH_ATTACHMENT_EXT.
  2. Una textura de profundidad solo puede ser 1D o 2D.
  3. Si quiero adjuntar un mapa de cubos, todas las demás texturas adjuntas también deben ser mapas de cubos.

Parece que no puedo usar ninguna prueba de profundidad cuando quiero renderizar en un mapa de cubos. ¿O exactamente qué me estoy perdiendo aquí?

EDITAR: parece que los controladores más nuevos de Nvidia (180.48) admiten mapas de cubos de profundidad.

¿Fue útil?

Solución

Ok, para responder algunas otras preguntas aquí:

Por supuesto, es posible usar 6 FBO, uno para cada cara. O para usar un FBO y adjuntar cada cara antes de dibujar. En ambos casos, la cara del mapa del cubo se tratará como cualquier otra textura 2D y puede usarla junto con texturas 2D normales o Renderbuffers. Y probablemente no haya mucha diferencia en todas las formas posibles (si el hardware las admite).

Sin embargo, también es posible dibujar todo en un solo paso y como tenía curiosidad sobre cómo se hace esto, investigué un poco.

Para crear un FBO con todas las caras de un mapa de cubo adjunto a un único punto de conexión utilicé este código (escrito en 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;
}
  • Si desea tener solo un mapa de profundidad, debe cambiar glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); a glDrawBuffer (GL_NONE); antes de validarlo (y antes de dibujarlo) )
  • Los filtros MIN y MAG deben establecerse en algo válido (el valor predeterminado sería GL_NEAREST_MIPMAP_LINEAR)
  • el ancho y la altura de todas las texturas deben ser iguales

Para renderizar a las caras de un mapa de cubo, necesita un sombreador de geometría. El siguiente sombreador pierde algunas rotaciones, pero debe quedar claro lo que hace. gl_Layer se usa para dirigir la primitiva a la cara correcta (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();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top