Аномальное смещение по Z

Я делаю точечное освещение с использованием 6 карт теней (Cube mapping или Cube shadows). И я столкнулся с проблемой, у меня матрицы +Z и -Z (матрицы, смотрящие вдоль оси Z) смещены по этой оси в - (смещение происходит только у 2 матриц). Я выяснил, что смещение происходит на 'near' матрицы. Матрицы в шейдер я передал правильно. Проверял я это через окрашивание пикселя в конкретный цвет, зависимости от того, какой стороной куба он должен освещается, и умножая на нормализированную глубину.

Часть кода из фрагментного шейдера

    vec4 lightDirection = matrix[4] * vec4(fragPosition,1.0f);

    int id = getNearestSideIdToPointLight(lightDirection.xyz);

    lightDirection = matrix[id] * vec4(fragPosition,1.0f);
    vec3 nPos = lightDirection.xyz/lightDirection.w;

    if (id==0) pixelColor = vec4(1,0,0,1);
    else if (id==1) pixelColor = vec4(0,1,0,1);
    else if (id==2) pixelColor = vec4(0,0,1,1);
    else if (id==3) pixelColor = vec4(1,1,0,1);
    else if (id==4) pixelColor = vec4(0,1,1,1);
    else if (id==5) pixelColor = vec4(1,0,1,1);

    pixelColor.rgb*=nPos.z;

    gl_FragColor = pixelColor;

Функция getNearestSideIdToPointLight

//0 - +X, 1 - -X, 2 - +Y, 3 - -Y, 4 - +Z, 5 - -Z
//Нахождение айди ближайшей стороны к точечному свету
//dist - вектор от источника света до пикселя. Координата пикселя должна быть не трансформированой матрицей
int getNearestSideIdToPointLight(vec3 dist) {
    float absX = abs(dist.x);
    float absY = abs(dist.y);
    float absZ = abs(dist.z);

    if (absX >= absY && absX >= absZ) return (dist.x >= 0.0) ? 1 : 0;
    else if (absY >= absZ) return (dist.y >= 0.0) ? 2 : 3;
    else return (dist.z >= 0.0) ? 4 : 5;
}

Функция, создающая матрицы

//0 - +X, 1 - -X, 2 - +Y, 3 - -Y, 4 - +Z, 5 - -Z
    public Matrix4f[] createMatrix (Vector3f position, float radius) {
        Matrix4f[] matrix = new Matrix4f[6];
        Vector3f correctPosition = position.negate();

        for (int i = 0; i < matrix.length; i++) {
            matrix[i] = new Matrix4f().identity();
            matrix[i].perspective((float)Math.toRadians(90),1,0.1f,radius);
        }

        matrix[0].lookAt(new Vector3f(0,0,0),new Vector3f(1,0,0),new Vector3f(0,1,0));
        matrix[1].lookAt(new Vector3f(0,0,0),new Vector3f(-1,0,0),new Vector3f(0,1,0));
        matrix[2].lookAt(new Vector3f(0,0,0),new Vector3f(0,1,0),new Vector3f(0,0,1));
        matrix[3].lookAt(new Vector3f(0,0,0),new Vector3f(0,-1,0),new Vector3f(0,0,1));
        matrix[4].lookAt(new Vector3f(0,0,0),new Vector3f(0,0,1),new Vector3f(0,1,0));
        matrix[5].lookAt(new Vector3f(0,0,0),new Vector3f(0,0,-1),new Vector3f(0,1,0));

        for (int i = 0; i < matrix.length; i++) matrix[i].translate(correctPosition);

        matrix[4].translate(0,0,1);
        matrix[5].translate(0,0,1);

        return matrix;
    }

Вот сам сдвиг. Чем темнее пиксель, тем он ближе к матрице, которая должна его освещать. В случае на картинке видно, что смещение происходит по оси Z (тёмные пиксели идут не от координаты источника света)

введите сюда описание изображения

тут near = 0.5. near - ближняя плоскость матрицы

введите сюда описание изображения

Может тут кто-то уже сталкивался с таким.


Ответы (1 шт):

Автор решения: user613146

Я отказался от такой реализации, предпочтя использование кубической текстуры. Реализация с ними намного проще. Кубическая текстура (или samplerCube) представляет собой текстуру, которая заполняется 6-ю текстурами на каждую сторону куба. Через вызов функции texture во фрагментном шейдере (texture(outSamplerCube,position.xyz)) можно получить проекцию вектора position на куб

введите сюда описание изображения

Используя такую текстуру, надо лишь правильно настроить 6 матриц.

Вот 1 из видео, где объясняется работа с кубическими текстурами https://www.youtube.com/watch?v=uhCbfZ_L7uc&t=485s

→ Ссылка