Я пытаюсь вычислить нормали моей поверхности сетки. Карта имеет размер 29952px x 19968px, а каждая ячейка имеет размер 128px x 128px . Итак, у меня 36895 вершин.
Сетка:
Мой массив плоских карт отправляется шейдерам со следующей структурой:
float vertices[368950] = {
// x y z znoise xTex yTex xNorm yNorm zNorm Type
16384,16256,-16256, 0, 0.54, 0.45, 0, 0, 1, 1,
16256,16384,-16384, 0, 0.54, 0.45, 0, 0, 1, 1,
......
}
Я вычисляюzNoise с функцией
float noise(float x, float y){};
И это работает (я добавляю его к y и z в вершинном шейдере) .
Метод 1
Если я вычислю нормали, используя метод конечных разностей , я получу хороший результат. Псевдокод:
vec3 off = vec3(1.0, 1.0, 0.0);
float hL = noise(P.xy - off.xz);
float hR = noise(P.xy + off.xz);
float hD = noise(P.xy - off.zy);
float hU = noise(P.xy + off.zy);
N.x = hL - hR;
N.y = hD - hU;
N.z = 2.0;
N = normalize(N);
Но, в случае, если мне нужно отредактировать карту вручную, например, в контексте редактора, где вы устанавливаете zNoise с помощью инструмента для создания гор, как вы хотите, этот метод не поможет .
Я получаю этот замечательный результат (видно из миникарты) (Нормальные значения довольно темные):
Метод 2
| | |
--6----1----+-
|\ |\ | Y
| \ | \ | ^
| \ | \ | |
| \| \| |
--5----+----2-- +-----> X
|\ |\ |
| \ | \ |
| \ | \ |
| \| \|
--+----4----3--
| | |
Итак, я пытаюсь вычислить нормаль, используя соседние треугольники, но результат сильно отличается (кажется, что где-то есть ошибка):
Код.
getVertex()
- это функция, которая принимает x, а y возвращает информацию о вершине, связанную с этой вершиной. VerticesPos
- это массив 1d, который содержит позицию каждой вершины , чтобы иметь возможность получить информацию из vertices
(той, которую я описал выше, с 10 значениями на вершину). я решил отредактировать y и z в вершинном шейдере, чтобы не трогать x и y и использовать их для индексации вершин до VerticesPos
. (Надеюсь, это вполне понятно).
glm::vec3 getVertex(int x, int y) {
int j = VerticesPos[(int)(y/128 * 29952 / 128 + x/128)];
float zNoise = vertices[j * 10 + 3] * 2;
float x1 = vertices[j * 10];
float y1 = vertices[j * 10 + 1] + zNoise;
float z1 = vertices[j * 10 + 2] + zNoise;
return glm::vec3(x1, y1, z1);
}
getAdjacentVertices()
- это функция, которая принимает vec2d (координаты x и y) и возвращает 6 соседних вершин , упорядоченных по часовой стрелке
std::array<glm::vec3, 6> getAdjacentVertices(glm::vec2 pos) {
std::array<glm::vec3, 6> output;
output = {
getVertex(pos.x, pos.y + 128), // up
getVertex(pos.x + 128, pos.y), // right
getVertex(pos.x + 128, pos.y - 128), // down-right
getVertex(pos.x, pos.y - 128), // down
getVertex(pos.x - 128, pos.y), // left
getVertex(pos.x - 128, pos.y + 128), // up-left
};
return output;
}
И последняя функция, которая выполняет эту работу:
glm::vec3 mapgen::updatedNormals(glm::vec2 pos) {
bool notBorderLineX = pos.x > 128 && pos.x < 29952 - 128;
bool notBorderLineY = pos.y > 128 && pos.y < 19968 - 128;
if (notBorderLineX && notBorderLineY) {
glm::vec3 a = getVertex(pos.x, pos.y);
std::array<glm::vec3, 6> adjVertices = getAdjacentVertices(pos);
glm::vec3 sum(0.f);
for (int i = 0; i < 6; i++) {
int j;
(i == 0) ? j = 5 : j = i - 1;
glm::vec3 side1 = adjVertices[i] - a;
glm::vec3 side2 = adjVertices[j] - a;
sum += glm::cross(side1, side2);
}
return glm::normalize(sum);
}
else {
return glm::vec3(0.3333f);
}
}
Я получаю плохой результат (видно из миникарты), к сожалению:
Примечание. Здания находятся в разных положениях, но поверхность имеет одинаковое начальное число с использованием двух методов.
Возможнокто-нибудь поможет? : -)
РЕДАКТИРОВАТЬ:
Я добавляю больше изображений, чтобы помочь понять проблему. Метод 1:
Метод 2: