Аномальное смещение по 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 шт):
Я отказался от такой реализации, предпочтя использование кубической текстуры. Реализация с ними намного проще. Кубическая текстура (или samplerCube) представляет собой текстуру, которая заполняется 6-ю текстурами на каждую сторону куба. Через вызов функции texture во фрагментном шейдере (texture(outSamplerCube,position.xyz)) можно получить проекцию вектора position на куб
Используя такую текстуру, надо лишь правильно настроить 6 матриц.
Вот 1 из видео, где объясняется работа с кубическими текстурами https://www.youtube.com/watch?v=uhCbfZ_L7uc&t=485s