O mapeamento de sombras do Cubemap não funciona

Eu estou tentando criar iluminação omnidirecional / ponto na versão 3.3 openGL. Eu pesquisei na internet e neste site, mas até agora não consegui fazer isso. Do meu entendimento, eu devo

Gerar um framebuffer usando o componente de profundidade

Gere um cubemap e ligue-o ao framebuffer

Desenhe para as partes individuais do cubemap como refrigido pelas enums GL_TEXTURE_CUBE_MAP_ *

Desenhe a cena normalmente e compare o valor da profundidade dos fragmentos com os que estão no cubemap

Agora, eu li que é melhor usar distâncias da luz para o fragmento, em vez de armazenar a profundidade do fragmento, uma vez que permite uma busca mais fácil do cubemap (algo sobre não precisar verificar cada textura individual?)

Minha edição atual é que a luz que sai está realmente em uma esfera, e não gera sombras. Outra questão é que o framebuffer se queixa de não estar completo, embora eu tenha a impressão de que um framebuffer não precisa de um renderbuffer se ele renderizar uma textura.

Aqui está minha inicialização do framebuffer e do mapa de cubos:

framebuffer = 0;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

glGenTextures(1, &shadowTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);GL_COMPARE_R_TO_TEXTURE);
for(int i = 0; i < 6; i++){
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i , 0,GL_DEPTH_COMPONENT16, 800, 800, 0,GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
}

glDrawBuffer(GL_NONE);
Sombreamento de vértice de sombra
void main(){
    gl_Position = depthMVP * M* vec4(position,1);
    pos =(M * vec4(position,1)).xyz;
}
Shadow Shader Fragment
void main(){
    fragmentDepth = distance(lightPos, pos);
}
Vertex Shader (bits não relacionados cortados)
uniform mat4 depthMVP;
void main() {
    PositionWorldSpace = (M * vec4(position,1.0)).xyz;
    gl_Position = MVP * vec4(position, 1.0 );

    ShadowCoord = depthMVP * M* vec4(position, 1.0);
}
Fragment Shader (corte de código não relacionado)
uniform samplerCube shadowMap;
void main(){
    float bias = 0.005;
    float visibility = 1;
    if(texture(shadowMap, ShadowCoord.xyz).x < distance(lightPos, PositionWorldSpace)-bias)
        visibility = 0.1
}

Agora, como você provavelmente está pensando, o que é o depthMVP? Matriz de projeção de profundidade é atualmente uma projeção ortogonal com os intervalos [-10, 10] em cada direção Bem, eles são definidos da seguinte forma:

glm::mat4 depthMVP = depthProjectionMatrix* ??? *i->getModelMatrix();

A questão aqui é que eu não sei o que ??? valor é suposto ser. Ela costumava ser a matriz da câmera, mas não tenho certeza se é isso que ela deveria ser. Então o código de desenho é feito para os lados do cubemap da seguinte forma:

for(int loop = 0; loop < 6; loop++){
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+loop, shadowTexture,0);
    glClear( GL_DEPTH_BUFFER_BIT);
    for(auto i: models){
        glUniformMatrix4fv(modelPos, 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
        glm::mat4 depthMVP = depthProjectionMatrix*???*i->getModelMatrix();
        glUniformMatrix4fv(glGetUniformLocation(shadowProgram, "depthMVP"),1, GL_FALSE, glm::value_ptr(depthMVP));
        glBindVertexArray(i->vao);
        glDrawElements(GL_TRIANGLES, i->triangles, GL_UNSIGNED_INT,0);
    }
}

Finalmente a cena é desenhada normalmente (vou poupar os detalhes). Antes das chamadas para desenhar no cubemap eu configurei o framebuffer para o que eu gerava anteriormente e mudei a viewport para 800 por 800. Eu mudo o framebuffer de volta para 0 e restaurei a viewport para 800 por 600 antes de fazer o desenho normal. Qualquer ajuda sobre este assunto será muito apreciada.

Atualização 1

Depois de alguns ajustes e correção de bugs, este é o resultado que recebo. Eu consertei um erro com o depthMVP não funcionando, o que estou desenhando aqui é a distância que está armazenada no cubemap.http://imgur.com/JekOMvf

Basicamente, o que acontece é que ele desenha a mesma projeção unilateral de cada lado. Isso faz sentido, já que usamos a mesma matriz de visualização para cada lado, mas não tenho certeza de que tipo de matriz de visualização devo usar. Eu acho que eles deveriam ser matrizes lookAt () que estão posicionadas no centro e olhar na direção do lado do mapa do cubo. No entanto, a questão que surge é como devo usar essas múltiplas projeções na chamada principal.

Atualização 2

Eu segui em frente e criei estas matrizes, mas não tenho certeza de como elas são válidas (elas foram copiadas de um site para cubemaps de DX, então eu inverti a coordenada Z).

case 1://Negative X
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(-1,0,0),glm::vec3(0,-1,0));
    break;
case 3://Negative Y
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,-1,0),glm::vec3(0,0,-1));
    break;
case 5://Negative Z
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,-1),glm::vec3(0,-1,0));
    break;
case 0://Positive X
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(1,0,0),glm::vec3(0,-1,0));
    break;
case 2://Positive Y
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,1,0),glm::vec3(0,0,1));
    break;
case 4://Positive Z
    sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,1),glm::vec3(0,-1,0));
    break;

A questão ainda permanece, o que eu deveria traduzir a parte da visão depthMVP por, como estas são 6 matrizes individuais. Aqui está uma captura de tela do que parece atualmente, com o mesmo frag shader (ou seja, renderizando sombras)http://i.imgur.com/HsOSG5v.png Como você pode ver as sombras parecem boas, no entanto, o posicionamento é obviamente um problema. A matriz de visualização que usei para gerar isso era apenas uma tradução inversa da posição da câmera (como faria a função lookAt).

Atualização 3

Código, como está atualmente: Shadow Vertex

void main(){
    gl_Position = depthMVP * vec4(position,1);
    pos =(M * vec4(position,1)).xyz;
}

Fragmento de Sombra

void main(){
    fragmentDepth = distance(lightPos, pos);
}

Vértice Principal

void main(){
    PositionWorldSpace = (M*vec4(position, 1)).xyz;
    ShadowCoord = vec4(PositionWorldSpace - lightPos, 1);
}

Frag Principal

void main(){
    float texDist = texture(shadowMap, ShadowCoord.xyz/ShadowCoord.w).x;
    float dist = distance(lightPos, PositionWorldSpace);
    if(texDist < distance(lightPos, PositionWorldSpace)
        visibility = 0.1;
    outColor = vec3(texDist);//This is to visualize the depth maps
}

A matriz de perspectiva sendo usada

glm::mat4 depthProjectionMatrix = glm::perspective(90.f, 1.f, 1.f, 50.f);

Tudo está funcionando atualmente, mais ou menos. Os dados que a textura armazena (isto é, a distância) parecem ser armazenados de uma maneira estranha. Parece normalizado, já que todos os valores estão entre 0 e 1. Além disso, há uma área 1x1x1 ao redor do visualizador que não tem projeção, mas isso é devido ao tronco e acho que será fácil de corrigir (como compensando as câmeras de volta .5 no centro).

questionAnswers(1)

yourAnswerToTheQuestion