Domanda

Secondo ARB_geometry_shader4 è possibile eseguire il rendering di una scena su 6 facce di una mappa cubica con uno shader di geometria e la mappa cubica attaccata a un oggetto framebuffer. Voglio creare una mappa ombra usando in questo modo. Tuttavia sembra esserci un conflitto che non riesco a risolvere:

  1. Posso solo associare una trama con GL_DEPTH_COMPONENT come tipo interno a GL_DEPTH_ATTACHMENT_EXT.
  2. Una trama di profondità può essere solo 1D o 2D.
  3. Se voglio allegare una mappa cubica, anche tutte le altre trame allegate devono essere mappe cubiche.

Quindi sembra che non posso usare alcun test di profondità quando voglio renderizzare su una mappa cubica. O cosa mi manca esattamente qui?

EDIT: Sembra che i driver Nvidia più recenti (180.48) supportino le mappe dei cubi di profondità.

È stato utile?

Soluzione

Ok, per rispondere ad altre domande qui:

Naturalmente è possibile usare 6 FBO, uno per ogni faccia. O per usare un FBO e attaccare ogni faccia prima di disegnare. In entrambi i casi la faccia della mappa cubica verrà trattata come qualsiasi altra trama 2D e puoi usarla insieme alle normali trame 2D o Renderbuffer. E probabilmente non c'è molta differenza in tutti i modi possibili (se l'hardware li supporta).

Tuttavia, è anche possibile disegnare tutto in un solo passaggio e poiché ero curioso di sapere come è stato fatto, ho fatto delle ricerche.

Per creare un FBO con tutte le facce di una mappa cubica collegata a un singolo punto di attacco ho usato questo codice (scritto in 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;
}
  • Se vuoi avere solo una mappa di profondità devi cambiare glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); in glDrawBuffer (GL_NONE); prima di convalidarlo (e prima di disegnarlo) )
  • I filtri MIN e MAG devono essere impostati su qualcosa di valido (il valore predefinito sarebbe GL_NEAREST_MIPMAP_LINEAR)
  • la larghezza e l'altezza di tutte le trame devono essere uguali

Per eseguire il rendering sulle facce di una mappa cubica è necessario uno shader di geometria. Il seguente shader manca alcune rotazioni ma dovrebbe essere chiaro cosa fa. gl_Layer è usato per dirigere la primitiva sulla faccia corretta (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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top