Графическая проблема с нормалями вершин - PullRequest
0 голосов
/ 24 февраля 2019

Я проверил несколько решений здесь и на других страницах для вычисления вершинных нормалей.Общее решение, которое, кажется, работает лучше всего для моей собственной реализации, которая визуализирует трехмерный рельеф, - это вычисление нормалей лица, что не проблемаА затем пройдитесь по каждому лицу и добавьте его в вершины, которые составляют его, а затем нормализуйте их, когда закончите.Кажется, это работает по большей части, но у меня есть некоторые странные графические проблемы, в основном, когда свет переходит от света к темноте, вы можете сказать, где находятся лица.На следующем изображении вы можете увидеть это в нижней правой части, на вершине этого холма.

Так что мне интересно, что вызывает этот странный паттерн.Это как-то связано с тем, как я вычисляю нормали, но я просто не вижу, в чем проблема.Любая помощь будет оценена.Lunar terrain render

Код для вычисления нормалей: ...

// Calclulate surface normals
vec3 v1, v2, v3, vec1, vec2;
for(GLuint i = 0; i < terrain->NumFaces; i++) {
   v1 = terrain->Vertices[terrain->Faces[i].vert_indices[0]];
   v2 = terrain->Vertices[terrain->Faces[i].vert_indices[1]];
   vec1 = vector(&v2, &v1);

   v3 = terrain->Vertices[terrain->Faces[i].vert_indices[2]];
   vec2 = vector(&v3, &v1);

   terrain->Faces[i].surface_normal = crossProduct(&vec1, &vec2);

   normalize(&terrain->Faces[i].surface_normal);
}


// Calculate vertex normals...
// Add all the surface normals to their attached vertex normals
for(GLuint currentFace = 0; currentFace < terrain->NumFaces; currentFace++) {
   vec3 *f = &terrain->Faces[currentFace].surface_normal;
   for(GLuint faceVertex = 0; faceVertex < 3; faceVertex++) {
      vec3 *n = &terrain->Normals[terrain->Faces[currentFace].vert_indices[faceVertex]];
      *n = vec3Add(n, f); // adds vector f to n
   }
}

// Go over all vertices and normalize them
for(GLuint currentVertice = 0; currentVertice < terrain->NumVertices; currentVertice++)
   normalize(&terrain->Normals[currentVertice]);

Другими вспомогательными функциями, которые я использую в приведенном выше коде, являются ...

// Returns the vector between two vertices
vec3 vector(const vec3 *vp1, const vec3 *vp2)
{
    vec3 ret;
   ret.x = vp1->x - vp2->x;
   ret.y = vp1->y - vp2->y;
   ret.z = vp1->z - vp2->z;
    return ret;
}


// Returns the normal of two vectors
vec3 crossProduct(const vec3 *v1, const vec3 *v2)
{
   vec3 normal;
   normal.x = v1->y * v2->z - v1->z * v2->y;
   normal.y = v1->z * v2->x - v1->x * v2->z;
   normal.z = v1->x * v2->y - v1->y * v2->x;

   return normal;
}


// Returns the length of a vector
float vec3Length(vec3 *v1) {
   return sqrt(v1->x * v1->x + v1->y * v1->y + v1->z * v1->z);
}


// Normalizes a vector
void normalize(vec3 *v1)
{
   float len = vec3Length(v1);
   if(len < EPSILON) return;
   float inv = 1.0f / len;
   v1->x *= inv;
   v1->y *= inv;
   v1->z *= inv;
}


// Adds vector v2 to v1
vec3 vec3Add(vec3 *v1, vec3 *v2)
{
   vec3 v;

   v.x = v1->x + v2->x;
   v.y = v1->y + v2->y;
   v.z = v1->z + v2->z;

   return v;
}

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

После экспериментов с различными решениями я обнаружил, что мое собственное нормальное поколение в этом посте на самом деле работает очень хорошо, это практически мгновенно и не было проблемой.Проблема заключалась в использовании большой текстуры для ландшафта.Я изменил текстуру, которую использовал для ландшафта, чтобы использовать мозаичную текстуру, которая не будет сильно растягиваться, и проблема с графикой, похоже, исчезла.Было облегчением, что нормальное поколение, которое я выложил, работает хорошо, так как другие решения были ужасно медленными.Это то, что я закончил, и, как вы можете видеть, графических проблем нет.Плюс это выглядит лучше с большим количеством деталей.Я хотел опубликовать то, что узнал, на случай, если кто-то еще увидит ту же проблему.

Lunar 3D Terrain

0 голосов
/ 25 февраля 2019

Одна проблема с использованием среднего значения нормали грани для вычисления нормалей вершины состоит в том, что вычисленные нормали могут быть смещены.Например, представьте, что есть хребет, который проходит с севера на юг.Одна вершина на вершине хребта имеет три многоугольника на восточной стороне и две на западе.Нормальная вершина будет расположена под углом к ​​востоку.Это может вызвать более темное освещение в этой точке, когда освещение идет с запада.

Возможным улучшением было бы применение веса к нормали каждой грани, пропорционального углу, который имеет угол грани в этой вершине., но это не избавит от всей предвзятости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...