¿Punteros en OpenGL sombra cubemapping?

Fondo

Estoy trabajando en un juego en 3D usando C ++ y OpenGL moderno (3.3). Ahora estoy trabajando en la iluminación y la representación de sombras, y he implementado con éxito el mapeo de sombras direccional. Después de leer los requisitos para el juego, decidí que iba a necesitar un mapa de sombra de luz de puntos. Después de investigar un poco, descubrí que para hacer un mapeo de sombras omnidireccional haré algo similar al mapeo de sombras direccional, pero con un mapa de cubos.

No tengo conocimiento previo de cubemaps, pero mi comprensión de ellos es que un mapa de cubos son seis texturas, que se adjuntan a la perfección. Miré a mi alrededor pero desafortunadamente luché para encontrar un "tutorial" definitivo sobre el tema para OpenGL moderno. Primero busco tutoriales que lo expliquen de principio a fin porque me costó mucho aprender de fragmentos de código fuente o solo de conceptos, pero lo intenté.

Entendimientos actuales

Aquí está mi comprensión general de la idea, menos los tecnicismos. Por favor corrigeme.

Para cada punto de luz, se configura un framebuffer, como el mapa de sombras direccionalA continuación, se genera una única textura de mapa de cubos y se enlaza conglBindTexture(GL_TEXTURE_CUBE_MAP, shadowmap).

El mapa de cubos está configurado con los siguientes atributos:

glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

(Esto también es similar al mapa de sombras direccional)

AhoraglTexImage2D() Se itera a través de seis veces, una para cada cara. Lo hago así:

 for (int face = 0; face < 6; face++) // Fill each face of the shadow cubemap
     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT32F , 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

La textura se adjunta al framebuffer con una llamada a

glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowmap, 0);

Cuando la escena se va a representar, se procesa en dos pasos, como el mapeo de sombras direccionales.

En primer lugar, el marcador de sombra se vincula, la ventana gráfica se ajusta al tamaño del mapa de sombras (1024 por 1024 en este caso).El sacrificio se establece en las caras frontales conglCullFace(GL_FRONT)El programa de sombreado activo se cambia a los sombreadores de sombra de vértice y fragmento del que proporcionaré las fuentes de más abajo

Se calculan las matrices de vista de luz para las seis vistas. Lo hago creando un vector de glm :: mat4's ypush_back() Las matrices, así:

// Create the six view matrices for all six sides
for (int i = 0; i < renderedObjects.size(); i++) // Iterate through all rendered objects
{
    renderedObjects[i]->bindBuffers(); // Bind buffers for rendering with it

    glm::mat4 depthModelMatrix = renderedObjects[i]->getModelMatrix(); // Set up model matrix

    for (int i = 0; i < 6; i++) // Draw for each side of the light
    {
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, shadowmap, 0);
        glClear(GL_DEPTH_BUFFER_BIT); // Clear depth buffer

        // Send MVP for shadow map
        glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrices[i] * depthModelMatrix;
        glUniformMatrix4fv(glGetUniformLocation(shadowMappingProgram, "depthMVP"), 1, GL_FALSE, glm::value_ptr(depthMVP));

        glUniformMatrix4fv(glGetUniformLocation(shadowMappingProgram, "lightViewMatrix"), 1, GL_FALSE, glm::value_ptr(depthViewMatrices[i]));
        glUniformMatrix4fv(glGetUniformLocation(shadowMappingProgram, "lightProjectionMatrix"), 1, GL_FALSE, glm::value_ptr(depthProjectionMatrix));
        glDrawElements(renderedObjects[i]->getDrawType(), renderedObjects[i]->getElementSize(), GL_UNSIGNED_INT, 0);
    }
}

El framebuffer predeterminado está enlazado y la escena se dibuja normalmente.

Problema

Ahora, a los shaders. Aquí es donde mi entendimiento se seca. No estoy completamente seguro de lo que debo hacer, mi investigación parece entrar en conflicto entre sí, porque es para diferentes versiones. Terminé copiando y pegando suavemente el código de fuentes aleatorias, y esperando que lograra algo más que una pantalla negra. Sé que esto es terrible, pero no parece haber definiciones claras sobre qué hacer. ¿En qué espacios trabajo? ¿Necesito un sombreador de sombras por separado, como el que usé en la iluminación de puntos direccionales? ¿Qué demonios utilizo como tipo para un mapa de cubos en la sombra? samplerCube? samplerCubeShadow? ¿Cómo muestro dicho cubemap correctamente? Espero que alguien me lo pueda aclarar y me brinde una buena explicación. Mi comprensión actual de la parte del sombreador es: - Cuando la escena se representa en el mapa de cubos, el sombreado de vértice simplemente toma el uniforme de depthMVP que calculé en mi código C ++ y transforma los vértices de entrada por ellos. - El fragmento de sombreado del pase cubemap simplemente asigna el valor de salida única a lagl_FragCoord.z. (Esta parte no ha cambiado desde cuando implementé el mapeo de sombras direccional. Supuse que sería lo mismo para el mapa de cubos porque los sombreadores ni siquiera interactúan con el mapa de cubos: OpenGL simplemente presenta la salida de ellos al mapa de cubos, ¿verdad? Porque es un framebuffer?)

El sombreador de vértices para la reproducción normal no se modifica.En el fragmento de sombreado para la reproducción normal, la posición del vértice se transforma en el espacio de la luz con la proyección de la luz y la matriz de vista.De alguna manera se usa en la búsqueda de texturas de mapa de página. ???Una vez que se ha recuperado la profundidad utilizando medios mágicos, se compara con la distancia de la luz al vértice, de forma muy similar a la asignación de sombras direccional. Si es menos, ese punto debe estar sombreado, y viceversa.

No es mucho de una comprensión. Me quedo en blanco en cuanto a cómo se transforman los vértices y cómo se usan para buscar el mapa de cubos, así que voy a pegar la fuente de mis sombreadores, con la esperanza de que la gente pueda aclarar esto. Tenga en cuenta que gran parte de este código es copiar y pegar a ciegas, no he alterado nada para no poner en peligro ningún entendimiento.

Sombreador de vértice de sombra:
#version 150

in vec3 position;

uniform mat4 depthMVP;

void main()
{
    gl_Position = depthMVP * vec4(position, 1);
}
Sombreador de fragmento de sombra:
#version 150

out float fragmentDepth;

void main()
{
    fragmentDepth = gl_FragCoord.z;
}
Sombreador de vértices estándar:
#version 150

in vec3 position;
in vec3 normal;
in vec2 texcoord;

uniform mat3 modelInverseTranspose;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

out vec3 fragnormal;
out vec3 fragnormaldirection;
out vec2 fragtexcoord;
out vec4 fragposition;
out vec4 fragshadowcoord;

void main()
{
    fragposition = modelMatrix * vec4(position, 1.0);
    fragtexcoord = texcoord;
    fragnormaldirection = normalize(modelInverseTranspose * normal);
    fragnormal = normalize(normal);
    fragshadowcoord = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);


    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
Sombreador de fragmentos estándar:
#version 150

out vec4 outColour;

in vec3 fragnormaldirection;
in vec2 fragtexcoord;
in vec3 fragnormal;
in vec4 fragposition;
in vec4 fragshadowcoord;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrixInversed;

uniform mat4 lightViewMatrix;
uniform mat4 lightProjectionMatrix;

uniform sampler2D tex;
uniform samplerCubeShadow shadowmap;

float VectorToDepthValue(vec3 Vec)
{
    vec3 AbsVec = abs(Vec);
    float LocalZcomp = max(AbsVec.x, max(AbsVec.y, AbsVec.z));

    const float f = 2048.0;
    const float n = 1.0;
    float NormZComp = (f+n) / (f-n) - (2*f*n)/(f-n)/LocalZcomp;
    return (NormZComp + 1.0) * 0.5;
}

float ComputeShadowFactor(samplerCubeShadow ShadowCubeMap, vec3 VertToLightWS)
{   
    float ShadowVec = texture(ShadowCubeMap, vec4(VertToLightWS, 1.0));
    if (ShadowVec + 0.0001 > VectorToDepthValue(VertToLightWS)) // To avoid self shadowing, I guess
        return 1.0;

    return 0.7;
}

void main()
{
    vec3 light_position = vec3(0.0, 0.0, 0.0);
    vec3 VertToLightWS = light_position - fragposition.xyz;
    outColour = texture(tex, fragtexcoord) * ComputeShadowFactor(shadowmap, VertToLightWS);
}

No recuerdo de dónde procedía el código de función ComputerShadowFactor y VectorToDepthValue, porque lo estaba investigando en mi computadora portátil, pero no es el momento, pero este es el resultado de esos shaders:

Es un pequeño cuadrado de espacio no sombreado rodeado de espacios sombreados.

Obviamente me estoy equivocando mucho aquí, probablemente centrado en mis sombreadores, debido a la falta de conocimiento sobre el tema porque me resulta difícil aprender de cualquier cosa que no sean tutoriales, y lo siento mucho. Estoy en una pérdida, sería maravilloso si alguien pudiera aclarar esto con una explicación clara sobre lo que estoy haciendo mal, por qué está mal, cómo puedo solucionarlo y quizás incluso algún código. Creo que el problema puede ser porque estoy trabajando en espacios equivocados.

Respuestas a la pregunta(1)

Su respuesta a la pregunta