opengl - Representación en el mapa del cubo
glsl fbo (1)
De acuerdo con ARB_geometry_shader4 , es posible renderizar una escena en las 6 caras de un mapa de cubo con un sombreador de geometría y el mapa de cubo conectado a un objeto framebuffer. Quiero crear un mapa de sombras usando esta forma. Sin embargo, parece haber un conflicto que no puedo resolver:
- Solo puedo adjuntar una textura con GL_DEPTH_COMPONENT como tipo interno al GL_DEPTH_ATTACHMENT_EXT.
- Una textura de profundidad solo puede ser 1D o 2D.
- Si deseo adjuntar un mapa de cubo, todas las demás texturas adjuntas también deben ser mapas de cubo.
Entonces parece que no puedo usar ninguna prueba de profundidad cuando quiero renderizar en un mapa de cubo. O qué exactamente me estoy perdiendo aquí?
EDITAR: Parece que los nuevos controladores de Nvidia (180.48) son compatibles con los mapas de cubo de profundidad.
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 ella. En ambos casos, la cara del mapa del cubo se tratará como cualquier otra textura 2D y se puede usar junto con texturas 2D normales o Renderbuffers. Y probablemente no haya mucha diferencia en todas las formas posibles (si el hardware los 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 conectado 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)
- ancho y alto de todas las texturas deben ser iguales
Para renderizar a las caras de un mapa de cubo, necesitas 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();
}
}